universal-dev-standards 3.5.1-beta.15 → 3.5.1-beta.17

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.
@@ -537,7 +537,11 @@ export async function initCommand(options) {
537
537
  integrations: [],
538
538
  skills: [],
539
539
  commands: [],
540
- errors: []
540
+ errors: [],
541
+ // New: hash tracking for enhanced file integrity
542
+ skillHashes: {},
543
+ commandHashes: {},
544
+ integrationBlockHashes: {}
541
545
  };
542
546
 
543
547
  // Get standards for the selected level
@@ -702,6 +706,14 @@ export async function initCommand(options) {
702
706
  if (result.success) {
703
707
  results.integrations.push(result.path);
704
708
  generatedFiles.add(targetFile);
709
+
710
+ // Capture integration block hash for tracking UDS content
711
+ if (result.blockHashInfo) {
712
+ results.integrationBlockHashes[result.path] = {
713
+ ...result.blockHashInfo,
714
+ installedAt: new Date().toISOString()
715
+ };
716
+ }
705
717
  } else {
706
718
  // Fall back to legacy static file copy
707
719
  const mapping = INTEGRATION_MAPPINGS[tool];
@@ -776,6 +788,11 @@ export async function initCommand(options) {
776
788
  }
777
789
  }
778
790
 
791
+ // Collect skill file hashes for integrity tracking
792
+ if (installResult.allFileHashes) {
793
+ Object.assign(results.skillHashes, installResult.allFileHashes);
794
+ }
795
+
779
796
  // Build location summary for display
780
797
  const targetLocations = skillsConfig.skillsInstallations.map(inst => {
781
798
  const displayName = getAgentDisplayName(inst.agent);
@@ -867,6 +884,11 @@ export async function initCommand(options) {
867
884
  }
868
885
  }
869
886
 
887
+ // Collect command file hashes for integrity tracking
888
+ if (cmdResult.allFileHashes) {
889
+ Object.assign(results.commandHashes, cmdResult.allFileHashes);
890
+ }
891
+
870
892
  // Build location summary
871
893
  const cmdLocations = skillsConfig.commandsInstallations.map(agent => {
872
894
  const displayName = getAgentDisplayName(agent);
@@ -983,7 +1005,7 @@ export async function initCommand(options) {
983
1005
  }
984
1006
 
985
1007
  const manifest = {
986
- version: '3.2.0',
1008
+ version: '3.3.0', // Updated for enhanced file tracking
987
1009
  upstream: {
988
1010
  repo: 'AsiaOstrich/universal-dev-standards',
989
1011
  version: repoInfo.standards.version,
@@ -1021,7 +1043,11 @@ export async function initCommand(options) {
1021
1043
  skipLimit: 3
1022
1044
  }
1023
1045
  } : null,
1024
- fileHashes
1046
+ fileHashes,
1047
+ // New: enhanced file tracking for Skills, Commands, and Integration blocks
1048
+ skillHashes: results.skillHashes || {},
1049
+ commandHashes: results.commandHashes || {},
1050
+ integrationBlockHashes: results.integrationBlockHashes || {}
1025
1051
  };
1026
1052
 
1027
1053
  writeManifest(manifest, projectPath);
@@ -336,6 +336,15 @@ export async function updateCommand(options) {
336
336
  if (result.success) {
337
337
  results.integrations.push(result.path);
338
338
  generatedFiles.add(targetFile);
339
+
340
+ // Track integration block hash for UDS content integrity
341
+ if (result.blockHashInfo) {
342
+ if (!manifest.integrationBlockHashes) manifest.integrationBlockHashes = {};
343
+ manifest.integrationBlockHashes[result.path] = {
344
+ ...result.blockHashInfo,
345
+ installedAt: new Date().toISOString()
346
+ };
347
+ }
339
348
  } else {
340
349
  results.errors.push(`${tool}: ${result.error}`);
341
350
  }
@@ -384,7 +393,7 @@ export async function updateCommand(options) {
384
393
  }
385
394
 
386
395
  // Update manifest
387
- manifest.version = '3.2.0';
396
+ manifest.version = '3.3.0';
388
397
  manifest.upstream.version = latestVersion;
389
398
  manifest.upstream.installed = new Date().toISOString().split('T')[0];
390
399
  writeManifest(manifest, projectPath);
@@ -405,15 +414,17 @@ export async function updateCommand(options) {
405
414
  }
406
415
  }
407
416
 
408
- // Check for new features (Skills/Commands) not yet installed
417
+ // Check for new features (Skills/Commands) not yet installed or outdated
409
418
  if (!options.standardsOnly) {
410
- const { missingSkills, missingCommands } = checkNewFeatures(projectPath, manifest);
419
+ const latestSkillsVersion = repoInfo.skills.version;
420
+ const { missingSkills, outdatedSkills, missingCommands } = checkNewFeatures(projectPath, manifest, latestSkillsVersion);
411
421
 
412
- if (missingSkills.length > 0 || missingCommands.length > 0) {
422
+ if (missingSkills.length > 0 || outdatedSkills.length > 0 || missingCommands.length > 0) {
413
423
  if (!options.yes) {
414
- // Interactive mode: prompt user to install
415
- const { installSkills, installCommands } = await promptNewFeatureInstallation(
424
+ // Interactive mode: prompt user to install/update
425
+ const { installSkills, updateSkills, installCommands } = await promptNewFeatureInstallation(
416
426
  missingSkills,
427
+ outdatedSkills,
417
428
  missingCommands
418
429
  );
419
430
 
@@ -431,6 +442,12 @@ export async function updateCommand(options) {
431
442
  ...installSkills
432
443
  ];
433
444
 
445
+ // Update skill hashes for integrity tracking
446
+ if (skillResult.allFileHashes) {
447
+ if (!manifest.skillHashes) manifest.skillHashes = {};
448
+ Object.assign(manifest.skillHashes, skillResult.allFileHashes);
449
+ }
450
+
434
451
  if (skillResult.totalErrors === 0) {
435
452
  skillSpinner.succeed((msg.newSkillsInstalled || 'Installed Skills for {count} AI tools')
436
453
  .replace('{count}', installSkills.length));
@@ -440,6 +457,30 @@ export async function updateCommand(options) {
440
457
  }
441
458
  }
442
459
 
460
+ // Update outdated Skills if user agreed
461
+ if (updateSkills.length > 0) {
462
+ const updateSpinner = ora(msg.updatingSkills || 'Updating Skills...').start();
463
+ const updateResult = await installSkillsToMultipleAgents(updateSkills, null, projectPath);
464
+
465
+ // Update manifest version
466
+ if (!manifest.skills) manifest.skills = {};
467
+ manifest.skills.version = repoInfo.skills.version;
468
+
469
+ // Update skill hashes for integrity tracking
470
+ if (updateResult.allFileHashes) {
471
+ if (!manifest.skillHashes) manifest.skillHashes = {};
472
+ Object.assign(manifest.skillHashes, updateResult.allFileHashes);
473
+ }
474
+
475
+ if (updateResult.totalErrors === 0) {
476
+ updateSpinner.succeed((msg.skillsUpdated || 'Updated Skills for {count} AI tools')
477
+ .replace('{count}', updateSkills.length));
478
+ } else {
479
+ updateSpinner.warn((msg.skillsUpdatedWithErrors || 'Updated Skills with {errors} errors')
480
+ .replace('{errors}', updateResult.totalErrors));
481
+ }
482
+ }
483
+
443
484
  // Install Commands if user agreed
444
485
  if (installCommands.length > 0) {
445
486
  const cmdSpinner = ora(msg.installingNewCommands || 'Installing commands...').start();
@@ -453,6 +494,12 @@ export async function updateCommand(options) {
453
494
  ...installCommands
454
495
  ];
455
496
 
497
+ // Update command hashes for integrity tracking
498
+ if (cmdResult.allFileHashes) {
499
+ if (!manifest.commandHashes) manifest.commandHashes = {};
500
+ Object.assign(manifest.commandHashes, cmdResult.allFileHashes);
501
+ }
502
+
456
503
  if (cmdResult.totalErrors === 0) {
457
504
  cmdSpinner.succeed((msg.newCommandsInstalled || 'Installed commands for {count} AI tools')
458
505
  .replace('{count}', installCommands.length));
@@ -462,8 +509,8 @@ export async function updateCommand(options) {
462
509
  }
463
510
  }
464
511
 
465
- // Write updated manifest if anything was installed
466
- if (installSkills.length > 0 || installCommands.length > 0) {
512
+ // Write updated manifest if anything was installed or updated
513
+ if (installSkills.length > 0 || updateSkills.length > 0 || installCommands.length > 0) {
467
514
  writeManifest(manifest, projectPath);
468
515
  }
469
516
  } else {
@@ -474,6 +521,10 @@ export async function updateCommand(options) {
474
521
  const toolNames = missingSkills.map(s => s.displayName).join(', ');
475
522
  console.log(chalk.gray(` • Skills (${toolNames}): run "uds update --skills" or "uds init" to install`));
476
523
  }
524
+ if (outdatedSkills.length > 0) {
525
+ const toolNames = outdatedSkills.map(s => `${s.displayName} (${s.currentVersion} → ${s.latestVersion})`).join(', ');
526
+ console.log(chalk.gray(` • Skills update (${toolNames}): run "uds update" interactively to update`));
527
+ }
477
528
  if (missingCommands.length > 0) {
478
529
  const toolNames = missingCommands.map(c => c.displayName).join(', ');
479
530
  console.log(chalk.gray(` • Commands (${toolNames}): run "uds update --commands" or "uds init" to install`));
@@ -527,26 +578,19 @@ export async function updateCommand(options) {
527
578
  }
528
579
 
529
580
  /**
530
- * Update integration files only (without updating standards)
581
+ * Regenerate integration files for all configured AI tools
582
+ * Reusable core logic that can be called from both updateIntegrationsOnly and configureCommand
531
583
  * @param {string} projectPath - Project path
532
- * @param {Object} manifest - Manifest object
584
+ * @param {Object} manifest - Manifest object (will be mutated with updated hashes)
585
+ * @returns {{success: boolean, updated: string[], errors: string[]}}
533
586
  */
534
- async function updateIntegrationsOnly(projectPath, manifest) {
535
- const msg = t().commands.update;
536
-
537
- console.log(chalk.cyan(msg.updatingIntegrationsOnly));
538
- console.log();
539
-
587
+ export function regenerateIntegrations(projectPath, manifest) {
540
588
  const aiTools = manifest.aiTools || [];
589
+
541
590
  if (aiTools.length === 0) {
542
- console.log(chalk.yellow(msg.noAiToolsConfigured));
543
- console.log(chalk.gray(` ${msg.runConfigure}`));
544
- console.log();
545
- return;
591
+ return { success: true, updated: [], errors: [] };
546
592
  }
547
593
 
548
- const spinner = ora(msg.regeneratingIntegrations).start();
549
-
550
594
  // Build installed standards list
551
595
  const installedStandardsList = manifest.standards?.map(s => basename(s)) || [];
552
596
 
@@ -596,15 +640,55 @@ async function updateIntegrationsOnly(projectPath, manifest) {
596
640
  }
597
641
  manifest.fileHashes[result.path] = { ...hashInfo, installedAt: now };
598
642
  }
643
+
644
+ // Track integration block hash for UDS content integrity
645
+ if (result.blockHashInfo) {
646
+ if (!manifest.integrationBlockHashes) manifest.integrationBlockHashes = {};
647
+ manifest.integrationBlockHashes[result.path] = {
648
+ ...result.blockHashInfo,
649
+ installedAt: now
650
+ };
651
+ }
599
652
  } else {
600
653
  results.errors.push(`${tool}: ${result.error}`);
601
654
  }
602
655
  }
603
656
 
657
+ return {
658
+ success: results.errors.length === 0,
659
+ updated: results.updated,
660
+ errors: results.errors
661
+ };
662
+ }
663
+
664
+ /**
665
+ * Update integration files only (without updating standards)
666
+ * @param {string} projectPath - Project path
667
+ * @param {Object} manifest - Manifest object
668
+ */
669
+ async function updateIntegrationsOnly(projectPath, manifest) {
670
+ const msg = t().commands.update;
671
+
672
+ console.log(chalk.cyan(msg.updatingIntegrationsOnly));
673
+ console.log();
674
+
675
+ const aiTools = manifest.aiTools || [];
676
+ if (aiTools.length === 0) {
677
+ console.log(chalk.yellow(msg.noAiToolsConfigured));
678
+ console.log(chalk.gray(` ${msg.runConfigure}`));
679
+ console.log();
680
+ return;
681
+ }
682
+
683
+ const spinner = ora(msg.regeneratingIntegrations).start();
684
+
685
+ // Use reusable regeneration function
686
+ const results = regenerateIntegrations(projectPath, manifest);
687
+
604
688
  spinner.succeed(msg.regeneratedIntegrations.replace('{count}', results.updated.length));
605
689
 
606
690
  // Update manifest
607
- manifest.version = '3.2.0';
691
+ manifest.version = '3.3.0';
608
692
  writeManifest(manifest, projectPath);
609
693
 
610
694
  // Summary
@@ -715,6 +799,15 @@ async function syncIntegrationReferences(projectPath, manifest) {
715
799
  manifest.fileHashes[integrationPath] = { ...hashInfo, installedAt: now };
716
800
  }
717
801
 
802
+ // Track integration block hash for UDS content integrity
803
+ if (result.blockHashInfo) {
804
+ if (!manifest.integrationBlockHashes) manifest.integrationBlockHashes = {};
805
+ manifest.integrationBlockHashes[integrationPath] = {
806
+ ...result.blockHashInfo,
807
+ installedAt: now
808
+ };
809
+ }
810
+
718
811
  updatedCount++;
719
812
  } else {
720
813
  console.log(chalk.red(` ${msg.failedToUpdate.replace('{path}', integrationPath).replace('{error}', result.error)}`));
@@ -723,7 +816,7 @@ async function syncIntegrationReferences(projectPath, manifest) {
723
816
 
724
817
  // Update manifest version and save
725
818
  if (updatedCount > 0) {
726
- manifest.version = '3.2.0';
819
+ manifest.version = '3.3.0';
727
820
  writeManifest(manifest, projectPath);
728
821
  }
729
822
 
@@ -840,6 +933,13 @@ async function updateSkillsOnly(projectPath, manifest) {
840
933
  // Update manifest
841
934
  manifest.skills.version = latestVersion;
842
935
  manifest.skills.installations = skillsInstallations;
936
+
937
+ // Update skill hashes for integrity tracking
938
+ if (result.allFileHashes) {
939
+ if (!manifest.skillHashes) manifest.skillHashes = {};
940
+ Object.assign(manifest.skillHashes, result.allFileHashes);
941
+ }
942
+
843
943
  writeManifest(manifest, projectPath);
844
944
 
845
945
  console.log();
@@ -908,6 +1008,13 @@ async function updateCommandsOnly(projectPath, manifest) {
908
1008
  manifest.commands = manifest.commands || {};
909
1009
  manifest.commands.installed = true;
910
1010
  manifest.commands.installations = commandsInstallations;
1011
+
1012
+ // Update command hashes for integrity tracking
1013
+ if (result.allFileHashes) {
1014
+ if (!manifest.commandHashes) manifest.commandHashes = {};
1015
+ Object.assign(manifest.commandHashes, result.allFileHashes);
1016
+ }
1017
+
911
1018
  writeManifest(manifest, projectPath);
912
1019
 
913
1020
  console.log();
@@ -915,19 +1022,21 @@ async function updateCommandsOnly(projectPath, manifest) {
915
1022
  }
916
1023
 
917
1024
  /**
918
- * Check manifest.aiTools and detect missing Skills/Commands
1025
+ * Check manifest.aiTools and detect missing/outdated Skills/Commands
919
1026
  * @param {string} projectPath - Project path
920
1027
  * @param {Object} manifest - Manifest object
921
- * @returns {{missingSkills: Array, missingCommands: Array}}
1028
+ * @param {string} latestSkillsVersion - Latest skills version from repository
1029
+ * @returns {{missingSkills: Array, outdatedSkills: Array, missingCommands: Array}}
922
1030
  */
923
- function checkNewFeatures(projectPath, manifest) {
1031
+ function checkNewFeatures(projectPath, manifest, latestSkillsVersion) {
924
1032
  const aiTools = manifest.aiTools || [];
925
1033
 
926
1034
  if (aiTools.length === 0) {
927
- return { missingSkills: [], missingCommands: [] };
1035
+ return { missingSkills: [], outdatedSkills: [], missingCommands: [] };
928
1036
  }
929
1037
 
930
1038
  const missingSkills = [];
1039
+ const outdatedSkills = [];
931
1040
  const missingCommands = [];
932
1041
 
933
1042
  for (const tool of aiTools) {
@@ -936,20 +1045,16 @@ function checkNewFeatures(projectPath, manifest) {
936
1045
 
937
1046
  // Check Skills support
938
1047
  if (config.supportsSkills && config.skills) {
939
- // Check if skills are installed for this agent
1048
+ // Check if skills are actually installed for this agent (file-based check)
940
1049
  const projectInfo = getInstalledSkillsInfoForAgent(tool, 'project', projectPath);
941
1050
  const userInfo = getInstalledSkillsInfoForAgent(tool, 'user');
942
1051
 
943
- // Check if already in manifest.skills.installations
944
- const existingInstallations = manifest.skills?.installations || [];
945
- const isInManifest = existingInstallations.some(
946
- inst => inst.agent === tool || (inst.agent === 'claude-code' && tool === 'claude-code')
947
- );
948
-
949
- // Check if using marketplace (Claude Code only)
1052
+ // Check if using marketplace (Claude Code only) - marketplace auto-updates
950
1053
  const usingMarketplace = manifest.skills?.location === 'marketplace' && tool === 'claude-code';
951
1054
 
952
- const hasSkills = projectInfo?.installed || userInfo?.installed || isInManifest || usingMarketplace;
1055
+ // Only trust actual file existence, not manifest records
1056
+ // (manifest records can be stale if user deleted the directory)
1057
+ const hasSkills = projectInfo?.installed || userInfo?.installed || usingMarketplace;
953
1058
 
954
1059
  if (!hasSkills) {
955
1060
  missingSkills.push({
@@ -957,6 +1062,23 @@ function checkNewFeatures(projectPath, manifest) {
957
1062
  displayName: getAgentDisplayName(tool),
958
1063
  paths: config.skills
959
1064
  });
1065
+ } else if (latestSkillsVersion) {
1066
+ // Check if installed Skills are outdated
1067
+ const installedInfo = userInfo || projectInfo;
1068
+ const installedVersion = installedInfo?.version;
1069
+
1070
+ // Skip marketplace (auto-updates) and unknown versions
1071
+ if (!usingMarketplace && installedVersion && installedVersion !== latestSkillsVersion) {
1072
+ outdatedSkills.push({
1073
+ agent: tool,
1074
+ displayName: getAgentDisplayName(tool),
1075
+ paths: config.skills,
1076
+ currentVersion: installedVersion,
1077
+ latestVersion: latestSkillsVersion,
1078
+ level: userInfo?.installed ? 'user' : 'project',
1079
+ path: installedInfo?.path
1080
+ });
1081
+ }
960
1082
  }
961
1083
  }
962
1084
 
@@ -964,11 +1086,8 @@ function checkNewFeatures(projectPath, manifest) {
964
1086
  if (config.commands !== null && config.commands) {
965
1087
  const cmdInfo = getInstalledCommandsForAgent(tool, projectPath);
966
1088
 
967
- // Check if already in manifest.commands.installations
968
- const existingCmdInstallations = manifest.commands?.installations || [];
969
- const isInCmdManifest = existingCmdInstallations.includes(tool);
970
-
971
- const hasCommands = cmdInfo?.installed || isInCmdManifest;
1089
+ // Only trust actual file existence, not manifest records
1090
+ const hasCommands = cmdInfo?.installed;
972
1091
 
973
1092
  if (!hasCommands) {
974
1093
  missingCommands.push({
@@ -980,21 +1099,22 @@ function checkNewFeatures(projectPath, manifest) {
980
1099
  }
981
1100
  }
982
1101
 
983
- return { missingSkills, missingCommands };
1102
+ return { missingSkills, outdatedSkills, missingCommands };
984
1103
  }
985
1104
 
986
1105
  /**
987
1106
  * Prompt user to install new features discovered during update
988
1107
  * @param {Array} missingSkills - Array of {agent, displayName, paths}
1108
+ * @param {Array} outdatedSkills - Array of {agent, displayName, paths, currentVersion, latestVersion, level, path}
989
1109
  * @param {Array} missingCommands - Array of {agent, displayName, path}
990
- * @returns {Promise<{installSkills: Array, installCommands: Array}>}
1110
+ * @returns {Promise<{installSkills: Array, updateSkills: Array, installCommands: Array}>}
991
1111
  */
992
- async function promptNewFeatureInstallation(missingSkills, missingCommands) {
1112
+ async function promptNewFeatureInstallation(missingSkills, outdatedSkills, missingCommands) {
993
1113
  const msg = t().commands.update;
994
1114
 
995
- // If nothing missing, return empty
996
- if (missingSkills.length === 0 && missingCommands.length === 0) {
997
- return { installSkills: [], installCommands: [] };
1115
+ // If nothing to do, return empty
1116
+ if (missingSkills.length === 0 && outdatedSkills.length === 0 && missingCommands.length === 0) {
1117
+ return { installSkills: [], updateSkills: [], installCommands: [] };
998
1118
  }
999
1119
 
1000
1120
  console.log();
@@ -1003,7 +1123,7 @@ async function promptNewFeatureInstallation(missingSkills, missingCommands) {
1003
1123
  console.log(chalk.cyan('━'.repeat(50)));
1004
1124
  console.log();
1005
1125
 
1006
- const result = { installSkills: [], installCommands: [] };
1126
+ const result = { installSkills: [], updateSkills: [], installCommands: [] };
1007
1127
 
1008
1128
  // Handle missing Skills with checkbox selection
1009
1129
  if (missingSkills.length > 0) {
@@ -1065,6 +1185,64 @@ async function promptNewFeatureInstallation(missingSkills, missingCommands) {
1065
1185
  console.log();
1066
1186
  }
1067
1187
 
1188
+ // Handle outdated Skills with checkbox selection
1189
+ if (outdatedSkills.length > 0) {
1190
+ console.log(chalk.yellow(msg.skillsOutdatedFor || 'Skills updates available for these AI tools:'));
1191
+ for (const skill of outdatedSkills) {
1192
+ const levelLabel = skill.level === 'user' ? 'user' : 'project';
1193
+ const pathDisplay = skill.path || getSkillsDirForAgent(skill.agent, skill.level);
1194
+ console.log(chalk.gray(` • ${skill.displayName} (${levelLabel}: ${pathDisplay})`));
1195
+ console.log(chalk.gray(` ${skill.currentVersion} → ${skill.latestVersion}`));
1196
+ }
1197
+ console.log();
1198
+
1199
+ // Build checkbox choices with path info
1200
+ const updateChoices = outdatedSkills.map(skill => {
1201
+ const levelLabel = skill.level === 'user' ? 'user' : 'project';
1202
+ const pathDisplay = skill.path || getSkillsDirForAgent(skill.agent, skill.level);
1203
+ return {
1204
+ name: `${skill.displayName} ${chalk.gray(`(${levelLabel}: ${pathDisplay}) ${skill.currentVersion} → ${skill.latestVersion}`)}`,
1205
+ value: skill.agent,
1206
+ checked: true // Default checked for opt-out behavior
1207
+ };
1208
+ });
1209
+
1210
+ // Add skip option
1211
+ updateChoices.push(new inquirer.Separator());
1212
+ updateChoices.push({
1213
+ name: chalk.gray(msg.skipSkillsUpdate || 'Skip Skills update'),
1214
+ value: '__skip__'
1215
+ });
1216
+
1217
+ const { selectedUpdateAgents } = await inquirer.prompt([{
1218
+ type: 'checkbox',
1219
+ name: 'selectedUpdateAgents',
1220
+ message: msg.selectSkillsToUpdate || 'Select AI tools to update Skills for:',
1221
+ choices: updateChoices,
1222
+ validate: (answer) => {
1223
+ if (answer.includes('__skip__') && answer.length > 1) {
1224
+ return msg.skipValidationError || 'Cannot select Skip with other options';
1225
+ }
1226
+ return true;
1227
+ }
1228
+ }]);
1229
+
1230
+ // Filter out skip and map to update info
1231
+ const filteredUpdateAgents = selectedUpdateAgents.filter(a => a !== '__skip__');
1232
+
1233
+ if (filteredUpdateAgents.length > 0) {
1234
+ result.updateSkills = filteredUpdateAgents.map(agent => {
1235
+ const skillInfo = outdatedSkills.find(s => s.agent === agent);
1236
+ return {
1237
+ agent,
1238
+ level: skillInfo.level,
1239
+ path: skillInfo.path
1240
+ };
1241
+ });
1242
+ }
1243
+ console.log();
1244
+ }
1245
+
1068
1246
  // Handle missing Commands with checkbox selection
1069
1247
  if (missingCommands.length > 0) {
1070
1248
  console.log(chalk.yellow(msg.commandsNotInstalledFor || 'Slash commands not yet installed for these AI tools:'));
@@ -604,7 +604,18 @@ export const messages = {
604
604
  skillsInstalledSuccess: 'Installed Skills for {count} AI tools',
605
605
  commandsInstalledSuccess: 'Installed commands for {count} AI tools',
606
606
  // Read-only hint
607
- missingSkillsHint: 'Tip: Run `uds update` to install missing Skills/Commands'
607
+ missingSkillsHint: 'Tip: Run `uds update` to install missing Skills/Commands',
608
+ // Summary mode (--summary)
609
+ summary_mode: {
610
+ title: 'UDS Status Summary',
611
+ notInitialized: 'Not initialized',
612
+ manifestError: 'Manifest error',
613
+ version: 'Version',
614
+ level: 'Level',
615
+ files: 'Files',
616
+ skills: 'Skills',
617
+ commands: 'Commands'
618
+ }
608
619
  },
609
620
 
610
621
  // init command (commands/init.js)
@@ -843,7 +854,12 @@ export const messages = {
843
854
  errors: 'Errors',
844
855
  noCommandSupportedTools: 'No AI tools with command support configured',
845
856
  commandSupportedList: 'Tools that support commands: OpenCode, Copilot, Roo Code, Gemini CLI',
846
- commandsInstalled: 'commands'
857
+ commandsInstalled: 'commands',
858
+ // Smart apply
859
+ applyChangesNow: 'Apply changes now? (regenerate integration files)',
860
+ runUpdateLater: 'Run `uds update --integrations-only` later to apply changes',
861
+ applyingChanges: 'Applying changes...',
862
+ changesApplied: 'Changes applied successfully'
847
863
  }
848
864
  }
849
865
  },
@@ -1444,7 +1460,18 @@ export const messages = {
1444
1460
  skillsInstalledSuccess: '已為 {count} 個 AI 工具安裝 Skills',
1445
1461
  commandsInstalledSuccess: '已為 {count} 個 AI 工具安裝斜線命令',
1446
1462
  // Read-only hint
1447
- missingSkillsHint: '提示:執行 `uds update` 安裝缺少的 Skills/斜線命令'
1463
+ missingSkillsHint: '提示:執行 `uds update` 安裝缺少的 Skills/斜線命令',
1464
+ // Summary mode (--summary)
1465
+ summary_mode: {
1466
+ title: 'UDS 狀態摘要',
1467
+ notInitialized: '尚未初始化',
1468
+ manifestError: 'Manifest 錯誤',
1469
+ version: '版本',
1470
+ level: '等級',
1471
+ files: '檔案',
1472
+ skills: 'Skills',
1473
+ commands: '斜線命令'
1474
+ }
1448
1475
  },
1449
1476
 
1450
1477
  // init command (commands/init.js)
@@ -1683,7 +1710,12 @@ export const messages = {
1683
1710
  errors: '錯誤',
1684
1711
  noCommandSupportedTools: '未設定支援命令的 AI 工具',
1685
1712
  commandSupportedList: '支援命令的工具:OpenCode、Copilot、Roo Code、Gemini CLI',
1686
- commandsInstalled: '個命令'
1713
+ commandsInstalled: '個命令',
1714
+ // Smart apply
1715
+ applyChangesNow: '是否立即套用變更?(重新產生整合檔案)',
1716
+ runUpdateLater: '稍後執行 `uds update --integrations-only` 以套用變更',
1717
+ applyingChanges: '正在套用變更...',
1718
+ changesApplied: '變更套用成功'
1687
1719
  }
1688
1720
  }
1689
1721
  },
@@ -2187,7 +2219,18 @@ export const messages = {
2187
2219
  skillsInstalledSuccess: '已为 {count} 个 AI 工具安装 Skills',
2188
2220
  commandsInstalledSuccess: '已为 {count} 个 AI 工具安装斜线命令',
2189
2221
  // Read-only hint
2190
- missingSkillsHint: '提示:执行 `uds update` 安装缺少的 Skills/斜线命令'
2222
+ missingSkillsHint: '提示:执行 `uds update` 安装缺少的 Skills/斜线命令',
2223
+ // Summary mode (--summary)
2224
+ summary_mode: {
2225
+ title: 'UDS 状态摘要',
2226
+ notInitialized: '尚未初始化',
2227
+ manifestError: 'Manifest 错误',
2228
+ version: '版本',
2229
+ level: '等级',
2230
+ files: '文件',
2231
+ skills: 'Skills',
2232
+ commands: '斜线命令'
2233
+ }
2191
2234
  },
2192
2235
 
2193
2236
  // update command
@@ -2355,7 +2398,12 @@ export const messages = {
2355
2398
  errors: '错误',
2356
2399
  noCommandSupportedTools: '未配置支持命令的 AI 工具',
2357
2400
  commandSupportedList: '支持命令的工具:OpenCode、Copilot、Roo Code、Gemini CLI',
2358
- commandsInstalled: '个命令'
2401
+ commandsInstalled: '个命令',
2402
+ // Smart apply
2403
+ applyChangesNow: '是否立即应用变更?(重新生成集成文件)',
2404
+ runUpdateLater: '稍后执行 `uds update --integrations-only` 以应用变更',
2405
+ applyingChanges: '正在应用变更...',
2406
+ changesApplied: '变更应用成功'
2359
2407
  }
2360
2408
  }
2361
2409
  }