universal-dev-standards 5.1.0-beta.7 → 5.1.0
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/README.md +6 -0
- package/bin/uds.js +2 -0
- package/bundled/ai/standards/translation-lifecycle-standards.ai.yaml +145 -0
- package/bundled/core/translation-lifecycle-standards.md +162 -0
- package/bundled/locales/zh-CN/CHANGELOG.md +32 -3
- package/bundled/locales/zh-CN/README.md +1 -1
- package/bundled/locales/zh-CN/core/anti-hallucination.md +22 -3
- package/bundled/locales/zh-CN/core/anti-sycophancy-prompting.md +192 -0
- package/bundled/locales/zh-CN/core/capability-declaration.md +123 -0
- package/bundled/locales/zh-CN/core/circuit-breaker.md +106 -0
- package/bundled/locales/zh-CN/core/dual-phase-output.md +103 -0
- package/bundled/locales/zh-CN/core/failure-source-taxonomy.md +99 -0
- package/bundled/locales/zh-CN/core/frontend-design-standards.md +289 -0
- package/bundled/locales/zh-CN/core/health-check-standards.md +144 -0
- package/bundled/locales/zh-CN/core/immutability-first.md +96 -0
- package/bundled/locales/zh-CN/core/packaging-standards.md +224 -0
- package/bundled/locales/zh-CN/core/recovery-recipe-registry.md +146 -0
- package/bundled/locales/zh-CN/core/retry-standards.md +131 -0
- package/bundled/locales/zh-CN/core/security-decision.md +104 -0
- package/bundled/locales/zh-CN/core/skill-standard-alignment-check.md +112 -0
- package/bundled/locales/zh-CN/core/standard-admission-criteria.md +104 -0
- package/bundled/locales/zh-CN/core/standard-lifecycle-management.md +116 -0
- package/bundled/locales/zh-CN/core/timeout-standards.md +117 -0
- package/bundled/locales/zh-CN/core/token-budget.md +108 -0
- package/bundled/locales/zh-CN/core/translation-lifecycle-standards.md +159 -0
- package/bundled/locales/zh-TW/CHANGELOG.md +32 -3
- package/bundled/locales/zh-TW/README.md +1 -1
- package/bundled/locales/zh-TW/core/anti-sycophancy-prompting.md +8 -0
- package/bundled/locales/zh-TW/core/capability-declaration.md +111 -0
- package/bundled/locales/zh-TW/core/circuit-breaker.md +111 -0
- package/bundled/locales/zh-TW/core/dual-phase-output.md +132 -0
- package/bundled/locales/zh-TW/core/failure-source-taxonomy.md +146 -0
- package/bundled/locales/zh-TW/core/frontend-design-standards.md +460 -0
- package/bundled/locales/zh-TW/core/health-check-standards.md +144 -0
- package/bundled/locales/zh-TW/core/immutability-first.md +159 -0
- package/bundled/locales/zh-TW/core/recovery-recipe-registry.md +146 -0
- package/bundled/locales/zh-TW/core/retry-standards.md +140 -0
- package/bundled/locales/zh-TW/core/security-decision.md +120 -0
- package/bundled/locales/zh-TW/core/skill-standard-alignment-check.md +112 -0
- package/bundled/locales/zh-TW/core/standard-admission-criteria.md +104 -0
- package/bundled/locales/zh-TW/core/standard-lifecycle-management.md +116 -0
- package/bundled/locales/zh-TW/core/timeout-standards.md +117 -0
- package/bundled/locales/zh-TW/core/token-budget.md +143 -0
- package/bundled/locales/zh-TW/core/translation-lifecycle-standards.md +159 -0
- package/package.json +2 -1
- package/src/commands/check.js +6 -0
- package/src/commands/init.js +6 -0
- package/src/commands/update.js +6 -0
- package/src/utils/detect-self-adoption.js +173 -0
- package/standards-registry.json +15 -4
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
source: ../../../core/translation-lifecycle-standards.md
|
|
3
|
+
source_version: 1.0.0
|
|
4
|
+
translation_version: 1.0.0
|
|
5
|
+
last_synced: 2026-04-20
|
|
6
|
+
status: current
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 翻譯生命週期標準
|
|
10
|
+
|
|
11
|
+
> **語言**: [English](../../../core/translation-lifecycle-standards.md) | 繁體中文
|
|
12
|
+
|
|
13
|
+
**版本**: 1.0.0
|
|
14
|
+
**最後更新**: 2026-04-20
|
|
15
|
+
**狀態**: Trial(到期 2026-10-20)
|
|
16
|
+
**適用範圍**: 所有具備多語言文件的專案
|
|
17
|
+
**來源**: UDS BUG-A06 事後分析(2026-04-20)
|
|
18
|
+
**父標準**: [documentation-lifecycle](documentation-lifecycle.md)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 目的
|
|
23
|
+
|
|
24
|
+
翻譯生命週期標準:MISSING 與 OUTDATED 的區別、Semver 嚴重度分級,以及自動化整合(pre-commit hook、release gate)。
|
|
25
|
+
|
|
26
|
+
`documentation-lifecycle` 標準提到翻譯同步是 release gate 的一環,但未定義如何分類或回應不同程度的漂移。本標準填補這個缺口:翻譯檔案不存在與略微過時有本質差異,major 版本落差與 patch 升版也有本質差異。若不作區分,團隊要麼過度阻塞(任何過時都 fail),要麼阻塞不足(忽略所有過時直到成為用戶可見的問題)。
|
|
27
|
+
|
|
28
|
+
**證據(BUG-A06 事後分析)**:
|
|
29
|
+
1. UDS 在 3 個月內新增 32 個標準時,因缺乏 MISSING gate,翻譯全部缺失,直到 Q2 audit 才發現。
|
|
30
|
+
2. `anti-hallucination.md` zh-CN 停在 1.5.0,來源已升至 1.5.1——新的 Agent 認識論校準框架段落在 zh-CN 版本中完全缺失,使用者看不到。
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 核心規範
|
|
35
|
+
|
|
36
|
+
- `MISSING`(翻譯檔案不存在)永遠是 release blocker — `exit 1`
|
|
37
|
+
- `MAJOR` 版本落差(來源 X > 翻譯 x,X > x)是 release blocker — `exit 1`
|
|
38
|
+
- `MINOR` 版本落差是 advisory — 醒目警告,不阻塞
|
|
39
|
+
- `PATCH` 版本落差是 advisory — 柔和警告,不阻塞
|
|
40
|
+
- 嚴重度由翻譯 frontmatter 的 `source_version` 與目前來源版本的 semver 比較決定
|
|
41
|
+
- 每個翻譯檔案必須有 YAML frontmatter,包含 `source`、`source_version`、`translation_version`、`last_synced`、`status`
|
|
42
|
+
- 來源標準被修改後,翻譯的 `source_version` 立即過時——這種漂移可在 commit 時透過 pre-commit hook 偵測
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 嚴重度分級
|
|
47
|
+
|
|
48
|
+
| 等級 | 條件 | Exit Code | 行動 |
|
|
49
|
+
|------|------|-----------|------|
|
|
50
|
+
| `MISSING` | 翻譯檔案不存在 | 1 | 發布前建立 |
|
|
51
|
+
| `MAJOR` | 來源 MAJOR > 翻譯 MAJOR | 1 | 正式版發布前更新 |
|
|
52
|
+
| `MINOR` | 來源 MINOR > 翻譯 MINOR(同 MAJOR)| 0 | 下次發布前更新(advisory)|
|
|
53
|
+
| `PATCH` | 來源 PATCH > 翻譯 PATCH(同 MAJOR.MINOR)| 0 | 方便時更新(advisory)|
|
|
54
|
+
| `CURRENT` | source_version == 目前來源版本 | 0 | 無需行動 |
|
|
55
|
+
|
|
56
|
+
### Semver 差異公式
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
diff_level = compare(
|
|
60
|
+
strip_prerelease(current_source_version),
|
|
61
|
+
strip_prerelease(translation.source_version)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
其中:major 不同 → MAJOR,minor 不同 → MINOR,其他 → PATCH
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 觸發條件
|
|
70
|
+
|
|
71
|
+
| 事件 | 必要行動 |
|
|
72
|
+
|------|---------|
|
|
73
|
+
| 新增標準到 `core/` | 在所有支援的語言建立翻譯(MISSING check 阻塞發布)|
|
|
74
|
+
| 標準 PATCH 升版 | 方便時更新翻譯的 `source_version` + `last_synced` |
|
|
75
|
+
| 標準 MINOR 升版(含新段落)| 更新翻譯內容 + frontmatter,下次發布前完成 |
|
|
76
|
+
| 標準 MAJOR 升版(大改寫)| 更新翻譯內容 + frontmatter,當前發布前完成(阻塞)|
|
|
77
|
+
| 手動更新翻譯 | 升版 `translation_version` + `last_synced` |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 翻譯 Frontmatter 協議
|
|
82
|
+
|
|
83
|
+
每個翻譯檔案必須以以下格式開頭:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
---
|
|
87
|
+
source: ../../../core/<filename>.md # 指向來源的相對路徑
|
|
88
|
+
source_version: <X.Y.Z> # 最後同步時的來源版本
|
|
89
|
+
translation_version: <X.Y.Z> # 翻譯自身的版本
|
|
90
|
+
last_synced: <YYYY-MM-DD> # 最後同步日期
|
|
91
|
+
status: current | outdated | draft # 人類可讀狀態
|
|
92
|
+
---
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
更新翻譯時:
|
|
96
|
+
1. 翻譯新增或修改的內容
|
|
97
|
+
2. 設定 `source_version` = 新的來源版本
|
|
98
|
+
3. 設定 `translation_version` = 與 `source_version` 相同(或獨立升版)
|
|
99
|
+
4. 設定 `last_synced` = 今天日期
|
|
100
|
+
5. 設定 `status: current`
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 自動化整合
|
|
105
|
+
|
|
106
|
+
### Pre-Commit Hook
|
|
107
|
+
|
|
108
|
+
當 `core/*.md` 檔案被暫存時,pre-commit hook 執行 `check-translation-sync.sh` 並顯示 OUTDATED 警告。Hook **永不阻塞** commit(在 commit 時阻塞過於擾人)——純提醒用途。
|
|
109
|
+
|
|
110
|
+
設定方式:`./scripts/install-hooks.sh`(clone 後執行一次)
|
|
111
|
+
|
|
112
|
+
### Release Gate(`check-translation-sync.sh`)
|
|
113
|
+
|
|
114
|
+
在 `npm publish` 前或作為 `pre-release-check.sh` 的一部分執行:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
bash scripts/check-translation-sync.sh
|
|
118
|
+
# MISSING 或 MAJOR 落差 → exit 1
|
|
119
|
+
# 僅 MINOR/PATCH 落差 → exit 0(附 advisory 輸出)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Version Bump 整合(`bump-version.sh`)
|
|
123
|
+
|
|
124
|
+
`bump-version.sh` 在更新版本檔案後自動執行 `check-translation-sync.sh`,在升版時即時顯示翻譯健康狀態快照——讓作者立即知道發布前需要更新什麼。
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 情境範例
|
|
129
|
+
|
|
130
|
+
**情境 1 — 標準 patch 升版(1.0.0 → 1.0.1)**
|
|
131
|
+
- 翻譯 `source_version: 1.0.0`,來源現在是 `1.0.1`
|
|
132
|
+
- 嚴重度:`PATCH` — advisory,exit 0
|
|
133
|
+
- 行動:下次方便時更新,不阻塞發布
|
|
134
|
+
|
|
135
|
+
**情境 2 — 標準 minor 升版含新段落(1.0.0 → 1.1.0)**
|
|
136
|
+
- 翻譯 `source_version: 1.0.0`,來源現在是 `1.1.0`
|
|
137
|
+
- 嚴重度:`MINOR` — advisory,exit 0
|
|
138
|
+
- 行動:下次發布前更新;zh-CN 使用者缺少新內容
|
|
139
|
+
|
|
140
|
+
**情境 3 — 標準 major 大改寫(1.x.x → 2.0.0)**
|
|
141
|
+
- 翻譯 `source_version: 1.5.0`,來源現在是 `2.0.0`
|
|
142
|
+
- 嚴重度:`MAJOR` — 阻塞,exit 1
|
|
143
|
+
- 行動:正式版發布前必須更新
|
|
144
|
+
|
|
145
|
+
**情境 4 — 新標準,無翻譯檔案**
|
|
146
|
+
- `locales/zh-TW/core/new-standard.md` 不存在
|
|
147
|
+
- 嚴重度:`MISSING` — 阻塞,exit 1
|
|
148
|
+
- 行動:發布前建立翻譯檔案
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 錯誤碼
|
|
153
|
+
|
|
154
|
+
| 代碼 | 說明 |
|
|
155
|
+
|------|------|
|
|
156
|
+
| `TRANS-001` | `MISSING_TRANSLATION` — 來源標準的翻譯檔案不存在 |
|
|
157
|
+
| `TRANS-002` | `MAJOR_VERSION_GAP` — 翻譯的 source_version 落後目前來源 MAJOR 版本 |
|
|
158
|
+
| `TRANS-003` | `MISSING_FRONTMATTER` — 翻譯檔案缺少必要的 YAML frontmatter |
|
|
159
|
+
| `TRANS-004` | `STALE_SOURCE_REF` — frontmatter 的 `source` 路徑指向不存在的檔案 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-dev-standards",
|
|
3
|
-
"version": "5.1.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "CLI tool for adopting Universal Development Standards",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"documentation",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"generate:e2e-spec": "node scripts/generate-e2e-spec.mjs",
|
|
56
56
|
"prepare": "node ../scripts/setup-husky.mjs",
|
|
57
57
|
"test:upgrade": "node scripts/test-upgrade-path.mjs",
|
|
58
|
+
"check:bundle-parity": "node scripts/check-bundle-parity.mjs",
|
|
58
59
|
"prepack": "node scripts/prepack.mjs"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
package/src/commands/check.js
CHANGED
|
@@ -36,6 +36,7 @@ import { writeUpdateCache } from '../utils/update-checker.js';
|
|
|
36
36
|
import { StandardValidator } from '../utils/standard-validator.js';
|
|
37
37
|
import { WorkflowGate } from '../utils/workflow-gate.js';
|
|
38
38
|
import { t, getLanguage, setLanguage, isLanguageExplicitlySet } from '../i18n/messages.js';
|
|
39
|
+
import { guardAgainstSelfAdoption } from '../utils/detect-self-adoption.js';
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Display the summary of file integrity status
|
|
@@ -212,6 +213,11 @@ function displayAdoptionStatus(manifest, msg, common, repoInfo) {
|
|
|
212
213
|
export async function checkCommand(options = {}) {
|
|
213
214
|
const projectPath = process.cwd();
|
|
214
215
|
|
|
216
|
+
// Refuse to run inside the UDS source repo itself.
|
|
217
|
+
// See DEC-044 / XSPEC-071 — adoption-drift check makes no sense for the
|
|
218
|
+
// source repo. `--force` bypasses (e.g. private forks of UDS).
|
|
219
|
+
guardAgainstSelfAdoption('check', options, projectPath);
|
|
220
|
+
|
|
215
221
|
// Handle --standard option (validate specific standard physical spec)
|
|
216
222
|
if (options.standard) {
|
|
217
223
|
const validator = new StandardValidator(projectPath);
|
package/src/commands/init.js
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from '../utils/github.js';
|
|
23
23
|
import { displayLanguageToLocale } from '../utils/locale.js';
|
|
24
24
|
import { generateReleaseConfig, RELEASE_MODE_LABELS } from '../utils/release-config.js';
|
|
25
|
+
import { guardAgainstSelfAdoption } from '../utils/detect-self-adoption.js';
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Init command - initialize standards in current project
|
|
@@ -32,6 +33,11 @@ export async function initCommand(options) {
|
|
|
32
33
|
let msg = t().commands.init;
|
|
33
34
|
let common = t().commands.common;
|
|
34
35
|
|
|
36
|
+
// Refuse to run inside the UDS source repo itself.
|
|
37
|
+
// See DEC-044 / XSPEC-071 — UDS source repo already ships its standards;
|
|
38
|
+
// running `uds init` here is nonsensical. `--force` bypasses.
|
|
39
|
+
guardAgainstSelfAdoption('init', options, projectPath);
|
|
40
|
+
|
|
35
41
|
console.log();
|
|
36
42
|
console.log(chalk.bold(msg.title));
|
|
37
43
|
console.log(chalk.gray('─'.repeat(50)));
|
package/src/commands/update.js
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
listBackups
|
|
50
50
|
} from '../reconciler/index.js';
|
|
51
51
|
import { restoreSingleFile } from './check.js';
|
|
52
|
+
import { guardAgainstSelfAdoption } from '../utils/detect-self-adoption.js';
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
55
|
* Determine the correct target directory for a standard file.
|
|
@@ -244,6 +245,11 @@ function resolveLocale(manifest, projectPath) {
|
|
|
244
245
|
export async function updateCommand(options) {
|
|
245
246
|
const projectPath = process.cwd();
|
|
246
247
|
|
|
248
|
+
// Refuse to run inside the UDS source repo itself.
|
|
249
|
+
// See DEC-044 / XSPEC-071 — without this guard `uds update` would overwrite
|
|
250
|
+
// source-of-truth `.standards/` with bundled copies. `--force` bypasses.
|
|
251
|
+
guardAgainstSelfAdoption('update', options, projectPath);
|
|
252
|
+
|
|
247
253
|
// Check if initialized first (use default language)
|
|
248
254
|
if (!isInitialized(projectPath)) {
|
|
249
255
|
const common = t().commands.common;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UDS Self-Adoption Detection
|
|
3
|
+
*
|
|
4
|
+
* Detect whether the current working directory is the UDS source repo itself.
|
|
5
|
+
* When detected, adoption-oriented CLI commands (update / check / init) MUST
|
|
6
|
+
* refuse to run — otherwise the CLI would overwrite source-of-truth
|
|
7
|
+
* `.standards/` with its own npm-bundled copy (DEC-044 / XSPEC-071).
|
|
8
|
+
*
|
|
9
|
+
* Detection uses three independent heuristics. ANY one being true is
|
|
10
|
+
* sufficient, but each is validated to reduce false positives:
|
|
11
|
+
*
|
|
12
|
+
* 1. `uds-manifest.json` in cwd whose `project === "Universal Development
|
|
13
|
+
* Standards"` (strong signal — bundled manifests are adopter-named).
|
|
14
|
+
* 2. `cli/package.json` in cwd whose `name === "universal-dev-standards"`
|
|
15
|
+
* (strong signal — only the UDS source repo ships this package).
|
|
16
|
+
* 3. `.uds-source-repo` marker file in cwd (explicit opt-in marker).
|
|
17
|
+
*
|
|
18
|
+
* The three signals are OR-combined: any single hit is enough. A consumer
|
|
19
|
+
* (adopter project) will hit none of them even if they installed UDS.
|
|
20
|
+
*
|
|
21
|
+
* Related:
|
|
22
|
+
* - DEC-044: UDS Self-Adoption Bug
|
|
23
|
+
* - XSPEC-071: UDS Self-Adoption Protection
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { existsSync, readFileSync } from 'fs';
|
|
27
|
+
import { join } from 'path';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Indicator returned when detection matches, useful for diagnostics.
|
|
31
|
+
*
|
|
32
|
+
* @typedef {Object} SelfAdoptionResult
|
|
33
|
+
* @property {boolean} isSelfAdoption - True when cwd is UDS source repo
|
|
34
|
+
* @property {string[]} signals - Names of heuristics that matched
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check whether `uds-manifest.json` at `cwd` identifies UDS source repo.
|
|
39
|
+
*/
|
|
40
|
+
function hasSourceManifest(cwd) {
|
|
41
|
+
const manifestPath = join(cwd, 'uds-manifest.json');
|
|
42
|
+
if (!existsSync(manifestPath)) return false;
|
|
43
|
+
try {
|
|
44
|
+
const content = readFileSync(manifestPath, 'utf8');
|
|
45
|
+
const manifest = JSON.parse(content);
|
|
46
|
+
return manifest?.project === 'Universal Development Standards';
|
|
47
|
+
} catch {
|
|
48
|
+
// Malformed JSON: fall back to "not matched" rather than throwing;
|
|
49
|
+
// the file alone is not strong enough proof without verified content.
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check whether `cli/package.json` at `cwd` identifies UDS source repo.
|
|
56
|
+
*/
|
|
57
|
+
function hasSourceCliPackage(cwd) {
|
|
58
|
+
const pkgPath = join(cwd, 'cli', 'package.json');
|
|
59
|
+
if (!existsSync(pkgPath)) return false;
|
|
60
|
+
try {
|
|
61
|
+
const content = readFileSync(pkgPath, 'utf8');
|
|
62
|
+
const pkg = JSON.parse(content);
|
|
63
|
+
return pkg?.name === 'universal-dev-standards';
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check whether the explicit marker file exists.
|
|
71
|
+
*/
|
|
72
|
+
function hasSourceMarker(cwd) {
|
|
73
|
+
return existsSync(join(cwd, '.uds-source-repo'));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Detect UDS self-adoption situation.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} [cwd=process.cwd()] - Directory to inspect
|
|
80
|
+
* @returns {boolean} True when cwd is (likely) the UDS source repo
|
|
81
|
+
*/
|
|
82
|
+
export function detectSelfAdoption(cwd = process.cwd()) {
|
|
83
|
+
return detectSelfAdoptionDetailed(cwd).isSelfAdoption;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Detect UDS self-adoption and return detailed signal breakdown.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} [cwd=process.cwd()] - Directory to inspect
|
|
90
|
+
* @returns {SelfAdoptionResult} Detection outcome with matched signals
|
|
91
|
+
*/
|
|
92
|
+
export function detectSelfAdoptionDetailed(cwd = process.cwd()) {
|
|
93
|
+
const signals = [];
|
|
94
|
+
if (hasSourceManifest(cwd)) signals.push('uds-manifest.json');
|
|
95
|
+
if (hasSourceCliPackage(cwd)) signals.push('cli/package.json');
|
|
96
|
+
if (hasSourceMarker(cwd)) signals.push('.uds-source-repo');
|
|
97
|
+
return {
|
|
98
|
+
isSelfAdoption: signals.length > 0,
|
|
99
|
+
signals
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Bilingual refuse message shown when self-adoption is detected and
|
|
105
|
+
* `--force` is not passed. Kept inline (not in i18n bundle) to avoid
|
|
106
|
+
* taking a translation dependency for a fail-safe error path.
|
|
107
|
+
*
|
|
108
|
+
* @param {string} commandName - e.g. 'update' / 'check' / 'init'
|
|
109
|
+
* @returns {string[]} Lines to print
|
|
110
|
+
*/
|
|
111
|
+
export function formatSelfAdoptionRefuseMessage(commandName) {
|
|
112
|
+
return [
|
|
113
|
+
`偵測到 UDS source repo。此指令(uds ${commandName})僅供採用專案使用。`,
|
|
114
|
+
'Source repo 維護請使用 scripts/bump-version.sh 或 npm run docs:sync。',
|
|
115
|
+
'詳見 DEC-044。',
|
|
116
|
+
'',
|
|
117
|
+
`Detected UDS source repo. This command (uds ${commandName}) is for`,
|
|
118
|
+
'adopter projects only. For source-repo maintenance use',
|
|
119
|
+
'scripts/bump-version.sh or npm run docs:sync. See DEC-044.',
|
|
120
|
+
'',
|
|
121
|
+
'Override with --force if you know what you are doing',
|
|
122
|
+
'(若確定要執行可加上 --force 旗標繞過).'
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Warning printed when `--force` bypasses the self-adoption guard.
|
|
128
|
+
*
|
|
129
|
+
* @param {string} commandName
|
|
130
|
+
* @returns {string[]} Lines to print
|
|
131
|
+
*/
|
|
132
|
+
export function formatSelfAdoptionForceWarning(commandName) {
|
|
133
|
+
return [
|
|
134
|
+
`警告:偵測到 UDS source repo,但 --force 已指定,繼續執行 uds ${commandName}。`,
|
|
135
|
+
`Warning: UDS source repo detected; --force was passed, continuing uds ${commandName}.`,
|
|
136
|
+
'若非預期操作,請立即 Ctrl+C 並改用 scripts/bump-version.sh。',
|
|
137
|
+
'If unintended, abort now (Ctrl+C) and use scripts/bump-version.sh.'
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Guard helper — prints refuse message and exits with non-zero code when
|
|
143
|
+
* cwd is the UDS source repo and `--force` was not supplied.
|
|
144
|
+
*
|
|
145
|
+
* Does nothing when not self-adoption, or when `--force` is set (in which
|
|
146
|
+
* case a warning is printed but execution proceeds).
|
|
147
|
+
*
|
|
148
|
+
* @param {string} commandName - CLI command being invoked (for message)
|
|
149
|
+
* @param {Object} [options] - Caller options; inspected for `force`
|
|
150
|
+
* @param {string} [cwd=process.cwd()]
|
|
151
|
+
* @returns {boolean} True if command should continue (caller keeps running)
|
|
152
|
+
*/
|
|
153
|
+
export function guardAgainstSelfAdoption(commandName, options = {}, cwd = process.cwd()) {
|
|
154
|
+
const { isSelfAdoption, signals } = detectSelfAdoptionDetailed(cwd);
|
|
155
|
+
if (!isSelfAdoption) return true;
|
|
156
|
+
|
|
157
|
+
const force = Boolean(options && options.force);
|
|
158
|
+
if (force) {
|
|
159
|
+
for (const line of formatSelfAdoptionForceWarning(commandName)) {
|
|
160
|
+
console.warn(line);
|
|
161
|
+
}
|
|
162
|
+
console.warn(`Matched signals: ${signals.join(', ')}`);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
for (const line of formatSelfAdoptionRefuseMessage(commandName)) {
|
|
167
|
+
console.error(line);
|
|
168
|
+
}
|
|
169
|
+
console.error(`Matched signals: ${signals.join(', ')}`);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
// Unreachable, but for tests that stub process.exit:
|
|
172
|
+
return false;
|
|
173
|
+
}
|
package/standards-registry.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "5.1.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"lastUpdated": "2026-04-16",
|
|
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": "5.1.0
|
|
61
|
+
"version": "5.1.0"
|
|
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": "5.1.0
|
|
68
|
+
"version": "5.1.0",
|
|
69
69
|
"note": "Skills are now included in the main repository under skills/"
|
|
70
70
|
}
|
|
71
71
|
},
|
|
@@ -2040,6 +2040,17 @@
|
|
|
2040
2040
|
},
|
|
2041
2041
|
"category": "core",
|
|
2042
2042
|
"description": "Skills must anchor to a Standard; Standards may exist without a Skill. Orphan-skill detection workflow (DEC-043 Wave 1 Governance Meta, XSPEC-070, trial)."
|
|
2043
|
+
},
|
|
2044
|
+
{
|
|
2045
|
+
"id": "translation-lifecycle-standards",
|
|
2046
|
+
"name": "Translation Lifecycle Standards",
|
|
2047
|
+
"nameZh": "翻譯生命週期標準",
|
|
2048
|
+
"source": {
|
|
2049
|
+
"human": "core/translation-lifecycle-standards.md",
|
|
2050
|
+
"ai": "ai/standards/translation-lifecycle-standards.ai.yaml"
|
|
2051
|
+
},
|
|
2052
|
+
"category": "core",
|
|
2053
|
+
"description": "MISSING vs OUTDATED distinction, semver-aware severity (PATCH/MINOR/MAJOR), and automation integration (pre-commit hook, release gate) for multi-locale documentation"
|
|
2043
2054
|
}
|
|
2044
2055
|
]
|
|
2045
|
-
}
|
|
2056
|
+
}
|