universal-dev-standards 6.14.0-beta.1 → 6.14.0-beta.2
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 +37 -0
- package/bundled/ai/standards/open-work-tracking.ai.yaml +3 -1
- package/bundled/core/open-work-tracking.md +1 -1
- package/bundled/hooks/turn-completion/locales/en.mjs +54 -5
- package/bundled/hooks/turn-completion/locales/zh-TW.mjs +37 -6
- package/bundled/locales/zh-CN/CHANGELOG.md +21 -3
- package/bundled/locales/zh-CN/README.md +2 -2
- package/bundled/locales/zh-CN/SECURITY.md +1 -1
- package/bundled/locales/zh-CN/docs/CHEATSHEET.md +2 -0
- package/bundled/locales/zh-CN/docs/CLI-INIT-OPTIONS.md +24 -0
- package/bundled/locales/zh-CN/docs/FEATURE-REFERENCE.md +11 -4
- package/bundled/locales/zh-TW/CHANGELOG.md +21 -3
- package/bundled/locales/zh-TW/README.md +2 -2
- package/bundled/locales/zh-TW/SECURITY.md +1 -1
- package/bundled/locales/zh-TW/core/open-work-tracking.md +2 -2
- package/bundled/locales/zh-TW/docs/CHEATSHEET.md +2 -0
- package/bundled/locales/zh-TW/docs/CLI-INIT-OPTIONS.md +24 -0
- package/bundled/locales/zh-TW/docs/FEATURE-REFERENCE.md +11 -4
- package/package.json +1 -1
- package/src/commands/init.js +2 -0
- package/src/commands/open-work.js +60 -0
- package/src/commands/update.js +91 -0
- package/src/i18n/messages.js +3 -0
- package/src/installers/hooks-installer.js +189 -11
- package/src/utils/detector.js +46 -1
- package/src/utils/open-work-tracking.mjs +693 -0
- package/standards-registry.json +7 -7
package/bin/uds.js
CHANGED
|
@@ -26,6 +26,7 @@ import { compileStandards } from '../src/commands/compile.js';
|
|
|
26
26
|
import { generateReport } from '../src/commands/report.js';
|
|
27
27
|
import { mcpCommand } from '../src/commands/mcp.js';
|
|
28
28
|
import { runIntentCommand } from '../src/commands/run-intent.js';
|
|
29
|
+
import { openWorkNextActionCommand, openWorkRevisionCommand, openWorkSeparationCommand, openWorkSelfTestCommand } from '../src/commands/open-work.js';
|
|
29
30
|
import { setLanguage, setLanguageExplicit, detectLanguage, t } from '../src/i18n/messages.js';
|
|
30
31
|
import { maybeCheckForUpdates, formatUpdateNotice, shouldCheckUpdateForCommand } from '../src/utils/update-checker.js';
|
|
31
32
|
import { config } from '../src/utils/config-manager.js';
|
|
@@ -231,6 +232,8 @@ program
|
|
|
231
232
|
.option('--rollback', 'Rollback to the most recent backup')
|
|
232
233
|
.option('--claude-target <target>', 'Switch an existing install to a different Claude Code integration target: project (CLAUDE.md) or local (CLAUDE.local.md) — moves the UDS block, keeps your content, no reinstall')
|
|
233
234
|
.option('--locale <locale>', 'Override locale for skills install (zh-tw, zh-cn, en); also reads .uds/install.yaml + UDS_LOCALE env')
|
|
235
|
+
.option('--with-hooks', 'Install the enforcement hooks that are missing from this already-initialized project (re-detects tools; hooks already there and your own hooks are not touched; with --plan, writes nothing; --force also overwrites edited hook scripts)')
|
|
236
|
+
.option('--ai-tool <tools>', 'With --with-hooks: comma-separated tools to install hooks for (claude-code, codex, gemini-cli, antigravity) instead of detecting them')
|
|
234
237
|
.action(updateCommand);
|
|
235
238
|
|
|
236
239
|
program
|
|
@@ -455,6 +458,40 @@ aiContextCommand
|
|
|
455
458
|
// MCP command for AI tool integration
|
|
456
459
|
mcpCommand(program);
|
|
457
460
|
|
|
461
|
+
// Open-work-tracking reference checks (OWT-017/018/019). A group of its own, not
|
|
462
|
+
// a flag on `check`: `check` validates the installed standards and has its own
|
|
463
|
+
// --ci/--json meaning, while these are three checks with different arguments and
|
|
464
|
+
// an exit-code contract in which 2 ("cannot decide") is not a pass.
|
|
465
|
+
const openWorkCommand = program
|
|
466
|
+
.command('open-work')
|
|
467
|
+
.description('Reference checks for open-work-tracking (OWT-017/018/019). Exit 0 no violation, 1 violation, 2 cannot decide (not a pass)');
|
|
468
|
+
|
|
469
|
+
openWorkCommand
|
|
470
|
+
.command('next-action [files...]')
|
|
471
|
+
.description('OWT-019: every "next action" field names a file path, test name, command or requirement identifier')
|
|
472
|
+
.option('--root <dir>', 'Directory relative paths are resolved against (default: cwd)')
|
|
473
|
+
.option('--id-pattern <regex>', 'Your own requirement-identifier pattern (the default is an uncalibrated initial judgment)')
|
|
474
|
+
.action(openWorkNextActionCommand);
|
|
475
|
+
|
|
476
|
+
openWorkCommand
|
|
477
|
+
.command('revision')
|
|
478
|
+
.description('OWT-018: a change to acceptance/goal/constraint sections needs a new, complete revision record')
|
|
479
|
+
.option('--file <path>', 'Carrier file (with --base)')
|
|
480
|
+
.option('--base <rev>', 'Git revision to compare --file against')
|
|
481
|
+
.option('--before <file>', 'Earlier version of the carrier (with --after)')
|
|
482
|
+
.option('--after <file>', 'Later version of the carrier (with --before)')
|
|
483
|
+
.action(openWorkRevisionCommand);
|
|
484
|
+
|
|
485
|
+
openWorkCommand
|
|
486
|
+
.command('separation [files...]')
|
|
487
|
+
.description('OWT-017: no single carrier holds both an intent section and a progress/next-action section')
|
|
488
|
+
.action(openWorkSeparationCommand);
|
|
489
|
+
|
|
490
|
+
openWorkCommand
|
|
491
|
+
.command('self-test')
|
|
492
|
+
.description('Run the checker\'s own self-test arms (a checker that fails them decides nothing)')
|
|
493
|
+
.action(openWorkSelfTestCommand);
|
|
494
|
+
|
|
458
495
|
// uds run <intent> — language-agnostic command proxy (XSPEC-029)
|
|
459
496
|
program
|
|
460
497
|
.command('run <intent>')
|
|
@@ -232,7 +232,9 @@ standard:
|
|
|
232
232
|
enforcement:
|
|
233
233
|
automated_gate: false
|
|
234
234
|
reference_check:
|
|
235
|
-
|
|
235
|
+
command: "uds open-work <next-action|revision|separation|self-test>" # 隨 npm 安裝包出貨,採用者不需要 clone
|
|
236
|
+
path: cli/src/utils/open-work-tracking.mjs # 規則本體只有這一份
|
|
237
|
+
repo_entry: scripts/check-open-work-tracking.mjs # 只在 UDS repo 副本裡的薄殼,不含規則
|
|
236
238
|
covers: [OWT-017, OWT-018, OWT-019]
|
|
237
239
|
status: "參考判定程序,作為 OWT-015 意義上的證據(已對違反樣本紅過);不是閘門,未接進任何 UDS 發版閘門,因為 UDS 沒有承載開放工作的地方可供檢查"
|
|
238
240
|
why_not: >
|
|
@@ -366,7 +366,7 @@ DEX-003 扮演的角色相同。上面每一條都指名了 artefact 與它們
|
|
|
366
366
|
|
|
367
367
|
## What enforces this standard
|
|
368
368
|
|
|
369
|
-
**Nothing in UDS gates on it, and that is recorded rather than implied.** UDS states the relations a carrier of open work must satisfy; whether anything decides them is the adopting project's call, per the [writing constraint](#how-this-standard-is-written--and-why-it-is-written-that-way) above — the same boundary [deferred-item-exit](deferred-item-exit.md) draws for its own exits. Since 1.1.0 UDS does ship one **reference decision procedure** for OWT-017–OWT-019 (`scripts/check-open-work-tracking.mjs`)
|
|
369
|
+
**Nothing in UDS gates on it, and that is recorded rather than implied.** UDS states the relations a carrier of open work must satisfy; whether anything decides them is the adopting project's call, per the [writing constraint](#how-this-standard-is-written--and-why-it-is-written-that-way) above — the same boundary [deferred-item-exit](deferred-item-exit.md) draws for its own exits. Since 1.1.0 UDS does ship one **reference decision procedure** for OWT-017–OWT-019 — `uds open-work next-action | revision | separation` from the npm package (`uds open-work self-test` runs the checker's own arms; from a clone of the UDS repository `node scripts/check-open-work-tracking.mjs` runs the same code) — offered as evidence in the OWT-015 sense — it has been observed to fail against violating samples — for an adopter to run or to reimplement. It is not wired into any UDS release gate, because UDS carries no open-work carrier for it to check.
|
|
370
370
|
|
|
371
371
|
**UDS 不對本標準設任何閘門,而這件事是被記錄的,不是被暗示的。** UDS 陳述一個承載開放工作的地方
|
|
372
372
|
必須滿足的關係;有沒有東西去判定它,依上面的[寫法約束](#how-this-standard-is-written--and-why-it-is-written-that-way),
|
|
@@ -50,11 +50,34 @@ const ASKING =
|
|
|
50
50
|
// request for information, so ASKING above never caught it (measured: the
|
|
51
51
|
// zh-TW mirror of this shape fired as an unkept commitment). Grammar-based, not
|
|
52
52
|
// a verb list, to match this pack's own design note above: "once/after/as soon
|
|
53
|
-
// as you", up to
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
// the
|
|
57
|
-
|
|
53
|
+
// as you", then everything up to the CLAUSE BOUNDARY, a comma, then "I".
|
|
54
|
+
//
|
|
55
|
+
// 🔴 The clause used to be capped at 20 characters, chosen by feel. Measured
|
|
56
|
+
// 2026-09-29 on the published 6.14.0-beta.1: "Once you choose, I will apply it."
|
|
57
|
+
// passed and "Once you choose option A or B, I will apply it." (21 characters)
|
|
58
|
+
// blocked — the cap, not the grammar, decided. A human's precondition is often a
|
|
59
|
+
// long clause ("Once you've reviewed the three options above and picked one,
|
|
60
|
+
// …"), so no count is the right count. The clause ends where the class stops:
|
|
61
|
+
// a comma, sentence punctuation, or a line break. A precondition cannot be
|
|
62
|
+
// longer than the sentence it sits in, and it cannot cross a sentence.
|
|
63
|
+
//
|
|
64
|
+
// What the boundary keeps out, and why the comma stays required: "I will apply
|
|
65
|
+
// it once the build finishes." is not conditional on the human (no "you"), and
|
|
66
|
+
// "After you merged it I will …" (no comma) still fires — see the corpus.
|
|
67
|
+
//
|
|
68
|
+
// A widened clause must not swallow a commitment of mine, so the clause may not
|
|
69
|
+
// contain "I will / I am going to / I am about to". Without that,
|
|
70
|
+
// "After you merged it I will follow up, I will …" — the no-comma shape above,
|
|
71
|
+
// then a comma and a second "I" — would match, where the 20-character cap used
|
|
72
|
+
// to stop it. The subject of the precondition is the human's; a clause that
|
|
73
|
+
// makes a promise of its own is not one. (Contractions are already expanded by
|
|
74
|
+
// normalize() before this runs.)
|
|
75
|
+
const CONDITIONAL_ON_YOU = new RegExp(
|
|
76
|
+
'\\b(once|after|as soon as) you\\b' +
|
|
77
|
+
'(?:(?!\\bI\\s+(?:will|am going to|am about to|going to|about to)\\b)[^,.;:!?\\n])*' +
|
|
78
|
+
',\\s*I\\b',
|
|
79
|
+
'i'
|
|
80
|
+
);
|
|
58
81
|
|
|
59
82
|
/**
|
|
60
83
|
* Expand contractions so the patterns below never have to fight an apostrophe.
|
|
@@ -171,6 +194,32 @@ export const corpus = [
|
|
|
171
194
|
'After you confirm the plan, I will kick off the deploy.'],
|
|
172
195
|
[false, 'conditional: once you decide, I will',
|
|
173
196
|
'Once you decide, I will draft the ADR and file the tickets.'],
|
|
197
|
+
// 🔴 Measured 2026-09-29 on 6.14.0-beta.1 (published): the SAME sentence
|
|
198
|
+
// blocked or passed depending on how many characters sat between "you" and the
|
|
199
|
+
// comma — the 20-character cap, not the grammar. Each of these is one of the
|
|
200
|
+
// sentences that was measured, and the last three are the long clauses real
|
|
201
|
+
// agents write.
|
|
202
|
+
[false, 'conditional: once you choose (short, always passed)',
|
|
203
|
+
'Once you choose, I will apply it.'],
|
|
204
|
+
[false, 'conditional: once you choose A (short, always passed)',
|
|
205
|
+
'Once you choose A, I will apply it.'],
|
|
206
|
+
[false, 'conditional: as soon as you choose A or B',
|
|
207
|
+
'As soon as you choose A or B, I will apply it.'],
|
|
208
|
+
[false, 'conditional: after you choose option A or B (was blocked: 21 chars)',
|
|
209
|
+
'After you choose option A or B, I will apply it.'],
|
|
210
|
+
[false, 'conditional: once you choose option A or B (was blocked: 21 chars)',
|
|
211
|
+
'Once you choose option A or B, I will apply it.'],
|
|
212
|
+
[false, 'conditional: a long precondition clause',
|
|
213
|
+
"Once you've reviewed the three options above and picked one, I will apply it."],
|
|
214
|
+
[false, 'conditional: a long precondition clause, no contraction',
|
|
215
|
+
'After you have read the summary and decided which of the two migrations to keep, I will start the rollout.'],
|
|
216
|
+
// The widening must not turn the clause into a place to hide a commitment.
|
|
217
|
+
[true, 'not conditional on the human: the condition is a build, not you',
|
|
218
|
+
'I will apply it once the build finishes.'],
|
|
219
|
+
[true, 'not conditional on the human: "you" appears only after the commitment',
|
|
220
|
+
'I will apply the fix now, and you can review it later.'],
|
|
221
|
+
[true, 'a promise of my own inside the clause is not the human\'s precondition',
|
|
222
|
+
'After you merged it I will follow up, I will push the tag.'],
|
|
174
223
|
[true, 'subject is not you, still commits',
|
|
175
224
|
"After I fix this, I'll push it up."],
|
|
176
225
|
// Known limit, not fixed here: no comma between the precondition and "I"
|
|
@@ -47,12 +47,26 @@ const ASKING = new RegExp(
|
|
|
47
47
|
'|(跟我說|告訴我|回報我|讓我知道)(一聲)?[,,]\\s*我' +
|
|
48
48
|
// 「你選定後,我會…」— the precondition is the human's decision, not a request
|
|
49
49
|
// for information or a report-back, so neither branch above caught it. Measured:
|
|
50
|
-
// fired as an unkept commitment.
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
'
|
|
50
|
+
// fired as an unkept commitment. Grammar, not a length: literal 你 as the SUBJECT
|
|
51
|
+
// of the clause, then everything up to the clause boundary that is not another
|
|
52
|
+
// 我/你, then 後 (or 之後), then a comma and 我.
|
|
53
|
+
//
|
|
54
|
+
// 🔴 The clause used to be capped at 1–6 characters "so it stays a short
|
|
55
|
+
// decision verb". That is the same mistake the en pack made with 20: a human's
|
|
56
|
+
// precondition is often a whole clause (「你看完上面三個選項並選好一個之後,我會…」),
|
|
57
|
+
// and a count decided it instead of the grammar. Measured 2026-09-29 (en side,
|
|
58
|
+
// 6.14.0-beta.1); this side had the identical cap and the identical miss.
|
|
59
|
+
// The clause ends at 逗號/句號/驚嘆/問號/分號/冒號/換行, and may not contain 我
|
|
60
|
+
// (a precondition that carries my own act is not the human's).
|
|
61
|
+
//
|
|
62
|
+
// What replaces the count as the thing keeping real commitments out:
|
|
63
|
+
// - 你 must OPEN the clause (line/clause start, or after 等/待/當/若/一旦/
|
|
64
|
+
// 如果/只要), and must not be 你的. 「我看了你的設定檔並判斷需要重構之後,
|
|
65
|
+
// 我會接著改」 has 你 in the middle as a possessive inside MY sentence; with
|
|
66
|
+
// the cap gone it would have been exempted, and it is my commitment.
|
|
67
|
+
// - no 後 right after 你…: 「你選定的那份我會接著處理」 falls through.
|
|
68
|
+
// - no 你 before it: 「改好後我接著合併」, 「他確認後,我會…」 fall through.
|
|
69
|
+
'|(?:^|[,,。!?;;::\\n]|等到|等|待|當|若|一旦|如果|只要)\\s*你(?!的)[^,,。!?;;::\\n我你]+(之)?後[,,]\\s*我)'
|
|
56
70
|
);
|
|
57
71
|
|
|
58
72
|
// First person + future marker + action verb, within one sentence.
|
|
@@ -185,6 +199,23 @@ export const corpus = [
|
|
|
185
199
|
'你選好後,我會接著跑一次測試。'],
|
|
186
200
|
[false, '條件式承諾:你點頭後',
|
|
187
201
|
'你點頭後,我會接著把這份規格送出。'],
|
|
202
|
+
// 🔴 2026-09-29 實測(6.14.0-beta.1):en 側同一句話因為「你」到逗號之間差一個字而擋或放,
|
|
203
|
+
// 是字數上限決定的,不是語法。本側原本的 1–6 字上限是同一個缺陷。下面三句是真實會出現的長前提子句。
|
|
204
|
+
[false, '條件式承諾:你選好方案 A 或 B 後(原本被擋:超過 6 字)',
|
|
205
|
+
'你選好方案 A 或 B 後,我會接著套用。'],
|
|
206
|
+
[false, '條件式承諾:長前提子句',
|
|
207
|
+
'你看完上面三個選項並選好一個之後,我會接著套用。'],
|
|
208
|
+
[false, '條件式承諾:長前提子句,含頓號',
|
|
209
|
+
'你把上面三個選項都看過、挑好一個後,我會接著套用。'],
|
|
210
|
+
[false, '條件式承諾:等你……後',
|
|
211
|
+
'等你把上面三個選項看完並選好後,我會接著套用。'],
|
|
212
|
+
// 放寬之後,子句不能變成藏承諾的地方。
|
|
213
|
+
[true, '「你的」是所有格,句子的主詞是我,仍必須擋',
|
|
214
|
+
'我看了你的設定檔並判斷需要重構之後,我會接著改。'],
|
|
215
|
+
[true, '「你」在受詞位置(我把你貼的…整理完),仍必須擋',
|
|
216
|
+
'我把你貼的那一段整理完之後,我會接著改。'],
|
|
217
|
+
[true, '前提不是你,是建置——沒有在等使用者,仍必須擋',
|
|
218
|
+
'建置跑完之後,我會接著套用修正。'],
|
|
188
219
|
[true, '主詞不是你,仍必須擋——「後」在,但前面不是你',
|
|
189
220
|
'改好後我接著合併。'],
|
|
190
221
|
[true, '主詞不是你,仍必須擋——第三人稱的「後」',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.14.0-beta.
|
|
4
|
-
translation_version: 6.14.0-beta.
|
|
5
|
-
last_synced: 2026-09-
|
|
3
|
+
source_version: 6.14.0-beta.2
|
|
4
|
+
translation_version: 6.14.0-beta.2
|
|
5
|
+
last_synced: 2026-09-30
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -17,6 +17,24 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.14.0-beta.2] - 2026-09-30
|
|
21
|
+
|
|
22
|
+
> **测试版**——以 `npm install -g universal-dev-standards@beta` 安装。要测什么、如何退回正式版:[docs/PRE-RELEASE.md](../../docs/PRE-RELEASE.md)。
|
|
23
|
+
>
|
|
24
|
+
> **修正 6.14.0-beta.1 的已知限制:**既有项目现在可以用 `uds update --with-hooks` 补装 Antigravity CLI 关卡(以及缺少的 Claude Code / Codex / Gemini CLI 关卡)。
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`uds open-work next-action | revision | separation | self-test` —— `open-work-tracking` 1.1.0 的参考检查(OWT-017/018/019)现在随 npm 安装包出货。** 6.14.0-beta.1 的这些检查只在 repo 的 `scripts/` 里,而 npm 安装包不含该目录,采用者不 clone UDS 就跑不了。规则现在只住在一个地方,`cli/src/utils/open-work-tracking.mjs`(在安装包内);`uds open-work` 与旧的 `node scripts/check-open-work-tracking.mjs`(现在是一个不含规则、只重新导出该模块的薄壳)跑的是同一份,并有测试要求两者输出完全相同。检查本身没有任何改变:退出码相同(0 没有违反、1 有违反、2 判定不了——2 不是通过),检查器仍先跑自己的自测臂,每次运行仍声明覆盖率未知(OWT-011)、词汇未校准(OWT-016)。它仍是作为证据提供的参考判定程序,不是闸门。**每次测试都观察到会红:**新测试复制 CLI,让命令吞掉退出码(永远 0)或让共用规则永远通过,并要求违反的样本对副本变绿;并断言 `npm pack --dry-run` 的清单包含该模块。标准的“什么在执行本标准”一节改为指向该命令,而不是只在 repo 里的路径。
|
|
29
|
+
|
|
30
|
+
- **`uds update --with-hooks`——为已初始化的项目补装强制执行 hooks,并放宽 Antigravity 的检测规则。** Hooks 过去只有 `uds init --with-hooks` 会接线,而 `uds init` 不能跑第二次,所以既有采用者永远拿不到 UDS 在他们初始化之后才开始支持的工具的 hook(这是把 6.14.0-beta.1 安装包装进全新项目时发现的,已记为那一版的已知限制)。`uds update --with-hooks` 会重新检测工具(manifest 里的工具,加上项目文件现在看得出来的)并补装缺少的 hooks;`--ai-tool <列表>`(`claude-code`、`codex`、`gemini-cli`、`antigravity`)可改为直接指定,找不到任何工具时它会说明如何指定并以 1 退出,而不是猜。已经装好的 hook 不会被重写(重跑一次不会有任何变化),采用者自己的 hooks 绝不会被移除或重排(Claude/Codex/Gemini 是合并进去;agy 的 `.agents/hooks.json` 只写在 UDS 自己的 `uds-turn-completion-integrity` 键下面,不是合法 JSON 的文件原样保留),采用者改过的 hook 脚本会被保留、除非加 `--force`,`--plan` 则什么都不写。它与 `--claude-target`、`--sync-refs` 一样是独立模式;在已初始化的项目执行 `uds init --with-hooks`,现在会指向它,而不是默默什么都没做。**Antigravity 检测:**原本要求 `.agents/AGENTS.md`,而一个项目可以长期使用 agy 却从不创建这个文件。现在也接受 `.agents/rules/`、`.agents/workflows/`、`.agents/plugins/` 与 `.agents/hooks.json`——这些是 agy 自己的可执行文件带着、且 antigravity.google 有文档记载的名称——并且刻意**不**把 `.agents/skills/` 算进去,因为 Codex 也读它(根目录 `AGENTS.md` 加 `.agents/skills/` 的 repo 仍是 Codex;有测试)。检测只看项目目录:agy 记录已打开项目的 `~/.gemini/projects.json` 有被考虑,但因为它是机器本地的而不采用。`.agents/hooks.json` 是标记,但它同时也是 UDS 自己写的文件,所以安装之后它证明的是“装过”,不是“采用者在用 agy”。**每次测试都观察到会红:**测试把真的 CLI 当子进程对一个已初始化的项目跑,并要求把补装拿掉的 CLI 副本——删掉该分支、一个报告成功却什么都没写的安装器、检测退回只看 `.agents/AGENTS.md`——对真 CLI 会通过的同一组断言失败。agy 关卡仍然只验证过 `agy -p` 模式下没有用工具的单一回合。
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **`turn-completion-integrity` 在用户的前提子句超过固定字数时,会把“正在等用户”的一轮拦下——自 6.13 起就存在。** 条件式承诺(“你选好后,我会套用”)的豁免,在英文语言包是 `you` 到逗号之间最多 20 个字符,在 zh-TW 语言包是 `你` 到 `後` 之间 1–6 个字;两个数字都是凭感觉定的。以已发布的 6.14.0-beta.1、真实的 Claude Code Stop hook 输入实测:“Once you choose A, I will apply it.”放行,“Once you choose option A or B, I will apply it.”(21 个字符)被拦,“After you choose option A or B, I will apply it.”同样被拦——决定结果的是子句长度,不是 `once`/`after`。此 hook 只看一轮的**最后**一条消息,所以采用者看到的是:代理明明已经正确地停下来问人,却被逼着继续说话。修正:豁免改为延伸到子句边界(逗号、句末标点或换行),不再是字数,因此“Once you've reviewed the three options above and picked one, I will apply it.”与“你看完上面三個選項並選好一個之後,我會接著套用。”都放行。放宽上限就是让真承诺漏过的方向,所以改用两道规则取代字数:英文的子句内不得含有我自己的承诺(“After you merged it I will follow up, I will push the tag.”仍被拦);zh-TW 的 `你` 必须是子句的开头、且不能是“你的”(“我看了你的設定檔並判斷需要重構之後,我會接著改。”仍被拦——那里的 `你` 是我自己那句话里的所有格)。“I will apply it once the build finishes.”不是在等用户,仍被拦。**每次测试都观察到会红:**新测试复制 hook 目录、把两个旧上限各自放回去,要求同样那几句话对副本重新被拦(且 `--self-test` 失败)。**已知限制,没有改变:**豁免以段落为单位,含有一个这种条件子句的段落,会连带豁免旁边不相干的无条件承诺(原本就如此);没有逗号的条件句(“After you merged it I will follow up”)仍会被拦。
|
|
35
|
+
|
|
36
|
+
- **运行 `scripts/pre-release-check.sh`——以及在这个 repo 里 `git commit`——会把 UDS 技能写进执行者真实的家目录。** 2026-09-29,维护者在自己的机器上跑发版前检查,54 个技能文件夹与一个 `.manifest.json` 被写进真实的 `~/.claude/skills/`。用户层技能会遮蔽项目层技能,于是一个使用繁中技能的项目静默地跑起了英文测试版。每一步都是绿的:做这件事的那些步骤是在 `mkdtemp` 目录里跑 CLI,而那隔离的是**项目**,不是**用户**——`uds init -y` 与 `uds update` 不论在哪里跑,都会写用户层文件(`~/.claude/skills`、`~/.uds`)。用一次性 `HOME` 重现并实测,不是推测:`scripts/check-upgrade-fidelity.sh` 写入 115 个文件(它的 `uds update` 与上一版的 `npx … init` 都继承了真实 `HOME`);一开始被怀疑的 `check-adopter-instruction-files.ts` 什么也没写。另外两处写入者是逐文件二分单元测试找到的:`tests/commands/update-language-fidelity.test.js` 与 `update-agents-md-generator-fidelity.test.js` 调用真的 `updateCommand`(115 个文件进 `~/.claude/skills`),`tests/commands/check.test.js` 写了 `~/.uds/update-check.json`——而 pre-commit hook 会跑单元测试,所以**这个 repo 的每一次 commit 都会这样**;修正者自己在修正落地前的下一次 commit 就又对真实家目录做了一次。修正分三层:每一个会跑 CLI 的脚本现在都在一次性 `HOME` 下跑,且统一出自 `scripts/lib/isolated-home.{mjs,sh}`(`HOME`、`USERPROFILE`、`XDG_*`、`APPDATA`、`CODEX_HOME`;变量清单只有一份,bash 端执行 mjs 来读它),涵盖 `pre-release-check.sh` 的自我采用步骤、`check-upgrade-fidelity.sh`、`check-prompt-footprint.mjs`、`check-adopter-instruction-files.ts`、`check-skills-install-paths.ts`、`generate-usage-docs.mjs`、`cli/scripts/check-command-existence.mjs`、`cli/scripts/test-upgrade-path.mjs` 与 `cli/scripts/test-refactoring.sh`;测试套件在 `cli/tests/setup.js` 为每个测试文件换掉 `HOME`;`pre-release-check.sh` 开始前先对 `HOME` 底下 UDS 会写的位置拍快照,结束时若有任何新增或修改就在摘要失败(`scripts/check-home-untouched.mjs`)。被监看的位置不是手列的:从安装器的路径表与 `cli/src` 里以 `homedir()` 为根的路径遍历得出,并打印数量,所以缩成空集合的守卫不可能通过。**每次测试都观察到会红,且是端到端:**不隔离地对一个代表真实家目录的目录跑 CLI,守卫 exit 1 并点名 `~/.claude/skills`;有隔离则 exit 0;一个测试遍历每一个会 spawn CLI 的脚本,某个调用点的隔离被拿掉就红;一个探针测试在没有 `tests/setup.js` 时会失败。**如果你在这个修正之前跑过 `pre-release-check.sh`,或在这个 repo 里 commit 过,**请检查 `~/.claude/skills/`:若有 `installedDate` 是当天的 `.manifest.json` 与旁边的 UDS 技能文件夹,而那不是你自己装的,就移除它们(用户层技能会遮蔽项目层)。**刻意不监看:**`~/.claude/skills/synced/`——Claude Code 自己在运行时会把账号的 claude.ai 技能同步进去(在真实家目录上的第一次完整运行就因它失败,写入者正是运行检查的那个 Claude Code 会话);它是守卫排除清单里唯一一项、附有理由,每次比对都会打印,且排除被拿掉或放宽成整个 `~/.claude/skills` 时测试会失败。**未涵盖:**没有任何安装器点名的路径上的写入;以及端到端(`tests/e2e`)测试——已逐文件二分过,没有写入。
|
|
37
|
+
|
|
20
38
|
## [6.14.0-beta.1] - 2026-09-29
|
|
21
39
|
|
|
22
40
|
> **测试版**——以 `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.2 (Pre-release) | **发布日期**: 2026-09-30 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
语言无关、框架无关的软件项目文档标准。通过 AI 原生工作流,确保不同技术栈之间的一致性、质量和可维护性。
|
|
21
21
|
|
|
@@ -79,7 +79,7 @@ npx universal-dev-standards init
|
|
|
79
79
|
| **核心标准** | 153 | 通用开发准则 |
|
|
80
80
|
| **AI Skills** | 55 | 互动式技能 |
|
|
81
81
|
| **斜线命令** | 51 | 快速操作 |
|
|
82
|
-
| **CLI 命令** |
|
|
82
|
+
| **CLI 命令** | 24 | 项目设置与维护 |
|
|
83
83
|
<!-- UDS_STATS_TABLE_END -->
|
|
84
84
|
|
|
85
85
|
> **5.0 新功能?** 请参阅[预发布说明](../../docs/PRE-RELEASE.md)了解新功能详情。
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
| `uds agent` | Manage UDS agents for AI tools |
|
|
33
33
|
| `uds ai-context` | Manage .ai-context.yaml configuration for AI-friendly architecture |
|
|
34
34
|
| `uds mcp` | MCP server commands for AI tool integration |
|
|
35
|
+
| `uds open-work` | Reference checks for open-work-tracking (OWT-017/018/019). Exit 0 no violation, 1 violation, 2 cannot decide (not a pass) |
|
|
35
36
|
| `uds run` | Run a project command by intent (test/lint/build/security) via uds.project.yaml |
|
|
36
37
|
|
|
37
38
|
## 💬 斜线命令
|
|
@@ -352,6 +353,7 @@
|
|
|
352
353
|
| `check-docs-sync.sh` | Documentation Sync Checker |
|
|
353
354
|
| `check-error-exit.mjs` | 🔴 沒填就是沒設定,而沒設定會 exit 2, |
|
|
354
355
|
| `check-external-references.mjs` | External Reference Checker (SPEC-SELFDIAG-001 REQ- |
|
|
356
|
+
| `check-home-untouched.mjs` | check-home-untouched — did this run write anywhere |
|
|
355
357
|
| `check-open-work-tracking.mjs` | Open-work-tracking reference checks for OWT-017 / |
|
|
356
358
|
| `check-orphan-specs.ps1` | Check Orphan Specs |
|
|
357
359
|
| `check-orphan-specs.sh` | Orphan Spec Detection Script |
|
|
@@ -886,6 +886,30 @@ UDS 的项目——并在 `[pre-commit]` 下回报同样的修复方式;此警
|
|
|
886
886
|
(已评估、不支持),见
|
|
887
887
|
[支持的执行环境](../../../core/turn-completion-integrity.md#supported-harnesses)。
|
|
888
888
|
|
|
889
|
+
### 为已初始化的项目补装 Hooks(`uds update --with-hooks`)
|
|
890
|
+
|
|
891
|
+
`uds init` 不能跑第二次,所以 `--with-hooks` 到不了已经初始化的项目——包括在 UDS 支持某个工具**之前**
|
|
892
|
+
(或在检测认得它之前)就初始化的项目。`uds update --with-hooks` 就是那扇门:
|
|
893
|
+
|
|
894
|
+
```bash
|
|
895
|
+
uds update --with-hooks --plan # 列出会装什么;不写任何文件
|
|
896
|
+
uds update --with-hooks # 补装缺少的 hooks
|
|
897
|
+
uds update --with-hooks --ai-tool antigravity # 直接指定工具,不做检测
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
- **装给哪些工具。** `.standards/manifest.json` 里的工具,加上项目文件现在看得出来的(Claude Code:
|
|
901
|
+
`.claude/` 或 `CLAUDE.md`;Codex:根目录 `AGENTS.md`;Gemini CLI:`GEMINI.md`;Antigravity:
|
|
902
|
+
`.agents/AGENTS.md`、`.agents/rules/`、`.agents/workflows/`、`.agents/plugins/` 或
|
|
903
|
+
`.agents/hooks.json`)。**`.agents/skills/` 不算 Antigravity 的标记**——Codex 也从同一个目录读项目技能,
|
|
904
|
+
所以它分不出是哪个工具。`--ai-tool <列表>`(`claude-code`、`codex`、`gemini-cli`、`antigravity`,
|
|
905
|
+
以逗号分隔)会取代检测。找不到任何工具时,它会说明、打印出如何指定,并以 1 退出。
|
|
906
|
+
- **不会动什么。** 已经装好的 hook 不会被重写。你自己的 hooks 不会被移除或重排:Claude、Codex、Gemini 的
|
|
907
|
+
条目是合并进去;Antigravity 的 `.agents/hooks.json` 只写在 `uds-turn-completion-integrity` 这个键下面
|
|
908
|
+
(不是合法 JSON 的 `hooks.json` 会原样保留并报告)。`scripts/hooks/` 里与随附版本不同的 hook 脚本会被保留并报告;
|
|
909
|
+
加上 `--force` 才会覆盖。
|
|
910
|
+
- **它不做什么。** 不更新标准、技能或集成文件(那是一般的 `uds update`),也不会把工具加进 manifest。
|
|
911
|
+
它不能与 `--skills`、`--commands` 等其他 update 模式合用,合用时会明说。
|
|
912
|
+
|
|
889
913
|
### Claude Code 集成目标文件(`--claude-target`)
|
|
890
914
|
|
|
891
915
|
UDS 默认把 Claude Code 内容写进 `CLAUDE.md`——团队共用、会进版本控制的那个文件。
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
|
|
10
10
|
## 目录
|
|
11
11
|
|
|
12
|
-
1. [CLI 指令](#cli-commands) (
|
|
12
|
+
1. [CLI 指令](#cli-commands) (24)
|
|
13
13
|
2. [斜线命令](#slash-commands) (51)
|
|
14
14
|
3. [技能](#skills) (55)
|
|
15
15
|
4. [代理](#agents) (5)
|
|
16
16
|
5. [工作流程](#workflows) (5)
|
|
17
17
|
6. [核心规范](#core-standards) (153)
|
|
18
|
-
7. [脚本](#scripts) (
|
|
18
|
+
7. [脚本](#scripts) (63)
|
|
19
19
|
|
|
20
|
-
**Total Features:
|
|
20
|
+
**Total Features: 356**
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -158,6 +158,8 @@
|
|
|
158
158
|
| `--rollback` | Rollback to the most recent backup |
|
|
159
159
|
| `--claude-target` | Switch an existing install to a different Claude Code integration target: project (CLAUDE.md) or local (CLAUDE.local.md) — moves the UDS block, keeps your content, no reinstall |
|
|
160
160
|
| `--locale` | Override locale for skills install (zh-tw, zh-cn, en); also reads .uds/install.yaml + UDS_LOCALE env |
|
|
161
|
+
| `--with-hooks` | Install the enforcement hooks that are missing from this already-initialized project (re-detects tools; hooks already there and your own hooks are not touched; with --plan, writes nothing; --force also overwrites edited hook scripts) |
|
|
162
|
+
| `--ai-tool` | With --with-hooks: comma-separated tools to install hooks for (claude-code, codex, gemini-cli, antigravity) instead of detecting them |
|
|
161
163
|
|
|
162
164
|
### `uds skills`
|
|
163
165
|
|
|
@@ -276,6 +278,10 @@
|
|
|
276
278
|
|
|
277
279
|
**说明**: MCP server commands for AI tool integration
|
|
278
280
|
|
|
281
|
+
### `uds open-work`
|
|
282
|
+
|
|
283
|
+
**说明**: Reference checks for open-work-tracking (OWT-017/018/019). Exit 0 no violation, 1 violation, 2 cannot decide (not a pass)
|
|
284
|
+
|
|
279
285
|
### `uds run`
|
|
280
286
|
|
|
281
287
|
**说明**: Run a project command by intent (test/lint/build/security) via uds.project.yaml
|
|
@@ -610,7 +616,8 @@
|
|
|
610
616
|
| `check-docs-sync.sh` | Documentation Sync Checker |
|
|
611
617
|
| `check-error-exit.mjs` | 🔴 沒填就是沒設定,而沒設定會 exit 2, |
|
|
612
618
|
| `check-external-references.mjs` | External Reference Checker (SPEC-SELFDIAG-001 REQ-5, AC-7) |
|
|
613
|
-
| `check-
|
|
619
|
+
| `check-home-untouched.mjs` | check-home-untouched — did this run write anywhere UDS writes under HOME? |
|
|
620
|
+
| `check-open-work-tracking.mjs` | Open-work-tracking reference checks for OWT-017 / OWT-018 / OWT-019 — repo entry point. |
|
|
614
621
|
| `check-orphan-specs.ps1` | Check Orphan Specs |
|
|
615
622
|
| `check-orphan-specs.sh` | Orphan Spec Detection Script |
|
|
616
623
|
| `check-prompt-footprint.mjs` | Prompt Footprint Ratchet — DEC-117 D2/L2 |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.14.0-beta.
|
|
4
|
-
translation_version: 6.14.0-beta.
|
|
5
|
-
last_synced: 2026-09-
|
|
3
|
+
source_version: 6.14.0-beta.2
|
|
4
|
+
translation_version: 6.14.0-beta.2
|
|
5
|
+
last_synced: 2026-09-30
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -17,6 +17,24 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.14.0-beta.2] - 2026-09-30
|
|
21
|
+
|
|
22
|
+
> **測試版**——以 `npm install -g universal-dev-standards@beta` 安裝。要測什麼、如何退回正式版:[docs/PRE-RELEASE.md](../../docs/PRE-RELEASE.md)。
|
|
23
|
+
>
|
|
24
|
+
> **修正 6.14.0-beta.1 的已知限制:**既有專案現在可以用 `uds update --with-hooks` 補裝 Antigravity CLI 關卡(以及缺少的 Claude Code / Codex / Gemini CLI 關卡)。
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`uds open-work next-action | revision | separation | self-test` —— `open-work-tracking` 1.1.0 的參考檢查(OWT-017/018/019)現在隨 npm 安裝包出貨。** 6.14.0-beta.1 的這些檢查只在 repo 的 `scripts/` 裡,而 npm 安裝包不含該目錄,採用者不 clone UDS 就跑不了。規則現在只住在一個地方,`cli/src/utils/open-work-tracking.mjs`(在安裝包內);`uds open-work` 與舊的 `node scripts/check-open-work-tracking.mjs`(現在是一個不含規則、只重新匯出該模組的薄殼)跑的是同一份,並有測試要求兩者輸出完全相同。檢查本身沒有任何改變:結束碼相同(0 沒有違反、1 有違反、2 判定不了——2 不是通過),檢查器仍先跑自己的自測臂,每次執行仍聲明涵蓋率未知(OWT-011)、詞彙未校準(OWT-016)。它仍是作為證據提供的參考判定程序,不是閘門。**每次測試都觀察到會紅:**新測試複製 CLI,讓指令吞掉結束碼(永遠 0)或讓共用規則永遠通過,並要求違反的樣本對副本變綠;並斷言 `npm pack --dry-run` 的清單包含該模組。標準的「什麼在執行本標準」一節改為指向該指令,而不是只在 repo 裡的路徑。
|
|
29
|
+
|
|
30
|
+
- **`uds update --with-hooks`——為已初始化的專案補裝強制執行 hooks,並放寬 Antigravity 的偵測規則。** Hooks 過去只有 `uds init --with-hooks` 會接線,而 `uds init` 不能跑第二次,所以既有採用者永遠拿不到 UDS 在他們初始化之後才開始支援的工具的 hook(這是把 6.14.0-beta.1 安裝包裝進全新專案時發現的,已記為那一版的已知限制)。`uds update --with-hooks` 會重新偵測工具(manifest 裡的工具,加上專案檔案現在看得出來的)並補裝缺少的 hooks;`--ai-tool <清單>`(`claude-code`、`codex`、`gemini-cli`、`antigravity`)可改為直接指定,找不到任何工具時它會說明如何指定並以 1 結束,而不是猜。已經裝好的 hook 不會被重寫(重跑一次不會有任何變化),採用者自己的 hooks 絕不會被移除或重排(Claude/Codex/Gemini 是合併進去;agy 的 `.agents/hooks.json` 只寫在 UDS 自己的 `uds-turn-completion-integrity` 鍵底下,不是合法 JSON 的檔案原樣保留),採用者改過的 hook 腳本會被保留、除非加 `--force`,`--plan` 則什麼都不寫。它與 `--claude-target`、`--sync-refs` 一樣是獨立模式;在已初始化的專案執行 `uds init --with-hooks`,現在會指向它,而不是默默什麼都沒做。**Antigravity 偵測:**原本要求 `.agents/AGENTS.md`,而一個專案可以長期使用 agy 卻從不建立這個檔。現在也接受 `.agents/rules/`、`.agents/workflows/`、`.agents/plugins/` 與 `.agents/hooks.json`——這些是 agy 自己的執行檔帶著、且 antigravity.google 有文件記載的名稱——並且刻意**不**把 `.agents/skills/` 算進去,因為 Codex 也讀它(根目錄 `AGENTS.md` 加 `.agents/skills/` 的 repo 仍是 Codex;有測試)。偵測只看專案目錄:agy 記錄已開啟專案的 `~/.gemini/projects.json` 有被考慮,但因為它是機器本地的而不採用。`.agents/hooks.json` 是標記,但它同時也是 UDS 自己寫的檔,所以安裝之後它證明的是「裝過」,不是「採用者在用 agy」。**每次測試都觀察到會紅:**測試把真的 CLI 當子行程對一個已初始化的專案跑,並要求把補裝拿掉的 CLI 複本——刪掉該分支、一個回報成功卻什麼都沒寫的安裝器、偵測退回只看 `.agents/AGENTS.md`——對真 CLI 會通過的同一組斷言失敗。agy 關卡仍然只驗證過 `agy -p` 模式下沒有用工具的單一回合。
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **`turn-completion-integrity` 在使用者的前提子句超過固定字數時,會把「正在等使用者」的一輪擋下——自 6.13 起就存在。** 條件式承諾(「你選好後,我會套用」)的豁免,在英文語言包是 `you` 到逗號之間最多 20 個字元,在 zh-TW 語言包是 `你` 到 `後` 之間 1–6 個字;兩個數字都是憑感覺訂的。以已發佈的 6.14.0-beta.1、真實的 Claude Code Stop hook 輸入實測:「Once you choose A, I will apply it.」放行,「Once you choose option A or B, I will apply it.」(21 個字元)被擋,「After you choose option A or B, I will apply it.」同樣被擋——決定結果的是子句長度,不是 `once`/`after`。此 hook 只看一輪的**最後**一則訊息,所以採用者看到的是:代理明明已經正確地停下來問人,卻被逼著繼續講話。修正:豁免改為延伸到子句邊界(逗號、句末標點或換行),不再是字數,因此「Once you've reviewed the three options above and picked one, I will apply it.」與「你看完上面三個選項並選好一個之後,我會接著套用。」都放行。放寬上限就是讓真承諾漏過的方向,所以改用兩道規則取代字數:英文的子句內不得含有我自己的承諾(「After you merged it I will follow up, I will push the tag.」仍被擋);zh-TW 的 `你` 必須是子句的開頭、且不能是「你的」(「我看了你的設定檔並判斷需要重構之後,我會接著改。」仍被擋——那裡的 `你` 是我自己那句話裡的所有格)。「I will apply it once the build finishes.」不是在等使用者,仍被擋。**每次測試都觀察到會紅:**新測試複製 hook 目錄、把兩個舊上限各自放回去,要求同樣那幾句話對複本重新被擋(且 `--self-test` 失敗)。**已知限制,沒有改變:**豁免以段落為單位,含有一個這種條件子句的段落,會連帶豁免旁邊不相干的無條件承諾(原本就如此);沒有逗號的條件句(「After you merged it I will follow up」)仍會被擋。
|
|
35
|
+
|
|
36
|
+
- **執行 `scripts/pre-release-check.sh`——以及在這個 repo 裡 `git commit`——會把 UDS 技能寫進執行者真實的家目錄。** 2026-09-29,維護者在自己的機器上跑發版前檢查,54 個技能資料夾與一個 `.manifest.json` 被寫進真實的 `~/.claude/skills/`。使用者層技能會遮蔽專案層技能,於是一個使用繁中技能的專案靜默地跑起英文測試版。每一步都是綠的:做這件事的那些步驟是在 `mkdtemp` 目錄裡跑 CLI,而那隔離的是**專案**,不是**使用者**——`uds init -y` 與 `uds update` 不論在哪裡跑,都會寫使用者層檔案(`~/.claude/skills`、`~/.uds`)。用拋棄式 `HOME` 重現並實測,不是推測:`scripts/check-upgrade-fidelity.sh` 寫入 115 個檔案(它的 `uds update` 與前一版的 `npx … init` 都繼承了真實 `HOME`);一開始被懷疑的 `check-adopter-instruction-files.ts` 什麼也沒寫。另外兩處寫入者是逐檔二分單元測試找到的:`tests/commands/update-language-fidelity.test.js` 與 `update-agents-md-generator-fidelity.test.js` 呼叫真的 `updateCommand`(115 個檔案進 `~/.claude/skills`),`tests/commands/check.test.js` 寫了 `~/.uds/update-check.json`——而 pre-commit hook 會跑單元測試,所以**這個 repo 的每一次 commit 都會這樣**;修正者自己在修正落地前的下一次 commit 就又對真實家目錄做了一次。修正分三層:每一支會跑 CLI 的腳本現在都在拋棄式 `HOME` 下跑,且統一出自 `scripts/lib/isolated-home.{mjs,sh}`(`HOME`、`USERPROFILE`、`XDG_*`、`APPDATA`、`CODEX_HOME`;變數清單只有一份,bash 端執行 mjs 來讀它),涵蓋 `pre-release-check.sh` 的自我採用步驟、`check-upgrade-fidelity.sh`、`check-prompt-footprint.mjs`、`check-adopter-instruction-files.ts`、`check-skills-install-paths.ts`、`generate-usage-docs.mjs`、`cli/scripts/check-command-existence.mjs`、`cli/scripts/test-upgrade-path.mjs` 與 `cli/scripts/test-refactoring.sh`;測試套件在 `cli/tests/setup.js` 為每個測試檔換掉 `HOME`;`pre-release-check.sh` 開始前先對 `HOME` 底下 UDS 會寫的位置拍快照,結束時若有任何新增或修改就在摘要失敗(`scripts/check-home-untouched.mjs`)。被監看的位置不是手列的:從安裝器的路徑表與 `cli/src` 裡以 `homedir()` 為根的路徑走訪得出,並印出數量,所以縮成空集合的守衛不可能通過。**每次測試都觀察到會紅,且是端到端:**不隔離地對一個代表真實家目錄的目錄跑 CLI,守衛 exit 1 並點名 `~/.claude/skills`;有隔離則 exit 0;一支測試走訪每一支會 spawn CLI 的腳本,某個呼叫點的隔離被拿掉就紅;一支探針測試在沒有 `tests/setup.js` 時會失敗。**如果你在這個修正之前跑過 `pre-release-check.sh`,或在這個 repo 裡 commit 過,**請檢查 `~/.claude/skills/`:若有 `installedDate` 是當天的 `.manifest.json` 與旁邊的 UDS 技能資料夾,而那不是你自己裝的,就移除它們(使用者層技能會遮蔽專案層)。**刻意不監看:**`~/.claude/skills/synced/`——Claude Code 自己在執行時會把帳號的 claude.ai 技能同步進去(在真實家目錄上的第一次完整執行就因它失敗,寫入者正是執行檢查的那個 Claude Code 工作階段);它是守衛排除清單裡唯一一項、附有理由,每次比對都會印出,且排除被拿掉或放寬成整個 `~/.claude/skills` 時測試會失敗。**未涵蓋:**沒有任何安裝器點名的路徑上的寫入;以及端到端(`tests/e2e`)測試——已逐檔二分過,沒有寫入。
|
|
37
|
+
|
|
20
38
|
## [6.14.0-beta.1] - 2026-09-29
|
|
21
39
|
|
|
22
40
|
> **測試版**——以 `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.2 (Pre-release) | **發布日期**: 2026-09-30 | **授權**: [雙重授權](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
語言無關、框架無關的軟體專案文件標準。透過 AI 原生工作流,確保不同技術堆疊之間的一致性、品質和可維護性。
|
|
21
21
|
|
|
@@ -79,7 +79,7 @@ npx universal-dev-standards init
|
|
|
79
79
|
| **核心標準** | 153 | 通用開發準則 |
|
|
80
80
|
| **AI Skills** | 55 | 互動式技能 |
|
|
81
81
|
| **斜線命令** | 51 | 快速操作 |
|
|
82
|
-
| **CLI 指令** |
|
|
82
|
+
| **CLI 指令** | 24 | 專案設定與維護 |
|
|
83
83
|
<!-- UDS_STATS_TABLE_END -->
|
|
84
84
|
|
|
85
85
|
> **5.0 新功能?** 請參閱[預發布說明](../../docs/PRE-RELEASE.md)了解新功能詳情。
|
|
@@ -3,7 +3,7 @@ source: ../../../core/open-work-tracking.md
|
|
|
3
3
|
source_version: 1.1.0
|
|
4
4
|
translation_version: 1.1.0
|
|
5
5
|
last_synced: 2026-09-29
|
|
6
|
-
source_hash:
|
|
6
|
+
source_hash: 0fcf3df23e12
|
|
7
7
|
status: current
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -284,7 +284,7 @@ DEX-003 扮演的角色相同。上面每一條都指名了 artefact 與它們
|
|
|
284
284
|
**UDS 不對本標準設任何閘門,而這件事是被記錄的,不是被暗示的。** UDS 陳述一個承載開放工作的地方
|
|
285
285
|
必須滿足的關係;有沒有東西去判定它,依上面的[寫法約束](#本標準的寫法以及為什麼這樣寫),
|
|
286
286
|
是採用專案的決定——與 [deferred-item-exit](deferred-item-exit.md) 對自己出口劃的界線相同。
|
|
287
|
-
自 1.1.0 起,UDS 為 OWT-017–OWT-019
|
|
287
|
+
自 1.1.0 起,UDS 為 OWT-017–OWT-019 附上一支**參考判定程序**——npm 安裝包裡的 `uds open-work next-action | revision | separation`(`uds open-work self-test` 只跑檢查器自己的自測臂;在 UDS repo 的副本裡,`node scripts/check-open-work-tracking.mjs` 跑的是同一份程式)——
|
|
288
288
|
作為 OWT-015 意義上的證據——它已被觀察到對違反的樣本回報失敗——供採用者直接執行或自行重做。
|
|
289
289
|
它沒有接進任何 UDS 發版閘門,因為 UDS 本身沒有承載開放工作的地方可供它檢查。
|
|
290
290
|
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
| `uds agent` | Manage UDS agents for AI tools |
|
|
33
33
|
| `uds ai-context` | Manage .ai-context.yaml configuration for AI-friendly architecture |
|
|
34
34
|
| `uds mcp` | MCP server commands for AI tool integration |
|
|
35
|
+
| `uds open-work` | Reference checks for open-work-tracking (OWT-017/018/019). Exit 0 no violation, 1 violation, 2 cannot decide (not a pass) |
|
|
35
36
|
| `uds run` | Run a project command by intent (test/lint/build/security) via uds.project.yaml |
|
|
36
37
|
|
|
37
38
|
## 💬 斜線命令
|
|
@@ -352,6 +353,7 @@
|
|
|
352
353
|
| `check-docs-sync.sh` | Documentation Sync Checker |
|
|
353
354
|
| `check-error-exit.mjs` | 🔴 沒填就是沒設定,而沒設定會 exit 2, |
|
|
354
355
|
| `check-external-references.mjs` | External Reference Checker (SPEC-SELFDIAG-001 REQ- |
|
|
356
|
+
| `check-home-untouched.mjs` | check-home-untouched — did this run write anywhere |
|
|
355
357
|
| `check-open-work-tracking.mjs` | Open-work-tracking reference checks for OWT-017 / |
|
|
356
358
|
| `check-orphan-specs.ps1` | Check Orphan Specs |
|
|
357
359
|
| `check-orphan-specs.sh` | Orphan Spec Detection Script |
|
|
@@ -886,6 +886,30 @@ UDS 的專案——並在 `[pre-commit]` 底下回報同樣的修復方式;此
|
|
|
886
886
|
(已評估、不支援),見
|
|
887
887
|
[支援的執行環境](../../../core/turn-completion-integrity.md#supported-harnesses)。
|
|
888
888
|
|
|
889
|
+
### 為已初始化的專案補裝 Hooks(`uds update --with-hooks`)
|
|
890
|
+
|
|
891
|
+
`uds init` 不能跑第二次,所以 `--with-hooks` 到不了已經初始化的專案——包括在 UDS 支援某個工具**之前**
|
|
892
|
+
(或在偵測認得它之前)就初始化的專案。`uds update --with-hooks` 就是那扇門:
|
|
893
|
+
|
|
894
|
+
```bash
|
|
895
|
+
uds update --with-hooks --plan # 列出會裝什麼;不寫任何檔
|
|
896
|
+
uds update --with-hooks # 補裝缺少的 hooks
|
|
897
|
+
uds update --with-hooks --ai-tool antigravity # 直接指定工具,不做偵測
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
- **裝給哪些工具。** `.standards/manifest.json` 裡的工具,加上專案檔案現在看得出來的(Claude Code:
|
|
901
|
+
`.claude/` 或 `CLAUDE.md`;Codex:根目錄 `AGENTS.md`;Gemini CLI:`GEMINI.md`;Antigravity:
|
|
902
|
+
`.agents/AGENTS.md`、`.agents/rules/`、`.agents/workflows/`、`.agents/plugins/` 或
|
|
903
|
+
`.agents/hooks.json`)。**`.agents/skills/` 不算 Antigravity 的標記**——Codex 也從同一個目錄讀專案技能,
|
|
904
|
+
所以它分不出是哪個工具。`--ai-tool <清單>`(`claude-code`、`codex`、`gemini-cli`、`antigravity`,
|
|
905
|
+
以逗號分隔)會取代偵測。找不到任何工具時,它會說明、印出如何指定,並以 1 結束。
|
|
906
|
+
- **不會動什麼。** 已經裝好的 hook 不會被重寫。你自己的 hooks 不會被移除或重排:Claude、Codex、Gemini 的
|
|
907
|
+
項目是合併進去;Antigravity 的 `.agents/hooks.json` 只寫在 `uds-turn-completion-integrity` 這個鍵底下
|
|
908
|
+
(不是合法 JSON 的 `hooks.json` 會原樣保留並回報)。`scripts/hooks/` 裡與隨附版本不同的 hook 腳本會被保留並回報;
|
|
909
|
+
加上 `--force` 才會覆寫。
|
|
910
|
+
- **它不做什麼。** 不更新標準、技能或整合檔(那是一般的 `uds update`),也不會把工具加進 manifest。
|
|
911
|
+
它不能與 `--skills`、`--commands` 等其他 update 模式合用,合用時會明說。
|
|
912
|
+
|
|
889
913
|
### Claude Code 整合目標檔(`--claude-target`)
|
|
890
914
|
|
|
891
915
|
UDS 預設把 Claude Code 內容寫進 `CLAUDE.md`——團隊共用、會進版控的那個檔案。
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
|
|
10
10
|
## 目錄
|
|
11
11
|
|
|
12
|
-
1. [CLI 指令](#cli-commands) (
|
|
12
|
+
1. [CLI 指令](#cli-commands) (24)
|
|
13
13
|
2. [斜線命令](#slash-commands) (51)
|
|
14
14
|
3. [技能](#skills) (55)
|
|
15
15
|
4. [代理](#agents) (5)
|
|
16
16
|
5. [工作流程](#workflows) (5)
|
|
17
17
|
6. [核心規範](#core-standards) (153)
|
|
18
|
-
7. [腳本](#scripts) (
|
|
18
|
+
7. [腳本](#scripts) (63)
|
|
19
19
|
|
|
20
|
-
**Total Features:
|
|
20
|
+
**Total Features: 356**
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -158,6 +158,8 @@
|
|
|
158
158
|
| `--rollback` | Rollback to the most recent backup |
|
|
159
159
|
| `--claude-target` | Switch an existing install to a different Claude Code integration target: project (CLAUDE.md) or local (CLAUDE.local.md) — moves the UDS block, keeps your content, no reinstall |
|
|
160
160
|
| `--locale` | Override locale for skills install (zh-tw, zh-cn, en); also reads .uds/install.yaml + UDS_LOCALE env |
|
|
161
|
+
| `--with-hooks` | Install the enforcement hooks that are missing from this already-initialized project (re-detects tools; hooks already there and your own hooks are not touched; with --plan, writes nothing; --force also overwrites edited hook scripts) |
|
|
162
|
+
| `--ai-tool` | With --with-hooks: comma-separated tools to install hooks for (claude-code, codex, gemini-cli, antigravity) instead of detecting them |
|
|
161
163
|
|
|
162
164
|
### `uds skills`
|
|
163
165
|
|
|
@@ -276,6 +278,10 @@
|
|
|
276
278
|
|
|
277
279
|
**說明**: MCP server commands for AI tool integration
|
|
278
280
|
|
|
281
|
+
### `uds open-work`
|
|
282
|
+
|
|
283
|
+
**說明**: Reference checks for open-work-tracking (OWT-017/018/019). Exit 0 no violation, 1 violation, 2 cannot decide (not a pass)
|
|
284
|
+
|
|
279
285
|
### `uds run`
|
|
280
286
|
|
|
281
287
|
**說明**: Run a project command by intent (test/lint/build/security) via uds.project.yaml
|
|
@@ -610,7 +616,8 @@
|
|
|
610
616
|
| `check-docs-sync.sh` | Documentation Sync Checker |
|
|
611
617
|
| `check-error-exit.mjs` | 🔴 沒填就是沒設定,而沒設定會 exit 2, |
|
|
612
618
|
| `check-external-references.mjs` | External Reference Checker (SPEC-SELFDIAG-001 REQ-5, AC-7) |
|
|
613
|
-
| `check-
|
|
619
|
+
| `check-home-untouched.mjs` | check-home-untouched — did this run write anywhere UDS writes under HOME? |
|
|
620
|
+
| `check-open-work-tracking.mjs` | Open-work-tracking reference checks for OWT-017 / OWT-018 / OWT-019 — repo entry point. |
|
|
614
621
|
| `check-orphan-specs.ps1` | Check Orphan Specs |
|
|
615
622
|
| `check-orphan-specs.sh` | Orphan Spec Detection Script |
|
|
616
623
|
| `check-prompt-footprint.mjs` | Prompt Footprint Ratchet — DEC-117 D2/L2 |
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -52,6 +52,8 @@ export async function initCommand(options) {
|
|
|
52
52
|
if (isInitialized(projectPath)) {
|
|
53
53
|
console.log(chalk.yellow(msg.alreadyInitialized));
|
|
54
54
|
console.log(chalk.gray(` ${msg.useUpdateOrDelete}`));
|
|
55
|
+
// `init` cannot run twice, so `--with-hooks` has no effect here; say where the door is.
|
|
56
|
+
if (options.withHooks) console.log(chalk.yellow(` ${msg.useUpdateWithHooks}`));
|
|
55
57
|
return;
|
|
56
58
|
}
|
|
57
59
|
|