universal-dev-standards 3.5.1-beta.3 → 3.5.1-beta.5
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 +1 -1
- package/src/commands/update.js +228 -0
- package/src/i18n/messages.js +51 -3
- package/standards-registry.json +3 -3
package/package.json
CHANGED
package/src/commands/update.js
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from '../utils/skills-installer.js';
|
|
27
27
|
import {
|
|
28
28
|
getAgentDisplayName,
|
|
29
|
+
getAgentConfig,
|
|
29
30
|
getSkillsDirForAgent,
|
|
30
31
|
getCommandsDirForAgent
|
|
31
32
|
} from '../config/ai-agent-paths.js';
|
|
@@ -404,6 +405,83 @@ export async function updateCommand(options) {
|
|
|
404
405
|
}
|
|
405
406
|
}
|
|
406
407
|
|
|
408
|
+
// Check for new features (Skills/Commands) not yet installed
|
|
409
|
+
if (!options.standardsOnly) {
|
|
410
|
+
const { missingSkills, missingCommands } = checkNewFeatures(projectPath, manifest);
|
|
411
|
+
|
|
412
|
+
if (missingSkills.length > 0 || missingCommands.length > 0) {
|
|
413
|
+
if (!options.yes) {
|
|
414
|
+
// Interactive mode: prompt user to install
|
|
415
|
+
const { installSkills, installCommands } = await promptNewFeatureInstallation(
|
|
416
|
+
missingSkills,
|
|
417
|
+
missingCommands
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
// Install Skills if user agreed
|
|
421
|
+
if (installSkills.length > 0) {
|
|
422
|
+
const skillSpinner = ora(msg.installingNewSkills || 'Installing Skills...').start();
|
|
423
|
+
const skillResult = await installSkillsToMultipleAgents(installSkills, null, projectPath);
|
|
424
|
+
|
|
425
|
+
// Update manifest
|
|
426
|
+
if (!manifest.skills) manifest.skills = {};
|
|
427
|
+
manifest.skills.installed = true;
|
|
428
|
+
manifest.skills.version = repoInfo.skills.version;
|
|
429
|
+
manifest.skills.installations = [
|
|
430
|
+
...(manifest.skills.installations || []),
|
|
431
|
+
...installSkills
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
if (skillResult.totalErrors === 0) {
|
|
435
|
+
skillSpinner.succeed((msg.newSkillsInstalled || 'Installed Skills for {count} AI tools')
|
|
436
|
+
.replace('{count}', installSkills.length));
|
|
437
|
+
} else {
|
|
438
|
+
skillSpinner.warn((msg.newSkillsInstalledWithErrors || 'Installed Skills with {errors} errors')
|
|
439
|
+
.replace('{errors}', skillResult.totalErrors));
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Install Commands if user agreed
|
|
444
|
+
if (installCommands.length > 0) {
|
|
445
|
+
const cmdSpinner = ora(msg.installingNewCommands || 'Installing commands...').start();
|
|
446
|
+
const cmdResult = await installCommandsToMultipleAgents(installCommands, null, projectPath);
|
|
447
|
+
|
|
448
|
+
// Update manifest
|
|
449
|
+
if (!manifest.commands) manifest.commands = {};
|
|
450
|
+
manifest.commands.installed = true;
|
|
451
|
+
manifest.commands.installations = [
|
|
452
|
+
...(manifest.commands.installations || []),
|
|
453
|
+
...installCommands
|
|
454
|
+
];
|
|
455
|
+
|
|
456
|
+
if (cmdResult.totalErrors === 0) {
|
|
457
|
+
cmdSpinner.succeed((msg.newCommandsInstalled || 'Installed commands for {count} AI tools')
|
|
458
|
+
.replace('{count}', installCommands.length));
|
|
459
|
+
} else {
|
|
460
|
+
cmdSpinner.warn((msg.newCommandsInstalledWithErrors || 'Installed commands with {errors} errors')
|
|
461
|
+
.replace('{errors}', cmdResult.totalErrors));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Write updated manifest if anything was installed
|
|
466
|
+
if (installSkills.length > 0 || installCommands.length > 0) {
|
|
467
|
+
writeManifest(manifest, projectPath);
|
|
468
|
+
}
|
|
469
|
+
} else {
|
|
470
|
+
// --yes mode: show hint but don't auto-install (conservative behavior)
|
|
471
|
+
console.log();
|
|
472
|
+
console.log(chalk.cyan(msg.newFeaturesAvailableHint || 'Note: New features available for your AI tools'));
|
|
473
|
+
if (missingSkills.length > 0) {
|
|
474
|
+
const toolNames = missingSkills.map(s => s.displayName).join(', ');
|
|
475
|
+
console.log(chalk.gray(` • Skills (${toolNames}): run "uds update --skills" or "uds init" to install`));
|
|
476
|
+
}
|
|
477
|
+
if (missingCommands.length > 0) {
|
|
478
|
+
const toolNames = missingCommands.map(c => c.displayName).join(', ');
|
|
479
|
+
console.log(chalk.gray(` • Commands (${toolNames}): run "uds update --commands" or "uds init" to install`));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
407
485
|
// Skills update reminder
|
|
408
486
|
if (manifest.skills?.installed) {
|
|
409
487
|
const skillsVersion = repoInfo.skills.version;
|
|
@@ -835,3 +913,153 @@ async function updateCommandsOnly(projectPath, manifest) {
|
|
|
835
913
|
console.log();
|
|
836
914
|
process.exit(0);
|
|
837
915
|
}
|
|
916
|
+
|
|
917
|
+
/**
|
|
918
|
+
* Check manifest.aiTools and detect missing Skills/Commands
|
|
919
|
+
* @param {string} projectPath - Project path
|
|
920
|
+
* @param {Object} manifest - Manifest object
|
|
921
|
+
* @returns {{missingSkills: Array, missingCommands: Array}}
|
|
922
|
+
*/
|
|
923
|
+
function checkNewFeatures(projectPath, manifest) {
|
|
924
|
+
const aiTools = manifest.aiTools || [];
|
|
925
|
+
|
|
926
|
+
if (aiTools.length === 0) {
|
|
927
|
+
return { missingSkills: [], missingCommands: [] };
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const missingSkills = [];
|
|
931
|
+
const missingCommands = [];
|
|
932
|
+
|
|
933
|
+
for (const tool of aiTools) {
|
|
934
|
+
const config = getAgentConfig(tool);
|
|
935
|
+
if (!config) continue;
|
|
936
|
+
|
|
937
|
+
// Check Skills support
|
|
938
|
+
if (config.supportsSkills && config.skills) {
|
|
939
|
+
// Check if skills are installed for this agent
|
|
940
|
+
const projectInfo = getInstalledSkillsInfoForAgent(tool, 'project', projectPath);
|
|
941
|
+
const userInfo = getInstalledSkillsInfoForAgent(tool, 'user');
|
|
942
|
+
|
|
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)
|
|
950
|
+
const usingMarketplace = manifest.skills?.location === 'marketplace' && tool === 'claude-code';
|
|
951
|
+
|
|
952
|
+
const hasSkills = projectInfo?.installed || userInfo?.installed || isInManifest || usingMarketplace;
|
|
953
|
+
|
|
954
|
+
if (!hasSkills) {
|
|
955
|
+
missingSkills.push({
|
|
956
|
+
agent: tool,
|
|
957
|
+
displayName: getAgentDisplayName(tool),
|
|
958
|
+
paths: config.skills
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// Check Commands support
|
|
964
|
+
if (config.commands !== null && config.commands) {
|
|
965
|
+
const cmdInfo = getInstalledCommandsForAgent(tool, projectPath);
|
|
966
|
+
|
|
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;
|
|
972
|
+
|
|
973
|
+
if (!hasCommands) {
|
|
974
|
+
missingCommands.push({
|
|
975
|
+
agent: tool,
|
|
976
|
+
displayName: getAgentDisplayName(tool),
|
|
977
|
+
path: config.commands.project
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
return { missingSkills, missingCommands };
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Prompt user to install new features discovered during update
|
|
988
|
+
* @param {Array} missingSkills - Array of {agent, displayName, paths}
|
|
989
|
+
* @param {Array} missingCommands - Array of {agent, displayName, path}
|
|
990
|
+
* @returns {Promise<{installSkills: Array, installCommands: Array}>}
|
|
991
|
+
*/
|
|
992
|
+
async function promptNewFeatureInstallation(missingSkills, missingCommands) {
|
|
993
|
+
const msg = t().commands.update;
|
|
994
|
+
|
|
995
|
+
// If nothing missing, return empty
|
|
996
|
+
if (missingSkills.length === 0 && missingCommands.length === 0) {
|
|
997
|
+
return { installSkills: [], installCommands: [] };
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
console.log();
|
|
1001
|
+
console.log(chalk.cyan('━'.repeat(50)));
|
|
1002
|
+
console.log(chalk.cyan.bold(msg.newFeaturesAvailable || 'New Features Available'));
|
|
1003
|
+
console.log(chalk.cyan('━'.repeat(50)));
|
|
1004
|
+
console.log();
|
|
1005
|
+
|
|
1006
|
+
const result = { installSkills: [], installCommands: [] };
|
|
1007
|
+
|
|
1008
|
+
// Handle missing Skills
|
|
1009
|
+
if (missingSkills.length > 0) {
|
|
1010
|
+
console.log(chalk.yellow(msg.skillsNotInstalledFor || 'Skills not yet installed for these AI tools:'));
|
|
1011
|
+
for (const skill of missingSkills) {
|
|
1012
|
+
console.log(chalk.gray(` • ${skill.displayName}`));
|
|
1013
|
+
}
|
|
1014
|
+
console.log();
|
|
1015
|
+
|
|
1016
|
+
const { shouldInstallSkills } = await inquirer.prompt([{
|
|
1017
|
+
type: 'confirm',
|
|
1018
|
+
name: 'shouldInstallSkills',
|
|
1019
|
+
message: msg.installSkillsNow || 'Would you like to install Skills for these AI tools?',
|
|
1020
|
+
default: true
|
|
1021
|
+
}]);
|
|
1022
|
+
|
|
1023
|
+
if (shouldInstallSkills) {
|
|
1024
|
+
// Prompt for installation level
|
|
1025
|
+
const { skillsLevel } = await inquirer.prompt([{
|
|
1026
|
+
type: 'list',
|
|
1027
|
+
name: 'skillsLevel',
|
|
1028
|
+
message: msg.skillsLevelQuestion || 'Where should Skills be installed?',
|
|
1029
|
+
choices: [
|
|
1030
|
+
{ name: `${msg.projectLevel || 'Project level'} (.claude/skills/, etc.)`, value: 'project' },
|
|
1031
|
+
{ name: `${msg.userLevel || 'User level'} (~/.claude/skills/, etc.)`, value: 'user' }
|
|
1032
|
+
],
|
|
1033
|
+
default: 'project'
|
|
1034
|
+
}]);
|
|
1035
|
+
|
|
1036
|
+
result.installSkills = missingSkills.map(s => ({
|
|
1037
|
+
agent: s.agent,
|
|
1038
|
+
level: skillsLevel
|
|
1039
|
+
}));
|
|
1040
|
+
}
|
|
1041
|
+
console.log();
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// Handle missing Commands
|
|
1045
|
+
if (missingCommands.length > 0) {
|
|
1046
|
+
console.log(chalk.yellow(msg.commandsNotInstalledFor || 'Slash commands not yet installed for these AI tools:'));
|
|
1047
|
+
for (const cmd of missingCommands) {
|
|
1048
|
+
console.log(chalk.gray(` • ${cmd.displayName} → ${cmd.path}`));
|
|
1049
|
+
}
|
|
1050
|
+
console.log();
|
|
1051
|
+
|
|
1052
|
+
const { shouldInstallCommands } = await inquirer.prompt([{
|
|
1053
|
+
type: 'confirm',
|
|
1054
|
+
name: 'shouldInstallCommands',
|
|
1055
|
+
message: msg.installCommandsNow || 'Would you like to install slash commands for these AI tools?',
|
|
1056
|
+
default: true
|
|
1057
|
+
}]);
|
|
1058
|
+
|
|
1059
|
+
if (shouldInstallCommands) {
|
|
1060
|
+
result.installCommands = missingCommands.map(c => c.agent);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
return result;
|
|
1065
|
+
}
|
package/src/i18n/messages.js
CHANGED
|
@@ -744,7 +744,23 @@ export const messages = {
|
|
|
744
744
|
categoriesChanged: 'Categories: {old} → {new}',
|
|
745
745
|
failedToUpdate: '✗ Failed to update {path}: {error}',
|
|
746
746
|
updatedCount: '✓ Updated {count} integration file(s)',
|
|
747
|
-
skippedCount: 'Skipped {count} file(s) (already in sync or not found)'
|
|
747
|
+
skippedCount: 'Skipped {count} file(s) (already in sync or not found)',
|
|
748
|
+
// New features discovery
|
|
749
|
+
newFeaturesAvailable: 'New Features Available',
|
|
750
|
+
newFeaturesAvailableHint: 'Note: New features available for your AI tools',
|
|
751
|
+
skillsNotInstalledFor: 'Skills not yet installed for these AI tools:',
|
|
752
|
+
commandsNotInstalledFor: 'Slash commands not yet installed for these AI tools:',
|
|
753
|
+
installSkillsNow: 'Would you like to install Skills for these AI tools?',
|
|
754
|
+
installCommandsNow: 'Would you like to install slash commands for these AI tools?',
|
|
755
|
+
skillsLevelQuestion: 'Where should Skills be installed?',
|
|
756
|
+
projectLevel: 'Project level',
|
|
757
|
+
userLevel: 'User level',
|
|
758
|
+
installingNewSkills: 'Installing Skills...',
|
|
759
|
+
installingNewCommands: 'Installing commands...',
|
|
760
|
+
newSkillsInstalled: 'Installed Skills for {count} AI tools',
|
|
761
|
+
newSkillsInstalledWithErrors: 'Installed Skills with {errors} errors',
|
|
762
|
+
newCommandsInstalled: 'Installed commands for {count} AI tools',
|
|
763
|
+
newCommandsInstalledWithErrors: 'Installed commands with {errors} errors'
|
|
748
764
|
},
|
|
749
765
|
|
|
750
766
|
// configure command
|
|
@@ -1553,7 +1569,23 @@ export const messages = {
|
|
|
1553
1569
|
categoriesChanged: '分類:{old} → {new}',
|
|
1554
1570
|
failedToUpdate: '✗ 更新 {path} 失敗:{error}',
|
|
1555
1571
|
updatedCount: '✓ 已更新 {count} 個整合檔案',
|
|
1556
|
-
skippedCount: '已跳過 {count} 個檔案(已同步或找不到)'
|
|
1572
|
+
skippedCount: '已跳過 {count} 個檔案(已同步或找不到)',
|
|
1573
|
+
// New features discovery
|
|
1574
|
+
newFeaturesAvailable: '發現新功能',
|
|
1575
|
+
newFeaturesAvailableHint: '提示:您的 AI 工具有新功能可用',
|
|
1576
|
+
skillsNotInstalledFor: '以下 AI 工具尚未安裝 Skills:',
|
|
1577
|
+
commandsNotInstalledFor: '以下 AI 工具尚未安裝斜線命令:',
|
|
1578
|
+
installSkillsNow: '是否要為這些 AI 工具安裝 Skills?',
|
|
1579
|
+
installCommandsNow: '是否要為這些 AI 工具安裝斜線命令?',
|
|
1580
|
+
skillsLevelQuestion: 'Skills 要安裝到哪裡?',
|
|
1581
|
+
projectLevel: '專案層級',
|
|
1582
|
+
userLevel: '使用者層級',
|
|
1583
|
+
installingNewSkills: '安裝 Skills 中...',
|
|
1584
|
+
installingNewCommands: '安裝斜線命令中...',
|
|
1585
|
+
newSkillsInstalled: '已為 {count} 個 AI 工具安裝 Skills',
|
|
1586
|
+
newSkillsInstalledWithErrors: '安裝 Skills 時發生 {errors} 個錯誤',
|
|
1587
|
+
newCommandsInstalled: '已為 {count} 個 AI 工具安裝斜線命令',
|
|
1588
|
+
newCommandsInstalledWithErrors: '安裝斜線命令時發生 {errors} 個錯誤'
|
|
1557
1589
|
},
|
|
1558
1590
|
|
|
1559
1591
|
// configure command
|
|
@@ -2194,7 +2226,23 @@ export const messages = {
|
|
|
2194
2226
|
categoriesChanged: '类别:{old} → {new}',
|
|
2195
2227
|
failedToUpdate: '✗ 更新 {path} 失败:{error}',
|
|
2196
2228
|
updatedCount: '✓ 已更新 {count} 个集成文件',
|
|
2197
|
-
skippedCount: '跳过 {count} 个文件(已同步或未找到)'
|
|
2229
|
+
skippedCount: '跳过 {count} 个文件(已同步或未找到)',
|
|
2230
|
+
// New features discovery
|
|
2231
|
+
newFeaturesAvailable: '发现新功能',
|
|
2232
|
+
newFeaturesAvailableHint: '提示:您的 AI 工具有新功能可用',
|
|
2233
|
+
skillsNotInstalledFor: '以下 AI 工具尚未安装 Skills:',
|
|
2234
|
+
commandsNotInstalledFor: '以下 AI 工具尚未安装斜线命令:',
|
|
2235
|
+
installSkillsNow: '是否要为这些 AI 工具安装 Skills?',
|
|
2236
|
+
installCommandsNow: '是否要为这些 AI 工具安装斜线命令?',
|
|
2237
|
+
skillsLevelQuestion: 'Skills 要安装到哪里?',
|
|
2238
|
+
projectLevel: '项目级别',
|
|
2239
|
+
userLevel: '用户级别',
|
|
2240
|
+
installingNewSkills: '正在安装 Skills...',
|
|
2241
|
+
installingNewCommands: '正在安装斜线命令...',
|
|
2242
|
+
newSkillsInstalled: '已为 {count} 个 AI 工具安装 Skills',
|
|
2243
|
+
newSkillsInstalledWithErrors: '安装 Skills 时发生 {errors} 个错误',
|
|
2244
|
+
newCommandsInstalled: '已为 {count} 个 AI 工具安装斜线命令',
|
|
2245
|
+
newCommandsInstalledWithErrors: '安装斜线命令时发生 {errors} 个错误'
|
|
2198
2246
|
},
|
|
2199
2247
|
|
|
2200
2248
|
// configure command
|
package/standards-registry.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "3.5.1-beta.
|
|
3
|
+
"version": "3.5.1-beta.5",
|
|
4
4
|
"lastUpdated": "2026-01-15",
|
|
5
5
|
"description": "Standards registry for universal-dev-standards with integrated skills and AI-optimized formats",
|
|
6
6
|
"formats": {
|
|
@@ -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.
|
|
51
|
+
"version": "3.5.1-beta.5"
|
|
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.
|
|
58
|
+
"version": "3.5.1-beta.5",
|
|
59
59
|
"note": "Skills are now included in the main repository under skills/"
|
|
60
60
|
}
|
|
61
61
|
},
|