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

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-dev-standards",
3
- "version": "3.5.1-beta.17",
3
+ "version": "3.5.1-beta.18",
4
4
  "description": "CLI tool for adopting Universal Development Standards",
5
5
  "keywords": [
6
6
  "documentation",
@@ -693,18 +693,21 @@ function displaySkillsStatus(manifest, projectPath, msg) {
693
693
  }
694
694
 
695
695
  // Check for Marketplace installation (Claude Code specific)
696
+ // Dynamically detect marketplace installation regardless of manifest
696
697
  const hasClaudeCode = aiTools.includes('claude-code');
698
+ const marketplaceInfo = getMarketplaceSkillsInfo();
699
+ const hasMarketplaceSkills = marketplaceInfo?.installed;
700
+
697
701
  const location = manifest.skills?.location || '';
698
- const isMarketplace = location === 'marketplace' ||
702
+ const isMarketplaceInManifest = location === 'marketplace' ||
699
703
  location.includes('plugins/cache') ||
700
704
  location.includes('plugins\\cache');
701
705
 
702
- if (isMarketplace && hasClaudeCode) {
706
+ // Show marketplace status if actually installed (not just manifest)
707
+ if (hasMarketplaceSkills && hasClaudeCode) {
703
708
  console.log(chalk.green(` ${msg.skillsViaMarketplace}`));
704
709
 
705
- // Try to get actual version from marketplace
706
- const marketplaceInfo = getMarketplaceSkillsInfo();
707
- if (marketplaceInfo && marketplaceInfo.version && marketplaceInfo.version !== 'unknown') {
710
+ if (marketplaceInfo.version && marketplaceInfo.version !== 'unknown') {
708
711
  console.log(chalk.gray(` ${t().commands.common.version}: ${marketplaceInfo.version}`));
709
712
  if (marketplaceInfo.lastUpdated) {
710
713
  const updateDate = marketplaceInfo.lastUpdated.split('T')[0];
@@ -732,7 +735,7 @@ function displaySkillsStatus(manifest, projectPath, msg) {
732
735
  const userSkillsInfo = getInstalledSkillsInfoForAgent(tool, 'user', projectPath);
733
736
 
734
737
  // Check if using marketplace for Claude Code
735
- const usingMarketplace = isMarketplace && tool === 'claude-code';
738
+ const usingMarketplace = (hasMarketplaceSkills || isMarketplaceInManifest) && tool === 'claude-code';
736
739
 
737
740
  if (projectSkillsInfo?.installed || userSkillsInfo?.installed || usingMarketplace) {
738
741
  console.log(chalk.green(` ✓ Skills ${msg.installed || 'installed'}:`));
@@ -1425,8 +1428,12 @@ function getSkillsStatusSummary(manifest, projectPath) {
1425
1428
  const parts = [];
1426
1429
 
1427
1430
  // Check for Marketplace installation (Claude Code specific)
1431
+ // Dynamically detect marketplace installation regardless of manifest
1432
+ const marketplaceInfo = getMarketplaceSkillsInfo();
1433
+ const hasMarketplaceSkills = marketplaceInfo?.installed;
1434
+
1428
1435
  const location = manifest.skills?.location || '';
1429
- const isMarketplace = location === 'marketplace' ||
1436
+ const isMarketplaceInManifest = location === 'marketplace' ||
1430
1437
  location.includes('plugins/cache') ||
1431
1438
  location.includes('plugins\\cache');
1432
1439
 
@@ -1435,7 +1442,7 @@ function getSkillsStatusSummary(manifest, projectPath) {
1435
1442
  if (!config || !config.supportsSkills) continue;
1436
1443
 
1437
1444
  const displayName = getAgentDisplayName(tool);
1438
- const usingMarketplace = isMarketplace && tool === 'claude-code';
1445
+ const usingMarketplace = (hasMarketplaceSkills || isMarketplaceInManifest) && tool === 'claude-code';
1439
1446
 
1440
1447
  if (usingMarketplace) {
1441
1448
  parts.push(chalk.green(`${displayName} ✓`));
@@ -44,6 +44,7 @@ import {
44
44
  writeIntegrationFile,
45
45
  getToolFilePath
46
46
  } from '../utils/integration-generator.js';
47
+ import { getMarketplaceSkillsInfo } from '../utils/github.js';
47
48
  import { t } from '../i18n/messages.js';
48
49
  import { regenerateIntegrations } from './update.js';
49
50
 
@@ -562,8 +563,21 @@ async function handleSkillsConfiguration(manifest, projectPath, msg, common, spe
562
563
  return;
563
564
  }
564
565
 
566
+ // Get declined skills from manifest
567
+ const declinedSkills = manifest.declinedFeatures?.skills || [];
568
+
569
+ // Check if Skills are installed via marketplace (Claude Code only)
570
+ const marketplaceInfo = getMarketplaceSkillsInfo();
571
+ const hasMarketplaceSkills = marketplaceInfo?.installed;
572
+
565
573
  // Show current Skills status
566
574
  console.log(chalk.cyan(msg.currentSkillsStatus || 'Current Skills status:'));
575
+
576
+ // Show marketplace status if applicable
577
+ if (hasMarketplaceSkills && aiTools.includes('claude-code')) {
578
+ console.log(chalk.green(` ✓ ${msg.viaMarketplace || 'Via Marketplace'}: ${marketplaceInfo.version || 'installed'}`));
579
+ }
580
+
567
581
  for (const tool of aiTools) {
568
582
  const config = getAgentConfig(tool);
569
583
  if (!config?.supportsSkills) continue;
@@ -580,23 +594,48 @@ async function handleSkillsConfiguration(manifest, projectPath, msg, common, spe
580
594
  if (projectInfo?.installed) {
581
595
  console.log(chalk.gray(` - Project: ${projectInfo.version || 'installed'}`));
582
596
  }
597
+ } else if (declinedSkills.includes(tool)) {
598
+ console.log(chalk.yellow(` ⊘ ${displayName}: ${msg.previouslyDeclined || 'Previously declined'}`));
599
+ } else if (hasMarketplaceSkills && tool === 'claude-code') {
600
+ // Claude Code has marketplace skills but no file-based installation
601
+ console.log(chalk.cyan(` ◎ ${displayName}: ${msg.marketplaceOnly || 'Marketplace only (no local files)'}`));
583
602
  } else {
584
603
  console.log(chalk.gray(` ○ ${displayName}: ${msg.notInstalled || 'Not installed'}`));
585
604
  }
586
605
  }
606
+
607
+ // Show marketplace coexistence note if user might want to install local files
608
+ if (hasMarketplaceSkills && aiTools.includes('claude-code')) {
609
+ console.log();
610
+ console.log(chalk.cyan(` ℹ ${msg.marketplaceCoexistNote || 'Note: File-based installation will coexist with Marketplace version'}`));
611
+ }
587
612
  console.log();
588
613
 
614
+ // Build menu choices
615
+ const menuChoices = [
616
+ { name: msg.installSkills || 'Install/Update Skills', value: 'install' }
617
+ ];
618
+
619
+ // Add reinstall declined option if there are declined skills
620
+ if (declinedSkills.length > 0) {
621
+ menuChoices.push({
622
+ name: msg.reinstallDeclinedSkills || 'Reinstall declined Skills',
623
+ value: 'reinstall_declined'
624
+ });
625
+ }
626
+
627
+ menuChoices.push(
628
+ { name: msg.viewStatus || 'View status only', value: 'view' },
629
+ { name: common.cancel || 'Cancel', value: 'cancel' }
630
+ );
631
+
589
632
  // Ask what action to take
590
633
  const { action } = await inquirer.default.prompt([
591
634
  {
592
635
  type: 'list',
593
636
  name: 'action',
594
637
  message: msg.skillsAction || 'What would you like to do?',
595
- choices: [
596
- { name: msg.installSkills || 'Install/Update Skills', value: 'install' },
597
- { name: msg.viewStatus || 'View status only', value: 'view' },
598
- { name: common.cancel || 'Cancel', value: 'cancel' }
599
- ]
638
+ choices: menuChoices
600
639
  }
601
640
  ]);
602
641
 
@@ -605,6 +644,63 @@ async function handleSkillsConfiguration(manifest, projectPath, msg, common, spe
605
644
  return;
606
645
  }
607
646
 
647
+ // Handle reinstall declined action
648
+ if (action === 'reinstall_declined') {
649
+ // Get only the declined tools that support skills
650
+ const declinedToolsWithSupport = declinedSkills.filter(tool => {
651
+ const config = getAgentConfig(tool);
652
+ return config?.supportsSkills;
653
+ });
654
+
655
+ if (declinedToolsWithSupport.length === 0) {
656
+ console.log(chalk.gray(msg.noChanges || 'No changes made'));
657
+ return;
658
+ }
659
+
660
+ // Prompt for installation level
661
+ const { skillsLevel } = await inquirer.default.prompt([{
662
+ type: 'list',
663
+ name: 'skillsLevel',
664
+ message: msg.skillsLevelQuestion || 'Where should Skills be installed?',
665
+ choices: [
666
+ { name: `${msg.projectLevel || 'Project level'} (.claude/skills/, etc.)`, value: 'project' },
667
+ { name: `${msg.userLevel || 'User level'} (~/.claude/skills/, etc.)`, value: 'user' }
668
+ ],
669
+ default: 'project'
670
+ }]);
671
+
672
+ const installations = declinedToolsWithSupport.map(agent => ({
673
+ agent,
674
+ location: skillsLevel
675
+ }));
676
+
677
+ // Install Skills
678
+ const spinner = ora(msg.installingSkills || 'Installing Skills...').start();
679
+ const result = await installSkillsToMultipleAgents(installations, null, projectPath);
680
+ spinner.stop();
681
+
682
+ if (result.success) {
683
+ console.log(chalk.green(msg.skillsInstallSuccess || 'Skills installed successfully'));
684
+ console.log(chalk.gray(` ${msg.totalInstalled || 'Total installed'}: ${result.totalInstalled}`));
685
+ } else {
686
+ console.log(chalk.yellow(msg.skillsInstallPartial || 'Skills installed with some issues'));
687
+ if (result.totalErrors > 0) {
688
+ console.log(chalk.red(` ${msg.errors || 'Errors'}: ${result.totalErrors}`));
689
+ }
690
+ }
691
+
692
+ // Update manifest - clear declined status for installed tools
693
+ manifest.skills = manifest.skills || {};
694
+ manifest.skills.installations = installations;
695
+ if (manifest.declinedFeatures?.skills) {
696
+ manifest.declinedFeatures.skills = manifest.declinedFeatures.skills.filter(
697
+ tool => !declinedToolsWithSupport.includes(tool)
698
+ );
699
+ }
700
+ writeManifest(manifest, projectPath);
701
+ return;
702
+ }
703
+
608
704
  // Use unified installation prompt
609
705
  const installations = await promptSkillsInstallLocation(aiTools);
610
706
  if (installations.length === 0) {
@@ -692,6 +788,9 @@ async function handleCommandsConfiguration(manifest, projectPath, msg, common, s
692
788
  return;
693
789
  }
694
790
 
791
+ // Get declined commands from manifest
792
+ const declinedCommands = manifest.declinedFeatures?.commands || [];
793
+
695
794
  // Show current Commands status
696
795
  console.log(chalk.cyan(msg.currentCommandsStatus || 'Current Commands status:'));
697
796
  for (const tool of commandSupportedTools) {
@@ -700,23 +799,42 @@ async function handleCommandsConfiguration(manifest, projectPath, msg, common, s
700
799
 
701
800
  if (commandsInfo?.installed) {
702
801
  console.log(chalk.green(` ✓ ${displayName}: ${commandsInfo.count} ${msg.commandsInstalled || 'commands'}`));
802
+ } else if (declinedCommands.includes(tool)) {
803
+ console.log(chalk.yellow(` ⊘ ${displayName}: ${msg.previouslyDeclined || 'Previously declined'}`));
703
804
  } else {
704
805
  console.log(chalk.gray(` ○ ${displayName}: ${msg.notInstalled || 'Not installed'}`));
705
806
  }
706
807
  }
707
808
  console.log();
708
809
 
810
+ // Build menu choices
811
+ const menuChoices = [
812
+ { name: msg.installCommands || 'Install/Update Commands', value: 'install' }
813
+ ];
814
+
815
+ // Add reinstall declined option if there are declined commands
816
+ const declinedCommandsWithSupport = declinedCommands.filter(tool =>
817
+ commandSupportedTools.includes(tool)
818
+ );
819
+ if (declinedCommandsWithSupport.length > 0) {
820
+ menuChoices.push({
821
+ name: msg.reinstallDeclinedCommands || 'Reinstall declined Commands',
822
+ value: 'reinstall_declined'
823
+ });
824
+ }
825
+
826
+ menuChoices.push(
827
+ { name: msg.viewStatus || 'View status only', value: 'view' },
828
+ { name: common.cancel || 'Cancel', value: 'cancel' }
829
+ );
830
+
709
831
  // Ask what action to take
710
832
  const { action } = await inquirer.default.prompt([
711
833
  {
712
834
  type: 'list',
713
835
  name: 'action',
714
836
  message: msg.commandsAction || 'What would you like to do?',
715
- choices: [
716
- { name: msg.installCommands || 'Install/Update Commands', value: 'install' },
717
- { name: msg.viewStatus || 'View status only', value: 'view' },
718
- { name: common.cancel || 'Cancel', value: 'cancel' }
719
- ]
837
+ choices: menuChoices
720
838
  }
721
839
  ]);
722
840
 
@@ -725,6 +843,40 @@ async function handleCommandsConfiguration(manifest, projectPath, msg, common, s
725
843
  return;
726
844
  }
727
845
 
846
+ // Handle reinstall declined action
847
+ if (action === 'reinstall_declined') {
848
+ if (declinedCommandsWithSupport.length === 0) {
849
+ console.log(chalk.gray(msg.noChanges || 'No changes made'));
850
+ return;
851
+ }
852
+
853
+ // Install Commands
854
+ const spinner = ora(msg.installingCommands || 'Installing Commands...').start();
855
+ const result = await installCommandsToMultipleAgents(declinedCommandsWithSupport, null, projectPath);
856
+ spinner.stop();
857
+
858
+ if (result.success) {
859
+ console.log(chalk.green(msg.commandsInstallSuccess || 'Commands installed successfully'));
860
+ console.log(chalk.gray(` ${msg.totalInstalled || 'Total installed'}: ${result.totalInstalled}`));
861
+ } else {
862
+ console.log(chalk.yellow(msg.commandsInstallPartial || 'Commands installed with some issues'));
863
+ if (result.totalErrors > 0) {
864
+ console.log(chalk.red(` ${msg.errors || 'Errors'}: ${result.totalErrors}`));
865
+ }
866
+ }
867
+
868
+ // Update manifest - clear declined status for installed tools
869
+ manifest.commands = manifest.commands || {};
870
+ manifest.commands.installations = declinedCommandsWithSupport;
871
+ if (manifest.declinedFeatures?.commands) {
872
+ manifest.declinedFeatures.commands = manifest.declinedFeatures.commands.filter(
873
+ tool => !declinedCommandsWithSupport.includes(tool)
874
+ );
875
+ }
876
+ writeManifest(manifest, projectPath);
877
+ return;
878
+ }
879
+
728
880
  // Use unified installation prompt
729
881
  const selectedAgents = await promptCommandsInstallation(commandSupportedTools);
730
882
  if (selectedAgents.length === 0) {
@@ -30,6 +30,7 @@ import {
30
30
  getSkillsDirForAgent,
31
31
  getCommandsDirForAgent
32
32
  } from '../config/ai-agent-paths.js';
33
+ import { getMarketplaceSkillsInfo } from '../utils/github.js';
33
34
 
34
35
  /**
35
36
  * Compare two semantic versions
@@ -422,7 +423,7 @@ export async function updateCommand(options) {
422
423
  if (missingSkills.length > 0 || outdatedSkills.length > 0 || missingCommands.length > 0) {
423
424
  if (!options.yes) {
424
425
  // Interactive mode: prompt user to install/update
425
- const { installSkills, updateSkills, installCommands } = await promptNewFeatureInstallation(
426
+ const { installSkills, updateSkills, installCommands, declinedSkills, declinedCommands } = await promptNewFeatureInstallation(
426
427
  missingSkills,
427
428
  outdatedSkills,
428
429
  missingCommands
@@ -509,8 +510,39 @@ export async function updateCommand(options) {
509
510
  }
510
511
  }
511
512
 
512
- // Write updated manifest if anything was installed or updated
513
- if (installSkills.length > 0 || updateSkills.length > 0 || installCommands.length > 0) {
513
+ // Update declined features in manifest
514
+ if (declinedSkills.length > 0 || declinedCommands.length > 0) {
515
+ if (!manifest.declinedFeatures) manifest.declinedFeatures = {};
516
+
517
+ // Merge with existing declined items (avoid duplicates)
518
+ if (declinedSkills.length > 0) {
519
+ const existing = manifest.declinedFeatures.skills || [];
520
+ manifest.declinedFeatures.skills = [...new Set([...existing, ...declinedSkills])];
521
+ }
522
+
523
+ if (declinedCommands.length > 0) {
524
+ const existing = manifest.declinedFeatures.commands || [];
525
+ manifest.declinedFeatures.commands = [...new Set([...existing, ...declinedCommands])];
526
+ }
527
+ }
528
+
529
+ // Remove from declined list if user decided to install this time
530
+ if (installSkills.length > 0 && manifest.declinedFeatures?.skills) {
531
+ const installedAgents = installSkills.map(s => s.agent);
532
+ manifest.declinedFeatures.skills = manifest.declinedFeatures.skills.filter(
533
+ agent => !installedAgents.includes(agent)
534
+ );
535
+ }
536
+ if (installCommands.length > 0 && manifest.declinedFeatures?.commands) {
537
+ manifest.declinedFeatures.commands = manifest.declinedFeatures.commands.filter(
538
+ agent => !installCommands.includes(agent)
539
+ );
540
+ }
541
+
542
+ // Write updated manifest if anything was installed, updated, or declined
543
+ const hasChanges = installSkills.length > 0 || updateSkills.length > 0 ||
544
+ installCommands.length > 0 || declinedSkills.length > 0 || declinedCommands.length > 0;
545
+ if (hasChanges) {
514
546
  writeManifest(manifest, projectPath);
515
547
  }
516
548
  } else {
@@ -1035,6 +1067,10 @@ function checkNewFeatures(projectPath, manifest, latestSkillsVersion) {
1035
1067
  return { missingSkills: [], outdatedSkills: [], missingCommands: [] };
1036
1068
  }
1037
1069
 
1070
+ // Get declined features from manifest (to exclude from prompts)
1071
+ const declinedSkills = manifest.declinedFeatures?.skills || [];
1072
+ const declinedCommands = manifest.declinedFeatures?.commands || [];
1073
+
1038
1074
  const missingSkills = [];
1039
1075
  const outdatedSkills = [];
1040
1076
  const missingCommands = [];
@@ -1056,7 +1092,8 @@ function checkNewFeatures(projectPath, manifest, latestSkillsVersion) {
1056
1092
  // (manifest records can be stale if user deleted the directory)
1057
1093
  const hasSkills = projectInfo?.installed || userInfo?.installed || usingMarketplace;
1058
1094
 
1059
- if (!hasSkills) {
1095
+ // Skip if user previously declined this tool's skills
1096
+ if (!hasSkills && !declinedSkills.includes(tool)) {
1060
1097
  missingSkills.push({
1061
1098
  agent: tool,
1062
1099
  displayName: getAgentDisplayName(tool),
@@ -1089,7 +1126,8 @@ function checkNewFeatures(projectPath, manifest, latestSkillsVersion) {
1089
1126
  // Only trust actual file existence, not manifest records
1090
1127
  const hasCommands = cmdInfo?.installed;
1091
1128
 
1092
- if (!hasCommands) {
1129
+ // Skip if user previously declined this tool's commands
1130
+ if (!hasCommands && !declinedCommands.includes(tool)) {
1093
1131
  missingCommands.push({
1094
1132
  agent: tool,
1095
1133
  displayName: getAgentDisplayName(tool),
@@ -1107,14 +1145,14 @@ function checkNewFeatures(projectPath, manifest, latestSkillsVersion) {
1107
1145
  * @param {Array} missingSkills - Array of {agent, displayName, paths}
1108
1146
  * @param {Array} outdatedSkills - Array of {agent, displayName, paths, currentVersion, latestVersion, level, path}
1109
1147
  * @param {Array} missingCommands - Array of {agent, displayName, path}
1110
- * @returns {Promise<{installSkills: Array, updateSkills: Array, installCommands: Array}>}
1148
+ * @returns {Promise<{installSkills: Array, updateSkills: Array, installCommands: Array, declinedSkills: Array, declinedCommands: Array}>}
1111
1149
  */
1112
1150
  async function promptNewFeatureInstallation(missingSkills, outdatedSkills, missingCommands) {
1113
1151
  const msg = t().commands.update;
1114
1152
 
1115
1153
  // If nothing to do, return empty
1116
1154
  if (missingSkills.length === 0 && outdatedSkills.length === 0 && missingCommands.length === 0) {
1117
- return { installSkills: [], updateSkills: [], installCommands: [] };
1155
+ return { installSkills: [], updateSkills: [], installCommands: [], declinedSkills: [], declinedCommands: [] };
1118
1156
  }
1119
1157
 
1120
1158
  console.log();
@@ -1123,22 +1161,42 @@ async function promptNewFeatureInstallation(missingSkills, outdatedSkills, missi
1123
1161
  console.log(chalk.cyan('━'.repeat(50)));
1124
1162
  console.log();
1125
1163
 
1126
- const result = { installSkills: [], updateSkills: [], installCommands: [] };
1164
+ const result = { installSkills: [], updateSkills: [], installCommands: [], declinedSkills: [], declinedCommands: [] };
1127
1165
 
1128
1166
  // Handle missing Skills with checkbox selection
1129
1167
  if (missingSkills.length > 0) {
1168
+ // Check if Skills are already installed via marketplace (Claude Code only)
1169
+ const marketplaceInfo = getMarketplaceSkillsInfo();
1170
+ const hasMarketplaceSkills = marketplaceInfo?.installed;
1171
+
1130
1172
  console.log(chalk.yellow(msg.skillsNotInstalledFor || 'Skills not yet installed for these AI tools:'));
1131
1173
  for (const skill of missingSkills) {
1132
- console.log(chalk.gray(` • ${skill.displayName}`));
1174
+ // Show marketplace hint for Claude Code if applicable
1175
+ if (hasMarketplaceSkills && skill.agent === 'claude-code') {
1176
+ console.log(chalk.gray(` • ${skill.displayName} ${chalk.cyan(`(${msg.alreadyViaMarketplace || 'already via Marketplace'})`)}`));
1177
+ } else {
1178
+ console.log(chalk.gray(` • ${skill.displayName}`));
1179
+ }
1180
+ }
1181
+
1182
+ // Show marketplace coexistence warning if applicable
1183
+ if (hasMarketplaceSkills && missingSkills.some(s => s.agent === 'claude-code')) {
1184
+ console.log();
1185
+ console.log(chalk.cyan(` ℹ ${msg.marketplaceCoexistNote || 'Note: File-based installation will coexist with Marketplace version'}`));
1133
1186
  }
1134
1187
  console.log();
1135
1188
 
1136
1189
  // Build checkbox choices
1137
- const skillChoices = missingSkills.map(skill => ({
1138
- name: skill.displayName,
1139
- value: skill.agent,
1140
- checked: true // Default checked for opt-out behavior
1141
- }));
1190
+ const skillChoices = missingSkills.map(skill => {
1191
+ const isClaudeWithMarketplace = hasMarketplaceSkills && skill.agent === 'claude-code';
1192
+ return {
1193
+ name: isClaudeWithMarketplace
1194
+ ? `${skill.displayName} ${chalk.cyan(`(${msg.alreadyViaMarketplace || 'already via Marketplace'})`)}`
1195
+ : skill.displayName,
1196
+ value: skill.agent,
1197
+ checked: !isClaudeWithMarketplace // Default unchecked if already via marketplace
1198
+ };
1199
+ });
1142
1200
 
1143
1201
  // Add skip option
1144
1202
  skillChoices.push(new inquirer.Separator());
@@ -1164,6 +1222,12 @@ async function promptNewFeatureInstallation(missingSkills, outdatedSkills, missi
1164
1222
  // Filter out skip and handle selection
1165
1223
  const filteredSkillAgents = selectedSkillAgents.filter(a => a !== '__skip__');
1166
1224
 
1225
+ // Track declined skills (user explicitly skipped or deselected)
1226
+ const skippedSkillAgents = missingSkills
1227
+ .map(s => s.agent)
1228
+ .filter(agent => !filteredSkillAgents.includes(agent));
1229
+ result.declinedSkills = skippedSkillAgents;
1230
+
1167
1231
  if (filteredSkillAgents.length > 0) {
1168
1232
  // Prompt for installation level
1169
1233
  const { skillsLevel } = await inquirer.prompt([{
@@ -1279,7 +1343,14 @@ async function promptNewFeatureInstallation(missingSkills, outdatedSkills, missi
1279
1343
  }]);
1280
1344
 
1281
1345
  // Filter out skip
1282
- result.installCommands = selectedCommandAgents.filter(a => a !== '__skip__');
1346
+ const filteredCommandAgents = selectedCommandAgents.filter(a => a !== '__skip__');
1347
+ result.installCommands = filteredCommandAgents;
1348
+
1349
+ // Track declined commands (user explicitly skipped or deselected)
1350
+ const skippedCommandAgents = missingCommands
1351
+ .map(c => c.agent)
1352
+ .filter(agent => !filteredCommandAgents.includes(agent));
1353
+ result.declinedCommands = skippedCommandAgents;
1283
1354
  }
1284
1355
 
1285
1356
  return result;
@@ -786,7 +786,10 @@ export const messages = {
786
786
  newSkillsInstalled: 'Installed Skills for {count} AI tools',
787
787
  newSkillsInstalledWithErrors: 'Installed Skills with {errors} errors',
788
788
  newCommandsInstalled: 'Installed commands for {count} AI tools',
789
- newCommandsInstalledWithErrors: 'Installed commands with {errors} errors'
789
+ newCommandsInstalledWithErrors: 'Installed commands with {errors} errors',
790
+ // Marketplace detection
791
+ alreadyViaMarketplace: 'already via Marketplace',
792
+ marketplaceCoexistNote: 'Note: File-based installation will coexist with Marketplace version'
790
793
  },
791
794
 
792
795
  // configure command
@@ -859,7 +862,18 @@ export const messages = {
859
862
  applyChangesNow: 'Apply changes now? (regenerate integration files)',
860
863
  runUpdateLater: 'Run `uds update --integrations-only` later to apply changes',
861
864
  applyingChanges: 'Applying changes...',
862
- changesApplied: 'Changes applied successfully'
865
+ changesApplied: 'Changes applied successfully',
866
+ // Declined features
867
+ previouslyDeclined: 'Previously declined',
868
+ reinstallDeclinedSkills: 'Reinstall declined Skills',
869
+ reinstallDeclinedCommands: 'Reinstall declined Commands',
870
+ skillsLevelQuestion: 'Where should Skills be installed?',
871
+ projectLevel: 'Project level',
872
+ userLevel: 'User level',
873
+ // Marketplace detection
874
+ viaMarketplace: 'Via Marketplace',
875
+ marketplaceOnly: 'Marketplace only (no local files)',
876
+ marketplaceCoexistNote: 'Note: File-based installation will coexist with Marketplace version'
863
877
  }
864
878
  }
865
879
  },
@@ -1642,7 +1656,10 @@ export const messages = {
1642
1656
  newSkillsInstalled: '已為 {count} 個 AI 工具安裝 Skills',
1643
1657
  newSkillsInstalledWithErrors: '安裝 Skills 時發生 {errors} 個錯誤',
1644
1658
  newCommandsInstalled: '已為 {count} 個 AI 工具安裝斜線命令',
1645
- newCommandsInstalledWithErrors: '安裝斜線命令時發生 {errors} 個錯誤'
1659
+ newCommandsInstalledWithErrors: '安裝斜線命令時發生 {errors} 個錯誤',
1660
+ // Marketplace detection
1661
+ alreadyViaMarketplace: '已透過 Marketplace 安裝',
1662
+ marketplaceCoexistNote: '注意:檔案安裝將與 Marketplace 版本並存'
1646
1663
  },
1647
1664
 
1648
1665
  // configure command
@@ -1715,7 +1732,18 @@ export const messages = {
1715
1732
  applyChangesNow: '是否立即套用變更?(重新產生整合檔案)',
1716
1733
  runUpdateLater: '稍後執行 `uds update --integrations-only` 以套用變更',
1717
1734
  applyingChanges: '正在套用變更...',
1718
- changesApplied: '變更套用成功'
1735
+ changesApplied: '變更套用成功',
1736
+ // Declined features
1737
+ previouslyDeclined: '先前已拒絕',
1738
+ reinstallDeclinedSkills: '重新安裝已拒絕的 Skills',
1739
+ reinstallDeclinedCommands: '重新安裝已拒絕的斜線命令',
1740
+ skillsLevelQuestion: 'Skills 要安裝到哪裡?',
1741
+ projectLevel: '專案層級',
1742
+ userLevel: '使用者層級',
1743
+ // Marketplace detection
1744
+ viaMarketplace: '透過 Marketplace',
1745
+ marketplaceOnly: '僅 Marketplace(無本機檔案)',
1746
+ marketplaceCoexistNote: '注意:檔案安裝將與 Marketplace 版本並存'
1719
1747
  }
1720
1748
  }
1721
1749
  },
@@ -2330,7 +2358,10 @@ export const messages = {
2330
2358
  newSkillsInstalled: '已为 {count} 个 AI 工具安装 Skills',
2331
2359
  newSkillsInstalledWithErrors: '安装 Skills 时发生 {errors} 个错误',
2332
2360
  newCommandsInstalled: '已为 {count} 个 AI 工具安装斜线命令',
2333
- newCommandsInstalledWithErrors: '安装斜线命令时发生 {errors} 个错误'
2361
+ newCommandsInstalledWithErrors: '安装斜线命令时发生 {errors} 个错误',
2362
+ // Marketplace detection
2363
+ alreadyViaMarketplace: '已通过 Marketplace 安装',
2364
+ marketplaceCoexistNote: '注意:文件安装将与 Marketplace 版本并存'
2334
2365
  },
2335
2366
 
2336
2367
  // configure command
@@ -2403,7 +2434,18 @@ export const messages = {
2403
2434
  applyChangesNow: '是否立即应用变更?(重新生成集成文件)',
2404
2435
  runUpdateLater: '稍后执行 `uds update --integrations-only` 以应用变更',
2405
2436
  applyingChanges: '正在应用变更...',
2406
- changesApplied: '变更应用成功'
2437
+ changesApplied: '变更应用成功',
2438
+ // Declined features
2439
+ previouslyDeclined: '之前已拒绝',
2440
+ reinstallDeclinedSkills: '重新安装已拒绝的 Skills',
2441
+ reinstallDeclinedCommands: '重新安装已拒绝的斜杠命令',
2442
+ skillsLevelQuestion: 'Skills 要安装到哪里?',
2443
+ projectLevel: '项目级别',
2444
+ userLevel: '用户级别',
2445
+ // Marketplace detection
2446
+ viaMarketplace: '通过 Marketplace',
2447
+ marketplaceOnly: '仅 Marketplace(无本地文件)',
2448
+ marketplaceCoexistNote: '注意:文件安装将与 Marketplace 版本并存'
2407
2449
  }
2408
2450
  }
2409
2451
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "version": "3.5.1-beta.17",
4
- "lastUpdated": "2026-01-15",
3
+ "version": "3.5.1-beta.18",
4
+ "lastUpdated": "2026-01-19",
5
5
  "description": "Standards registry for universal-dev-standards with integrated skills and AI-optimized formats",
6
6
  "formats": {
7
7
  "ai": {
@@ -48,14 +48,14 @@
48
48
  "standards": {
49
49
  "name": "universal-dev-standards",
50
50
  "url": "https://github.com/AsiaOstrich/universal-dev-standards",
51
- "version": "3.5.1-beta.17"
51
+ "version": "3.5.1-beta.18"
52
52
  },
53
53
  "skills": {
54
54
  "name": "universal-dev-standards",
55
55
  "url": "https://github.com/AsiaOstrich/universal-dev-standards",
56
56
  "localPath": "skills/claude-code",
57
57
  "rawUrl": "https://raw.githubusercontent.com/AsiaOstrich/universal-dev-standards/main/skills/claude-code",
58
- "version": "3.5.1-beta.17",
58
+ "version": "3.5.1-beta.18",
59
59
  "note": "Skills are now included in the main repository under skills/"
60
60
  }
61
61
  },