universal-dev-standards 6.14.0-beta.4 → 6.14.0-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/bin/uds.js +7 -1
- package/bundled/ai/standards/full-coverage-testing.ai.yaml +46 -5
- package/bundled/core/full-coverage-testing.md +57 -3
- package/bundled/locales/zh-CN/CHANGELOG.md +29 -2
- package/bundled/locales/zh-CN/README.md +1 -1
- package/bundled/locales/zh-CN/SECURITY.md +1 -1
- package/bundled/locales/zh-CN/core/full-coverage-testing.md +61 -7
- package/bundled/locales/zh-CN/docs/CHEATSHEET.md +3 -1
- package/bundled/locales/zh-CN/docs/FEATURE-REFERENCE.md +8 -5
- package/bundled/locales/zh-TW/CHANGELOG.md +29 -2
- package/bundled/locales/zh-TW/README.md +1 -1
- package/bundled/locales/zh-TW/SECURITY.md +1 -1
- package/bundled/locales/zh-TW/core/full-coverage-testing.md +61 -7
- package/bundled/locales/zh-TW/docs/CHEATSHEET.md +3 -1
- package/bundled/locales/zh-TW/docs/FEATURE-REFERENCE.md +8 -5
- package/bundled/templates/gates/check-anti-fake-tests.mjs +991 -0
- package/bundled/templates/gates/check-stubs.mjs +644 -0
- package/package.json +2 -2
- package/src/commands/audit.js +11 -0
- package/src/commands/check.js +124 -24
- package/src/commands/init.js +16 -0
- package/src/commands/update.js +180 -19
- package/src/core/install-records.js +2 -1
- package/src/i18n/messages.js +50 -9
- package/src/reconciler/backup-manager.js +418 -82
- package/src/reconciler/index.js +27 -5
- package/src/reconciler/install-roots.js +90 -0
- package/src/reconciler/plan-executor.js +23 -2
- package/src/uninstallers/hook-uninstaller.js +2 -1
- package/src/utils/command-hash-ownership.js +103 -0
- package/src/utils/copier.js +21 -1
- package/src/utils/gate-scripts.js +141 -0
- package/src/utils/health-scorer.js +10 -7
- package/src/utils/skill-hash-ownership.js +64 -0
- package/src/utils/skills-installer.js +12 -1
- package/src/utils/test-change-check.js +160 -0
- package/src/utils/test-policy.js +214 -0
- package/src/utils/update-summary.js +29 -0
- package/standards-registry.json +7 -7
- package/bundled/extensions/languages/php/fat-free-patterns.md +0 -915
- package/bundled/extensions/languages/php/php-style.md +0 -693
package/bin/uds.js
CHANGED
|
@@ -106,9 +106,13 @@ program
|
|
|
106
106
|
// Fallback to OS environment variable detection
|
|
107
107
|
setLanguage(detectLanguage(null));
|
|
108
108
|
})
|
|
109
|
-
.hook('postAction', async (thisCommand) => {
|
|
109
|
+
.hook('postAction', async (thisCommand, actionCommand) => {
|
|
110
110
|
const cmd = thisCommand.name();
|
|
111
111
|
if (!shouldCheckUpdateForCommand(cmd)) return;
|
|
112
|
+
// XSPEC-454 R3: --offline promises no network. This hook runs after every command and
|
|
113
|
+
// asks the npm registry for the latest version; it ignored the flag, so `check --offline`
|
|
114
|
+
// and `audit --offline` still made that request (whenever the terminal was interactive).
|
|
115
|
+
if (actionCommand?.opts?.().offline) return;
|
|
112
116
|
await printUpdateNoticeIfAvailable();
|
|
113
117
|
});
|
|
114
118
|
|
|
@@ -253,6 +257,8 @@ program
|
|
|
253
257
|
.option('--gh', 'Force gh CLI for submission')
|
|
254
258
|
.option('--format <format>', 'Output format (json)')
|
|
255
259
|
.option('--quiet', 'Summary only')
|
|
260
|
+
// XSPEC-454 R3: `check` and `update` already take --offline; `audit` rejected it with "unknown option".
|
|
261
|
+
.option('--offline', 'No network access at all: no CLI version check, and --report does not submit')
|
|
256
262
|
.option('--score', 'Run multi-dimensional health score analysis')
|
|
257
263
|
.option('--self', 'Self mode: analyze UDS repo itself (use with --score)')
|
|
258
264
|
.option('--save', 'Save score snapshot for trend tracking (use with --score)')
|
|
@@ -8,11 +8,11 @@ standard:
|
|
|
8
8
|
description: Behavior-completeness full coverage paradigm replacing pyramid thresholds. Enforces anti-fake-test rules, STUB marker protocol, ratchet CI, and @ac traceability.
|
|
9
9
|
|
|
10
10
|
meta:
|
|
11
|
-
version: "1.
|
|
12
|
-
updated: "2026-06
|
|
11
|
+
version: "1.2.0"
|
|
12
|
+
updated: "2026-10-06"
|
|
13
13
|
source: core/full-coverage-testing.md
|
|
14
14
|
replaces: "testing pyramid thresholds (UT≥80%/IT≥70%/E2E happy-path-only)"
|
|
15
|
-
xspec: "XSPEC-178"
|
|
15
|
+
xspec: "XSPEC-178, XSPEC-444"
|
|
16
16
|
description: AI-era full coverage paradigm — cost of writing tests equals cost of writing code, so there is no reason to set lower thresholds for any test layer.
|
|
17
17
|
|
|
18
18
|
rationale: |
|
|
@@ -180,6 +180,32 @@ standard:
|
|
|
180
180
|
trigger: '"// WARNING: STUB" marker found in src/'
|
|
181
181
|
message: "[STUB-WARN] STUB markers found. Must remove before merging to main."
|
|
182
182
|
|
|
183
|
+
# XSPEC-444 R2 + R5: what UDS itself ships so these rules are not only prose.
|
|
184
|
+
# Everything here WARNS by default; `mode: block` in the policy file tightens it.
|
|
185
|
+
shipped_gates:
|
|
186
|
+
default_mode: warn
|
|
187
|
+
policy_file: ".standards/test-policy.json" # optional; every list adds to the defaults
|
|
188
|
+
scripts: # written to scripts/ by `uds init`; never overwritten
|
|
189
|
+
- file: scripts/check-anti-fake-tests.mjs
|
|
190
|
+
finds: [no-assertion, tautology, all-skipped]
|
|
191
|
+
exit: "0 clean | 1 findings | 2 could not judge (never a pass)"
|
|
192
|
+
- file: scripts/check-stubs.mjs
|
|
193
|
+
finds: [stub-marker, not-implemented, empty-function]
|
|
194
|
+
exit: "0 clean | 1 findings | 2 could not judge (never a pass)"
|
|
195
|
+
pre_commit_checks: # run by `uds check` on what is staged
|
|
196
|
+
- id: code-without-test
|
|
197
|
+
finds: "code files changed and no test file changed in the same commit"
|
|
198
|
+
exempt: ["pure rename (git R100)", "policy exempt entry WITH a reason"]
|
|
199
|
+
- id: unclassified-file
|
|
200
|
+
finds: "a changed file of a type UDS does not recognise — listed, never assumed fine, never blocks"
|
|
201
|
+
language_coverage:
|
|
202
|
+
test_files: [javascript, typescript, python, java, kotlin, scala, csharp, go, rust, ruby, elixir, php, swift, dart, lua, cpp]
|
|
203
|
+
empty_function: [javascript, typescript, python, go, rust, ruby, php]
|
|
204
|
+
other_languages: "listed as NOT scanned — never counted as clean"
|
|
205
|
+
not_implemented_yet:
|
|
206
|
+
- "ratchet on the number of unpaired changes (spec does not define the baseline location or unit)"
|
|
207
|
+
- "per-commit exemption reason (a pre-commit hook cannot read the commit message)"
|
|
208
|
+
|
|
183
209
|
migration_from_pyramid:
|
|
184
210
|
deprecated:
|
|
185
211
|
- "UT ≥ 80% coverage threshold"
|
|
@@ -225,7 +251,22 @@ standard:
|
|
|
225
251
|
|
|
226
252
|
physical_spec:
|
|
227
253
|
type: custom_script
|
|
254
|
+
# XSPEC-444 R5: this used to check that two scripts EXIST — scripts UDS did not ship.
|
|
255
|
+
# Now it RUNS them (`uds check --standard full-coverage-testing`); a missing script,
|
|
256
|
+
# or a scanner that exits non-zero, fails the check. The scanners' findings go to stderr
|
|
257
|
+
# (`stdio: ['ignore', 2, 2]`) because a failing validator's stdout is not shown. Inline Node
|
|
258
|
+
# keeps it portable.
|
|
228
259
|
validator:
|
|
229
260
|
command: >
|
|
230
|
-
|
|
231
|
-
|
|
261
|
+
node -e "
|
|
262
|
+
const fs=require('fs'),cp=require('child_process');
|
|
263
|
+
let bad=0;
|
|
264
|
+
for(const f of ['check-anti-fake-tests.mjs','check-stubs.mjs']){
|
|
265
|
+
const p='scripts/'+f;
|
|
266
|
+
if(!fs.existsSync(p)){console.error('MISSING: '+p+' (uds update offers to write it)');bad=1;continue}
|
|
267
|
+
const r=cp.spawnSync(process.execPath,[p],{stdio:['ignore',2,2]});
|
|
268
|
+
if(r.status!==0){console.error('FAILED: '+p+' exited with '+r.status);bad=1}
|
|
269
|
+
}
|
|
270
|
+
process.exit(bad)
|
|
271
|
+
"
|
|
272
|
+
rule: "full_coverage_gate_scripts_clean"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Full Coverage Testing Standards
|
|
2
2
|
|
|
3
3
|
> **AI-optimized version**: `ai/standards/full-coverage-testing.ai.yaml`
|
|
4
|
-
> **XSPEC**: XSPEC-178
|
|
4
|
+
> **XSPEC**: XSPEC-178, XSPEC-444 (R2, R5 — pre-commit warnings and shipped gate scripts)
|
|
5
5
|
> **Replaces**: Pyramid threshold model (UT≥80%, IT≥70%, E2E happy-path-only)
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
@@ -228,6 +228,60 @@ Axis ⑨ is satisfied when this section declares all three: **derive** (Step 1 m
|
|
|
228
228
|
|
|
229
229
|
---
|
|
230
230
|
|
|
231
|
+
## Pre-commit Warnings and Gate Scripts Shipped by UDS (XSPEC-444 R2, R5)
|
|
232
|
+
|
|
233
|
+
The rules above used to depend on scripts the standard told you to write yourself. `uds init` now writes the scanners for you, and `uds check` — the command UDS's pre-commit hook runs — prints what they and one more check find. **All of it warns by default and blocks nothing**; tightening is opt-in (see "Warn first, tighten later").
|
|
234
|
+
|
|
235
|
+
### The two scanners (`uds init` writes them to `scripts/`)
|
|
236
|
+
|
|
237
|
+
| Script | Finds |
|
|
238
|
+
|--------|-------|
|
|
239
|
+
| `scripts/check-anti-fake-tests.mjs` | a test with **no assertion**; a test whose only assertions are **tautologies** (`expect(true).toBe(true)`, `assert 200 == 200`); a test file in which **every test is skipped or todo** |
|
|
240
|
+
| `scripts/check-stubs.mjs` | `// WARNING: STUB` markers; a body that says it is **not implemented** (`raise NotImplementedError`, `todo!()`, `TODO()` ...) with no marker beside it; a named function whose body is **empty** with no marker beside it |
|
|
241
|
+
|
|
242
|
+
- Pure Node, no dependencies, no test framework assumed. They are **your files**: edit them, wire them into CI. Run on its own, each exits non-zero when it finds something — `node scripts/check-stubs.mjs` is the pre-push/deploy gate this standard's deployment gates describe.
|
|
243
|
+
- `uds init` never overwrites a file that exists, and `uds update` never overwrites one either; for a project initialised earlier, `uds update` offers to write them (the prompt defaults to no; `uds update -y` answers it yes).
|
|
244
|
+
- With files staged they read only those files; with nothing staged (a CI run, a manual `uds check`) each walks the whole project — the walk stops at 200,000 files, and `uds check` gives each scanner 120 seconds (past that it reports "could not judge", never a pass) — so in a very large repository run them in CI rather than expecting them to be instant.
|
|
245
|
+
- A placeholder is *declared* by `STUB` or `COVERAGE_EXEMPT` on its line or the three above; a declared placeholder is reported once, as its marker.
|
|
246
|
+
- **Languages.** Test-file rules exist for JavaScript/TypeScript, Python, Java/Kotlin/Scala/C#, Go, Rust, Ruby, Elixir, PHP, Swift, Dart, Lua and C/C++. A test file in any **other** language is listed as "NOT scanned" — never counted as clean. Empty-function rules exist for JavaScript/TypeScript, Python, Go, Rust, Ruby and PHP; elsewhere markers and "not implemented" bodies are still found and the output says which languages had no empty-function rule.
|
|
247
|
+
- They read text; they do not run your tests. A helper that asserts under a name the scanner cannot recognise is reported as "no-assertion": name it `assert*` / `verify*` / `expect*`, or list its pattern under `assertionPatterns` in the policy file.
|
|
248
|
+
- Each run first checks itself against known fakes and known good tests; if that fails it exits `2` ("could not judge"), which is never a pass.
|
|
249
|
+
|
|
250
|
+
### Code changed without a test (`uds check`, on staged changes)
|
|
251
|
+
|
|
252
|
+
When files are staged for commit, `uds check` compares what changed:
|
|
253
|
+
|
|
254
|
+
- code files changed and **no test file** changed in the same commit → a warning that lists the code files;
|
|
255
|
+
- a changed file of a type UDS does not recognise → a warning that lists it and says how to classify it (never assumed fine, never blocks);
|
|
256
|
+
- a deletion is not a change that needs a test; a **pure rename** (git's `R100`) and a path matching an `exempt` entry are exempt, and the output records the reason.
|
|
257
|
+
|
|
258
|
+
With nothing staged (a CI run, a manual `uds check`) the diff check says nothing; the two scanners then look at the whole project.
|
|
259
|
+
|
|
260
|
+
### The policy file `.standards/test-policy.json` (optional)
|
|
261
|
+
|
|
262
|
+
Which paths are tests and which are code is data with defaults for the common ecosystems, not a list of frameworks. Every list **adds to** the defaults:
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"mode": "warn",
|
|
267
|
+
"testDirs": ["integration"],
|
|
268
|
+
"testPatterns": ["*.itest.*"],
|
|
269
|
+
"sourceExtensions": ["zig"],
|
|
270
|
+
"nonCodeExtensions": ["gradle"],
|
|
271
|
+
"ignore": ["generated/**"],
|
|
272
|
+
"exempt": [{ "pattern": "src/gen/**", "reason": "generated by protoc" }],
|
|
273
|
+
"assertionPatterns": ["\\bmustMatch\\w*\\s*\\("]
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
An `exempt` entry without a `reason` is not honored and is reported: an exemption must say why.
|
|
278
|
+
|
|
279
|
+
### Warn first, tighten later
|
|
280
|
+
|
|
281
|
+
`"mode": "warn"` (the default) prints and lets the commit through. `"mode": "block"` makes `uds check` exit non-zero — and so stops the commit — when a scanner finds something, a scanner cannot judge, or code changed without a test. A file type UDS does not recognise never blocks. **Not implemented yet** (the specification does not say where a baseline would live or what it counts): a ratchet on the number of unpaired changes, and a per-commit exemption reason (a pre-commit hook cannot read the commit message).
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
231
285
|
## Migration from Pyramid Model
|
|
232
286
|
|
|
233
287
|
If your project previously used pyramid thresholds:
|
|
@@ -235,8 +289,8 @@ If your project previously used pyramid thresholds:
|
|
|
235
289
|
1. **Delete** any hardcoded coverage thresholds from `jest.config.js` / `vitest.config.ts` (`coverageThreshold` option)
|
|
236
290
|
2. **Install** `.coverage-baseline.json` with current coverage as the starting ratchet
|
|
237
291
|
3. **Add** `scripts/check-coverage-ratchet.sh` to CI
|
|
238
|
-
4. **Add** `scripts/check-stubs.
|
|
239
|
-
5. **Add** `scripts/check-anti-fake-tests.
|
|
292
|
+
4. **Add** `scripts/check-stubs.mjs` to deploy.sh and pre-push hook (written by `uds init`; `uds update` offers it to an existing project)
|
|
293
|
+
5. **Add** `scripts/check-anti-fake-tests.mjs` to pre-commit or CI (written by `uds init`; `uds check` already runs it and warns)
|
|
240
294
|
|
|
241
295
|
The ratchet starts at your current coverage. From that point on, it can only increase.
|
|
242
296
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.14.0-beta.
|
|
4
|
-
translation_version: 6.14.0-beta.
|
|
3
|
+
source_version: 6.14.0-beta.5
|
|
4
|
+
translation_version: 6.14.0-beta.5
|
|
5
5
|
last_synced: 2026-10-06
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
@@ -17,6 +17,33 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.14.0-beta.5] - 2026-10-06
|
|
21
|
+
|
|
22
|
+
> **测试版**——以 `npm install -g universal-dev-standards@beta` 安装。要测什么、如何退回正式版:[docs/PRE-RELEASE.md](../../docs/PRE-RELEASE.md)。
|
|
23
|
+
>
|
|
24
|
+
> **行为改变:**`uds check` 计入技能与命令文件的缺失或修改(`--ci` 以 1 结束);`uds check --diff` 以所装包为原稿,不再抓取 GitHub `main`;`uds init` 会加入两个在提交时警告的扫描脚本。
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- **行为改变——`uds check --diff` 现在以你所安装的 UDS 包内的文件为原稿,不再对照 GitHub `main`。** 这个差异回答的是“我改了 UDS 给我的哪些地方”;它过去从 GitHub `main` 下载原稿,所以离线会失败(扩展文件也一样),而且 UDS 在你安装后自己改过的内容,会被列成你改的差异。现在原稿一律从所装包读取——标准、选项、扩展文件皆同——不下载任何内容。命令会打印比对基准(`installed UDS package (version X)`),并提示查看 UDS 之后的变更请用 `uds update --plan`。若项目内的标准是从另一个 UDS 版本安装的、与当前安装的包版本不同,也会明说,因为两个版本之间 UDS 改过的文件会显示成差异。包内找不到某个受追踪文件的原稿时,命令会**点名**该文件、不下载、以退出码 1 结束;不再退回 GitHub,也不再静默跳过。没有被修改的文件时,`--diff` 现在会说“没有差异可显示”,而不是什么都不打印。**谁会看到不同:**执行 `uds check --diff`(或在交互式 `uds check` 中选择“查看”)的人——凡是 `main` 与你所装版本不同之处,差异可能与以往不同;而原本在包缺原稿时读到退出码 0 的脚本,现在会读到 1。**要做什么:**无需任何操作;要查看上游有什么新内容,请执行 `uds update --plan`。落实 dev-platform XSPEC-453 R1。
|
|
29
|
+
|
|
30
|
+
### Removed
|
|
31
|
+
|
|
32
|
+
- **移除 `extensions/languages/php/`**——两个没有任何东西引用的文件(`php-style.md`、`fat-free-patterns.md`,约 37 KB);安装器、registry 与文档使用的是 `extensions/languages/php-style.md` 与 `extensions/frameworks/fat-free-patterns.md`,两者不变。npm 包因此少了这两个文件,现在恰好只含安装器装得到的 5 个扩展文件;新增的测试会在有未声明的扩展文件被打包时变红。`uds init --lang php` 与 `--framework fat-free` 安装的文件与先前相同。落实 dev-platform XSPEC-453 R2。
|
|
33
|
+
|
|
34
|
+
### 修复
|
|
35
|
+
|
|
36
|
+
- **健康分数的覆盖度维度不再报告永远是 0 的 `has_tests`。**`calculateCoverage` 声明了 `hasTests = 0` 却从未改动它,所以 `uds audit --score` 打印出一个看起来像“标准有没有测试”的度量、实际上不会动的数字。它已从加总与 `details` 移除;**任何项目的覆盖度分数都不变**(分母本来就是每个标准两份——`check-<id>.sh` 与 `check-<id>-sync.sh`)。(XSPEC-444 R5)
|
|
37
|
+
- **行为改变——`uds check` 现在会把缺失或被改过的技能文件计入判定。它以前会打出红色 ✗,结尾却仍说「项目符合标准」、exit 0。** Skills 完整性检查的结果算出来之后被丢掉了。现在删掉或改过技能文件,`uds check` 会说「检测到一些问题」并点名该文件,`uds check --ci` 会 exit 1(不带 `--ci` 时 exit code 仍是 0,与其他各类发现一致;UDS 写的 pre-commit hook 运行的是不带参数的 `uds check`,所以不会因此被挡)。**谁会看到差别:**技能文件夹被改过或丢了文件的项目。**怎么处理:**运行消息打印出的命令 `uds update --apply --skills`。**幽灵记录先处理,所以已有项目不会突然开始失败:**项目的 manifest 可能列着 UDS 从未安装的技能文件——采用者自己的技能,以及旧版 UDS 因为哈希整个文件夹而误拷进技能文件夹的 `agents/`、`workflows/`、`_shared/`,后来 `uds update` 把它们删了却没忘掉记录(有个项目显示 26 个「缺失」,6.11.0 与 6.14.0-beta.4 相同)。现在安装器只记录自己装的技能(也不记录自己的 `.manifest.json`);`uds update` 删掉技能文件夹时一并删掉它的记录;`uds check` 忽略不描述任何发布技能的记录并说出有几条(`N skill record(s) ignored`);`uds update`(`--apply`、`--skills`,或已是最新版的路径)会把它们从 `.standards/manifest.json` 永久清掉。**斜杠命令文件同样适用**——它的检查结果原本也被丢弃:命令文件被删或被改,`uds check` 现在会点名,`--ci` 会 exit 1(修复:`uds update --apply --commands`)。UDS 不发布的命令记录由 `uds update` 清掉;装在用户级(所有项目共用,本项目无从背书)的命令记录,检查会忽略并说明。另外,当「改代码没动测试」或「假测试」检查设为 `"mode": "block"` 时,`uds check` 打印 BLOCKED 后不再以「符合标准」收尾。落实 dev-platform XSPEC-454 R2。
|
|
38
|
+
- **`uds update --rollback` 现在还原整个升级,而不只是标准文件。** 依次运行 `update --apply`、`update --apply --skills`、`update --apply --commands` 后,一次 `--rollback` 只还原标准文件与 `CLAUDE.md`/`AGENTS.md`,新增的技能文件夹(`comprehension-ladder`)、技能与命令的 `.manifest.json`、以及 `.standards/manifest.json` 里的哈希记录都留在新版,于是 `uds check` 报修改过的文件,项目同时不符合两个版本。原因:备份只记录计划要覆盖的文件(没有更新所创建的文件,也没有 `.standards/manifest.json`);`--skills` 与 `--commands` 写文件时完全没有备份;还原用的 `copyFileSync` 还原不了文件夹。现在 `--apply`、`--apply --skills`、`--apply --commands` 的每一步都创建备份,并记录它所创建的文件(`--skills`/`--commands` 自己创建备份,没有备份就不写;只备份 UDS 发布的技能与命令,不碰你自己的);不带 `--apply` 的一般 `uds update` 仍和以前一样不创建备份;连续的步骤以 `.standards/manifest.json` 前后的哈希串起来,所以一次 `--rollback` 会一路退过整串没有被打断的升级,并在中间有别的变更处停下来、明说;还原后会读回验证;命令会打印还原了什么、移除了什么,若有任何失败,**不会以「成功」收尾**(exit 1,并说明怎么重试)。**没有涵盖、并会如实打印:**用户级的技能/命令(`~/.claude/skills`,由所有项目共用),以及旧版本做的备份(它们从未记录所创建的文件与 manifest)。落实 dev-platform XSPEC-454 R1。
|
|
39
|
+
- **`uds update --commands` 把命令数打成了工具数**(只有一个 OpenCode 却打「为 51 个 AI 工具更新」)。该消息键在每个语言都写成「N 个 AI 工具」,却被填入命令文件数。现在有独立的消息,两个字段各放各的数字:「Updated 51 commands for 1 AI tool(s)」/「已為 1 個 AI 工具更新 51 個斜線命令」/「已为 1 个 AI 工具更新 51 个斜线命令」。旧键的其他用法本来就传工具数,不变。落实 dev-platform XSPEC-454 R4。
|
|
40
|
+
|
|
41
|
+
### 新增
|
|
42
|
+
|
|
43
|
+
- **`uds init` 现在会附上 `full-coverage-testing` 一直要你自己写的假测试与空壳扫描脚本,`uds check` 会把它们找到的东西以警告打印。**标准一直写着“新增 `scripts/check-stubs.sh` 与 `scripts/check-anti-fake-tests.sh`”,验证器也只检查这两个文件存在——但 UDS 两个都没附,这条指示根本照做不了。`uds init` 现在会写入 `scripts/check-anti-fake-tests.mjs`(找**没有断言**的测试、唯一的断言是 `expect(true).toBe(true)` 或 `assert 200 == 200` 这类**恒真式**的测试、**每个测试都被跳过或标 todo** 的测试文件)与 `scripts/check-stubs.mjs`(`// WARNING: STUB` 标记、声称**尚未实现**而旁边没有标记的函数体、函数体**为空**而旁边没有标记的具名函数)。纯 Node、零依赖、不预设测试框架;它们是你的文件。单独运行时,找到东西就以非 0 退出。**`uds check`——pre-commit hook 执行的命令——会运行它们并把找到的东西打印成警告;不拦任何东西**,除非你在 `.standards/test-policy.json` 设 `"mode": "block"`。有暂存文件时扫描那些文件;没有暂存任何东西时(CI 运行)扫描整个项目。**测试文件规则覆盖 JavaScript/TypeScript、Python、Java/Kotlin/Scala/C#、Go、Rust、Ruby、Elixir、PHP、Swift、Dart、Lua 与 C/C++;其他语言的测试文件会被列为“未扫描”,绝不当成干净。**它们读的是文本、不运行你的测试,所以用扫描器认不出的名称做断言的辅助函数会被报为“no-assertion”(请命名为 `assert*`/`verify*`/`expect*`,或把模式列在 `assertionPatterns`)。每次运行都先拿已知的假测试与好测试检验自己,失败就以 `2`(“无法判定”,绝不算通过)退出。已存在的文件绝不覆盖;`uds uninstall` 只移除 `uds init` 写入且未被改动的文件;较早初始化的项目由 `uds update` 询问是否写入(提示的默认为否;**`uds update -y` 会直接回答是**,所以升级命令是 `uds update -y` 的项目,下次更新就会多这两个文件)。**谁会看到差别:**本版之后每次 `uds init` 会在 `scripts/` 多两个文件,每次提交 `uds check` 会多打印两行(或找到的东西)。**怎么处理:**读它的发现;想让某类文件不再被报,加一份 `test-policy.json`;想强制执行,设 `"mode": "block"` 或在 CI 跑这两个脚本。`uds check --standard full-coverage-testing` 现在会运行这两个脚本,不再只检查它们存在。(XSPEC-444 R5)
|
|
44
|
+
- **`uds check` 在一次提交改了代码却没动任何测试时发出警告。**有文件暂存时,`uds check` 会在“改了代码文件、同一次提交没有测试文件变动”时列出那些代码文件,并列出它不认识类型的变更文件(绝不当成没事,也绝不拦)。删除不需要测试;纯重命名(git `R100`)与匹配 `exempt` 条目的路径可免,输出会记下理由。哪些路径是测试、哪些是代码,是带有常见生态默认值的数据——`*.test.*`、`*_test.go`、`test_*.py`、`*Test.java`、`tests/` 等——由 `.standards/test-policy.json`(`testDirs`、`testPatterns`、`sourceExtensions`、`nonCodeExtensions`、`ignore`,以及每条都必须附 `reason` 否则不生效的 `exempt`)**加进**而不是取代。**它只警告、放行提交。**同一份文件里的 `"mode": "block"` 会让它拦下提交;这是目前提供的唯一收紧步骤。**没有做,因为规格没有定义:**未配测试的变更数棘轮(基线放在哪、以什么计数),以及逐次提交的豁免理由(pre-commit hook 读不到提交信息)。(XSPEC-444 R2)
|
|
45
|
+
- **`uds audit --offline`。** `check` 与 `update` 早就有,`audit` 却回「unknown option」。加上它之后,`audit` 不发任何网络请求——包含每个命令结束后的「有新版本」提示(它对 `check`、`update` 也忽略 `--offline`,现在都遵守);`--report` 会说「离线模式:不提交回报。」(并指出出路 `--dry-run`),而不是去启动 `gh`、浏览器或剪贴板。落实 dev-platform XSPEC-454 R3。
|
|
46
|
+
|
|
20
47
|
## [6.14.0-beta.4] - 2026-10-06
|
|
21
48
|
|
|
22
49
|
> **测试版**——以 `npm install -g universal-dev-standards@beta` 安装。要测什么、如何退回正式版:[docs/PRE-RELEASE.md](../../docs/PRE-RELEASE.md)。
|
|
@@ -15,7 +15,7 @@ status: current
|
|
|
15
15
|
|
|
16
16
|
> **语言**: [English](../../README.md) | [繁體中文](../zh-TW/README.md) | 简体中文
|
|
17
17
|
|
|
18
|
-
**版本**: 6.14.0-beta.
|
|
18
|
+
**版本**: 6.14.0-beta.5 (Pre-release) | **发布日期**: 2026-10-06 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
语言无关、框架无关的软件项目文档标准。通过 AI 原生工作流,确保不同技术栈之间的一致性、质量和可维护性。
|
|
21
21
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../../core/full-coverage-testing.md
|
|
3
|
-
source_version: 1.
|
|
4
|
-
translation_version: 1.
|
|
5
|
-
last_synced: 2026-
|
|
6
|
-
source_hash:
|
|
3
|
+
source_version: 1.2.0
|
|
4
|
+
translation_version: 1.2.0
|
|
5
|
+
last_synced: 2026-10-06
|
|
6
|
+
source_hash: 1fe2966d8684
|
|
7
7
|
status: current
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ status: current
|
|
|
12
12
|
> **Language**: [English](../../../core/full-coverage-testing.md) | [繁體中文](../../zh-TW/core/full-coverage-testing.md) | 简体中文
|
|
13
13
|
|
|
14
14
|
> **AI 最优化版本**: `ai/standards/full-coverage-testing.ai.yaml`
|
|
15
|
-
> **XSPEC**: XSPEC-178
|
|
15
|
+
> **XSPEC**: XSPEC-178、XSPEC-444(R2、R5——提交前警告与随附闸门脚本)
|
|
16
16
|
> **取代**: 金字塔门槛模型(UT≥80%、IT≥70%、E2E 仅 happy-path)
|
|
17
17
|
|
|
18
18
|
## 概述
|
|
@@ -239,6 +239,60 @@ legacy 降级模式(外部服务失败时的 fallback、重试、部分结果
|
|
|
239
239
|
|
|
240
240
|
---
|
|
241
241
|
|
|
242
|
+
## UDS 随附的提交前警告与闸门脚本(XSPEC-444 R2、R5)
|
|
243
|
+
|
|
244
|
+
上面的规则过去要靠标准让你自己写的脚本来执行。现在 `uds init` 会直接把扫描脚本写进你的项目,而 `uds check`——UDS 的 pre-commit hook 执行的命令——会打印这些脚本和另一项检查找到的东西。**默认一律只警告、不拦任何东西**;要收紧是可选的(见“先警告,之后再收紧”)。
|
|
245
|
+
|
|
246
|
+
### 两个扫描脚本(`uds init` 写到 `scripts/`)
|
|
247
|
+
|
|
248
|
+
| 脚本 | 找什么 |
|
|
249
|
+
|------|--------|
|
|
250
|
+
| `scripts/check-anti-fake-tests.mjs` | **没有断言**的测试;唯一的断言是**恒真式**的测试(`expect(true).toBe(true)`、`assert 200 == 200`);**每个测试都被跳过或标为 todo** 的测试文件 |
|
|
251
|
+
| `scripts/check-stubs.mjs` | `// WARNING: STUB` 标记;声称**尚未实现**的函数体(`raise NotImplementedError`、`todo!()`、`TODO()` 等)而旁边没有标记;函数体**为空**的具名函数而旁边没有标记 |
|
|
252
|
+
|
|
253
|
+
- 纯 Node、零依赖、不预设任何测试框架。它们是**你的文件**:可以改、可以接入 CI。单独运行时,找到东西就以非 0 退出——`node scripts/check-stubs.mjs` 就是本标准部署闸门所说的 pre-push/部署闸门。
|
|
254
|
+
- `uds init` 不会覆盖已存在的文件,`uds update` 也不会;较早初始化的项目,`uds update` 会询问是否写入(提示的默认为否;`uds update -y` 会直接回答是)。
|
|
255
|
+
- 有暂存文件时只读那些文件;没有暂存任何东西时(CI 运行、手动 `uds check`)每个都会遍历整个项目——遍历最多 200,000 个文件,`uds check` 给每个 120 秒(超过就报告“无法判定”,绝不算通过)——所以在很大的仓库里,请在 CI 运行,不要期待立刻完成。
|
|
256
|
+
- 同一行或上面三行内出现 `STUB` 或 `COVERAGE_EXEMPT`,该临时实现就算已**声明**;已声明的只以标记报告一次。
|
|
257
|
+
- **语言范围。**测试文件规则覆盖 JavaScript/TypeScript、Python、Java/Kotlin/Scala/C#、Go、Rust、Ruby、Elixir、PHP、Swift、Dart、Lua 与 C/C++。其他语言的测试文件会被列为“未扫描”——绝不当成干净。空函数规则覆盖 JavaScript/TypeScript、Python、Go、Rust、Ruby 与 PHP;其他语言仍会找标记与“尚未实现”的函数体,输出也会写明哪些语言没有空函数规则。
|
|
258
|
+
- 它们读的是文本,不运行你的测试。若某个辅助函数用扫描器认不出的名称做断言,会被报为“no-assertion”:把它命名为 `assert*`/`verify*`/`expect*`,或把它的模式列在策略文件的 `assertionPatterns`。
|
|
259
|
+
- 每次运行都先拿已知的假测试与已知的好测试检验自己;检验失败就以 `2`(“无法判定”)退出,这绝不算通过。
|
|
260
|
+
|
|
261
|
+
### 改了代码却没动测试(`uds check`,针对已暂存的变更)
|
|
262
|
+
|
|
263
|
+
有文件暂存准备提交时,`uds check` 会比对变更内容:
|
|
264
|
+
|
|
265
|
+
- 改了代码文件,**同一次提交没有任何测试文件变动** → 警告,并列出代码文件;
|
|
266
|
+
- 变更中有 UDS 不认识的文件类型 → 警告,列出它并说明如何分类(绝不当成没事,也绝不拦);
|
|
267
|
+
- 删除不算需要测试的变更;**纯重命名**(git 的 `R100`)与匹配 `exempt` 条目的路径可免,输出会记下理由。
|
|
268
|
+
|
|
269
|
+
没有暂存任何东西时(CI 运行、手动 `uds check`),差异检查不出声;两个扫描脚本则改为扫整个项目。
|
|
270
|
+
|
|
271
|
+
### 策略文件 `.standards/test-policy.json`(可选)
|
|
272
|
+
|
|
273
|
+
哪些路径是测试、哪些是代码,是带有常见生态默认值的数据,不是一份框架清单。每个列表都是**加进**默认值:
|
|
274
|
+
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"mode": "warn",
|
|
278
|
+
"testDirs": ["integration"],
|
|
279
|
+
"testPatterns": ["*.itest.*"],
|
|
280
|
+
"sourceExtensions": ["zig"],
|
|
281
|
+
"nonCodeExtensions": ["gradle"],
|
|
282
|
+
"ignore": ["generated/**"],
|
|
283
|
+
"exempt": [{ "pattern": "src/gen/**", "reason": "generated by protoc" }],
|
|
284
|
+
"assertionPatterns": ["\\bmustMatch\\w*\\s*\\("]
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
没有 `reason` 的 `exempt` 条目不会生效,并会被报告:豁免必须说明原因。
|
|
289
|
+
|
|
290
|
+
### 先警告,之后再收紧
|
|
291
|
+
|
|
292
|
+
`"mode": "warn"`(默认)只打印警告、放行提交。`"mode": "block"` 会让 `uds check` 在以下情况以非 0 退出,因此拦下提交:扫描脚本找到东西、扫描脚本无法判定、或改了代码却没动测试。UDS 不认识的文件类型永远不会拦。**尚未实现**(规格没有定义基线放在哪里、以什么计数):未配测试的变更数棘轮,以及逐次提交的豁免理由(pre-commit hook 读不到提交信息)。
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
242
296
|
## 从金字塔模型迁移
|
|
243
297
|
|
|
244
298
|
若你的项目先前使用金字塔门槛:
|
|
@@ -246,8 +300,8 @@ legacy 降级模式(外部服务失败时的 fallback、重试、部分结果
|
|
|
246
300
|
1. **删除** `jest.config.js` / `vitest.config.ts` 中任何硬编码的覆盖率门槛(`coverageThreshold` 选项)
|
|
247
301
|
2. **安装** `.coverage-baseline.json`,以当前的覆盖率作为棘轮起点
|
|
248
302
|
3. **新增** `scripts/check-coverage-ratchet.sh` 到 CI
|
|
249
|
-
4. **新增** `scripts/check-stubs.
|
|
250
|
-
5. **新增** `scripts/check-anti-fake-tests.
|
|
303
|
+
4. **新增** `scripts/check-stubs.mjs` 到 deploy.sh 与 pre-push hook(由 `uds init` 写入;已有项目由 `uds update` 提供)
|
|
304
|
+
5. **新增** `scripts/check-anti-fake-tests.mjs` 到 pre-commit 或 CI(由 `uds init` 写入;`uds check` 已会运行并警告)
|
|
251
305
|
|
|
252
306
|
棘轮从你当前的覆盖率开始。从那一刻起,它只能上升。
|
|
253
307
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UDS 速查表
|
|
2
2
|
|
|
3
|
-
> Quick reference for all UDS features | Last updated: 2026-
|
|
3
|
+
> Quick reference for all UDS features | Last updated: 2026-10-06
|
|
4
4
|
|
|
5
5
|
**Language**: [English](../../../docs/user/CHEATSHEET.md) | [繁體中文](../../zh-TW/docs/CHEATSHEET.md) | 简体中文
|
|
6
6
|
|
|
@@ -110,6 +110,7 @@
|
|
|
110
110
|
| `ci-cd-assistant` | 引导 CI/CD 流水线的设计、配置与优化。 |
|
|
111
111
|
| `code-review-assistant` | [UDS] 系统性代码审查的参考资料:八大审查类别,以及 BLOCKING/IMPORTANT/SUGGESTION 评 |
|
|
112
112
|
| `commit-standards` | [UDS] 生成符合 Conventional Commits 规范的 commit message,包含双语格式。 |
|
|
113
|
+
| `comprehension-ladder` | [UDS] 把一段难懂的 AI 输出换成较好懂的形式:受控文字、Mermaid 图、单文件 HTML 解说页。所有形式都 |
|
|
113
114
|
| `contract-test-assistant` | [UDS] 引导 API 与微服务的契约测试策略。 |
|
|
114
115
|
| `database-assistant` | 引导数据库设计、迁移与查询优化。 |
|
|
115
116
|
| `deploy-assistant` | 引导在没有 CI/CD 平台(GitHub Actions/GitLab CI)的情况下完成可靠部署。 |
|
|
@@ -388,6 +389,7 @@
|
|
|
388
389
|
| `generate-version-manifest.mjs` | Generate Version Manifest (SPEC-SELFDIAG-001 REQ-9 |
|
|
389
390
|
| `install-hooks.mjs` | Install Hooks |
|
|
390
391
|
| `install-hooks.sh` | Thin wrapper — scripts/install-hooks.mjs is the on |
|
|
392
|
+
| `npm-pack-files.mjs` | @param {string} stdout @returns {string[]} package |
|
|
391
393
|
| `pre-commit.mjs` | Build a platform-aware shell command for a .sh scr |
|
|
392
394
|
| `pre-release-check.ps1` | Pre Release Check |
|
|
393
395
|
| `pre-release-check.sh` | Pre-release Check Script |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# UDS 功能参考手册
|
|
2
2
|
|
|
3
3
|
> Universal Development Standards - 完整功能文档
|
|
4
|
-
> Auto-generated | Last updated: 2026-
|
|
4
|
+
> Auto-generated | Last updated: 2026-10-06
|
|
5
5
|
|
|
6
6
|
**Language**: [English](../../../docs/reference/FEATURE-REFERENCE.md) | [繁體中文](../../zh-TW/docs/FEATURE-REFERENCE.md) | 简体中文
|
|
7
7
|
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
|
|
12
12
|
1. [CLI 指令](#cli-commands) (24)
|
|
13
13
|
2. [斜线命令](#slash-commands) (51)
|
|
14
|
-
3. [技能](#skills) (
|
|
14
|
+
3. [技能](#skills) (56)
|
|
15
15
|
4. [代理](#agents) (5)
|
|
16
16
|
5. [工作流程](#workflows) (5)
|
|
17
17
|
6. [核心规范](#core-standards) (153)
|
|
18
|
-
7. [脚本](#scripts) (
|
|
18
|
+
7. [脚本](#scripts) (64)
|
|
19
19
|
|
|
20
|
-
**Total Features:
|
|
20
|
+
**Total Features: 358**
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -181,6 +181,7 @@
|
|
|
181
181
|
| `--gh` | Force gh CLI for submission |
|
|
182
182
|
| `--format` | Output format (json) |
|
|
183
183
|
| `--quiet` | Summary only |
|
|
184
|
+
| `--offline` | No network access at all: no CLI version check, and --report does not submit |
|
|
184
185
|
| `--score` | Run multi-dimensional health score analysis |
|
|
185
186
|
| `--self` | Self mode: analyze UDS repo itself (use with --score) |
|
|
186
187
|
| `--save` | Save score snapshot for trend tracking (use with --score) |
|
|
@@ -365,6 +366,7 @@
|
|
|
365
366
|
| `ci-cd-assistant` | 引导 CI/CD 流水线的设计、配置与优化。 |
|
|
366
367
|
| `code-review-assistant` | [UDS] 系统性代码审查的参考资料:八大审查类别,以及 BLOCKING/IMPORTANT/SUGGESTION 评论前缀。 |
|
|
367
368
|
| `commit-standards` | [UDS] 生成符合 Conventional Commits 规范的 commit message,包含双语格式。 |
|
|
369
|
+
| `comprehension-ladder` | [UDS] 把一段难懂的 AI 输出换成较好懂的形式:受控文字、Mermaid 图、单文件 HTML 解说页。所有形式都来自同一份大纲,所以形式会变,事实不会变。 |
|
|
368
370
|
| `contract-test-assistant` | [UDS] 引导 API 与微服务的契约测试策略。 |
|
|
369
371
|
| `database-assistant` | 引导数据库设计、迁移与查询优化。 |
|
|
370
372
|
| `deploy-assistant` | 引导在没有 CI/CD 平台(GitHub Actions/GitLab CI)的情况下完成可靠部署。 |
|
|
@@ -448,7 +450,7 @@
|
|
|
448
450
|
| `ai-command-behavior` | 1.0.0 | This standard defines a structure for specifying AI Agent runtime behavior in co |
|
|
449
451
|
| `ai-friendly-architecture` | 1.0.0 | This standard defines architecture and documentation practices that maximize the |
|
|
450
452
|
| `ai-instruction-standards` | 1.1.1 | This standard defines best practices for creating and maintaining AI instruction |
|
|
451
|
-
| `ai-response-navigation` | 1.
|
|
453
|
+
| `ai-response-navigation` | 1.4.0 | This standard defines navigation behavior for AI responses: every substantive AI |
|
|
452
454
|
| `alerting-standards` | 1.0.0 | |
|
|
453
455
|
| `anti-hallucination` | 1.5.1 | This standard defines strict guidelines for AI assistants to prevent hallucinati |
|
|
454
456
|
| `anti-sycophancy-prompting` | 1.0.0 | This standard defines techniques and rules for designing prompts that elicit gen |
|
|
@@ -651,6 +653,7 @@
|
|
|
651
653
|
| `generate-version-manifest.mjs` | Generate Version Manifest (SPEC-SELFDIAG-001 REQ-9, AC-14) |
|
|
652
654
|
| `install-hooks.mjs` | Install Hooks |
|
|
653
655
|
| `install-hooks.sh` | Thin wrapper — scripts/install-hooks.mjs is the only copy of the installer |
|
|
656
|
+
| `npm-pack-files.mjs` | @param {string} stdout @returns {string[]} package-relative file paths |
|
|
654
657
|
| `pre-commit.mjs` | Build a platform-aware shell command for a .sh script. |
|
|
655
658
|
| `pre-release-check.ps1` | Pre Release Check |
|
|
656
659
|
| `pre-release-check.sh` | Pre-release Check Script |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.14.0-beta.
|
|
4
|
-
translation_version: 6.14.0-beta.
|
|
3
|
+
source_version: 6.14.0-beta.5
|
|
4
|
+
translation_version: 6.14.0-beta.5
|
|
5
5
|
last_synced: 2026-10-06
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
@@ -17,6 +17,33 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.14.0-beta.5] - 2026-10-06
|
|
21
|
+
|
|
22
|
+
> **測試版**——以 `npm install -g universal-dev-standards@beta` 安裝。要測什麼、如何退回正式版:[docs/PRE-RELEASE.md](../../docs/PRE-RELEASE.md)。
|
|
23
|
+
>
|
|
24
|
+
> **行為改變:**`uds check` 計入技能與命令檔的遺失或修改(`--ci` 以 1 結束);`uds check --diff` 以所裝套件為原稿,不再抓 GitHub `main`;`uds init` 會加入兩支在提交時警告的掃描腳本。
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- **行為改變——`uds check --diff` 現在以你所安裝的 UDS 套件內的檔為原稿,不再對照 GitHub `main`。** 這個差異回答的是「我改了 UDS 給我的哪些地方」;它過去從 GitHub `main` 下載原稿,所以離線會失敗(擴充檔也一樣),而且 UDS 在你安裝後自己改過的內容,會被列成你改的差異。現在原稿一律從所裝套件讀取——標準、選項、擴充檔皆同——不下載任何東西。指令會印出比對基準(`installed UDS package (version X)`),並提示看 UDS 之後的變更請用 `uds update --plan`。若專案內的標準是從另一個 UDS 版本安裝的、與目前安裝的套件版本不同,也會明說,因為兩版之間 UDS 改過的檔會顯示成差異。套件內找不到某個受追蹤檔的原稿時,指令會**點名**該檔、不下載、以結束碼 1 結束;不再退回 GitHub,也不再靜默略過。沒有被修改的檔時,`--diff` 現在會說「沒有差異可顯示」,而不是什麼都不印。**誰會看到不同:**執行 `uds check --diff`(或在互動式 `uds check` 按「檢視」)的人——凡是 `main` 與你所裝版本不同之處,差異可能與以往不同;而原本在套件缺原稿時讀到結束碼 0 的腳本,現在會讀到 1。**要做什麼:**不用做任何事;要看上游有什麼新內容,請執行 `uds update --plan`。落實 dev-platform XSPEC-453 R1。
|
|
29
|
+
|
|
30
|
+
### Removed
|
|
31
|
+
|
|
32
|
+
- **移除 `extensions/languages/php/`**——兩個沒有任何東西引用的檔(`php-style.md`、`fat-free-patterns.md`,約 37 KB);安裝器、registry 與文件使用的是 `extensions/languages/php-style.md` 與 `extensions/frameworks/fat-free-patterns.md`,兩者不變。npm 套件因此少了這兩個檔,現在剛好只含安裝器裝得到的 5 個擴充檔;新增的測試會在有未宣告的擴充檔被打包時變紅。`uds init --lang php` 與 `--framework fat-free` 裝的檔與先前相同。落實 dev-platform XSPEC-453 R2。
|
|
33
|
+
|
|
34
|
+
### 修正
|
|
35
|
+
|
|
36
|
+
- **健康分數的覆蓋度維度不再回報永遠是 0 的 `has_tests`。**`calculateCoverage` 宣告了 `hasTests = 0` 卻從未改動它,所以 `uds audit --score` 印出一個看起來像「標準有沒有測試」的量測、實際上不會動的數字。它已從加總與 `details` 移除;**任何專案的覆蓋度分數都不變**(分母本來就是每個標準兩份——`check-<id>.sh` 與 `check-<id>-sync.sh`)。(XSPEC-444 R5)
|
|
37
|
+
- **行為改變——`uds check` 現在會把遺失或被改過的技能檔算進判定。它以前會印出紅色 ✗,結尾卻仍說「專案符合標準」、exit 0。** Skills 完整性檢查的結果算出來之後被丟掉了。現在刪掉或改過技能檔,`uds check` 會說「偵測到一些問題」並點名該檔,`uds check --ci` 會 exit 1(不帶 `--ci` 時 exit code 仍是 0,與其他各類發現一致;UDS 寫的 pre-commit hook 執行的是不帶參數的 `uds check`,所以不會因此被擋)。**誰會看到差別:**技能資料夾被改過或掉了檔的專案。**怎麼處理:**執行訊息印出的指令 `uds update --apply --skills`。**幽靈紀錄先處理,所以既有專案不會突然開始失敗:**專案的 manifest 可能列著 UDS 從未安裝的技能檔——採用者自己的技能,以及舊版 UDS 因為雜湊整個資料夾而誤拷進技能資料夾的 `agents/`、`workflows/`、`_shared/`,後來 `uds update` 把它們刪了卻沒忘掉紀錄(有個專案顯示 26 個「遺失」,6.11.0 與 6.14.0-beta.4 相同)。現在安裝器只記錄自己裝的技能(也不記錄自己的 `.manifest.json`);`uds update` 刪掉技能資料夾時一併刪掉它的紀錄;`uds check` 忽略不描述任何出貨技能的紀錄並說出有幾筆(`N skill record(s) ignored`);`uds update`(`--apply`、`--skills`,或已是最新版的路徑)會把它們從 `.standards/manifest.json` 永久清掉。**斜線命令檔同樣適用**——它的檢查結果原本也被丟棄:命令檔被刪或被改,`uds check` 現在會點名,`--ci` 會 exit 1(修復:`uds update --apply --commands`)。UDS 不出貨的命令紀錄由 `uds update` 清掉;裝在使用者層級(所有專案共用,本專案無從背書)的命令紀錄,檢查會忽略並說明。另外,當「改程式沒動測試」或「假測試」檢查設為 `"mode": "block"` 時,`uds check` 印出 BLOCKED 後不再以「符合標準」收尾。落實 dev-platform XSPEC-454 R2。
|
|
38
|
+
- **`uds update --rollback` 現在還原整個升級,而不只是標準檔。** 依序執行 `update --apply`、`update --apply --skills`、`update --apply --commands` 後,一次 `--rollback` 只還原標準檔與 `CLAUDE.md`/`AGENTS.md`,新增的技能資料夾(`comprehension-ladder`)、技能與命令的 `.manifest.json`、以及 `.standards/manifest.json` 裡的雜湊紀錄都留在新版,於是 `uds check` 報修改過的檔,專案同時不符合兩個版本。原因:備份只記錄計畫要覆寫的檔(沒有更新所建立的檔,也沒有 `.standards/manifest.json`);`--skills` 與 `--commands` 寫檔時完全沒有備份;還原用的 `copyFileSync` 還原不了資料夾。現在 `--apply`、`--apply --skills`、`--apply --commands` 的每一步都建立備份,並記錄它所建立的檔(`--skills`/`--commands` 自己建立備份,沒有備份就不寫;只備份 UDS 出貨的技能與命令,不碰你自己的);不帶 `--apply` 的一般 `uds update` 仍和以前一樣不建立備份;連續的步驟以 `.standards/manifest.json` 前後的雜湊串起來,所以一次 `--rollback` 會一路退過整串沒有被打斷的升級,並在中間有別的變更處停下來、明說;還原後會讀回驗證;指令會印出還原了什麼、移除了什麼,若有任何失敗,**不會以「成功」收尾**(exit 1,並說明怎麼重試)。**沒有涵蓋、並會如實印出:**使用者層級的技能/命令(`~/.claude/skills`,由所有專案共用),以及舊版本做的備份(它們從未記錄所建立的檔與 manifest)。落實 dev-platform XSPEC-454 R1。
|
|
39
|
+
- **`uds update --commands` 把命令數印成了工具數**(只有一個 OpenCode 卻印「為 51 個 AI 工具更新」)。該訊息鍵在每個語言都寫成「N 個 AI 工具」,卻被填入命令檔數。現在有獨立的訊息,兩個欄位各放各的數字:「Updated 51 commands for 1 AI tool(s)」/「已為 1 個 AI 工具更新 51 個斜線命令」/「已为 1 个 AI 工具更新 51 个斜线命令」。舊鍵的其他用法本來就傳工具數,不變。落實 dev-platform XSPEC-454 R4。
|
|
40
|
+
|
|
41
|
+
### 新增
|
|
42
|
+
|
|
43
|
+
- **`uds init` 現在會附上 `full-coverage-testing` 一直要你自己寫的假測試與空殼掃描腳本,`uds check` 會把它們找到的東西以警告印出。**標準一直寫著「新增 `scripts/check-stubs.sh` 與 `scripts/check-anti-fake-tests.sh`」,驗證器也只檢查這兩個檔案存在——但 UDS 兩個都沒附,這條指示根本照做不了。`uds init` 現在會寫入 `scripts/check-anti-fake-tests.mjs`(找**沒有斷言**的測試、唯一的斷言是 `expect(true).toBe(true)` 或 `assert 200 == 200` 這類**恆真式**的測試、**每支測試都被跳過或標 todo** 的測試檔)與 `scripts/check-stubs.mjs`(`// WARNING: STUB` 標記、宣稱**尚未實作**而旁邊沒有標記的函式本體、本體**為空**而旁邊沒有標記的具名函式)。純 Node、零相依、不預設測試框架;它們是你的檔案。單獨執行時,找到東西就以非 0 結束。**`uds check`——pre-commit hook 執行的指令——會執行它們並把找到的東西印成警告;不擋任何東西**,除非你在 `.standards/test-policy.json` 設 `"mode": "block"`。有暫存檔案時掃描那些檔案;沒有暫存任何東西時(CI 執行)掃描整個專案。**測試檔規則涵蓋 JavaScript/TypeScript、Python、Java/Kotlin/Scala/C#、Go、Rust、Ruby、Elixir、PHP、Swift、Dart、Lua 與 C/C++;其他語言的測試檔會被列為「未掃描」,絕不當成乾淨。**它們讀的是文字、不執行你的測試,所以用掃描器認不得的名稱做斷言的輔助函式會被報為「no-assertion」(請命名為 `assert*`/`verify*`/`expect*`,或把樣式列在 `assertionPatterns`)。每次執行都先拿已知的假測試與好測試檢驗自己,失敗就以 `2`(「無法判定」,絕不算通過)結束。已存在的檔案絕不覆寫;`uds uninstall` 只移除 `uds init` 寫入且未被改動的檔案;較早初始化的專案由 `uds update` 詢問是否寫入(提示的預設為否;**`uds update -y` 會直接回答是**,所以升級指令是 `uds update -y` 的專案,下次更新就會多這兩個檔案)。**誰會看到差別:**本版之後每次 `uds init` 會在 `scripts/` 多兩個檔案,每次提交 `uds check` 會多印兩行(或找到的東西)。**怎麼處理:**讀它的發現;想讓某類檔案不再被報,加一份 `test-policy.json`;想強制執行,設 `"mode": "block"` 或在 CI 跑這兩支腳本。`uds check --standard full-coverage-testing` 現在會執行這兩支腳本,不再只檢查它們存在。(XSPEC-444 R5)
|
|
44
|
+
- **`uds check` 在一次提交改了程式碼卻沒動任何測試時發出警告。**有檔案暫存時,`uds check` 會在「改了程式檔、同一次提交沒有測試檔變動」時列出那些程式檔,並列出它不認得類型的變更檔案(絕不當成沒事,也絕不擋)。刪除不需要測試;純重新命名(git `R100`)與符合 `exempt` 條目的路徑可免,輸出會記下理由。哪些路徑是測試、哪些是程式,是附有常見生態預設值的資料——`*.test.*`、`*_test.go`、`test_*.py`、`*Test.java`、`tests/` 等——由 `.standards/test-policy.json`(`testDirs`、`testPatterns`、`sourceExtensions`、`nonCodeExtensions`、`ignore`,以及每筆都必須附 `reason` 否則不生效的 `exempt`)**加進**而不是取代。**它只警告、放行提交。**同一份檔案裡的 `"mode": "block"` 會讓它擋下提交;這是目前提供的唯一收緊步驟。**沒有做,因為規格沒有定義:**未配測試的變更數棘輪(基線放在哪、以什麼計數),以及逐次提交的豁免理由(pre-commit hook 讀不到提交訊息)。(XSPEC-444 R2)
|
|
45
|
+
- **`uds audit --offline`。** `check` 與 `update` 早就有,`audit` 卻回「unknown option」。加上它之後,`audit` 不發任何網路請求——包含每個指令結束後的「有新版本」提示(它對 `check`、`update` 也忽略 `--offline`,現在都遵守);`--report` 會說「離線模式:不提交回報。」(並指出出路 `--dry-run`),而不是去啟動 `gh`、瀏覽器或剪貼簿。落實 dev-platform XSPEC-454 R3。
|
|
46
|
+
|
|
20
47
|
## [6.14.0-beta.4] - 2026-10-06
|
|
21
48
|
|
|
22
49
|
> **測試版**——以 `npm install -g universal-dev-standards@beta` 安裝。要測什麼、如何退回正式版:[docs/PRE-RELEASE.md](../../docs/PRE-RELEASE.md)。
|
|
@@ -15,7 +15,7 @@ status: current
|
|
|
15
15
|
|
|
16
16
|
> **語言**: [English](../../README.md) | 繁體中文 | [简体中文](../zh-CN/README.md)
|
|
17
17
|
|
|
18
|
-
**版本**: 6.14.0-beta.
|
|
18
|
+
**版本**: 6.14.0-beta.5 (Pre-release) | **發布日期**: 2026-10-06 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
語言無關、框架無關的軟體專案文件標準。透過 AI 原生工作流,確保不同技術堆疊之間的一致性、品質和可維護性。
|
|
21
21
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../../core/full-coverage-testing.md
|
|
3
|
-
source_version: 1.
|
|
4
|
-
translation_version: 1.
|
|
5
|
-
last_synced: 2026-
|
|
6
|
-
source_hash:
|
|
3
|
+
source_version: 1.2.0
|
|
4
|
+
translation_version: 1.2.0
|
|
5
|
+
last_synced: 2026-10-06
|
|
6
|
+
source_hash: 1fe2966d8684
|
|
7
7
|
status: current
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ status: current
|
|
|
12
12
|
> **Language**: [English](../../../core/full-coverage-testing.md) | 繁體中文
|
|
13
13
|
|
|
14
14
|
> **AI 最佳化版本**: `ai/standards/full-coverage-testing.ai.yaml`
|
|
15
|
-
> **XSPEC**: XSPEC-178
|
|
15
|
+
> **XSPEC**: XSPEC-178、XSPEC-444(R2、R5——提交前警告與隨附閘門腳本)
|
|
16
16
|
> **取代**: 金字塔門檻模型(UT≥80%、IT≥70%、E2E 僅 happy-path)
|
|
17
17
|
|
|
18
18
|
## 概述
|
|
@@ -233,6 +233,60 @@ legacy 降級模式(外部服務失敗時的 fallback、重試、部分結果
|
|
|
233
233
|
|
|
234
234
|
---
|
|
235
235
|
|
|
236
|
+
## UDS 隨附的提交前警告與閘門腳本(XSPEC-444 R2、R5)
|
|
237
|
+
|
|
238
|
+
上面的規則過去要靠標準叫你自己寫的腳本來執行。現在 `uds init` 會直接把掃描腳本寫進你的專案,而 `uds check`——UDS 的 pre-commit hook 執行的指令——會印出這些腳本和另一項檢查找到的東西。**預設一律只警告、不擋任何東西**;要收緊是選擇性的(見「先警告,之後再收緊」)。
|
|
239
|
+
|
|
240
|
+
### 兩支掃描腳本(`uds init` 寫到 `scripts/`)
|
|
241
|
+
|
|
242
|
+
| 腳本 | 找什麼 |
|
|
243
|
+
|------|--------|
|
|
244
|
+
| `scripts/check-anti-fake-tests.mjs` | **沒有斷言**的測試;唯一的斷言是**恆真式**的測試(`expect(true).toBe(true)`、`assert 200 == 200`);**每一支測試都被跳過或標為 todo** 的測試檔 |
|
|
245
|
+
| `scripts/check-stubs.mjs` | `// WARNING: STUB` 標記;宣稱**尚未實作**的函式本體(`raise NotImplementedError`、`todo!()`、`TODO()` 等)而旁邊沒有標記;本體**為空**的具名函式而旁邊沒有標記 |
|
|
246
|
+
|
|
247
|
+
- 純 Node、零相依、不預設任何測試框架。它們是**你的檔案**:可以改、可以接進 CI。單獨執行時,找到東西就以非 0 結束——`node scripts/check-stubs.mjs` 就是本標準部署閘門所說的 pre-push/部署閘門。
|
|
248
|
+
- `uds init` 不會覆寫已存在的檔案,`uds update` 也不會;較早初始化的專案,`uds update` 會詢問是否寫入(提示的預設為否;`uds update -y` 會直接回答是)。
|
|
249
|
+
- 有暫存檔案時只讀那些檔案;沒有暫存任何東西時(CI 執行、手動 `uds check`)每支都會走訪整個專案——走訪最多 200,000 個檔案,`uds check` 給每支 120 秒(超過就回報「無法判定」,絕不算通過)——所以在很大的儲存庫裡,請在 CI 執行,不要期待立刻完成。
|
|
250
|
+
- 同一行或上面三行內出現 `STUB` 或 `COVERAGE_EXEMPT`,該暫時實作就算已**宣告**;已宣告的只以標記回報一次。
|
|
251
|
+
- **語言範圍。**測試檔規則涵蓋 JavaScript/TypeScript、Python、Java/Kotlin/Scala/C#、Go、Rust、Ruby、Elixir、PHP、Swift、Dart、Lua 與 C/C++。其他語言的測試檔會被列為「未掃描」——絕不當成乾淨。空函式規則涵蓋 JavaScript/TypeScript、Python、Go、Rust、Ruby 與 PHP;其他語言仍會找標記與「尚未實作」的本體,輸出也會寫出哪些語言沒有空函式規則。
|
|
252
|
+
- 它們讀的是文字,不執行你的測試。若某個輔助函式用掃描器認不得的名稱做斷言,會被報為「no-assertion」:把它命名為 `assert*`/`verify*`/`expect*`,或把它的樣式列在政策檔的 `assertionPatterns`。
|
|
253
|
+
- 每次執行都先拿已知的假測試與已知的好測試檢驗自己;檢驗失敗就以 `2`(「無法判定」)結束,這絕不算通過。
|
|
254
|
+
|
|
255
|
+
### 改了程式碼卻沒動測試(`uds check`,針對已暫存的變更)
|
|
256
|
+
|
|
257
|
+
有檔案暫存準備提交時,`uds check` 會比對變更內容:
|
|
258
|
+
|
|
259
|
+
- 改了程式檔,**同一次提交沒有任何測試檔變動** → 警告,並列出程式檔;
|
|
260
|
+
- 變更中有 UDS 不認得的檔案類型 → 警告,列出它並說明如何分類(絕不當成沒事,也絕不擋);
|
|
261
|
+
- 刪除不算需要測試的變更;**純重新命名**(git 的 `R100`)與符合 `exempt` 條目的路徑可免,輸出會記下理由。
|
|
262
|
+
|
|
263
|
+
沒有暫存任何東西時(CI 執行、手動 `uds check`),差異檢查不出聲;兩支掃描腳本則改為掃整個專案。
|
|
264
|
+
|
|
265
|
+
### 政策檔 `.standards/test-policy.json`(選用)
|
|
266
|
+
|
|
267
|
+
哪些路徑是測試、哪些是程式,是附有常見生態預設值的資料,不是一份框架清單。每個清單都是**加進**預設值:
|
|
268
|
+
|
|
269
|
+
```json
|
|
270
|
+
{
|
|
271
|
+
"mode": "warn",
|
|
272
|
+
"testDirs": ["integration"],
|
|
273
|
+
"testPatterns": ["*.itest.*"],
|
|
274
|
+
"sourceExtensions": ["zig"],
|
|
275
|
+
"nonCodeExtensions": ["gradle"],
|
|
276
|
+
"ignore": ["generated/**"],
|
|
277
|
+
"exempt": [{ "pattern": "src/gen/**", "reason": "generated by protoc" }],
|
|
278
|
+
"assertionPatterns": ["\\bmustMatch\\w*\\s*\\("]
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
沒有 `reason` 的 `exempt` 條目不會生效,並會被回報:豁免必須說明原因。
|
|
283
|
+
|
|
284
|
+
### 先警告,之後再收緊
|
|
285
|
+
|
|
286
|
+
`"mode": "warn"`(預設)只印出警告、放行提交。`"mode": "block"` 會讓 `uds check` 在以下情況以非 0 結束,因此擋下提交:掃描腳本找到東西、掃描腳本無法判定、或改了程式碼卻沒動測試。UDS 不認得的檔案類型永遠不會擋。**尚未實作**(規格沒有定義基線放在哪裡、以什麼計數):未配測試的變更數棘輪,以及逐次提交的豁免理由(pre-commit hook 讀不到提交訊息)。
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
236
290
|
## 從金字塔模型遷移
|
|
237
291
|
|
|
238
292
|
若你的專案先前使用金字塔門檻:
|
|
@@ -240,8 +294,8 @@ legacy 降級模式(外部服務失敗時的 fallback、重試、部分結果
|
|
|
240
294
|
1. **刪除** `jest.config.js` / `vitest.config.ts` 中任何硬編碼的覆蓋率門檻(`coverageThreshold` 選項)
|
|
241
295
|
2. **安裝** `.coverage-baseline.json`,以目前的覆蓋率作為棘輪起點
|
|
242
296
|
3. **新增** `scripts/check-coverage-ratchet.sh` 到 CI
|
|
243
|
-
4. **新增** `scripts/check-stubs.
|
|
244
|
-
5. **新增** `scripts/check-anti-fake-tests.
|
|
297
|
+
4. **新增** `scripts/check-stubs.mjs` 到 deploy.sh 與 pre-push hook(由 `uds init` 寫入;既有專案由 `uds update` 提供)
|
|
298
|
+
5. **新增** `scripts/check-anti-fake-tests.mjs` 到 pre-commit 或 CI(由 `uds init` 寫入;`uds check` 已會執行並警告)
|
|
245
299
|
|
|
246
300
|
棘輪從你目前的覆蓋率開始。從那一刻起,它只能上升。
|
|
247
301
|
|