universal-dev-standards 6.7.3 → 6.7.4

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.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  source: ../../CHANGELOG.md
3
- source_version: 6.7.3
4
- translation_version: 6.7.3
3
+ source_version: 6.7.4
4
+ translation_version: 6.7.4
5
5
  last_synced: 2026-08-18
6
6
  status: current
7
7
  ---
@@ -17,6 +17,15 @@ status: current
17
17
 
18
18
  ## [Unreleased]
19
19
 
20
+ ## [6.7.4] - 2026-08-18
21
+
22
+ ### 修正
23
+
24
+ - **6.7.3 让 `uds check` 每个 repo 报出 52 个不存在的「缺失」文件。** 6.7.3 的两个改动要**同时在场**才会互相作用:R1 给了 skill 内容哈希,使它们第一次走进 `unchanged` 分支;而 R6b 会把那个分支的条目收进 `manifest.fileHashes`。那张表是用 `isFile()` 验证的,而 skill 是目录,于是每一个都被报成缺失。**没有任何东西被删除——错的是记录不是磁盘**(已验证:59 个 skill 目录与其内容完好)。`verifiedPristine` 现在限缩于文件类别;而且**修好写入端不会让已经写进去的东西消失**,所以 `uds update` 也会清掉 `fileHashes` 里的 `.claude/skills/` 与 `.claude/commands/` 键——**一个坏掉的键不会有第二次机会被访问**,因为磁盘上没有任何东西对应它。
25
+ - **commands 也改为内容比对(XSPEC-382 R7)。** R1 只涵盖 skills,把 commands 留在 `hash: null`,于是无条件重装的分支对它们仍然活着。与 skills 同一个形状:`resolveCommandContent(name, agent, locale)` 说明一次安装会包含什么(locale 选择+英文回退,加上逐 agent 的转换),安装器写它、计划器哈希它。
26
+ - **装了 locale 版的人,拿到的 SKILL.md 指向从来不会被安装的文件。** locale 包不是英文来源的完整副本——实测 **zh-TW 59 个中有 4 个、zh-CN 59 个中有 5 个**缺少英文有出货的文件——而安装器把 locale 目录整包换上去,于是那些伴随文件根本没被写入。其中两个缺口**是被引用的**:zh-TW 的 `dev-workflow-guide/SKILL.md` 引用 `workflow-phases.md` 三次、`testing-guide/SKILL.md` 引用 `test-skeleton-templates.md` 三次。**回退改为逐文件而非逐 skill**——locale 有就用 locale 的,没有就用英文的。
27
+ - **UDS 不出货的文件,不再让一个 skill 永远停在「已变更」。** 安装一个 skill 现在会移除其目录下**解析结果没有指名**的顶层文件(实地发现:`deploy-assistant/guide.md`,它不在任何 UDS skills 树里,而且从来就不在)。范围由同一个 provenance 判准界定,也就是让采用者自己的 skill 目录不进入此处任何路径的那一个——**已验证手写的 skill 目录与其额外文件在 `--force` 之后完好无损**——子目录一律不动,因为安装器从来没有写过它们。
28
+
20
29
  ## [6.7.3] - 2026-08-18
21
30
 
22
31
  ### 修正
@@ -15,7 +15,7 @@ status: current
15
15
 
16
16
  > **语言**: [English](../../README.md) | [繁體中文](../zh-TW/README.md) | 简体中文
17
17
 
18
- **版本**: 6.7.3 | **发布日期**: 2026-08-18 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
18
+ **版本**: 6.7.4 | **发布日期**: 2026-08-18 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
19
19
 
20
20
  语言无关、框架无关的软件项目文档标准。通过 AI 原生工作流,确保不同技术栈之间的一致性、质量和可维护性。
21
21
 
@@ -13,7 +13,7 @@ status: current
13
13
  <!-- UDS_SUPPORTED_VERSIONS_START -->
14
14
  | 版本 | 支持状态 |
15
15
  |------|--------|
16
- | 6.7.3 | ✅ 最新正式版 |
16
+ | 6.7.4 | ✅ 最新正式版 |
17
17
  | < 6.0.0 | ❌ 已终止支持 |
18
18
  <!-- UDS_SUPPORTED_VERSIONS_END -->
19
19
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  source: ../../CHANGELOG.md
3
- source_version: 6.7.3
4
- translation_version: 6.7.3
3
+ source_version: 6.7.4
4
+ translation_version: 6.7.4
5
5
  last_synced: 2026-08-18
6
6
  status: current
7
7
  ---
@@ -17,6 +17,15 @@ status: current
17
17
 
18
18
  ## [Unreleased]
19
19
 
20
+ ## [6.7.4] - 2026-08-18
21
+
22
+ ### 修正
23
+
24
+ - **6.7.3 讓 `uds check` 每個 repo 報出 52 個不存在的「遺失」檔案。** 6.7.3 的兩個改動要**同時在場**才會互相作用:R1 給了 skill 內容雜湊,使它們第一次走進 `unchanged` 分支;而 R6b 會把那個分支的項目收進 `manifest.fileHashes`。那張表是用 `isFile()` 驗證的,而 skill 是目錄,於是每一個都被報成遺失。**沒有任何東西被刪除——錯的是紀錄不是磁碟**(已驗證:59 個 skill 目錄與其內容完好)。`verifiedPristine` 現在限縮於檔案類別;而且**修好寫入端不會讓已經寫進去的東西消失**,所以 `uds update` 也會清掉 `fileHashes` 裡的 `.claude/skills/` 與 `.claude/commands/` 鍵——**一個壞掉的鍵不會有第二次機會被造訪**,因為磁碟上沒有任何東西對應它。
25
+ - **commands 也改為內容比對(XSPEC-382 R7)。** R1 只涵蓋 skills,把 commands 留在 `hash: null`,於是無條件重裝的分支對它們仍然活著。與 skills 同一個形狀:`resolveCommandContent(name, agent, locale)` 說明一次安裝會包含什麼(locale 選擇+英文回退,加上逐 agent 的轉換),安裝器寫它、計畫器雜湊它。
26
+ - **裝了 locale 版的人,拿到的 SKILL.md 指向從來不會被安裝的檔案。** locale 包不是英文來源的完整複本——實測 **zh-TW 59 個中有 4 個、zh-CN 59 個中有 5 個**缺少英文有出貨的檔——而安裝器把 locale 目錄整包換上去,於是那些伴隨檔根本沒被寫入。其中兩個缺口**是被引用的**:zh-TW 的 `dev-workflow-guide/SKILL.md` 引用 `workflow-phases.md` 三次、`testing-guide/SKILL.md` 引用 `test-skeleton-templates.md` 三次。**回退改為逐檔而非逐 skill**——locale 有就用 locale 的,沒有就用英文的。
27
+ - **UDS 不出貨的檔案,不再讓一個 skill 永遠停在「已變更」。** 安裝一個 skill 現在會移除其目錄下**解析結果沒有指名**的頂層檔案(實地發現:`deploy-assistant/guide.md`,它不在任何 UDS skills 樹裡,而且從來就不在)。範圍由同一個 provenance 判準界定,也就是讓採用者自己的 skill 目錄不進入此處任何路徑的那一個——**已驗證手寫的 skill 目錄與其額外檔案在 `--force` 之後完好無損**——子目錄一律不動,因為安裝器從來沒有寫過它們。
28
+
20
29
  ## [6.7.3] - 2026-08-18
21
30
 
22
31
  ### 修正
@@ -15,7 +15,7 @@ status: current
15
15
 
16
16
  > **語言**: [English](../../README.md) | 繁體中文 | [简体中文](../zh-CN/README.md)
17
17
 
18
- **版本**: 6.7.3 | **發布日期**: 2026-08-18 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
18
+ **版本**: 6.7.4 | **發布日期**: 2026-08-18 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
19
19
 
20
20
  語言無關、框架無關的軟體專案文件標準。透過 AI 原生工作流,確保不同技術堆疊之間的一致性、品質和可維護性。
21
21
 
@@ -13,7 +13,7 @@ status: current
13
13
  <!-- UDS_SUPPORTED_VERSIONS_START -->
14
14
  | 版本 | 支援狀態 |
15
15
  |------|--------|
16
- | 6.7.3 | ✅ 最新正式版 |
16
+ | 6.7.4 | ✅ 最新正式版 |
17
17
  | < 6.0.0 | ❌ 已終止支援 |
18
18
  <!-- UDS_SUPPORTED_VERSIONS_END -->
19
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-dev-standards",
3
- "version": "6.7.3",
3
+ "version": "6.7.4",
4
4
  "description": "CLI tool for adopting Universal Development Standards",
5
5
  "keywords": [
6
6
  "documentation",
@@ -434,9 +434,26 @@ function scanCommands(state, projectPath, manifest) {
434
434
  ? getRelativePath(projectPath, join(cmdsDir, entry.name))
435
435
  : join(cmdsDir, entry.name);
436
436
 
437
+ // Content hash of the installed file, for UDS-managed commands only —
438
+ // same reasoning as skills: an adopter's own command has no desired
439
+ // counterpart to compare against. (XSPEC-382 R7)
440
+ const cmdUdsManaged = shippedCommandNames().has(cmdName);
441
+ let cmdHash = null;
442
+ if (cmdUdsManaged) {
443
+ try {
444
+ cmdHash = `sha256:${createHash('sha256')
445
+ .update(readFileSync(join(cmdsDir, entry.name), 'utf-8'))
446
+ .digest('hex')}`;
447
+ } catch {
448
+ // Unreadable → no hash. A partial answer would claim a match that
449
+ // was never checked.
450
+ cmdHash = null;
451
+ }
452
+ }
453
+
437
454
  state.commands.set(key, {
438
455
  relativePath: relPath,
439
- hash: null,
456
+ hash: cmdHash,
440
457
  size: null,
441
458
  category: 'command',
442
459
  sourcePath: null,
@@ -445,7 +462,7 @@ function scanCommands(state, projectPath, manifest) {
445
462
  level,
446
463
  commandName: cmdName,
447
464
  scanned: true,
448
- udsManaged: shippedCommandNames().has(cmdName)
465
+ udsManaged: cmdUdsManaged
449
466
  }
450
467
  });
451
468
  }
@@ -26,7 +26,9 @@ import {
26
26
  getAvailableSkillNames,
27
27
  getAvailableCommandNames,
28
28
  resolveSkillFiles,
29
- computeSkillContentHash
29
+ computeSkillContentHash,
30
+ resolveCommandContent,
31
+ computeCommandContentHash
30
32
  } from '../utils/skills-installer.js';
31
33
  import { MARKETPLACE_NAMES_SENTINEL } from '../core/manifest.js';
32
34
 
@@ -379,6 +381,9 @@ function calculateSkills(state, projectPath, manifest) {
379
381
  function calculateCommands(state, projectPath, manifest) {
380
382
  const commands = manifest.commands;
381
383
  if (!commands || !commands.installed) return;
384
+ // Commands are installed alongside skills and share their locale; fall back
385
+ // to the skills locale, then English.
386
+ const commandsLocale = commands.locale || manifest.skills?.locale || 'en';
382
387
 
383
388
  const commandNames = getAvailableCommandNames();
384
389
  if (commandNames.length === 0) {
@@ -404,9 +409,12 @@ function calculateCommands(state, projectPath, manifest) {
404
409
  : null;
405
410
 
406
411
  if (relativeBase) {
412
+ // Content hash of what installing this command WOULD produce, from the
413
+ // same function the installer writes from. (XSPEC-382 R7)
414
+ const resolvedCmd = resolveCommandContent(commandName, agent, commandsLocale);
407
415
  state.commands.set(`command:${agent}:${level}:${commandName}`, {
408
416
  relativePath: relativeBase,
409
- hash: null,
417
+ hash: resolvedCmd.error ? null : computeCommandContentHash(resolvedCmd.content),
410
418
  size: null,
411
419
  category: 'command',
412
420
  sourcePath: null,
@@ -182,7 +182,17 @@ function diffCategory(desiredMap, actualMap, category, actions, warnings, summar
182
182
  // reverted `fileHashes` along with `upstream.version`). Recording it here
183
183
  // is safe precisely because we got here by proving disk === desired.
184
184
  summary.unchanged++;
185
- if (actualEntry.hash) {
185
+ // Only file-backed categories. `manifest.fileHashes` is a FILE map that
186
+ // `uds check` validates with a `isFile()` test; skills are directories and
187
+ // commands live in `commandHashes`, so recording either there makes the
188
+ // integrity check report them as missing.
189
+ //
190
+ // This branch was unreachable for skills until R1 gave them hashes, so
191
+ // the two changes shipped together and the fault only appeared once both
192
+ // were in: 6.7.3 put 52 skill directory paths into `fileHashes` in every
193
+ // adopter repo and `uds check` reported 52 phantom missing files. Nothing
194
+ // was deleted — the record was wrong, not the disk. (XSPEC-382 R7)
195
+ if (actualEntry.hash && (category === 'standard' || category === 'option')) {
186
196
  verifiedPristine.push({
187
197
  path: desiredEntry.relativePath,
188
198
  hash: actualEntry.hash,
@@ -59,15 +59,28 @@ import { rollback } from './backup-manager.js';
59
59
  * is the one thing that check exists to do.
60
60
  */
61
61
  function reconcileFileHashes(manifest, verifiedPristine) {
62
- if (!verifiedPristine?.length) return null;
63
-
64
62
  const current = manifest.fileHashes || {};
63
+
64
+ // Drop entries 6.7.3 wrote here that do not belong: skill directories and
65
+ // command files are tracked in `skillHashes` / `commandHashes`, and
66
+ // `uds check` validates everything in `fileHashes` with an `isFile()` test,
67
+ // so those entries surfaced as phantom "missing" reports — 52 of them per
68
+ // adopter repo. Fixing the writer does not remove what it already wrote, and
69
+ // there is no other path that would: a bad key is never revisited because
70
+ // nothing on disk corresponds to it. (XSPEC-382 R7)
71
+ const stale = Object.keys(current).filter(
72
+ (k) => k.startsWith('.claude/skills/') || k.startsWith('.claude/commands/')
73
+ );
74
+
75
+ if (!verifiedPristine?.length && stale.length === 0) return null;
76
+
77
+ const kept = Object.fromEntries(Object.entries(current).filter(([k]) => !stale.includes(k)));
65
78
  const corrected = {};
66
- let count = 0;
79
+ let count = stale.length;
67
80
 
68
- for (const entry of verifiedPristine) {
81
+ for (const entry of verifiedPristine || []) {
69
82
  const key = entry.path.replace(/\\/g, '/');
70
- const recorded = current[key];
83
+ const recorded = kept[key];
71
84
  if (recorded && recorded.hash === entry.hash && recorded.size === entry.size) continue;
72
85
  corrected[key] = {
73
86
  hash: entry.hash,
@@ -79,7 +92,7 @@ function reconcileFileHashes(manifest, verifiedPristine) {
79
92
 
80
93
  if (count === 0) return null;
81
94
  return {
82
- manifest: { ...manifest, fileHashes: { ...current, ...corrected } },
95
+ manifest: { ...manifest, fileHashes: { ...kept, ...corrected } },
83
96
  count
84
97
  };
85
98
  }
@@ -452,12 +452,36 @@ export function resolveSkillFiles(skillName, locale = 'en') {
452
452
  return { files: [], fallbackToEn, error: `Skill not found: ${skillName}` };
453
453
  }
454
454
 
455
+ // Per-FILE fallback to English, not per-skill.
456
+ //
457
+ // A locale pack that has SKILL.md but not its companion files used to install
458
+ // just the SKILL.md, leaving the companions uninstalled entirely. Measured:
459
+ // 4 of 59 localized skills in zh-TW and 5 of 59 in zh-CN are short of the
460
+ // English source, and two of those gaps are REFERENCED — the zh-TW
461
+ // `dev-workflow-guide/SKILL.md` points at `workflow-phases.md` three times
462
+ // and `testing-guide/SKILL.md` at `test-skeleton-templates.md` three times,
463
+ // neither of which the locale pack ships. Those installs shipped a document
464
+ // pointing at files that were never going to be there.
465
+ //
466
+ // Taking the union — locale file where it exists, English where it does not —
467
+ // is also what makes the content comparison usable: without it those skills
468
+ // would report as changed on every upgrade forever. (XSPEC-382 R7)
469
+ const names = new Map(); // fileName -> absolute source path
470
+ const collect = (dir) => {
471
+ if (!existsSync(dir)) return;
472
+ for (const fileName of readdirSync(dir)) {
473
+ const sourcePath = join(dir, fileName);
474
+ // Subdirectories are skipped — matching what the installer has always done.
475
+ if (statSync(sourcePath).isDirectory()) continue;
476
+ if (!names.has(fileName)) names.set(fileName, sourcePath);
477
+ }
478
+ };
479
+ collect(sourceDir); // locale first, so it wins
480
+ if (sourceDir !== enSourceDir) collect(enSourceDir);
481
+
455
482
  const files = [];
456
- for (const fileName of readdirSync(sourceDir)) {
457
- const sourcePath = join(sourceDir, fileName);
458
- // Subdirectories are skipped — matching what the installer has always done.
459
- if (statSync(sourcePath).isDirectory()) continue;
460
- files.push({ name: fileName, content: readFileSync(sourcePath, 'utf-8') });
483
+ for (const [name, sourcePath] of names) {
484
+ files.push({ name, content: readFileSync(sourcePath, 'utf-8') });
461
485
  }
462
486
 
463
487
  if (needsFrontmatterMerge) {
@@ -547,7 +571,32 @@ function installSingleSkill(skillName, targetBaseDir, locale = 'en') {
547
571
  writeFileSync(join(targetDir, file.name), file.content, 'utf-8');
548
572
  }
549
573
 
550
- return { success: true, skillName, path: targetDir, fallbackToEn };
574
+ // Remove top-level files UDS does not ship for this skill.
575
+ //
576
+ // Without this, a file UDS once shipped (or that arrived some other way)
577
+ // stays forever, and the content comparison reports the skill as changed on
578
+ // every upgrade with no way to make it stop — the same permanently-true
579
+ // false positive that made `uds check` useless before R6. Found in vibeops:
580
+ // `deploy-assistant/guide.md`, which is in no UDS skills tree and never was.
581
+ //
582
+ // Scoped to files directly inside a directory whose name UDS itself ships,
583
+ // which is the same provenance test that keeps an adopter's OWN skill
584
+ // directories out of every code path here. Subdirectories are left alone —
585
+ // the installer has never written them, so it has no claim on them.
586
+ // (XSPEC-382 R7)
587
+ const shipped = new Set(resolved.files.map((f) => f.name));
588
+ const pruned = [];
589
+ for (const entry of readdirSync(targetDir, { withFileTypes: true })) {
590
+ if (!entry.isFile() || shipped.has(entry.name)) continue;
591
+ try {
592
+ unlinkSync(join(targetDir, entry.name));
593
+ pruned.push(entry.name);
594
+ } catch {
595
+ // Leave it; a stale file is a smaller problem than a failed install.
596
+ }
597
+ }
598
+
599
+ return { success: true, skillName, path: targetDir, fallbackToEn, pruned };
551
600
  } catch (error) {
552
601
  return {
553
602
  success: false,
@@ -683,44 +732,77 @@ export async function installCommandsForAgent(agent, level = 'project', commandN
683
732
  * @param {string} locale - Locale for command content (default: 'en')
684
733
  * @returns {Object} Result
685
734
  */
686
- function installSingleCommand(cmdName, targetDir, agent, locale = 'en') {
735
+ /**
736
+ * Resolve what installing a command would put on disk, without writing anything.
737
+ *
738
+ * The command-side twin of `resolveSkillFiles`, and for the same reason: what
739
+ * gets installed is not what is in the source tree. The source is chosen at
740
+ * runtime by locale with fallback to English, and `transformCommandForAgent`
741
+ * rewrites the content per agent. Hashing the source file would report every
742
+ * command as changed on every upgrade for any agent that transforms.
743
+ *
744
+ * XSPEC-382 R1 covered skills and left commands on `hash: null`, which kept the
745
+ * unconditional-reinstall branch alive for them. R7 closes it the same way —
746
+ * one function the installer writes from and the planner hashes, rather than a
747
+ * second copy of the resolution in the planner.
748
+ *
749
+ * @param {string} cmdName
750
+ * @param {string} agent
751
+ * @param {string} locale
752
+ * @returns {{content: string|null, error: string|null}}
753
+ */
754
+ export function resolveCommandContent(cmdName, agent, locale = 'en') {
687
755
  let sourcePath = join(COMMANDS_LOCAL_DIR, `${cmdName}.md`);
688
756
 
689
- // Check for localized command file
690
757
  if (isLocalizedLocale(locale)) {
691
- const localizedDir = getLocalizedCommandsSourceDir(locale);
692
- const localizedPath = join(localizedDir, `${cmdName}.md`);
693
- if (existsSync(localizedPath)) {
694
- sourcePath = localizedPath;
695
- }
758
+ const localizedPath = join(getLocalizedCommandsSourceDir(locale), `${cmdName}.md`);
759
+ if (existsSync(localizedPath)) sourcePath = localizedPath;
696
760
  // else: fall back to English source
697
761
  }
698
762
 
699
- const targetExt = getCommandFileExtension(agent);
700
- const targetPath = join(targetDir, `${cmdName}${targetExt}`);
701
-
702
763
  if (!existsSync(sourcePath)) {
764
+ return { content: null, error: `Command not found: ${cmdName}` };
765
+ }
766
+
767
+ try {
703
768
  return {
704
- success: false,
705
- command: cmdName,
706
- error: `Command not found: ${cmdName}`
769
+ content: transformCommandForAgent(readFileSync(sourcePath, 'utf-8'), cmdName, agent),
770
+ error: null
707
771
  };
772
+ } catch (error) {
773
+ return { content: null, error: error.message };
708
774
  }
775
+ }
709
776
 
710
- try {
711
- let content = readFileSync(sourcePath, 'utf-8');
777
+ /**
778
+ * Content hash of a resolved command.
779
+ *
780
+ * Same `sha256:` shape as `computeSkillContentHash` so the two sides of the
781
+ * diff can be compared without caring which category an entry came from.
782
+ *
783
+ * @param {string|null} content
784
+ * @returns {string|null}
785
+ */
786
+ export function computeCommandContentHash(content) {
787
+ if (content === null || content === undefined) return null;
788
+ return `sha256:${createHash('sha256').update(content).digest('hex')}`;
789
+ }
790
+
791
+ function installSingleCommand(cmdName, targetDir, agent, locale = 'en') {
792
+ const targetPath = join(targetDir, `${cmdName}${getCommandFileExtension(agent)}`);
712
793
 
713
- // Transform content if needed for specific agents
714
- content = transformCommandForAgent(content, cmdName, agent);
794
+ // Write what `resolveCommandContent` says this install is; the planner asks
795
+ // the same function what it WOULD be. (XSPEC-382 R7)
796
+ const resolved = resolveCommandContent(cmdName, agent, locale);
797
+ if (resolved.error) {
798
+ return { success: false, command: cmdName, error: resolved.error };
799
+ }
715
800
 
716
- writeFileSync(targetPath, content);
801
+ try {
802
+ writeFileSync(targetPath, resolved.content);
717
803
  return { success: true, command: cmdName, path: targetPath };
718
804
  } catch (error) {
719
- return {
720
- success: false,
721
- command: cmdName,
722
- error: error.message
723
- };
805
+ return { success: false, command: cmdName, error: error.message };
724
806
  }
725
807
  }
726
808
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "version": "6.7.3",
3
+ "version": "6.7.4",
4
4
  "lastUpdated": "2026-05-13",
5
5
  "description": "Standards registry for universal-dev-standards with integrated skills and AI-optimized formats",
6
6
  "formats": {
@@ -58,14 +58,14 @@
58
58
  "standards": {
59
59
  "name": "universal-dev-standards",
60
60
  "url": "https://github.com/AsiaOstrich/universal-dev-standards",
61
- "version": "6.7.3"
61
+ "version": "6.7.4"
62
62
  },
63
63
  "skills": {
64
64
  "name": "universal-dev-standards",
65
65
  "url": "https://github.com/AsiaOstrich/universal-dev-standards",
66
66
  "localPath": "skills",
67
67
  "rawUrl": "https://raw.githubusercontent.com/AsiaOstrich/universal-dev-standards/main/skills",
68
- "version": "6.7.3",
68
+ "version": "6.7.4",
69
69
  "note": "Skills are now included in the main repository under skills/"
70
70
  }
71
71
  },
@@ -2260,7 +2260,7 @@
2260
2260
  "id": "license-compliance",
2261
2261
  "name": "License Compliance Standards",
2262
2262
  "nameZh": "授權合規標準",
2263
- "version": "6.7.3",
2263
+ "version": "6.7.4",
2264
2264
  "source": {
2265
2265
  "human": "core/license-compliance.md",
2266
2266
  "ai": "ai/standards/license-compliance.ai.yaml"
@@ -2272,7 +2272,7 @@
2272
2272
  "id": "verification-oracle",
2273
2273
  "name": "Verification Oracle Standards",
2274
2274
  "nameZh": "驗證 Oracle 標準",
2275
- "version": "6.7.3",
2275
+ "version": "6.7.4",
2276
2276
  "source": {
2277
2277
  "human": "core/verification-oracle.md",
2278
2278
  "ai": "ai/standards/verification-oracle.ai.yaml"
@@ -2284,7 +2284,7 @@
2284
2284
  "id": "model-provenance",
2285
2285
  "name": "Model Provenance Policy Standards",
2286
2286
  "nameZh": "模型來源政策標準",
2287
- "version": "6.7.3",
2287
+ "version": "6.7.4",
2288
2288
  "source": {
2289
2289
  "human": "core/model-provenance.md",
2290
2290
  "ai": "ai/standards/model-provenance.ai.yaml"
@@ -2296,7 +2296,7 @@
2296
2296
  "id": "resource-cost-boundary",
2297
2297
  "name": "Resource / Cost Boundary Declaration Standards",
2298
2298
  "nameZh": "資源/成本邊界宣告標準",
2299
- "version": "6.7.3",
2299
+ "version": "6.7.4",
2300
2300
  "source": {
2301
2301
  "human": "core/resource-cost-boundary.md",
2302
2302
  "ai": "ai/standards/resource-cost-boundary.ai.yaml"