proagents 1.6.12 → 1.6.15

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.
Files changed (40) hide show
  1. package/.proagents/.cursorrules +16 -2
  2. package/.proagents/.learning/global/common-patterns.template.json +60 -0
  3. package/.proagents/.learning/global/user-preferences.template.json +78 -0
  4. package/.proagents/.windsurfrules +16 -2
  5. package/.proagents/AGENTS.md +55 -0
  6. package/.proagents/AI_INSTRUCTIONS.md +1252 -53
  7. package/.proagents/ANTIGRAVITY.md +16 -2
  8. package/.proagents/BOLT.md +16 -2
  9. package/.proagents/CHATGPT.md +16 -2
  10. package/.proagents/CLAUDE.md +16 -2
  11. package/.proagents/GEMINI.md +16 -2
  12. package/.proagents/GROQ.md +16 -2
  13. package/.proagents/KIRO.md +16 -2
  14. package/.proagents/LOVABLE.md +16 -2
  15. package/.proagents/PROAGENTS.md +52 -26
  16. package/.proagents/REPLIT.md +16 -2
  17. package/.proagents/active-features/_index.template.json +75 -0
  18. package/.proagents/changelog/_recent.template.md +51 -0
  19. package/.proagents/docs/command-details.md +985 -82
  20. package/.proagents/worklog/_context.md +31 -1
  21. package/.proagents/worklog/_context.template.md +82 -0
  22. package/.proagents/worklog/ai-stats.json +19 -0
  23. package/.proagents/worklog/ai-stats.template.json +54 -0
  24. package/README.md +85 -1
  25. package/bin/proagents.js +132 -1
  26. package/lib/commands/ai.js +103 -11
  27. package/lib/commands/changelog.js +389 -0
  28. package/lib/commands/completion.js +413 -0
  29. package/lib/commands/config.js +248 -0
  30. package/lib/commands/doctor.js +222 -25
  31. package/lib/commands/help.js +22 -2
  32. package/lib/commands/init.js +171 -2
  33. package/lib/commands/open.js +188 -0
  34. package/lib/commands/release.js +1007 -0
  35. package/lib/commands/restore.js +150 -0
  36. package/lib/commands/stats.js +320 -0
  37. package/lib/commands/uninstall.js +98 -4
  38. package/lib/commands/upgrade.js +102 -10
  39. package/lib/commands/version.js +140 -0
  40. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync } from 'fs';
2
2
  import { join } from 'path';
3
+ import { execSync } from 'child_process';
3
4
  import chalk from 'chalk';
4
5
  import yaml from 'js-yaml';
5
6
 
@@ -98,7 +99,9 @@ function checkPlatformSync(targetDir) {
98
99
  const content = readFileSync(configPath, 'utf-8');
99
100
  const config = yaml.load(content);
100
101
  configPlatforms = config?.platforms || config?.ai_platforms || [];
101
- } catch { }
102
+ } catch {
103
+ // Config file unreadable - will be caught by other checks
104
+ }
102
105
  }
103
106
 
104
107
  // Check each platform file
@@ -134,7 +137,7 @@ function checkPlatformSync(targetDir) {
134
137
  * Check for lock file
135
138
  */
136
139
  function checkLockFile(targetDir) {
137
- const lockPath = join(targetDir, 'proagents', '.lock');
140
+ const lockPath = join(targetDir, '.proagents', '.lock');
138
141
  const checks = [];
139
142
 
140
143
  if (existsSync(lockPath)) {
@@ -163,18 +166,187 @@ function checkLockFile(targetDir) {
163
166
  }
164
167
 
165
168
  /**
166
- * Check version
169
+ * Extended checks for --full mode
167
170
  */
168
- async function checkVersion() {
171
+ function checkExtended(targetDir) {
169
172
  const checks = [];
170
173
 
174
+ // Check changelog size
175
+ const recentPath = join(targetDir, '.proagents', 'changelog', '_recent.md');
176
+ if (existsSync(recentPath)) {
177
+ try {
178
+ const content = readFileSync(recentPath, 'utf-8');
179
+ const entries = (content.match(/^### /gm) || []).length;
180
+ if (entries > 50) {
181
+ checks.push({ name: 'Changelog size', status: 'warning', message: `${entries} entries (consider archiving)` });
182
+ } else {
183
+ checks.push({ name: 'Changelog size', status: 'ok', message: `${entries} entries` });
184
+ }
185
+ } catch {
186
+ checks.push({ name: 'Changelog size', status: 'skip', message: 'Could not read' });
187
+ }
188
+ } else {
189
+ checks.push({ name: 'Changelog', status: 'info', message: 'No recent changelog' });
190
+ }
191
+
192
+ // Check activity log freshness
193
+ const activityPath = join(targetDir, '.proagents', 'activity.log');
194
+ if (existsSync(activityPath)) {
195
+ try {
196
+ const content = readFileSync(activityPath, 'utf-8');
197
+ const lines = content.trim().split('\n').filter(l => l && !l.startsWith('#') && !l.includes('Activity Log'));
198
+ if (lines.length > 0) {
199
+ const lastLine = lines[lines.length - 1];
200
+ const dateMatch = lastLine.match(/^\[?(\d{4}-\d{2}-\d{2})/);
201
+ if (dateMatch) {
202
+ const lastDate = new Date(dateMatch[1]);
203
+ const daysAgo = Math.floor((Date.now() - lastDate.getTime()) / (1000 * 60 * 60 * 24));
204
+ if (daysAgo > 7) {
205
+ checks.push({ name: 'Activity log', status: 'warning', message: `Last entry ${daysAgo} days ago` });
206
+ } else if (daysAgo > 0) {
207
+ checks.push({ name: 'Activity log', status: 'ok', message: `Last entry ${daysAgo} day(s) ago` });
208
+ } else {
209
+ checks.push({ name: 'Activity log', status: 'ok', message: 'Activity today' });
210
+ }
211
+ } else {
212
+ checks.push({ name: 'Activity log', status: 'ok', message: `${lines.length} entries` });
213
+ }
214
+ } else {
215
+ checks.push({ name: 'Activity log', status: 'info', message: 'No entries yet' });
216
+ }
217
+ } catch {
218
+ checks.push({ name: 'Activity log', status: 'skip', message: 'Could not read' });
219
+ }
220
+ } else {
221
+ checks.push({ name: 'Activity log', status: 'info', message: 'No activity log' });
222
+ }
223
+
224
+ // Check for stale feature branches
171
225
  try {
172
- // Get current version from package.json
226
+ const branches = execSync('git branch --list "feature/*" 2>/dev/null', { encoding: 'utf-8' }).trim();
227
+ if (branches) {
228
+ const branchCount = branches.split('\n').filter(b => b.trim()).length;
229
+ if (branchCount > 5) {
230
+ checks.push({ name: 'Feature branches', status: 'warning', message: `${branchCount} branches (consider cleanup)` });
231
+ } else if (branchCount > 0) {
232
+ checks.push({ name: 'Feature branches', status: 'ok', message: `${branchCount} active` });
233
+ }
234
+ } else {
235
+ checks.push({ name: 'Feature branches', status: 'ok', message: 'None' });
236
+ }
237
+ } catch {
238
+ checks.push({ name: 'Feature branches', status: 'skip', message: 'Not a git repo or no feature branches' });
239
+ }
240
+
241
+ // Check active features
242
+ const featuresPath = join(targetDir, '.proagents', 'active-features', '_index.json');
243
+ if (existsSync(featuresPath)) {
244
+ try {
245
+ const content = readFileSync(featuresPath, 'utf-8');
246
+ const index = JSON.parse(content);
247
+ const activeCount = index.active_features?.length || 0;
248
+ const completedCount = index.completed_features?.length || 0;
249
+
250
+ if (activeCount > 0) {
251
+ checks.push({ name: 'Active features', status: 'ok', message: `${activeCount} active, ${completedCount} completed` });
252
+ } else {
253
+ checks.push({ name: 'Active features', status: 'info', message: `None active, ${completedCount} completed` });
254
+ }
255
+ } catch {
256
+ checks.push({ name: 'Active features', status: 'skip', message: 'Could not read index' });
257
+ }
258
+ } else {
259
+ checks.push({ name: 'Active features', status: 'info', message: 'No features tracked' });
260
+ }
261
+
262
+ // Check worklog context
263
+ const contextPath = join(targetDir, '.proagents', 'worklog', '_context.md');
264
+ if (existsSync(contextPath)) {
265
+ checks.push({ name: 'Worklog context', status: 'ok', message: 'Present' });
266
+ } else {
267
+ checks.push({ name: 'Worklog context', status: 'warning', message: 'Missing (cross-AI sync may be affected)' });
268
+ }
269
+
270
+ // Check for required folders
271
+ const requiredFolders = [
272
+ { path: '.proagents/prompts', name: 'Prompts folder' },
273
+ { path: '.proagents/templates', name: 'Templates folder' },
274
+ { path: '.proagents/changelog', name: 'Changelog folder' },
275
+ { path: '.proagents/worklog', name: 'Worklog folder' }
276
+ ];
277
+
278
+ for (const folder of requiredFolders) {
279
+ if (existsSync(join(targetDir, folder.path))) {
280
+ checks.push({ name: folder.name, status: 'ok', message: 'Present' });
281
+ } else {
282
+ checks.push({ name: folder.name, status: 'warning', message: 'Missing' });
283
+ }
284
+ }
285
+
286
+ return checks;
287
+ }
288
+
289
+ /**
290
+ * Compare semantic versions
291
+ * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
292
+ */
293
+ function compareVersions(v1, v2) {
294
+ const parts1 = v1.split('.').map(Number);
295
+ const parts2 = v2.split('.').map(Number);
296
+
297
+ for (let i = 0; i < 3; i++) {
298
+ const p1 = parts1[i] || 0;
299
+ const p2 = parts2[i] || 0;
300
+ if (p1 < p2) return -1;
301
+ if (p1 > p2) return 1;
302
+ }
303
+ return 0;
304
+ }
305
+
306
+ /**
307
+ * Check version (CLI, project, and npm)
308
+ */
309
+ async function checkVersion(targetDir) {
310
+ const checks = [];
311
+ const recommendations = [];
312
+
313
+ try {
314
+ // Get CLI version from package.json
173
315
  const packagePath = new URL('../../package.json', import.meta.url);
174
316
  const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
175
- const currentVersion = packageJson.version;
176
-
177
- checks.push({ name: 'Installed version', status: 'info', message: `v${currentVersion}` });
317
+ const cliVersion = packageJson.version;
318
+
319
+ checks.push({ name: 'CLI version', status: 'info', message: `v${cliVersion}` });
320
+
321
+ // Get project version from .proagents/.version
322
+ const projectVersionPath = join(targetDir, '.proagents', '.version');
323
+ let projectVersion = null;
324
+
325
+ if (existsSync(projectVersionPath)) {
326
+ try {
327
+ projectVersion = readFileSync(projectVersionPath, 'utf-8').trim();
328
+
329
+ if (projectVersion === cliVersion) {
330
+ checks.push({ name: 'Project version', status: 'ok', message: `v${projectVersion} (synced with CLI)` });
331
+ } else if (compareVersions(projectVersion, cliVersion) < 0) {
332
+ checks.push({ name: 'Project version', status: 'warning', message: `v${projectVersion} (outdated)` });
333
+ recommendations.push({
334
+ issue: 'Project framework is outdated',
335
+ action: 'Run `npx proagents init` to update framework files'
336
+ });
337
+ } else {
338
+ checks.push({ name: 'Project version', status: 'info', message: `v${projectVersion}` });
339
+ }
340
+ } catch {
341
+ checks.push({ name: 'Project version', status: 'warning', message: 'Could not read version file' });
342
+ }
343
+ } else {
344
+ checks.push({ name: 'Project version', status: 'warning', message: 'No version marker (older installation)' });
345
+ recommendations.push({
346
+ issue: 'No version tracking',
347
+ action: 'Run `npx proagents init` to update and add version tracking'
348
+ });
349
+ }
178
350
 
179
351
  // Try to fetch latest version from npm (with timeout)
180
352
  try {
@@ -190,20 +362,24 @@ async function checkVersion() {
190
362
  const data = await response.json();
191
363
  const latestVersion = data.version;
192
364
 
193
- if (currentVersion === latestVersion) {
194
- checks.push({ name: 'Latest version', status: 'ok', message: 'Up to date' });
365
+ if (compareVersions(cliVersion, latestVersion) >= 0) {
366
+ checks.push({ name: 'npm registry', status: 'ok', message: `v${latestVersion} (up to date)` });
195
367
  } else {
196
- checks.push({ name: 'Latest version', status: 'warning', message: `v${latestVersion} available. Run: npm update -g proagents` });
368
+ checks.push({ name: 'npm registry', status: 'warning', message: `v${latestVersion} available` });
369
+ recommendations.push({
370
+ issue: 'CLI update available',
371
+ action: 'Run `npm update -g proagents` to update CLI'
372
+ });
197
373
  }
198
374
  }
199
375
  } catch {
200
- checks.push({ name: 'Version check', status: 'skip', message: 'Could not check npm registry' });
376
+ checks.push({ name: 'npm registry', status: 'skip', message: 'Could not check (offline?)' });
201
377
  }
202
- } catch {
203
- checks.push({ name: 'Version', status: 'error', message: 'Could not read version' });
378
+ } catch (error) {
379
+ checks.push({ name: 'Version', status: 'error', message: `Could not read version: ${error.message}` });
204
380
  }
205
381
 
206
- return checks;
382
+ return { checks, recommendations };
207
383
  }
208
384
 
209
385
  /**
@@ -248,16 +424,14 @@ function printChecks(title, checks) {
248
424
  /**
249
425
  * Doctor command - check health of ProAgents installation
250
426
  */
251
- export async function doctorCommand() {
427
+ export async function doctorCommand(options = {}) {
252
428
  const targetDir = process.cwd();
429
+ const isFullMode = options.full || false;
253
430
 
254
- console.log(chalk.bold('\nProAgents Doctor'));
255
- console.log(chalk.gray('================'));
431
+ console.log(chalk.bold('\nProAgents Doctor' + (isFullMode ? ' (Full)' : '')));
432
+ console.log(chalk.gray(''.repeat(40)));
256
433
  console.log(chalk.gray(`Checking: ${targetDir}\n`));
257
434
 
258
- let hasErrors = false;
259
- let hasWarnings = false;
260
-
261
435
  // Run all checks
262
436
  const installChecks = checkInstallation(targetDir);
263
437
  printChecks('Installation', installChecks);
@@ -271,14 +445,32 @@ export async function doctorCommand() {
271
445
  const lockChecks = checkLockFile(targetDir);
272
446
  printChecks('Lock Status', lockChecks);
273
447
 
274
- const versionChecks = await checkVersion();
275
- printChecks('Version', versionChecks);
448
+ const versionResult = await checkVersion(targetDir);
449
+ printChecks('Version', versionResult.checks);
450
+
451
+ // Extended checks for --full mode
452
+ let extendedChecks = [];
453
+ if (isFullMode) {
454
+ extendedChecks = checkExtended(targetDir);
455
+ printChecks('Extended Health Checks', extendedChecks);
456
+ }
276
457
 
277
458
  // Count issues
278
- const allChecks = [...installChecks, ...configChecks, ...platformChecks, ...lockChecks, ...versionChecks];
459
+ const allChecks = [...installChecks, ...configChecks, ...platformChecks, ...lockChecks, ...versionResult.checks, ...extendedChecks];
279
460
  const errors = allChecks.filter(c => c.status === 'error').length;
280
461
  const warnings = allChecks.filter(c => c.status === 'warning').length;
281
462
 
463
+ // Recommendations section (if any)
464
+ if (versionResult.recommendations && versionResult.recommendations.length > 0) {
465
+ console.log(chalk.bold('\nRecommendations'));
466
+ console.log(chalk.gray('─'.repeat(40)));
467
+
468
+ for (const rec of versionResult.recommendations) {
469
+ console.log(chalk.yellow(` ⚡ ${rec.issue}`));
470
+ console.log(chalk.cyan(` → ${rec.action}`));
471
+ }
472
+ }
473
+
282
474
  // Summary
283
475
  console.log(chalk.bold('\nSummary'));
284
476
  console.log(chalk.gray('─'.repeat(40)));
@@ -298,8 +490,13 @@ export async function doctorCommand() {
298
490
  console.log(chalk.gray('Run `npx proagents init` to fix installation issues.'));
299
491
  }
300
492
  if (platformChecks.some(c => c.status === 'warning')) {
301
- console.log(chalk.gray('Run `pa:ai-sync` to fix platform sync issues.'));
493
+ console.log(chalk.gray('Run `npx proagents ai add` to fix platform sync issues.'));
302
494
  }
303
495
  console.log('');
304
496
  }
497
+
498
+ // Hint for full mode
499
+ if (!isFullMode) {
500
+ console.log(chalk.gray('Run `proagents doctor --full` for extended health checks.\n'));
501
+ }
305
502
  }
@@ -53,10 +53,30 @@ export async function helpCommand() {
53
53
  console.log(chalk.bold.white('Status & Info'));
54
54
  console.log(chalk.gray('─'.repeat(40)));
55
55
  console.log(chalk.cyan('proagents status') + ' Show ProAgents status');
56
+ console.log(chalk.cyan('proagents version') + ' Show detailed version info');
57
+ console.log(chalk.cyan('proagents doctor') + ' Health check installation');
56
58
  console.log(chalk.cyan('proagents docs') + ' Open documentation');
57
59
  console.log(chalk.cyan('proagents commands') + ' Show this help');
58
- console.log(chalk.cyan('proagents uninstall') + ' Remove ProAgents from project');
59
- console.log(chalk.cyan('proagents --version') + ' Show version');
60
+ console.log('');
61
+
62
+ // Release & Maintenance
63
+ console.log(chalk.bold.white('Release & Maintenance'));
64
+ console.log(chalk.gray('─'.repeat(40)));
65
+ console.log(chalk.cyan('proagents release') + ' Interactive release notes');
66
+ console.log(chalk.gray(' Types: -t detailed | short | client | developer | hotfix | prerelease'));
67
+ console.log(chalk.gray(' Filters:'));
68
+ console.log(chalk.cyan(' --include fixes') + ' Only include bug fixes');
69
+ console.log(chalk.cyan(' --include features') + ' Only include features');
70
+ console.log(chalk.cyan(' --exclude docs,deps') + ' Exclude docs and deps');
71
+ console.log(chalk.cyan(' --module auth') + ' Filter by module name');
72
+ console.log(chalk.cyan(' --path src/lib') + ' Filter by file path');
73
+ console.log(chalk.gray(' Options:'));
74
+ console.log(chalk.cyan(' --append') + ' Append to existing notes');
75
+ console.log(chalk.cyan(' --bump') + ' Suggest version bump');
76
+ console.log(chalk.cyan(' --prerelease beta') + ' Mark as beta/rc/alpha');
77
+ console.log(chalk.cyan(' --since v1.0.0') + ' From specific tag');
78
+ console.log(chalk.cyan('proagents upgrade') + ' Upgrade .proagents folder');
79
+ console.log(chalk.cyan('proagents uninstall') + ' Remove ProAgents from project');
60
80
  console.log('');
61
81
 
62
82
  // Commands for AI Assistants
@@ -14,8 +14,133 @@ const PRESERVE_PATHS = [
14
14
  'active-features', // User's work in progress
15
15
  '.learning', // Learned patterns
16
16
  'cache', // Cached analysis
17
+ 'changelog', // Change history (user data)
18
+ 'worklog', // Work context (user data)
19
+ 'sessions', // Session data
20
+ 'backups', // User backups
17
21
  ];
18
22
 
23
+ // Files within PRESERVE_PATHS that should always be UPDATED (framework files)
24
+ // These patterns match files that should be overwritten with latest framework version
25
+ const UPDATE_WITHIN_PRESERVED = [
26
+ 'README.md', // Documentation
27
+ 'entry-template.md', // Changelog entry template
28
+ '*.template.md', // All template markdown files
29
+ '*.template.json', // All template JSON files
30
+ 'schemas', // Schema folders
31
+ ];
32
+
33
+ /**
34
+ * Backup user data before fresh install
35
+ * Returns object mapping path to temp backup location
36
+ */
37
+ function backupUserData(proagentsDir) {
38
+ const preserved = {};
39
+ for (const path of PRESERVE_PATHS) {
40
+ const fullPath = join(proagentsDir, path);
41
+ if (existsSync(fullPath)) {
42
+ const tempPath = join(proagentsDir, '..', `.proagents-backup-${path.replace(/\//g, '-')}`);
43
+ try {
44
+ cpSync(fullPath, tempPath, { recursive: true });
45
+ preserved[path] = tempPath;
46
+ } catch (err) {
47
+ // Silently continue if backup fails
48
+ }
49
+ }
50
+ }
51
+ return preserved;
52
+ }
53
+
54
+ /**
55
+ * Restore user data after fresh install
56
+ */
57
+ function restoreUserData(proagentsDir, preserved) {
58
+ for (const [path, tempPath] of Object.entries(preserved)) {
59
+ const fullPath = join(proagentsDir, path);
60
+ if (existsSync(tempPath)) {
61
+ try {
62
+ // Remove the framework's empty/default version
63
+ if (existsSync(fullPath)) {
64
+ rmSync(fullPath, { recursive: true, force: true });
65
+ }
66
+ // Restore user's data
67
+ cpSync(tempPath, fullPath, { recursive: true });
68
+ // Clean up temp backup
69
+ rmSync(tempPath, { recursive: true, force: true });
70
+ } catch (err) {
71
+ // Silently continue if restore fails
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Update framework files within preserved paths
79
+ * After restoring user data, this copies framework files like README.md, *.template.*, schemas/
80
+ */
81
+ function updateFrameworkInPreserved(sourceDir, proagentsDir) {
82
+ for (const preservedPath of PRESERVE_PATHS) {
83
+ const sourcePath = join(sourceDir, preservedPath);
84
+ const targetPath = join(proagentsDir, preservedPath);
85
+
86
+ if (!existsSync(sourcePath) || !existsSync(targetPath)) continue;
87
+
88
+ try {
89
+ // Update README.md if exists
90
+ const sourceReadme = join(sourcePath, 'README.md');
91
+ const targetReadme = join(targetPath, 'README.md');
92
+ if (existsSync(sourceReadme)) {
93
+ cpSync(sourceReadme, targetReadme, { force: true });
94
+ }
95
+
96
+ // Update entry-template.md (for changelog)
97
+ const sourceEntryTemplate = join(sourcePath, 'entry-template.md');
98
+ const targetEntryTemplate = join(targetPath, 'entry-template.md');
99
+ if (existsSync(sourceEntryTemplate)) {
100
+ cpSync(sourceEntryTemplate, targetEntryTemplate, { force: true });
101
+ }
102
+
103
+ // Update schemas folder if exists
104
+ const sourceSchemas = join(sourcePath, 'schemas');
105
+ const targetSchemas = join(targetPath, 'schemas');
106
+ if (existsSync(sourceSchemas)) {
107
+ if (existsSync(targetSchemas)) {
108
+ rmSync(targetSchemas, { recursive: true, force: true });
109
+ }
110
+ cpSync(sourceSchemas, targetSchemas, { recursive: true });
111
+ }
112
+
113
+ // Update all *.template.md and *.template.json files
114
+ if (existsSync(sourcePath)) {
115
+ const entries = readdirSync(sourcePath, { withFileTypes: true });
116
+ for (const entry of entries) {
117
+ if (entry.isFile() && (entry.name.endsWith('.template.md') || entry.name.endsWith('.template.json'))) {
118
+ cpSync(join(sourcePath, entry.name), join(targetPath, entry.name), { force: true });
119
+ }
120
+ // Also check subdirectories (like .learning/global/)
121
+ if (entry.isDirectory()) {
122
+ const subPath = join(sourcePath, entry.name);
123
+ const subTargetPath = join(targetPath, entry.name);
124
+ if (existsSync(subPath)) {
125
+ const subEntries = readdirSync(subPath, { withFileTypes: true });
126
+ for (const subEntry of subEntries) {
127
+ if (subEntry.isFile() && (subEntry.name.endsWith('.template.md') || subEntry.name.endsWith('.template.json'))) {
128
+ if (!existsSync(subTargetPath)) {
129
+ mkdirSync(subTargetPath, { recursive: true });
130
+ }
131
+ cpSync(join(subPath, subEntry.name), join(subTargetPath, subEntry.name), { force: true });
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ } catch (err) {
139
+ // Silently continue if update fails
140
+ }
141
+ }
142
+ }
143
+
19
144
  // Config file is handled specially - merged not preserved
20
145
  const CONFIG_FILE = 'proagents.config.yaml';
21
146
 
@@ -41,7 +166,6 @@ const FRAMEWORK_FOLDERS = [
41
166
  'api-versioning',
42
167
  'approval-workflows',
43
168
  'automation',
44
- 'changelog',
45
169
  'cicd',
46
170
  'collaboration',
47
171
  'compliance',
@@ -89,6 +213,7 @@ const FRAMEWORK_FILES = [
89
213
  'GETTING-STARTED-STORY.md',
90
214
  'slash-commands.json',
91
215
  'AI_INSTRUCTIONS.md', // Universal instructions kept for reference
216
+ 'AGENTS.md', // Universal AI instruction file (works with most AI platforms)
92
217
  ];
93
218
 
94
219
  // Project type definitions for detection
@@ -610,7 +735,7 @@ function checkIncompleteSetup(targetDir) {
610
735
  }
611
736
 
612
737
  // Check 2: No AI instruction files at all = incomplete
613
- const aiFiles = ['CLAUDE.md', '.cursorrules', '.windsurfrules', 'CHATGPT.md', 'GEMINI.md'];
738
+ const aiFiles = ['AGENTS.md', 'CLAUDE.md', '.cursorrules', '.windsurfrules', 'CHATGPT.md', 'GEMINI.md'];
614
739
  const hasAnyAiFile = aiFiles.some(f => existsSync(join(targetDir, f)));
615
740
  if (!hasAnyAiFile) {
616
741
  return true;
@@ -666,6 +791,27 @@ async function promptIncompleteSetupChoice() {
666
791
  return 'continue';
667
792
  }
668
793
 
794
+ /**
795
+ * Confirm destructive "Restart fresh" action
796
+ */
797
+ async function confirmRestartFresh() {
798
+ const rl = createInterface({
799
+ input: process.stdin,
800
+ output: process.stdout
801
+ });
802
+
803
+ const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
804
+
805
+ console.log(chalk.red.bold('\n⚠️ WARNING: This will DELETE all data in .proagents/'));
806
+ console.log(chalk.yellow(' Including: changelog, worklog, sessions, learning data, etc.'));
807
+ console.log(chalk.gray(' This action cannot be undone.\n'));
808
+
809
+ const answer = await question(chalk.red('Type "DELETE" to confirm, or press Enter to cancel: '));
810
+ rl.close();
811
+
812
+ return answer.trim().toUpperCase() === 'DELETE';
813
+ }
814
+
669
815
  /**
670
816
  * Prompt user for .gitignore preference
671
817
  */
@@ -980,6 +1126,12 @@ export async function initCommand(options = {}) {
980
1126
  console.log(chalk.cyan('\nContinuing setup...\n'));
981
1127
  // Fall through to fresh install (but keep .proagents folder)
982
1128
  } else if (choice === 'restart') {
1129
+ // Confirm destructive action
1130
+ const confirmed = await confirmRestartFresh();
1131
+ if (!confirmed) {
1132
+ console.log(chalk.yellow('\nCancelled. No changes made.\n'));
1133
+ return;
1134
+ }
983
1135
  console.log(chalk.cyan('\nRestarting fresh setup...\n'));
984
1136
  rmSync(proagentsDir, { recursive: true, force: true });
985
1137
  // Fall through to fresh install
@@ -1025,7 +1177,21 @@ export async function initCommand(options = {}) {
1025
1177
 
1026
1178
  // Fresh install or force overwrite
1027
1179
  console.log(chalk.gray('Copying framework files...'));
1180
+
1181
+ // Backup user data if .proagents exists (to preserve changelog, worklog, etc.)
1182
+ const userDataBackup = existsSync(proagentsDir) ? backupUserData(proagentsDir) : {};
1183
+
1028
1184
  cpSync(sourceDir, proagentsDir, { recursive: true, force: true });
1185
+
1186
+ // Restore user data after framework copy
1187
+ if (Object.keys(userDataBackup).length > 0) {
1188
+ restoreUserData(proagentsDir, userDataBackup);
1189
+ // Update framework files within preserved paths (README.md, templates, schemas)
1190
+ updateFrameworkInPreserved(sourceDir, proagentsDir);
1191
+ console.log(chalk.green('✓ Preserved user data (changelog, worklog, sessions, etc.)'));
1192
+ console.log(chalk.green('✓ Updated templates and documentation in preserved folders'));
1193
+ }
1194
+
1029
1195
  console.log(chalk.green('✓ Framework files copied to ./.proagents/'));
1030
1196
 
1031
1197
  // Create config if not skipped
@@ -1397,6 +1563,9 @@ async function smartUpdate(sourceDir, targetDir) {
1397
1563
  }
1398
1564
  }
1399
1565
 
1566
+ // Update framework files within preserved paths (templates, README, schemas)
1567
+ updateFrameworkInPreserved(sourceDir, targetDir);
1568
+
1400
1569
  console.log(chalk.gray('\nTip: Use "proagents ai add" to add more AI platforms'));
1401
1570
  }
1402
1571