@bhimudev/gnanai 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +270 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +188 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/commands/cleanup.d.ts +21 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +380 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/dispatch.d.ts +13 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/dispatch.js +85 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +155 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +167 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +711 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/knowledge-sync.d.ts +69 -0
- package/dist/commands/knowledge-sync.d.ts.map +1 -0
- package/dist/commands/knowledge-sync.js +661 -0
- package/dist/commands/knowledge-sync.js.map +1 -0
- package/dist/commands/knowledge.d.ts +35 -0
- package/dist/commands/knowledge.d.ts.map +1 -0
- package/dist/commands/knowledge.js +254 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/rollback.d.ts +13 -0
- package/dist/commands/rollback.d.ts.map +1 -0
- package/dist/commands/rollback.js +186 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/setup-config.d.ts +6 -0
- package/dist/commands/setup-config.d.ts.map +1 -0
- package/dist/commands/setup-config.js +663 -0
- package/dist/commands/setup-config.js.map +1 -0
- package/dist/commands/setup-project.d.ts +6 -0
- package/dist/commands/setup-project.d.ts.map +1 -0
- package/dist/commands/setup-project.js +361 -0
- package/dist/commands/setup-project.js.map +1 -0
- package/dist/commands/setup.d.ts +3 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +293 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +51 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +182 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +3 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +173 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +435 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/worktree.d.ts +30 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +262 -0
- package/dist/commands/worktree.js.map +1 -0
- package/dist/generator/claude-cli.d.ts +24 -0
- package/dist/generator/claude-cli.d.ts.map +1 -0
- package/dist/generator/claude-cli.js +239 -0
- package/dist/generator/claude-cli.js.map +1 -0
- package/dist/generator/prompt-builder.d.ts +7 -0
- package/dist/generator/prompt-builder.d.ts.map +1 -0
- package/dist/generator/prompt-builder.js +144 -0
- package/dist/generator/prompt-builder.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/embeddings.d.ts +53 -0
- package/dist/mcp/embeddings.d.ts.map +1 -0
- package/dist/mcp/embeddings.js +68 -0
- package/dist/mcp/embeddings.js.map +1 -0
- package/dist/mcp/hybrid-search.d.ts +25 -0
- package/dist/mcp/hybrid-search.d.ts.map +1 -0
- package/dist/mcp/hybrid-search.js +72 -0
- package/dist/mcp/hybrid-search.js.map +1 -0
- package/dist/mcp/knowledge-server.d.ts +4 -0
- package/dist/mcp/knowledge-server.d.ts.map +1 -0
- package/dist/mcp/knowledge-server.js +294 -0
- package/dist/mcp/knowledge-server.js.map +1 -0
- package/dist/mcp/knowledge-utils.d.ts +65 -0
- package/dist/mcp/knowledge-utils.d.ts.map +1 -0
- package/dist/mcp/knowledge-utils.js +207 -0
- package/dist/mcp/knowledge-utils.js.map +1 -0
- package/dist/mcp/search-factory.d.ts +9 -0
- package/dist/mcp/search-factory.d.ts.map +1 -0
- package/dist/mcp/search-factory.js +23 -0
- package/dist/mcp/search-factory.js.map +1 -0
- package/dist/mcp/search-index.d.ts +45 -0
- package/dist/mcp/search-index.d.ts.map +1 -0
- package/dist/mcp/search-index.js +2 -0
- package/dist/mcp/search-index.js.map +1 -0
- package/dist/mcp/search-minisearch.d.ts +46 -0
- package/dist/mcp/search-minisearch.d.ts.map +1 -0
- package/dist/mcp/search-minisearch.js +99 -0
- package/dist/mcp/search-minisearch.js.map +1 -0
- package/dist/mcp/search-sqlite.d.ts +30 -0
- package/dist/mcp/search-sqlite.d.ts.map +1 -0
- package/dist/mcp/search-sqlite.js +188 -0
- package/dist/mcp/search-sqlite.js.map +1 -0
- package/dist/mcp/vector-store.d.ts +52 -0
- package/dist/mcp/vector-store.d.ts.map +1 -0
- package/dist/mcp/vector-store.js +183 -0
- package/dist/mcp/vector-store.js.map +1 -0
- package/dist/scaffold/copy-core-agents.d.ts +2 -0
- package/dist/scaffold/copy-core-agents.d.ts.map +1 -0
- package/dist/scaffold/copy-core-agents.js +90 -0
- package/dist/scaffold/copy-core-agents.js.map +1 -0
- package/dist/scaffold/create-claude-settings.d.ts +40 -0
- package/dist/scaffold/create-claude-settings.d.ts.map +1 -0
- package/dist/scaffold/create-claude-settings.js +422 -0
- package/dist/scaffold/create-claude-settings.js.map +1 -0
- package/dist/scaffold/create-config.d.ts +14 -0
- package/dist/scaffold/create-config.d.ts.map +1 -0
- package/dist/scaffold/create-config.js +199 -0
- package/dist/scaffold/create-config.js.map +1 -0
- package/dist/scaffold/create-project-description.d.ts +12 -0
- package/dist/scaffold/create-project-description.d.ts.map +1 -0
- package/dist/scaffold/create-project-description.js +104 -0
- package/dist/scaffold/create-project-description.js.map +1 -0
- package/dist/scaffold/create-structure.d.ts +2 -0
- package/dist/scaffold/create-structure.d.ts.map +1 -0
- package/dist/scaffold/create-structure.js +146 -0
- package/dist/scaffold/create-structure.js.map +1 -0
- package/dist/types/dependency-analysis.d.ts +11 -0
- package/dist/types/dependency-analysis.d.ts.map +1 -0
- package/dist/types/dependency-analysis.js +2 -0
- package/dist/types/dependency-analysis.js.map +1 -0
- package/dist/types/index.d.ts +526 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/task.d.ts +25 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +3 -0
- package/dist/types/task.js.map +1 -0
- package/dist/utils/analyze-files.d.ts +7 -0
- package/dist/utils/analyze-files.d.ts.map +1 -0
- package/dist/utils/analyze-files.js +27 -0
- package/dist/utils/analyze-files.js.map +1 -0
- package/dist/utils/backup.d.ts +102 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +352 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/ci-provider.d.ts +23 -0
- package/dist/utils/ci-provider.d.ts.map +1 -0
- package/dist/utils/ci-provider.js +525 -0
- package/dist/utils/ci-provider.js.map +1 -0
- package/dist/utils/ci-status.d.ts +57 -0
- package/dist/utils/ci-status.d.ts.map +1 -0
- package/dist/utils/ci-status.js +349 -0
- package/dist/utils/ci-status.js.map +1 -0
- package/dist/utils/dependency-analysis.d.ts +34 -0
- package/dist/utils/dependency-analysis.d.ts.map +1 -0
- package/dist/utils/dependency-analysis.js +298 -0
- package/dist/utils/dependency-analysis.js.map +1 -0
- package/dist/utils/detect-git.d.ts +57 -0
- package/dist/utils/detect-git.d.ts.map +1 -0
- package/dist/utils/detect-git.js +439 -0
- package/dist/utils/detect-git.js.map +1 -0
- package/dist/utils/detect-mcp.d.ts +32 -0
- package/dist/utils/detect-mcp.d.ts.map +1 -0
- package/dist/utils/detect-mcp.js +178 -0
- package/dist/utils/detect-mcp.js.map +1 -0
- package/dist/utils/detect-project.d.ts +3 -0
- package/dist/utils/detect-project.d.ts.map +1 -0
- package/dist/utils/detect-project.js +155 -0
- package/dist/utils/detect-project.js.map +1 -0
- package/dist/utils/file-comparison.d.ts +89 -0
- package/dist/utils/file-comparison.d.ts.map +1 -0
- package/dist/utils/file-comparison.js +301 -0
- package/dist/utils/file-comparison.js.map +1 -0
- package/dist/utils/file-merger.d.ts +74 -0
- package/dist/utils/file-merger.d.ts.map +1 -0
- package/dist/utils/file-merger.js +350 -0
- package/dist/utils/file-merger.js.map +1 -0
- package/dist/utils/logger.d.ts +26 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +72 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/managed-process.d.ts +109 -0
- package/dist/utils/managed-process.d.ts.map +1 -0
- package/dist/utils/managed-process.js +481 -0
- package/dist/utils/managed-process.js.map +1 -0
- package/dist/utils/merge-claude-settings.d.ts +65 -0
- package/dist/utils/merge-claude-settings.d.ts.map +1 -0
- package/dist/utils/merge-claude-settings.js +133 -0
- package/dist/utils/merge-claude-settings.js.map +1 -0
- package/dist/utils/migration.d.ts +74 -0
- package/dist/utils/migration.d.ts.map +1 -0
- package/dist/utils/migration.js +345 -0
- package/dist/utils/migration.js.map +1 -0
- package/dist/utils/process-health.d.ts +51 -0
- package/dist/utils/process-health.d.ts.map +1 -0
- package/dist/utils/process-health.js +123 -0
- package/dist/utils/process-health.js.map +1 -0
- package/dist/utils/process-registry.d.ts +20 -0
- package/dist/utils/process-registry.d.ts.map +1 -0
- package/dist/utils/process-registry.js +151 -0
- package/dist/utils/process-registry.js.map +1 -0
- package/dist/utils/process-tree.d.ts +51 -0
- package/dist/utils/process-tree.d.ts.map +1 -0
- package/dist/utils/process-tree.js +499 -0
- package/dist/utils/process-tree.js.map +1 -0
- package/dist/utils/repair-mcp-config.d.ts +15 -0
- package/dist/utils/repair-mcp-config.d.ts.map +1 -0
- package/dist/utils/repair-mcp-config.js +129 -0
- package/dist/utils/repair-mcp-config.js.map +1 -0
- package/dist/utils/task-lifecycle.d.ts +60 -0
- package/dist/utils/task-lifecycle.d.ts.map +1 -0
- package/dist/utils/task-lifecycle.js +310 -0
- package/dist/utils/task-lifecycle.js.map +1 -0
- package/dist/utils/update-agent-mcp.d.ts +7 -0
- package/dist/utils/update-agent-mcp.d.ts.map +1 -0
- package/dist/utils/update-agent-mcp.js +115 -0
- package/dist/utils/update-agent-mcp.js.map +1 -0
- package/dist/utils/update-agent-templates.d.ts +6 -0
- package/dist/utils/update-agent-templates.d.ts.map +1 -0
- package/dist/utils/update-agent-templates.js +56 -0
- package/dist/utils/update-agent-templates.js.map +1 -0
- package/dist/utils/update-config-ci.d.ts +7 -0
- package/dist/utils/update-config-ci.d.ts.map +1 -0
- package/dist/utils/update-config-ci.js +72 -0
- package/dist/utils/update-config-ci.js.map +1 -0
- package/dist/utils/update-config-git.d.ts +18 -0
- package/dist/utils/update-config-git.d.ts.map +1 -0
- package/dist/utils/update-config-git.js +146 -0
- package/dist/utils/update-config-git.js.map +1 -0
- package/dist/utils/update-config-mcp.d.ts +7 -0
- package/dist/utils/update-config-mcp.d.ts.map +1 -0
- package/dist/utils/update-config-mcp.js +98 -0
- package/dist/utils/update-config-mcp.js.map +1 -0
- package/dist/utils/validate-config.d.ts +3 -0
- package/dist/utils/validate-config.d.ts.map +1 -0
- package/dist/utils/validate-config.js +109 -0
- package/dist/utils/validate-config.js.map +1 -0
- package/dist/utils/version-tracker.d.ts +130 -0
- package/dist/utils/version-tracker.d.ts.map +1 -0
- package/dist/utils/version-tracker.js +298 -0
- package/dist/utils/version-tracker.js.map +1 -0
- package/dist/utils/worktree.d.ts +68 -0
- package/dist/utils/worktree.d.ts.map +1 -0
- package/dist/utils/worktree.js +446 -0
- package/dist/utils/worktree.js.map +1 -0
- package/package.json +77 -0
- package/templates/ARCHAI_README.md +329 -0
- package/templates/CLAUDE.md +67 -0
- package/templates/PROMPTS.md +506 -0
- package/templates/core-agents/boss-agent.md +671 -0
- package/templates/core-agents/cleanup-agent.md +145 -0
- package/templates/core-agents/code-reviewer.md +175 -0
- package/templates/core-agents/critical-reviewer.md +117 -0
- package/templates/core-agents/deep-analyst.md +216 -0
- package/templates/core-agents/finalization-agent.md +252 -0
- package/templates/core-agents/git-coordinator.md +240 -0
- package/templates/core-agents/implementation-agent.md +151 -0
- package/templates/core-agents/maestro-agent.md +413 -0
- package/templates/core-agents/maestro-headless-agent.md +422 -0
- package/templates/core-agents/plan-validator.md +198 -0
- package/templates/core-agents/quick-fix.md +56 -0
- package/templates/core-agents/routing-templates.md +338 -0
- package/templates/core-agents/task-orchestrator.md +143 -0
- package/templates/core-agents/task-prep.md +202 -0
- package/templates/core-agents/tdd-designer.md +143 -0
- package/templates/specialist-meta.md +275 -0
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { scaffoldProject } from '../scaffold/create-structure.js';
|
|
7
|
+
import { copyCoreAgents } from '../scaffold/copy-core-agents.js';
|
|
8
|
+
import { createConfigTemplate } from '../scaffold/create-config.js';
|
|
9
|
+
import { createProjectDescription } from '../scaffold/create-project-description.js';
|
|
10
|
+
import { createClaudeSettings } from '../scaffold/create-claude-settings.js';
|
|
11
|
+
import { detectProject } from '../utils/detect-project.js';
|
|
12
|
+
import { logger } from '../utils/logger.js';
|
|
13
|
+
import { createBackup, pruneOldBackups } from '../utils/backup.js';
|
|
14
|
+
import { loadVersionFile, saveVersionFile, createVersionFile, bulkUpdateFileHashes, } from '../utils/version-tracker.js';
|
|
15
|
+
import { detectLegacyInstall, hasExistingInstall, migrateFromLegacy, getArchaiVersion, getTemplateFiles, getTemplatesDir, } from '../utils/migration.js';
|
|
16
|
+
import { hashFile, } from '../utils/file-comparison.js';
|
|
17
|
+
import { mergeFile, applyMerge, } from '../utils/file-merger.js';
|
|
18
|
+
import { analyzeAllFiles } from '../utils/analyze-files.js';
|
|
19
|
+
import { setup } from './setup.js';
|
|
20
|
+
const PROJECT_TYPES = [
|
|
21
|
+
{ name: 'Web Application (frontend/backend/fullstack)', value: 'web' },
|
|
22
|
+
{ name: 'Mobile Application', value: 'mobile' },
|
|
23
|
+
{ name: 'CLI Tool / Library', value: 'cli' },
|
|
24
|
+
{ name: 'Game', value: 'game' },
|
|
25
|
+
{ name: 'Data Science / ML', value: 'ml' },
|
|
26
|
+
{ name: 'DevOps / Infrastructure', value: 'devops' },
|
|
27
|
+
{ name: 'Other', value: 'other' },
|
|
28
|
+
];
|
|
29
|
+
const CLAUDE_DIR = '.claude';
|
|
30
|
+
// Folders that will be created by scaffoldProject
|
|
31
|
+
const FOLDERS = [
|
|
32
|
+
'.claude/agents',
|
|
33
|
+
'.claude/state',
|
|
34
|
+
'.claude/state/archived',
|
|
35
|
+
'.claude/plans',
|
|
36
|
+
'.claude/plans/archived',
|
|
37
|
+
'.claude/templates',
|
|
38
|
+
'.knowledge/context',
|
|
39
|
+
'.knowledge/decisions',
|
|
40
|
+
'.knowledge/learnings',
|
|
41
|
+
'.knowledge/planning',
|
|
42
|
+
'.knowledge/status',
|
|
43
|
+
'.tasks/inbox',
|
|
44
|
+
'.tasks/done',
|
|
45
|
+
'.tasks/epics',
|
|
46
|
+
'.tasks/review',
|
|
47
|
+
'.tasks/blocked',
|
|
48
|
+
'.tasks/templates',
|
|
49
|
+
'.supervisor',
|
|
50
|
+
'.agents/plans',
|
|
51
|
+
'.agents/scratch',
|
|
52
|
+
'.agents/thoughts',
|
|
53
|
+
];
|
|
54
|
+
export async function init(options) {
|
|
55
|
+
logger.banner();
|
|
56
|
+
const archaiVersion = await getArchaiVersion();
|
|
57
|
+
const existingInstall = await hasExistingInstall(CLAUDE_DIR);
|
|
58
|
+
const isLegacy = await detectLegacyInstall(CLAUDE_DIR);
|
|
59
|
+
// Handle existing installation
|
|
60
|
+
if (existingInstall && !options.force) {
|
|
61
|
+
// Check if we can do a smart update instead of failing
|
|
62
|
+
if (isLegacy) {
|
|
63
|
+
logger.info('Found existing archai installation (pre-0.2.0).');
|
|
64
|
+
logger.info('Running migration to enable smart updates...');
|
|
65
|
+
console.log('');
|
|
66
|
+
const migration = await migrateFromLegacy(CLAUDE_DIR, archaiVersion);
|
|
67
|
+
if (!migration.success) {
|
|
68
|
+
logger.error(`Migration failed: ${migration.error}`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (migration.warnings.length > 0) {
|
|
72
|
+
for (const warning of migration.warnings) {
|
|
73
|
+
logger.warn(warning);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
logger.success('Migration complete!');
|
|
77
|
+
logger.info('Your files have been analyzed. Run "archai update" to check for updates.');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Already has version.json - suggest using update command
|
|
81
|
+
logger.warn('archai is already initialized in this directory.');
|
|
82
|
+
logger.info('To update archai, run: archai update');
|
|
83
|
+
logger.info('To reinitialize from scratch, use: archai init --force');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// --force mode with existing installation: do smart comparison
|
|
87
|
+
if (existingInstall && options.force) {
|
|
88
|
+
await handleForceInit(options, archaiVersion);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Fresh installation
|
|
92
|
+
await handleFreshInit(options, archaiVersion);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Handle --force init on existing installation.
|
|
96
|
+
* Creates backup, compares files, and updates intelligently.
|
|
97
|
+
*/
|
|
98
|
+
async function handleForceInit(options, archaiVersion) {
|
|
99
|
+
// First, ensure we have version.json (migrate if needed)
|
|
100
|
+
const isLegacy = await detectLegacyInstall(CLAUDE_DIR);
|
|
101
|
+
if (isLegacy) {
|
|
102
|
+
const migration = await migrateFromLegacy(CLAUDE_DIR, archaiVersion);
|
|
103
|
+
if (!migration.success) {
|
|
104
|
+
logger.error(`Migration failed: ${migration.error}`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Create backup before any changes
|
|
109
|
+
logger.info('Creating backup...');
|
|
110
|
+
const backup = await createBackup(CLAUDE_DIR, 'pre-force-init', archaiVersion);
|
|
111
|
+
if (!backup.success) {
|
|
112
|
+
logger.error(`Backup failed: ${backup.error}`);
|
|
113
|
+
logger.info('Aborting to prevent data loss. Fix the issue and try again.');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
logger.success(`Backup created: ${backup.timestamp}`);
|
|
117
|
+
// Prune old backups
|
|
118
|
+
await pruneOldBackups(CLAUDE_DIR, 5);
|
|
119
|
+
// Analyze all files
|
|
120
|
+
console.log('');
|
|
121
|
+
const analysisSpinner = ora('Analyzing files...').start();
|
|
122
|
+
const analyses = await analyzeAllFiles(CLAUDE_DIR);
|
|
123
|
+
analysisSpinner.succeed(`Analyzed ${analyses.length} files`);
|
|
124
|
+
// Categorize files
|
|
125
|
+
const newFiles = analyses.filter(a => a.status === 'new');
|
|
126
|
+
const unchanged = analyses.filter(a => a.status === 'unchanged');
|
|
127
|
+
const modifiedByArchai = analyses.filter(a => a.status === 'modified_by_archai');
|
|
128
|
+
const modifiedByUser = analyses.filter(a => a.status === 'modified_by_user');
|
|
129
|
+
const conflicts = analyses.filter(a => a.status === 'conflict');
|
|
130
|
+
// Show summary
|
|
131
|
+
console.log('');
|
|
132
|
+
logger.section('File Analysis');
|
|
133
|
+
console.log('');
|
|
134
|
+
if (newFiles.length > 0)
|
|
135
|
+
console.log(chalk.green(` New files: ${newFiles.length}`));
|
|
136
|
+
if (unchanged.length > 0)
|
|
137
|
+
console.log(chalk.gray(` Unchanged: ${unchanged.length}`));
|
|
138
|
+
if (modifiedByArchai.length > 0)
|
|
139
|
+
console.log(chalk.cyan(` Updated by archai: ${modifiedByArchai.length}`));
|
|
140
|
+
if (modifiedByUser.length > 0)
|
|
141
|
+
console.log(chalk.yellow(` Modified by you: ${modifiedByUser.length}`));
|
|
142
|
+
if (conflicts.length > 0)
|
|
143
|
+
console.log(chalk.red(` Conflicts: ${conflicts.length}`));
|
|
144
|
+
console.log('');
|
|
145
|
+
// Handle dry run
|
|
146
|
+
if (options.dryRun) {
|
|
147
|
+
await showDryRunSummary(analyses);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Handle files that need attention
|
|
151
|
+
const needsAttention = [...modifiedByUser, ...conflicts.filter(c => !c.canAutoMerge)];
|
|
152
|
+
if (needsAttention.length > 0 && !options.yes) {
|
|
153
|
+
// Interactive mode - ask user about each file
|
|
154
|
+
await handleConflictsInteractively(needsAttention);
|
|
155
|
+
}
|
|
156
|
+
else if (needsAttention.length > 0 && options.yes) {
|
|
157
|
+
// Non-interactive mode - skip user-modified files
|
|
158
|
+
logger.warn(`Skipping ${needsAttention.length} user-modified files (use interactive mode to resolve).`);
|
|
159
|
+
}
|
|
160
|
+
// Apply changes
|
|
161
|
+
await applyFileChanges(analyses, options, archaiVersion);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Handle fresh installation (no existing .claude directory).
|
|
165
|
+
*/
|
|
166
|
+
async function handleFreshInit(options, archaiVersion) {
|
|
167
|
+
// Detect project info
|
|
168
|
+
const spinner = ora('Detecting project information...').start();
|
|
169
|
+
const detected = await detectProject();
|
|
170
|
+
spinner.succeed('Project detected');
|
|
171
|
+
if (detected.languages.length > 0) {
|
|
172
|
+
logger.info(`Found: ${detected.languages.join(', ')}`);
|
|
173
|
+
}
|
|
174
|
+
let answers;
|
|
175
|
+
if (options.skipWizard || options.yes) {
|
|
176
|
+
// Non-interactive mode
|
|
177
|
+
answers = {
|
|
178
|
+
projectName: detected.name || 'my-project',
|
|
179
|
+
projectType: detected.languages.length > 0 ? 'web' : '',
|
|
180
|
+
isMonorepo: detected.isMonorepo,
|
|
181
|
+
permissionPreset: 'permissive',
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// Interactive wizard
|
|
186
|
+
answers = await runWizard(detected);
|
|
187
|
+
}
|
|
188
|
+
// Dry run mode
|
|
189
|
+
if (options.dryRun) {
|
|
190
|
+
showFreshDryRun(answers);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// Initialize rollback context
|
|
194
|
+
const rollback = {
|
|
195
|
+
createdPaths: [],
|
|
196
|
+
modifiedFiles: new Map(),
|
|
197
|
+
};
|
|
198
|
+
try {
|
|
199
|
+
console.log('');
|
|
200
|
+
logger.section('Creating Agent System');
|
|
201
|
+
console.log('');
|
|
202
|
+
// Backup .gitignore if exists
|
|
203
|
+
if (await fs.pathExists('.gitignore')) {
|
|
204
|
+
const content = await fs.readFile('.gitignore', 'utf-8');
|
|
205
|
+
rollback.modifiedFiles.set('.gitignore', content);
|
|
206
|
+
}
|
|
207
|
+
// Create folder structure
|
|
208
|
+
const structureSpinner = ora('Creating folder structure...').start();
|
|
209
|
+
await scaffoldProject();
|
|
210
|
+
rollback.createdPaths.push(...FOLDERS.filter(f => !f.includes('/archived')));
|
|
211
|
+
structureSpinner.succeed('Created folder structure');
|
|
212
|
+
// Copy core agents
|
|
213
|
+
const agentsSpinner = ora('Installing core agents (14 agents)...').start();
|
|
214
|
+
await copyCoreAgents();
|
|
215
|
+
agentsSpinner.succeed('Installed core agents');
|
|
216
|
+
// Create config template — merge detected info with wizard answers
|
|
217
|
+
const configSpinner = ora('Creating configuration template...').start();
|
|
218
|
+
await createConfigTemplate({
|
|
219
|
+
projectName: answers.projectName,
|
|
220
|
+
projectType: answers.projectType,
|
|
221
|
+
isMonorepo: answers.isMonorepo,
|
|
222
|
+
languages: detected.languages.length > 0 ? detected.languages.join(', ') : undefined,
|
|
223
|
+
frameworks: detected.frameworks?.length > 0 ? detected.frameworks.join(', ') : undefined,
|
|
224
|
+
testFramework: detected.testFramework || undefined,
|
|
225
|
+
packageManager: detected.packageManager || undefined,
|
|
226
|
+
platform: detected.platform,
|
|
227
|
+
shell: detected.shell,
|
|
228
|
+
});
|
|
229
|
+
rollback.createdPaths.push('archai.config.md');
|
|
230
|
+
configSpinner.succeed('Created archai.config.md');
|
|
231
|
+
// Create CLAUDE.md (root-level agent guidelines)
|
|
232
|
+
const claudeMdSpinner = ora('Creating CLAUDE.md...').start();
|
|
233
|
+
await copyClaudeMd();
|
|
234
|
+
rollback.createdPaths.push('CLAUDE.md');
|
|
235
|
+
claudeMdSpinner.succeed('Created CLAUDE.md');
|
|
236
|
+
// Create project description template
|
|
237
|
+
const descSpinner = ora('Creating project description template...').start();
|
|
238
|
+
await createProjectDescription(answers);
|
|
239
|
+
descSpinner.succeed('Created project-description.md');
|
|
240
|
+
// Create permission settings
|
|
241
|
+
const packageManager = detected.packageManager || 'npm';
|
|
242
|
+
if (answers.permissionPreset !== 'skip') {
|
|
243
|
+
const permSpinner = ora('Creating permission settings...').start();
|
|
244
|
+
await createClaudeSettings({
|
|
245
|
+
preset: answers.permissionPreset,
|
|
246
|
+
packageManager,
|
|
247
|
+
customAllowCommands: answers.customAllowCommands,
|
|
248
|
+
customDenyCommands: answers.customDenyCommands,
|
|
249
|
+
});
|
|
250
|
+
rollback.createdPaths.push('.claude/settings.local.json');
|
|
251
|
+
const presetLabel = answers.permissionPreset.charAt(0).toUpperCase() + answers.permissionPreset.slice(1);
|
|
252
|
+
permSpinner.succeed(`Created .claude/settings.local.json (${presetLabel} mode)`);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
logger.info('Skipped permission settings (configure manually later)');
|
|
256
|
+
}
|
|
257
|
+
// Create version.json
|
|
258
|
+
const versionSpinner = ora('Creating version tracking...').start();
|
|
259
|
+
await createVersionTracking(archaiVersion);
|
|
260
|
+
versionSpinner.succeed('Created version.json');
|
|
261
|
+
// Final output
|
|
262
|
+
showSuccessMessage();
|
|
263
|
+
// Offer to run environment setup
|
|
264
|
+
await offerSetup(options);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
logger.error('Initialization failed. Rolling back changes...');
|
|
268
|
+
await performRollback(rollback);
|
|
269
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
270
|
+
logger.debug('Init failed', { error: errorMessage });
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Offer to run environment setup after init completes.
|
|
276
|
+
*/
|
|
277
|
+
async function offerSetup(options) {
|
|
278
|
+
if (options.yes || options.skipWizard) {
|
|
279
|
+
// Non-interactive mode - auto-run setup with --yes
|
|
280
|
+
await setup({ yes: true });
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
// Interactive mode - ask user
|
|
284
|
+
const { runSetup } = await inquirer.prompt([{
|
|
285
|
+
type: 'list',
|
|
286
|
+
name: 'runSetup',
|
|
287
|
+
message: 'Would you like to auto-configure environment integrations? (Git, MCP servers)',
|
|
288
|
+
choices: [
|
|
289
|
+
{ name: 'Yes - run setup now', value: true },
|
|
290
|
+
{ name: 'Skip - run archai setup later', value: false },
|
|
291
|
+
],
|
|
292
|
+
default: true,
|
|
293
|
+
}]);
|
|
294
|
+
if (runSetup) {
|
|
295
|
+
await setup({});
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
console.log('');
|
|
299
|
+
logger.info('You can run environment setup later with: archai setup');
|
|
300
|
+
console.log('');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Run the interactive wizard.
|
|
305
|
+
*/
|
|
306
|
+
async function runWizard(detected) {
|
|
307
|
+
console.log('');
|
|
308
|
+
logger.section('Project Setup');
|
|
309
|
+
console.log(chalk.gray(' (Press Enter to skip questions you\'re unsure about)'));
|
|
310
|
+
console.log('');
|
|
311
|
+
const mainAnswers = await inquirer.prompt([
|
|
312
|
+
{
|
|
313
|
+
type: 'input',
|
|
314
|
+
name: 'projectName',
|
|
315
|
+
message: '1. Project name:',
|
|
316
|
+
default: detected.name || 'my-project',
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
type: 'list',
|
|
320
|
+
name: 'projectType',
|
|
321
|
+
message: '2. What type of project is this?',
|
|
322
|
+
choices: [...PROJECT_TYPES, { name: 'Skip (decide later)', value: '' }],
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
type: 'confirm',
|
|
326
|
+
name: 'isMonorepo',
|
|
327
|
+
message: '3. Do you use a monorepo structure?',
|
|
328
|
+
default: detected.isMonorepo,
|
|
329
|
+
},
|
|
330
|
+
]);
|
|
331
|
+
// Permission preset section
|
|
332
|
+
console.log('');
|
|
333
|
+
logger.section('Permissions');
|
|
334
|
+
console.log(chalk.gray(' Configure what commands Claude agents can execute.'));
|
|
335
|
+
console.log('');
|
|
336
|
+
const { permissionPreset } = await inquirer.prompt([{
|
|
337
|
+
type: 'list',
|
|
338
|
+
name: 'permissionPreset',
|
|
339
|
+
message: '4. Permission level:',
|
|
340
|
+
choices: [
|
|
341
|
+
{ name: `${chalk.green('Permissive')} - Everything except irreversible actions`, value: 'permissive' },
|
|
342
|
+
{ name: `${chalk.yellow('Strict')} - Only safe operations (no network, no push)`, value: 'strict' },
|
|
343
|
+
{ name: `${chalk.cyan('Custom')} - Define your own commands`, value: 'custom' },
|
|
344
|
+
{ name: `${chalk.gray('Skip')} - Configure manually later`, value: 'skip' },
|
|
345
|
+
],
|
|
346
|
+
default: 'permissive',
|
|
347
|
+
}]);
|
|
348
|
+
let customAllowCommands;
|
|
349
|
+
let customDenyCommands;
|
|
350
|
+
if (permissionPreset === 'custom') {
|
|
351
|
+
console.log('');
|
|
352
|
+
console.log(chalk.gray(' Enter commands separated by commas. Use * as wildcard.'));
|
|
353
|
+
console.log(chalk.gray(' Example: npm *, git status*, tsc'));
|
|
354
|
+
console.log('');
|
|
355
|
+
const customAnswers = await inquirer.prompt([
|
|
356
|
+
{
|
|
357
|
+
type: 'input',
|
|
358
|
+
name: 'allowCommands',
|
|
359
|
+
message: 'Allowed commands:',
|
|
360
|
+
default: `${detected.packageManager || 'npm'} *, git status*, git diff*, git log*`,
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
type: 'input',
|
|
364
|
+
name: 'denyCommands',
|
|
365
|
+
message: 'Additional denied commands (dangerous ones are always blocked):',
|
|
366
|
+
default: '',
|
|
367
|
+
},
|
|
368
|
+
]);
|
|
369
|
+
customAllowCommands = customAnswers.allowCommands
|
|
370
|
+
.split(',')
|
|
371
|
+
.map((c) => c.trim())
|
|
372
|
+
.filter((c) => c);
|
|
373
|
+
customDenyCommands = customAnswers.denyCommands
|
|
374
|
+
.split(',')
|
|
375
|
+
.map((c) => c.trim())
|
|
376
|
+
.filter((c) => c);
|
|
377
|
+
}
|
|
378
|
+
return {
|
|
379
|
+
...mainAnswers,
|
|
380
|
+
permissionPreset,
|
|
381
|
+
customAllowCommands,
|
|
382
|
+
customDenyCommands,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Show dry run summary.
|
|
387
|
+
*/
|
|
388
|
+
async function showDryRunSummary(analyses) {
|
|
389
|
+
console.log('');
|
|
390
|
+
logger.section('Would Process');
|
|
391
|
+
console.log('');
|
|
392
|
+
const newFiles = analyses.filter(a => a.status === 'new');
|
|
393
|
+
const updates = analyses.filter(a => a.status === 'modified_by_archai');
|
|
394
|
+
const userModified = analyses.filter(a => a.status === 'modified_by_user');
|
|
395
|
+
const conflicts = analyses.filter(a => a.status === 'conflict');
|
|
396
|
+
if (newFiles.length > 0) {
|
|
397
|
+
console.log(chalk.green(' New files:'));
|
|
398
|
+
newFiles.forEach(f => console.log(chalk.gray(` + ${f.path}`)));
|
|
399
|
+
console.log('');
|
|
400
|
+
}
|
|
401
|
+
if (updates.length > 0) {
|
|
402
|
+
console.log(chalk.cyan(' Would update:'));
|
|
403
|
+
updates.forEach(f => console.log(chalk.gray(` ~ ${f.path}`)));
|
|
404
|
+
console.log('');
|
|
405
|
+
}
|
|
406
|
+
if (userModified.length > 0) {
|
|
407
|
+
console.log(chalk.yellow(' User-modified (would skip):'));
|
|
408
|
+
userModified.forEach(f => console.log(chalk.gray(` ! ${f.path}`)));
|
|
409
|
+
console.log('');
|
|
410
|
+
}
|
|
411
|
+
if (conflicts.length > 0) {
|
|
412
|
+
console.log(chalk.red(' Conflicts (would need resolution):'));
|
|
413
|
+
conflicts.forEach(f => {
|
|
414
|
+
const auto = f.canAutoMerge ? chalk.gray(' (can auto-merge)') : '';
|
|
415
|
+
console.log(chalk.gray(` ⚠ ${f.path}${auto}`));
|
|
416
|
+
});
|
|
417
|
+
console.log('');
|
|
418
|
+
}
|
|
419
|
+
logger.info('Dry run complete. No files were modified.');
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Show dry run for fresh install.
|
|
423
|
+
*/
|
|
424
|
+
function showFreshDryRun(answers) {
|
|
425
|
+
console.log('');
|
|
426
|
+
logger.section('Would Create');
|
|
427
|
+
console.log('');
|
|
428
|
+
console.log(chalk.cyan(' Directories:'));
|
|
429
|
+
FOLDERS.forEach(f => console.log(chalk.gray(` ${f}`)));
|
|
430
|
+
console.log('');
|
|
431
|
+
console.log(chalk.cyan(' Files:'));
|
|
432
|
+
console.log(chalk.gray(' .claude/agents/*.md (14 core agents)'));
|
|
433
|
+
console.log(chalk.gray(' .claude/version.json'));
|
|
434
|
+
console.log(chalk.gray(' CLAUDE.md'));
|
|
435
|
+
console.log(chalk.gray(' archai.config.md'));
|
|
436
|
+
console.log(chalk.gray(' .knowledge/context/project-description.md'));
|
|
437
|
+
console.log(chalk.gray(' PROMPTS.md'));
|
|
438
|
+
console.log(chalk.gray(' ARCHAI_README.md'));
|
|
439
|
+
if (answers.permissionPreset !== 'skip') {
|
|
440
|
+
console.log(chalk.gray(' .claude/settings.local.json'));
|
|
441
|
+
}
|
|
442
|
+
console.log('');
|
|
443
|
+
console.log(chalk.cyan(' Modifications:'));
|
|
444
|
+
console.log(chalk.gray(' .gitignore (append archai entries)'));
|
|
445
|
+
console.log('');
|
|
446
|
+
logger.info('Dry run complete. No files were created.');
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Handle conflicts interactively.
|
|
450
|
+
*/
|
|
451
|
+
async function handleConflictsInteractively(files) {
|
|
452
|
+
console.log('');
|
|
453
|
+
logger.section('Files Requiring Attention');
|
|
454
|
+
console.log('');
|
|
455
|
+
for (const file of files) {
|
|
456
|
+
console.log(chalk.yellow(` ${file.path}`));
|
|
457
|
+
console.log(chalk.gray(` Status: ${file.status}`));
|
|
458
|
+
const { action } = await inquirer.prompt([{
|
|
459
|
+
type: 'list',
|
|
460
|
+
name: 'action',
|
|
461
|
+
message: `What would you like to do with ${file.path}?`,
|
|
462
|
+
choices: [
|
|
463
|
+
{ name: 'Keep my version', value: 'keep' },
|
|
464
|
+
{ name: 'Use new template', value: 'overwrite' },
|
|
465
|
+
{ name: 'Try to merge', value: 'merge' },
|
|
466
|
+
{ name: 'Skip', value: 'skip' },
|
|
467
|
+
],
|
|
468
|
+
}]);
|
|
469
|
+
// Store the decision for later processing
|
|
470
|
+
file.userAction = action;
|
|
471
|
+
console.log('');
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Apply file changes based on analysis.
|
|
476
|
+
*/
|
|
477
|
+
async function applyFileChanges(analyses, options, archaiVersion) {
|
|
478
|
+
const spinner = ora('Applying changes...').start();
|
|
479
|
+
let applied = 0;
|
|
480
|
+
let skipped = 0;
|
|
481
|
+
const templates = await getTemplateFiles();
|
|
482
|
+
const templateMap = new Map(templates.map(t => [t.relativePath, t]));
|
|
483
|
+
for (const analysis of analyses) {
|
|
484
|
+
const template = templateMap.get(analysis.path);
|
|
485
|
+
if (!template)
|
|
486
|
+
continue;
|
|
487
|
+
const localPath = analysis.path;
|
|
488
|
+
try {
|
|
489
|
+
// Handle based on status
|
|
490
|
+
switch (analysis.status) {
|
|
491
|
+
case 'new':
|
|
492
|
+
// Copy new file from template
|
|
493
|
+
await fs.ensureDir(path.dirname(localPath));
|
|
494
|
+
await fs.copy(template.templatePath, localPath);
|
|
495
|
+
applied++;
|
|
496
|
+
break;
|
|
497
|
+
case 'modified_by_archai':
|
|
498
|
+
// Update from template (user hasn't modified)
|
|
499
|
+
await fs.copy(template.templatePath, localPath, { overwrite: true });
|
|
500
|
+
applied++;
|
|
501
|
+
break;
|
|
502
|
+
case 'conflict':
|
|
503
|
+
if (analysis.canAutoMerge) {
|
|
504
|
+
// Try auto-merge
|
|
505
|
+
const result = await mergeFile(localPath, template.templatePath);
|
|
506
|
+
if (result.success) {
|
|
507
|
+
await applyMerge(localPath, result);
|
|
508
|
+
applied++;
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
skipped++;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
const conflictAction = analysis.userAction;
|
|
516
|
+
if (conflictAction === 'overwrite') {
|
|
517
|
+
await fs.copy(template.templatePath, localPath, { overwrite: true });
|
|
518
|
+
applied++;
|
|
519
|
+
}
|
|
520
|
+
else if (conflictAction === 'merge') {
|
|
521
|
+
const result = await mergeFile(localPath, template.templatePath);
|
|
522
|
+
if (result.success) {
|
|
523
|
+
await applyMerge(localPath, result);
|
|
524
|
+
applied++;
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
skipped++;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
skipped++;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
535
|
+
case 'modified_by_user':
|
|
536
|
+
// Skip unless user specified action
|
|
537
|
+
const action = analysis.userAction;
|
|
538
|
+
if (action === 'overwrite') {
|
|
539
|
+
await fs.copy(template.templatePath, localPath, { overwrite: true });
|
|
540
|
+
applied++;
|
|
541
|
+
}
|
|
542
|
+
else if (action === 'merge') {
|
|
543
|
+
const result = await mergeFile(localPath, template.templatePath);
|
|
544
|
+
if (result.success) {
|
|
545
|
+
await applyMerge(localPath, result);
|
|
546
|
+
applied++;
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
skipped++;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
skipped++;
|
|
554
|
+
}
|
|
555
|
+
break;
|
|
556
|
+
case 'unchanged':
|
|
557
|
+
case 'generated':
|
|
558
|
+
// No action needed
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
logger.debug(`Failed to process ${analysis.path}`, error);
|
|
564
|
+
skipped++;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
spinner.succeed(`Applied ${applied} changes, skipped ${skipped}`);
|
|
568
|
+
// Update version.json
|
|
569
|
+
await updateVersionTracking(archaiVersion, analyses);
|
|
570
|
+
console.log('');
|
|
571
|
+
logger.success('Initialization complete!');
|
|
572
|
+
console.log('');
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Create version tracking for fresh install.
|
|
576
|
+
*/
|
|
577
|
+
async function createVersionTracking(archaiVersion) {
|
|
578
|
+
const templates = await getTemplateFiles();
|
|
579
|
+
const fileHashes = [];
|
|
580
|
+
for (const template of templates) {
|
|
581
|
+
const localPath = template.relativePath;
|
|
582
|
+
if (await fs.pathExists(localPath)) {
|
|
583
|
+
const hash = await hashFile(localPath);
|
|
584
|
+
fileHashes.push({ path: template.relativePath, hash, isGenerated: false });
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
let versionFile = createVersionFile(archaiVersion);
|
|
588
|
+
versionFile = bulkUpdateFileHashes(versionFile, fileHashes);
|
|
589
|
+
versionFile.expectedFiles = templates.map(t => t.relativePath);
|
|
590
|
+
await saveVersionFile(CLAUDE_DIR, versionFile);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Update version tracking after init/update.
|
|
594
|
+
*/
|
|
595
|
+
async function updateVersionTracking(archaiVersion, analyses) {
|
|
596
|
+
let versionFile = await loadVersionFile(CLAUDE_DIR);
|
|
597
|
+
if (!versionFile) {
|
|
598
|
+
versionFile = createVersionFile(archaiVersion);
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
versionFile.archai = archaiVersion;
|
|
602
|
+
versionFile.lastUpdated = new Date().toISOString();
|
|
603
|
+
}
|
|
604
|
+
// Update hashes for all processed files
|
|
605
|
+
const updates = [];
|
|
606
|
+
for (const analysis of analyses) {
|
|
607
|
+
const userAction = analysis.userAction;
|
|
608
|
+
const wasApplied = analysis.status === 'new' ||
|
|
609
|
+
analysis.status === 'modified_by_archai' ||
|
|
610
|
+
(analysis.status === 'conflict' && analysis.canAutoMerge) ||
|
|
611
|
+
(analysis.status === 'conflict' && (userAction === 'overwrite' || userAction === 'merge')) ||
|
|
612
|
+
(analysis.status === 'modified_by_user' && (userAction === 'overwrite' || userAction === 'merge'));
|
|
613
|
+
if (wasApplied) {
|
|
614
|
+
const hash = await hashFile(analysis.path);
|
|
615
|
+
updates.push({
|
|
616
|
+
path: analysis.path,
|
|
617
|
+
hash,
|
|
618
|
+
isGenerated: analysis.isGenerated,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
versionFile = bulkUpdateFileHashes(versionFile, updates);
|
|
623
|
+
await saveVersionFile(CLAUDE_DIR, versionFile);
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Show success message after initialization.
|
|
627
|
+
*/
|
|
628
|
+
function showSuccessMessage() {
|
|
629
|
+
console.log('');
|
|
630
|
+
logger.divider();
|
|
631
|
+
console.log('');
|
|
632
|
+
logger.success('archai initialized successfully!');
|
|
633
|
+
console.log('');
|
|
634
|
+
logger.section('Next Steps');
|
|
635
|
+
console.log('');
|
|
636
|
+
console.log(chalk.white('1. Fill in the project description:'));
|
|
637
|
+
console.log(chalk.cyan(' → .knowledge/context/project-description.md'));
|
|
638
|
+
console.log(chalk.gray(' (or run: archai setup-project)'));
|
|
639
|
+
console.log('');
|
|
640
|
+
console.log(chalk.white('2. Complete the configuration:'));
|
|
641
|
+
console.log(chalk.cyan(' → archai.config.md'));
|
|
642
|
+
console.log(chalk.gray(' (or run: archai setup-config)'));
|
|
643
|
+
console.log('');
|
|
644
|
+
console.log(chalk.white('3. Configure environment:'));
|
|
645
|
+
console.log(chalk.cyan(' → archai setup'));
|
|
646
|
+
console.log(chalk.gray(' (auto-configures Git settings, MCP servers)'));
|
|
647
|
+
console.log('');
|
|
648
|
+
console.log(chalk.white('4. Generate specialist agents:'));
|
|
649
|
+
console.log(chalk.cyan(' → archai generate'));
|
|
650
|
+
console.log('');
|
|
651
|
+
console.log(chalk.gray(' (This will use Claude Code to create project-specific specialists)'));
|
|
652
|
+
console.log('');
|
|
653
|
+
console.log(chalk.white('5. Read the usage guide:'));
|
|
654
|
+
console.log(chalk.cyan(' → ARCHAI_README.md'));
|
|
655
|
+
console.log('');
|
|
656
|
+
console.log(chalk.white('6. See prompt examples:'));
|
|
657
|
+
console.log(chalk.cyan(' → PROMPTS.md'));
|
|
658
|
+
console.log('');
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Copy CLAUDE.md template to project root.
|
|
662
|
+
*/
|
|
663
|
+
async function copyClaudeMd() {
|
|
664
|
+
const templatePath = path.join(getTemplatesDir(), 'CLAUDE.md');
|
|
665
|
+
if (await fs.pathExists(templatePath)) {
|
|
666
|
+
await fs.copy(templatePath, 'CLAUDE.md');
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
async function performRollback(ctx) {
|
|
670
|
+
const rollbackSpinner = ora('Rolling back...').start();
|
|
671
|
+
// Restore modified files
|
|
672
|
+
for (const [filePath, content] of ctx.modifiedFiles) {
|
|
673
|
+
try {
|
|
674
|
+
await fs.writeFile(filePath, content);
|
|
675
|
+
logger.debug(`Restored: ${filePath}`);
|
|
676
|
+
}
|
|
677
|
+
catch (error) {
|
|
678
|
+
logger.debug(`Failed to restore ${filePath}`, error);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
// Remove created paths (reverse order for proper cleanup)
|
|
682
|
+
for (const filePath of ctx.createdPaths.reverse()) {
|
|
683
|
+
try {
|
|
684
|
+
if (await fs.pathExists(filePath)) {
|
|
685
|
+
await fs.remove(filePath);
|
|
686
|
+
logger.debug(`Removed: ${filePath}`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
catch (error) {
|
|
690
|
+
logger.debug(`Failed to remove ${filePath}`, error);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
// Try to clean up parent directories if empty
|
|
694
|
+
const parentDirs = ['.claude', '.knowledge', '.tasks', '.agents', '.supervisor'];
|
|
695
|
+
for (const dir of parentDirs) {
|
|
696
|
+
try {
|
|
697
|
+
if (await fs.pathExists(dir)) {
|
|
698
|
+
const contents = await fs.readdir(dir);
|
|
699
|
+
if (contents.length === 0 || contents.every(f => f === '.gitkeep')) {
|
|
700
|
+
await fs.remove(dir);
|
|
701
|
+
logger.debug(`Removed empty dir: ${dir}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
catch (error) {
|
|
706
|
+
logger.debug(`Failed to clean up ${dir}`, error);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
rollbackSpinner.succeed('Rolled back changes');
|
|
710
|
+
}
|
|
711
|
+
//# sourceMappingURL=init.js.map
|