universal-dev-standards 6.3.2 → 6.3.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.
- package/bin/uds.js +1 -1
- package/bundled/locales/zh-CN/CHANGELOG.md +17 -3
- package/bundled/locales/zh-CN/README.md +1 -1
- package/bundled/locales/zh-TW/CHANGELOG.md +17 -3
- package/bundled/locales/zh-TW/README.md +1 -1
- package/package.json +1 -1
- package/src/commands/deps.js +19 -5
- package/src/utils/dependency-resolution.js +50 -15
- package/standards-registry.json +7 -7
package/bin/uds.js
CHANGED
|
@@ -247,7 +247,7 @@ program
|
|
|
247
247
|
|
|
248
248
|
program
|
|
249
249
|
.command('deps')
|
|
250
|
-
.description('Compare
|
|
250
|
+
.description('Compare the versions you test against the versions your declared ranges resolve to')
|
|
251
251
|
.option('--path <dir>', 'Directory containing package.json (default: cwd)')
|
|
252
252
|
.option('--json', 'Output raw JSON')
|
|
253
253
|
.option('--concurrency <n>', 'Parallel registry lookups (default: 8)')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.3.
|
|
4
|
-
translation_version: 6.3.
|
|
5
|
-
last_synced: 2026-08-
|
|
3
|
+
source_version: 6.3.4
|
|
4
|
+
translation_version: 6.3.4
|
|
5
|
+
last_synced: 2026-08-07
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -17,6 +17,20 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.3.4] - 2026-08-07
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **`uds deps` 指名了一个 npm 不会安装的版本。** 解析字段原本取「所有已发布版本中满足声明范围的最高版本」。那是 semver 的规则,不是 npm 的:`npm-pick-manifest` 在 `latest` dist-tag 满足范围时优先采用它,存在的目的正是不让带着普通版本号的 `next` 或 `beta` 发布落到只要了一个 caret 的人身上。以 `@anthropic-ai/claude-agent-sdk` 实测(`latest = 0.3.223`、`next = 0.3.224`):命令回报 0.3.224,而 `npm install …@^0.3` 实际装 0.3.223。**那个字段存在的全部目的就是说出「安装会拿到什么」,而它指名了没有任何安装会拿到的东西。** 现改为单次 `npm view` 同时取版本清单与 dist-tags,套用 npm 自己的优先顺序;`latest` 落在范围外时退回「范围内最高版本」——锁在旧 major 的项目仍得到诚实的答案。两个分支各有测试覆盖。
|
|
25
|
+
- 前两个版本修的是这个命令的**措辞**,这一版修的是它的**算术**。值得直说:先前那些修正只是让一个错的数字变得更好读。
|
|
26
|
+
|
|
27
|
+
## [6.3.3] - 2026-08-07
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **6.3.2 改好了说明,却把说明刚刚撤回的那个主张留在它上方的标题里。** 漂移区段的标题是 `N shipped ≠ tested`——黄色,就在那段说明「出货的与测到的是否不同,取决于项目怎么出货」的 dim 文字上一行。对随产物出货 lockfile 的产物而言,出货的**就是**测到的,因此那个标题在整份报告最醒目的位置说了与事实相反的话。这正是 1.1.0 改写 Lock Strategy 条目所要根除的形状:一句误导的话,下面附一句限定。标题现在改为指出两个不一致的字段——`N tested ≠ resolves`——这是对测量结果的陈述,不是对「谁收到了它」的结论。已加测试钉住。
|
|
32
|
+
- **另有两处在说同一件事,其中一处是采用者最先读到的。** `uds deps --help` 把这个命令描述为「Compare what you test against what your users install (published packages ship no lockfile)」,模块自身的摘要行则写「does what you test match what your users install?」。两者现在都改以「声明范围会解析到什么」表述。发现方式是修完标题后对整个 repo grep 已撤回的措辞——那是我自己那一轮修正漏掉的两处。
|
|
33
|
+
|
|
20
34
|
## [6.3.2] - 2026-08-06
|
|
21
35
|
|
|
22
36
|
### 修复
|
|
@@ -15,7 +15,7 @@ status: current
|
|
|
15
15
|
|
|
16
16
|
> **语言**: [English](../../README.md) | [繁體中文](../zh-TW/README.md) | 简体中文
|
|
17
17
|
|
|
18
|
-
**版本**: 6.3.
|
|
18
|
+
**版本**: 6.3.4 | **发布日期**: 2026-07-31 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
语言无关、框架无关的软件项目文档标准。通过 AI 原生工作流,确保不同技术栈之间的一致性、质量和可维护性。
|
|
21
21
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.3.
|
|
4
|
-
translation_version: 6.3.
|
|
5
|
-
last_synced: 2026-08-
|
|
3
|
+
source_version: 6.3.4
|
|
4
|
+
translation_version: 6.3.4
|
|
5
|
+
last_synced: 2026-08-07
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -17,6 +17,20 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.3.4] - 2026-08-07
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **`uds deps` 指名了一個 npm 不會安裝的版本。** 解析欄位原本取「所有已發布版本中滿足宣告範圍的最高版本」。那是 semver 的規則,不是 npm 的:`npm-pick-manifest` 在 `latest` dist-tag 滿足範圍時優先採用它,存在的目的正是不讓帶著普通版本號的 `next` 或 `beta` 發布落到只要了一個 caret 的人身上。以 `@anthropic-ai/claude-agent-sdk` 實測(`latest = 0.3.223`、`next = 0.3.224`):指令回報 0.3.224,而 `npm install …@^0.3` 實際裝 0.3.223。**那個欄位存在的全部目的就是說出「安裝會拿到什麼」,而它指名了沒有任何安裝會拿到的東西。** 現改為單次 `npm view` 同時取版本清單與 dist-tags,套用 npm 自己的優先順序;`latest` 落在範圍外時退回「範圍內最高版本」——鎖在舊 major 的專案仍得到誠實的答案。兩個分支各有測試覆蓋。
|
|
25
|
+
- 前兩個版本修的是這個指令的**措辭**,這一版修的是它的**算術**。值得直說:先前那些修正只是讓一個錯的數字變得更好讀。
|
|
26
|
+
|
|
27
|
+
## [6.3.3] - 2026-08-07
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **6.3.2 改好了說明,卻把說明剛剛撤回的那個主張留在它上方的標題裡。** 漂移區段的標題是 `N shipped ≠ tested`——黃色,就在那段說明「出貨的與測到的是否不同,取決於專案怎麼出貨」的 dim 文字上一行。對隨產物出貨 lockfile 的產物而言,出貨的**就是**測到的,因此那個標題在整份報告最醒目的位置說了與事實相反的話。這正是 1.1.0 改寫 Lock Strategy 條目所要根除的形狀:一句誤導的話,下面附一句限定。標題現在改為指出兩個不一致的欄位——`N tested ≠ resolves`——這是對量測結果的陳述,不是對「誰收到了它」的結論。已加測試釘住。
|
|
32
|
+
- **另有兩處在說同一件事,其中一處是採用者最先讀到的。** `uds deps --help` 把這個指令描述為「Compare what you test against what your users install (published packages ship no lockfile)」,模組自身的摘要行則寫「does what you test match what your users install?」。兩者現在都改以「宣告範圍會解析到什麼」表述。發現方式是修完標題後對整個 repo grep 已撤回的措辭——那是我自己那一輪修正漏掉的兩處。
|
|
33
|
+
|
|
20
34
|
## [6.3.2] - 2026-08-06
|
|
21
35
|
|
|
22
36
|
### 修復
|
|
@@ -15,7 +15,7 @@ status: current
|
|
|
15
15
|
|
|
16
16
|
> **語言**: [English](../../README.md) | 繁體中文 | [简体中文](../zh-CN/README.md)
|
|
17
17
|
|
|
18
|
-
**版本**: 6.3.
|
|
18
|
+
**版本**: 6.3.4 | **發布日期**: 2026-07-31 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
語言無關、框架無關的軟體專案文件標準。透過 AI 原生工作流,確保不同技術堆疊之間的一致性、品質和可維護性。
|
|
21
21
|
|
package/package.json
CHANGED
package/src/commands/deps.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `uds deps` — does what you test match what your
|
|
2
|
+
* `uds deps` — does what you test match what your ranges resolve to?
|
|
3
3
|
* // implements XSPEC-366 R1
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Compares, per runtime dependency, the declared range, the version the
|
|
6
|
+
* lockfile pins, and the version a fresh install would resolve that range to.
|
|
7
|
+
*
|
|
8
|
+
* It deliberately stops there. Whether a gap between the second and third
|
|
9
|
+
* numbers is already in a user's hands depends on how the project ships —
|
|
10
|
+
* a published npm package carries no lockfile, so consumers resolve the
|
|
11
|
+
* ranges themselves; an artifact that ships its lockfile (a container image,
|
|
12
|
+
* a deployed service) hands users the pinned column and meets the third one
|
|
13
|
+
* at its next lockfile regeneration. This module cannot know which applies,
|
|
14
|
+
* so it never phrases the gap as something users already have.
|
|
8
15
|
*
|
|
9
16
|
* See `utils/dependency-resolution.js` for why resolution goes through
|
|
10
17
|
* `npm view` and why a failed lookup is never reported as agreement.
|
|
@@ -36,7 +43,14 @@ export function render(result) {
|
|
|
36
43
|
|
|
37
44
|
if (result.drifted.length > 0) {
|
|
38
45
|
lines.push('');
|
|
39
|
-
|
|
46
|
+
// Named after the two columns that disagree, not after a conclusion about
|
|
47
|
+
// who receives them. `shipped ≠ tested` — the wording this replaced — is
|
|
48
|
+
// false for an artifact that ships its own lockfile, where shipped IS
|
|
49
|
+
// tested. 6.3.2 rewrote the explanation below to state both readings but
|
|
50
|
+
// left this heading asserting one of them, in yellow, one line above the
|
|
51
|
+
// dim correction. That is the "misleading line with a qualification
|
|
52
|
+
// underneath it" shape that R4 rewrote the supply-chain standard to stop.
|
|
53
|
+
lines.push(chalk.yellow(` ${result.drifted.length} tested ≠ resolves:`));
|
|
40
54
|
for (const d of result.drifted) {
|
|
41
55
|
lines.push(
|
|
42
56
|
` ${chalk.bold(d.name)} ${chalk.dim(d.range)}` +
|
|
@@ -38,6 +38,12 @@
|
|
|
38
38
|
* silently answer a different question for anyone who does not install from
|
|
39
39
|
* the public registry, and would answer it confidently.
|
|
40
40
|
*
|
|
41
|
+
* **And it applies npm's resolution rule, not semver's.** The highest version
|
|
42
|
+
* satisfying a range is *not* what npm installs: npm prefers the `latest`
|
|
43
|
+
* dist-tag whenever it satisfies, so a `next` or `beta` publish carrying an
|
|
44
|
+
* ordinary version number does not land on people. Getting this wrong made the
|
|
45
|
+
* tool name a version no consumer receives — see `resolveViaNpm`.
|
|
46
|
+
*
|
|
41
47
|
* **A registry lookup that fails is never folded into "consistent".** It
|
|
42
48
|
* becomes `unverifiable` and makes the whole check non-zero. A tool whose
|
|
43
49
|
* "everything is fine" and "I could not find out" look the same is worse than
|
|
@@ -68,18 +74,30 @@ import semver from 'semver';
|
|
|
68
74
|
const DEFAULT_CONCURRENCY = 8;
|
|
69
75
|
|
|
70
76
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
77
|
+
* Return the version an install of `range` would actually receive.
|
|
78
|
+
*
|
|
79
|
+
* **This deliberately reproduces npm's rule, not semver's.** The obvious
|
|
80
|
+
* implementation — take the highest published version satisfying the range —
|
|
81
|
+
* is wrong, and wrong in the direction this module exists to catch. npm's
|
|
82
|
+
* resolver (`npm-pick-manifest`) prefers the `latest` dist-tag whenever it
|
|
83
|
+
* satisfies the range, and only falls back to the maximum otherwise. That rule
|
|
84
|
+
* exists so a `next` or `beta` publish does not land on people who asked for a
|
|
85
|
+
* caret.
|
|
86
|
+
*
|
|
87
|
+
* Measured on 2026-08-07: `@anthropic-ai/claude-agent-sdk` published
|
|
88
|
+
* `latest = 0.3.223` and `next = 0.3.224`, both ordinary semver strings, both
|
|
89
|
+
* satisfying `^0.3`. The maximum-satisfying rule named 0.3.224;
|
|
90
|
+
* `npm install @anthropic-ai/claude-agent-sdk@^0.3` installs 0.3.223. **The
|
|
91
|
+
* earlier implementation reported a version no consumer receives** — in the one
|
|
92
|
+
* column whose entire purpose is to say what they receive.
|
|
73
93
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* final element. Guessing here would produce a confident wrong answer, which
|
|
79
|
-
* is the failure mode this whole module exists to detect.
|
|
94
|
+
* Versions and tags are read in a single `npm view` call. The version list is
|
|
95
|
+
* in publish order, **not** semver order — a backport released after a major
|
|
96
|
+
* bump appears last while being the lowest version — so the fallback maximum is
|
|
97
|
+
* computed with semver rather than by taking the final element.
|
|
80
98
|
*/
|
|
81
99
|
async function resolveViaNpm(name, range, run) {
|
|
82
|
-
const { code, stdout, stderr } = await run(['view',
|
|
100
|
+
const { code, stdout, stderr } = await run(['view', name, 'versions', 'dist-tags', '--json']);
|
|
83
101
|
|
|
84
102
|
if (code !== 0) {
|
|
85
103
|
const detail = (stderr || stdout || '').split('\n').find((l) => l.trim()) ?? '';
|
|
@@ -93,13 +111,30 @@ async function resolveViaNpm(name, range, run) {
|
|
|
93
111
|
throw new Error(`npm view returned output that is not JSON: ${stdout.slice(0, 120)}`);
|
|
94
112
|
}
|
|
95
113
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
114
|
+
// npm flattens the response when only one of the requested fields exists on
|
|
115
|
+
// the package, so neither key can be assumed present. A package with exactly
|
|
116
|
+
// one published version reports `versions` as a bare string.
|
|
117
|
+
const versions = Array.isArray(parsed?.versions)
|
|
118
|
+
? parsed.versions
|
|
119
|
+
: typeof parsed?.versions === 'string'
|
|
120
|
+
? [parsed.versions]
|
|
121
|
+
: Array.isArray(parsed)
|
|
122
|
+
? parsed
|
|
123
|
+
: typeof parsed === 'string'
|
|
124
|
+
? [parsed]
|
|
125
|
+
: [];
|
|
126
|
+
const tags = parsed?.['dist-tags'] ?? {};
|
|
127
|
+
|
|
128
|
+
if (versions.length === 0) throw new Error('npm view returned no versions');
|
|
129
|
+
|
|
130
|
+
const latest = tags.latest;
|
|
131
|
+
if (typeof latest === 'string' && semver.valid(latest) && semver.satisfies(latest, range)) {
|
|
132
|
+
return latest;
|
|
101
133
|
}
|
|
102
|
-
|
|
134
|
+
|
|
135
|
+
const max = semver.maxSatisfying(versions, range);
|
|
136
|
+
if (max) return max;
|
|
137
|
+
throw new Error(`no published version of ${name} satisfies ${range}`);
|
|
103
138
|
}
|
|
104
139
|
|
|
105
140
|
/**
|
package/standards-registry.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.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.3.
|
|
61
|
+
"version": "6.3.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.3.
|
|
68
|
+
"version": "6.3.4",
|
|
69
69
|
"note": "Skills are now included in the main repository under skills/"
|
|
70
70
|
}
|
|
71
71
|
},
|
|
@@ -2236,7 +2236,7 @@
|
|
|
2236
2236
|
"id": "license-compliance",
|
|
2237
2237
|
"name": "License Compliance Standards",
|
|
2238
2238
|
"nameZh": "授權合規標準",
|
|
2239
|
-
"version": "6.3.
|
|
2239
|
+
"version": "6.3.4",
|
|
2240
2240
|
"source": {
|
|
2241
2241
|
"human": "core/license-compliance.md",
|
|
2242
2242
|
"ai": "ai/standards/license-compliance.ai.yaml"
|
|
@@ -2248,7 +2248,7 @@
|
|
|
2248
2248
|
"id": "verification-oracle",
|
|
2249
2249
|
"name": "Verification Oracle Standards",
|
|
2250
2250
|
"nameZh": "驗證 Oracle 標準",
|
|
2251
|
-
"version": "6.3.
|
|
2251
|
+
"version": "6.3.4",
|
|
2252
2252
|
"source": {
|
|
2253
2253
|
"human": "core/verification-oracle.md",
|
|
2254
2254
|
"ai": "ai/standards/verification-oracle.ai.yaml"
|
|
@@ -2260,7 +2260,7 @@
|
|
|
2260
2260
|
"id": "model-provenance",
|
|
2261
2261
|
"name": "Model Provenance Policy Standards",
|
|
2262
2262
|
"nameZh": "模型來源政策標準",
|
|
2263
|
-
"version": "6.3.
|
|
2263
|
+
"version": "6.3.4",
|
|
2264
2264
|
"source": {
|
|
2265
2265
|
"human": "core/model-provenance.md",
|
|
2266
2266
|
"ai": "ai/standards/model-provenance.ai.yaml"
|
|
@@ -2272,7 +2272,7 @@
|
|
|
2272
2272
|
"id": "resource-cost-boundary",
|
|
2273
2273
|
"name": "Resource / Cost Boundary Declaration Standards",
|
|
2274
2274
|
"nameZh": "資源/成本邊界宣告標準",
|
|
2275
|
-
"version": "6.3.
|
|
2275
|
+
"version": "6.3.4",
|
|
2276
2276
|
"source": {
|
|
2277
2277
|
"human": "core/resource-cost-boundary.md",
|
|
2278
2278
|
"ai": "ai/standards/resource-cost-boundary.ai.yaml"
|