universal-dev-standards 6.3.1 → 6.3.3

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 CHANGED
@@ -247,7 +247,7 @@ program
247
247
 
248
248
  program
249
249
  .command('deps')
250
- .description('Compare what you test against what your users install (published packages ship no lockfile)')
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.1
4
- translation_version: 6.3.1
5
- last_synced: 2026-08-06
3
+ source_version: 6.3.3
4
+ translation_version: 6.3.3
5
+ last_synced: 2026-08-07
6
6
  status: current
7
7
  ---
8
8
 
@@ -17,6 +17,19 @@ status: current
17
17
 
18
18
  ## [Unreleased]
19
19
 
20
+ ## [6.3.3] - 2026-08-07
21
+
22
+ ### Fixed
23
+
24
+ - **6.3.2 改好了说明,却把说明刚刚撤回的那个主张留在它上方的标题里。** 漂移区段的标题是 `N shipped ≠ tested`——黄色,就在那段说明「出货的与测到的是否不同,取决于项目怎么出货」的 dim 文字上一行。对随产物出货 lockfile 的产物而言,出货的**就是**测到的,因此那个标题在整份报告最醒目的位置说了与事实相反的话。这正是 1.1.0 改写 Lock Strategy 条目所要根除的形状:一句误导的话,下面附一句限定。标题现在改为指出两个不一致的字段——`N tested ≠ resolves`——这是对测量结果的陈述,不是对「谁收到了它」的结论。已加测试钉住。
25
+ - **另有两处在说同一件事,其中一处是采用者最先读到的。** `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 已撤回的措辞——那是我自己那一轮修正漏掉的两处。
26
+
27
+ ## [6.3.2] - 2026-08-06
28
+
29
+ ### 修复
30
+
31
+ - **`uds deps` 断言了一个它无从得知的出货渠道。** 报告结尾写着「consumers resolve the range themselves, because a published package does not ship a lockfile」,第三列标为 `users get=`。对一个以 `npm ci` 构建、出货 Docker image 的产品,这两句都是错的——它的用户拿到的正是 `tested=` 那一列,而解析出的那一列实际代表的是「下一次 lockfile 重新生成时会被无人审阅地拉进来的东西」。发现方式是拿这个命令去跑一个出货 Docker image、根本没发到 npm 的闭源产品。列名改为 `resolves=`,报告同时陈述两种读法——因为单独读一行时,它不能说出与事实相反的话。这与 1.1.0 对 Lock Strategy 条目所做的修正是同一件事:在一句误导的话下面补「但是……」,那句话仍然误导,而报告和标准表格一样,多半是一次读一行。现在有三个测试把措辞钉住,此前一个都没有。
32
+
20
33
  ## [6.3.1] - 2026-08-06
21
34
 
22
35
  ### 修复
@@ -15,7 +15,7 @@ status: current
15
15
 
16
16
  > **语言**: [English](../../README.md) | [繁體中文](../zh-TW/README.md) | 简体中文
17
17
 
18
- **版本**: 6.3.1 | **发布日期**: 2026-07-31 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
18
+ **版本**: 6.3.3 | **发布日期**: 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.1
4
- translation_version: 6.3.1
5
- last_synced: 2026-08-06
3
+ source_version: 6.3.3
4
+ translation_version: 6.3.3
5
+ last_synced: 2026-08-07
6
6
  status: current
7
7
  ---
8
8
 
@@ -17,6 +17,19 @@ status: current
17
17
 
18
18
  ## [Unreleased]
19
19
 
20
+ ## [6.3.3] - 2026-08-07
21
+
22
+ ### Fixed
23
+
24
+ - **6.3.2 改好了說明,卻把說明剛剛撤回的那個主張留在它上方的標題裡。** 漂移區段的標題是 `N shipped ≠ tested`——黃色,就在那段說明「出貨的與測到的是否不同,取決於專案怎麼出貨」的 dim 文字上一行。對隨產物出貨 lockfile 的產物而言,出貨的**就是**測到的,因此那個標題在整份報告最醒目的位置說了與事實相反的話。這正是 1.1.0 改寫 Lock Strategy 條目所要根除的形狀:一句誤導的話,下面附一句限定。標題現在改為指出兩個不一致的欄位——`N tested ≠ resolves`——這是對量測結果的陳述,不是對「誰收到了它」的結論。已加測試釘住。
25
+ - **另有兩處在說同一件事,其中一處是採用者最先讀到的。** `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 已撤回的措辭——那是我自己那一輪修正漏掉的兩處。
26
+
27
+ ## [6.3.2] - 2026-08-06
28
+
29
+ ### 修復
30
+
31
+ - **`uds deps` 斷言了一個它無從得知的出貨管道。** 報告結尾寫著「consumers resolve the range themselves, because a published package does not ship a lockfile」,第三欄標為 `users get=`。對一個以 `npm ci` 建置、出貨 Docker image 的產品,這兩句都是錯的——它的使用者拿到的正是 `tested=` 那一欄,而解析出的那一欄實際代表的是「下一次 lockfile 重新產生時會被無人審閱地拉進來的東西」。發現方式是拿這個指令去跑一個出貨 Docker image、根本沒發到 npm 的閉源產品。欄位改為 `resolves=`,報告同時陳述兩種讀法——因為單獨讀一列時,它不能說出與事實相反的話。這與 1.1.0 對 Lock Strategy 條目所做的修正是同一件事:在一句誤導的話下面補「但是……」,那句話仍然誤導,而報告和標準表格一樣,多半是一次讀一行。現在有三個測試把措辭釘住,先前一個都沒有。
32
+
20
33
  ## [6.3.1] - 2026-08-06
21
34
 
22
35
  ### 修復
@@ -15,7 +15,7 @@ status: current
15
15
 
16
16
  > **語言**: [English](../../README.md) | 繁體中文 | [简体中文](../zh-CN/README.md)
17
17
 
18
- **版本**: 6.3.1 | **發布日期**: 2026-07-31 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
18
+ **版本**: 6.3.3 | **發布日期**: 2026-07-31 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
19
19
 
20
20
  語言無關、框架無關的軟體專案文件標準。透過 AI 原生工作流,確保不同技術堆疊之間的一致性、品質和可維護性。
21
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-dev-standards",
3
- "version": "6.3.1",
3
+ "version": "6.3.3",
4
4
  "description": "CLI tool for adopting Universal Development Standards",
5
5
  "keywords": [
6
6
  "documentation",
@@ -1,10 +1,17 @@
1
1
  /**
2
- * `uds deps` — does what you test match what your users install?
2
+ * `uds deps` — does what you test match what your ranges resolve to?
3
3
  * // implements XSPEC-366 R1
4
4
  *
5
- * A published npm package does not carry its lockfile. This compares, per
6
- * runtime dependency, the declared range, the version the lockfile pins, and
7
- * the version a consumer's install would actually resolve to.
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.
@@ -23,7 +30,7 @@ import { measureResolutionDrift } from '../utils/dependency-resolution.js';
23
30
  * denominator is still printed, because "no drift" and "nothing was checked"
24
31
  * produce the same silence otherwise, and only one of them is good news.
25
32
  */
26
- function render(result) {
33
+ export function render(result) {
27
34
  const lines = [];
28
35
  const label = result.packageName ? chalk.bold(result.packageName) : result.root;
29
36
 
@@ -36,16 +43,42 @@ function render(result) {
36
43
 
37
44
  if (result.drifted.length > 0) {
38
45
  lines.push('');
39
- lines.push(chalk.yellow(` ${result.drifted.length} shipped ≠ tested:`));
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)}` +
43
- ` tested=${chalk.cyan(d.locked)} users get=${chalk.yellow(d.resolved)}`
57
+ ` tested=${chalk.cyan(d.locked)} resolves=${chalk.yellow(d.resolved)}`
44
58
  );
45
59
  }
46
60
  lines.push('');
47
- lines.push(chalk.dim(' Your lockfile pins the tested column; consumers resolve the range'));
48
- lines.push(chalk.dim(' themselves, because a published package does not ship a lockfile.'));
61
+ // Which of these two readings applies depends on how the project ships,
62
+ // and this command cannot know that — so it states both rather than
63
+ // asserting one. The first draft said only "consumers resolve the range
64
+ // themselves, because a published package does not ship a lockfile",
65
+ // which is plainly false for a product distributed as a container image
66
+ // built with `npm ci`. The standard this command implements scopes itself
67
+ // to published artifacts; the command did not, and a check that overstates
68
+ // its own conclusion is the thing it exists to catch.
69
+ // The column is labelled `resolves=`, not `users get=`. The second reads
70
+ // correctly on its own only for a published package; for a container image
71
+ // its users get the `tested=` column exactly, and a row read alone would
72
+ // then say the opposite of the truth. Leaving the label and explaining it
73
+ // underneath is the "but note…" this project's own supply-chain standard
74
+ // was rewritten to stop doing — a line of a report, like a line of a
75
+ // standards table, is mostly read one line at a time.
76
+ lines.push(chalk.dim(' Your lockfile pins the tested column.'));
77
+ lines.push(chalk.dim(' If you publish this package, that column reaches nobody — a published'));
78
+ lines.push(chalk.dim(' package ships no lockfile, so consumers resolve the ranges themselves.'));
79
+ lines.push(chalk.dim(' If instead you ship the lockfile with the artifact (a container image,'));
80
+ lines.push(chalk.dim(' a deployed service), the third column is what the next lockfile'));
81
+ lines.push(chalk.dim(' regeneration pulls in — unreviewed, and by whoever happens to run it.'));
49
82
  }
50
83
 
51
84
  if (result.unpinnedNative.length > 0) {
@@ -62,7 +95,7 @@ function render(result) {
62
95
  lines.push(chalk.dim(' promise about native ABI compatibility, and this ecosystem has'));
63
96
  lines.push(chalk.dim(' broken it inside a minor range. A range that matches one published'));
64
97
  lines.push(chalk.dim(' version is safe because upstream has not published again — waiting'));
65
- lines.push(chalk.dim(' for drift means waiting until your users already have it.'));
98
+ lines.push(chalk.dim(' for drift means waiting until it is already inside something you ship.'));
66
99
  }
67
100
 
68
101
  if (result.unverifiable.length > 0) {
@@ -2,10 +2,20 @@
2
2
  * Shipped dependency resolution integrity. // implements XSPEC-366 R1
3
3
  *
4
4
  * **The problem this measures.** A published npm package does not carry its
5
- * lockfile. Your CI tests the versions `package-lock.json` pins; your users get
6
- * whatever the declared ranges resolve to at their install time. When those two
7
- * differ, the entire test suite is green about a combination nobody installs —
8
- * and that green is indistinguishable from a real one.
5
+ * lockfile. Your CI tests the versions `package-lock.json` pins; whoever
6
+ * installs the package gets whatever the declared ranges resolve to at their
7
+ * install time. When those two differ, the entire test suite is green about a
8
+ * combination nobody installs — and that green is indistinguishable from a
9
+ * real one.
10
+ *
11
+ * **Who "whoever" is depends on how the project ships, and this module cannot
12
+ * know that.** For a published package it is every consumer. For a product
13
+ * distributed as a container image built with `npm ci`, its users get the
14
+ * pinned column exactly, and the resolved column is instead what the next
15
+ * lockfile regeneration will pull in — unreviewed, whenever someone happens to
16
+ * run it. Both are worth knowing; neither is safe to assert as the other. The
17
+ * report says both rather than picking one, and labels the column `resolves=`
18
+ * for the same reason.
9
19
  *
10
20
  * This is not hypothetical. `engramgraph` declared
11
21
  * `"tree-sitter-c-sharp": "^0.23.1"`. Three published versions satisfy that
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "version": "6.3.1",
3
+ "version": "6.3.3",
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.1"
61
+ "version": "6.3.3"
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.1",
68
+ "version": "6.3.3",
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.1",
2239
+ "version": "6.3.3",
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.1",
2251
+ "version": "6.3.3",
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.1",
2263
+ "version": "6.3.3",
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.1",
2275
+ "version": "6.3.3",
2276
2276
  "source": {
2277
2277
  "human": "core/resource-cost-boundary.md",
2278
2278
  "ai": "ai/standards/resource-cost-boundary.ai.yaml"