universal-dev-standards 6.7.5 → 6.9.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/bin/uds.js +19 -2
- package/bundled/ai/standards/acceptance-criteria-traceability.ai.yaml +14 -2
- package/bundled/ai/standards/adr-standards.ai.yaml +14 -2
- package/bundled/ai/standards/ai-instruction-standards.ai.yaml +6 -6
- package/bundled/ai/standards/code-review.ai.yaml +13 -3
- package/bundled/ai/standards/commit-message.ai.yaml +8 -4
- package/bundled/ai/standards/deferred-item-exit.ai.yaml +225 -0
- package/bundled/ai/standards/feature-discovery-standards.ai.yaml +14 -2
- package/bundled/ai/standards/governance-layer.ai.yaml +128 -2
- package/bundled/ai/standards/logging.ai.yaml +2 -2
- package/bundled/ai/standards/retrospective-standards.ai.yaml +14 -2
- package/bundled/ai/standards/reverse-engineering-standards.ai.yaml +73 -2
- package/bundled/ai/standards/security-standards.ai.yaml +2 -2
- package/bundled/ai/standards/spec-driven-development.ai.yaml +14 -2
- package/bundled/ai/standards/tech-debt-standards.ai.yaml +87 -3
- package/bundled/ai/standards/turn-completion-integrity.ai.yaml +131 -0
- package/bundled/core/acceptance-criteria-traceability.md +5 -2
- package/bundled/core/adr-standards.md +26 -2
- package/bundled/core/ai-instruction-standards.md +9 -7
- package/bundled/core/code-review-checklist.md +5 -2
- package/bundled/core/context-aware-loading.md +1 -1
- package/bundled/core/deferred-item-exit.md +254 -0
- package/bundled/core/feature-discovery-standards.md +5 -1
- package/bundled/core/governance-layer.md +114 -2
- package/bundled/core/retrospective-standards.md +4 -2
- package/bundled/core/reverse-engineering-standards.md +81 -2
- package/bundled/core/spec-driven-development.md +8 -2
- package/bundled/core/tech-debt-standards.md +67 -8
- package/bundled/core/turn-completion-integrity.md +196 -0
- package/bundled/hooks/check-dangerous-cmd.mjs +60 -0
- package/bundled/hooks/check-logging-standard.mjs +59 -0
- package/bundled/hooks/check-turn-completion.mjs +233 -0
- package/bundled/hooks/inject-standards.mjs +183 -0
- package/bundled/hooks/telemetry-wrapper.mjs +77 -0
- package/bundled/hooks/turn-completion/detect.mjs +99 -0
- package/bundled/hooks/turn-completion/locales/en.mjs +159 -0
- package/bundled/hooks/turn-completion/locales/zh-TW.mjs +166 -0
- package/bundled/hooks/validate-commit-msg.mjs +104 -0
- package/bundled/locales/zh-CN/CHANGELOG.md +65 -3
- package/bundled/locales/zh-CN/CLAUDE.md +1 -1
- package/bundled/locales/zh-CN/README.md +7 -7
- package/bundled/locales/zh-CN/SECURITY.md +1 -1
- package/bundled/locales/zh-CN/core/adr-standards.md +1 -1
- package/bundled/locales/zh-CN/core/ai-instruction-standards.md +10 -8
- package/bundled/locales/zh-CN/core/governance-layer.md +118 -6
- package/bundled/locales/zh-CN/core/retrospective-standards.md +1 -1
- package/bundled/locales/zh-CN/core/tech-debt-standards.md +71 -4
- package/bundled/locales/zh-CN/core/turn-completion-integrity.md +190 -0
- package/bundled/locales/zh-CN/docs/CHEATSHEET.md +27 -6
- package/bundled/locales/zh-CN/docs/CLI-INIT-OPTIONS.md +29 -68
- package/bundled/locales/zh-CN/docs/FEATURE-REFERENCE.md +172 -24
- package/bundled/locales/zh-CN/docs/USAGE-MODES-COMPARISON.md +1 -2
- package/bundled/locales/zh-CN/integrations/google-antigravity/{INSTRUCTIONS.md → AGENTS.md} +1 -1
- package/bundled/locales/zh-CN/integrations/google-antigravity/README.md +3 -3
- package/bundled/locales/zh-CN/skills/agents/README.md +1 -1
- package/bundled/locales/zh-CN/skills/atdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/bdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/brainstorm-assistant/SKILL.md +22 -12
- package/bundled/locales/zh-CN/skills/brainstorm-assistant/guide.md +12 -9
- package/bundled/locales/zh-CN/skills/code-review-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/commands/brainstorm.md +17 -13
- package/bundled/locales/zh-CN/skills/commands/config.md +0 -1
- package/bundled/locales/zh-CN/skills/commands/init.md +1 -2
- package/bundled/locales/zh-CN/skills/commit-standards/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/contract-test-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/dev-methodology/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/observability-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/project-structure-guide/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/release-standards/SKILL.md +3 -0
- package/bundled/locales/zh-CN/skills/requirement-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/reverse-engineer/SKILL.md +3 -0
- package/bundled/locales/zh-CN/skills/reverse-engineer/tdd-analysis.md +13 -23
- package/bundled/locales/zh-CN/skills/runbook-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/slo-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-CN/skills/tdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-CN/skills/workflows/README.md +2 -11
- package/bundled/locales/zh-TW/CHANGELOG.md +65 -3
- package/bundled/locales/zh-TW/CLAUDE.md +1 -1
- package/bundled/locales/zh-TW/README.md +7 -7
- package/bundled/locales/zh-TW/SECURITY.md +1 -1
- package/bundled/locales/zh-TW/core/acceptance-criteria-traceability.md +2 -0
- package/bundled/locales/zh-TW/core/adr-standards.md +26 -5
- package/bundled/locales/zh-TW/core/ai-instruction-standards.md +10 -8
- package/bundled/locales/zh-TW/core/code-review-checklist.md +2 -0
- package/bundled/locales/zh-TW/core/container-image-standards.md +2 -2
- package/bundled/locales/zh-TW/core/contract-testing-standards.md +2 -2
- package/bundled/locales/zh-TW/core/cross-flow-regression.md +8 -7
- package/bundled/locales/zh-TW/core/data-contract.md +2 -2
- package/bundled/locales/zh-TW/core/data-migration-testing.md +2 -2
- package/bundled/locales/zh-TW/core/data-pipeline.md +2 -2
- package/bundled/locales/zh-TW/core/deferred-item-exit.md +251 -0
- package/bundled/locales/zh-TW/core/documentation-writing-standards.md +228 -3
- package/bundled/locales/zh-TW/core/full-coverage-testing.md +15 -2
- package/bundled/locales/zh-TW/core/governance-layer.md +118 -5
- package/bundled/locales/zh-TW/core/iac-design-principles.md +2 -2
- package/bundled/locales/zh-TW/core/incident-response.md +2 -2
- package/bundled/locales/zh-TW/core/model-provenance.md +4 -2
- package/bundled/locales/zh-TW/core/pii-classification.md +42 -6
- package/bundled/locales/zh-TW/core/prd-standards.md +4 -2
- package/bundled/locales/zh-TW/core/product-metrics-standards.md +4 -2
- package/bundled/locales/zh-TW/core/release-readiness-gate.md +2 -2
- package/bundled/locales/zh-TW/core/resource-cost-boundary.md +2 -2
- package/bundled/locales/zh-TW/core/retrospective-standards.md +5 -3
- package/bundled/locales/zh-TW/core/reverse-engineering-standards.md +83 -5
- package/bundled/locales/zh-TW/core/runbook.md +2 -2
- package/bundled/locales/zh-TW/core/schema-evolution.md +2 -2
- package/bundled/locales/zh-TW/core/secret-management-standards.md +2 -2
- package/bundled/locales/zh-TW/core/slo-sli.md +2 -2
- package/bundled/locales/zh-TW/core/spec-driven-development.md +2 -0
- package/bundled/locales/zh-TW/core/tech-debt-standards.md +71 -4
- package/bundled/locales/zh-TW/core/turn-completion-integrity.md +190 -0
- package/bundled/locales/zh-TW/core/user-journey-testing.md +2 -2
- package/bundled/locales/zh-TW/core/user-story-mapping.md +2 -2
- package/bundled/locales/zh-TW/core/verification-oracle.md +2 -2
- package/bundled/locales/zh-TW/docs/CHEATSHEET.md +27 -6
- package/bundled/locales/zh-TW/docs/CLI-INIT-OPTIONS.md +29 -68
- package/bundled/locales/zh-TW/docs/FEATURE-REFERENCE.md +172 -24
- package/bundled/locales/zh-TW/docs/USAGE-MODES-COMPARISON.md +1 -2
- package/bundled/locales/zh-TW/integrations/google-antigravity/{INSTRUCTIONS.md → AGENTS.md} +1 -1
- package/bundled/locales/zh-TW/integrations/google-antigravity/README.md +3 -3
- package/bundled/locales/zh-TW/skills/adr-assistant/SKILL.md +1 -1
- package/bundled/locales/zh-TW/skills/agents/README.md +1 -1
- package/bundled/locales/zh-TW/skills/atdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/bdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/brainstorm-assistant/SKILL.md +22 -12
- package/bundled/locales/zh-TW/skills/brainstorm-assistant/guide.md +12 -9
- package/bundled/locales/zh-TW/skills/code-review-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/commands/brainstorm.md +17 -13
- package/bundled/locales/zh-TW/skills/commands/config.md +0 -1
- package/bundled/locales/zh-TW/skills/commands/init.md +1 -2
- package/bundled/locales/zh-TW/skills/commit-standards/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/contract-test-assistant/SKILL.md +2 -1
- package/bundled/locales/zh-TW/skills/dev-methodology/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/dev-workflow-guide/SKILL.md +1 -1
- package/bundled/locales/zh-TW/skills/knowledge-graph/guide.md +2 -2
- package/bundled/locales/zh-TW/skills/migration-assistant/SKILL.md +1 -1
- package/bundled/locales/zh-TW/skills/observability-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/project-discovery/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/project-structure-guide/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/release-standards/SKILL.md +3 -0
- package/bundled/locales/zh-TW/skills/requirement-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/reverse-engineer/SKILL.md +3 -0
- package/bundled/locales/zh-TW/skills/reverse-engineer/tdd-analysis.md +13 -23
- package/bundled/locales/zh-TW/skills/runbook-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/slo-assistant/SKILL.md +1 -0
- package/bundled/locales/zh-TW/skills/tdd-assistant/SKILL.md +2 -0
- package/bundled/locales/zh-TW/skills/workflows/README.md +2 -11
- package/bundled/skills/agents/README.md +1 -1
- package/bundled/skills/atdd-assistant/SKILL.md +2 -0
- package/bundled/skills/bdd-assistant/SKILL.md +2 -0
- package/bundled/skills/brainstorm-assistant/SKILL.md +31 -13
- package/bundled/skills/brainstorm-assistant/guide.md +9 -6
- package/bundled/skills/code-review-assistant/SKILL.md +1 -0
- package/bundled/skills/commands/brainstorm.md +12 -9
- package/bundled/skills/commands/config.md +0 -1
- package/bundled/skills/commands/init.md +2 -3
- package/bundled/skills/commit-standards/SKILL.md +2 -0
- package/bundled/skills/contract-test-assistant/SKILL.md +1 -0
- package/bundled/skills/dev-methodology/SKILL.md +4 -0
- package/bundled/skills/observability-assistant/SKILL.md +1 -0
- package/bundled/skills/project-discovery/SKILL.md +1 -0
- package/bundled/skills/project-structure-guide/SKILL.md +1 -0
- package/bundled/skills/release-standards/SKILL.md +3 -0
- package/bundled/skills/requirement-assistant/SKILL.md +2 -0
- package/bundled/skills/reverse-engineer/SKILL.md +3 -0
- package/bundled/skills/reverse-engineer/tdd-analysis.md +16 -23
- package/bundled/skills/runbook-assistant/SKILL.md +1 -0
- package/bundled/skills/slo-assistant/SKILL.md +1 -0
- package/bundled/skills/tdd-assistant/SKILL.md +2 -0
- package/bundled/skills/workflows/README.md +2 -11
- package/bundled/templates/.ai-context.yaml.template +194 -0
- package/bundled/templates/CLAUDE.md.template +145 -0
- package/bundled/templates/DESIGN.md +237 -0
- package/bundled/templates/SKILL-BRIEF-TEMPLATE.md +57 -0
- package/bundled/templates/SKILL-CANDIDATES.md +39 -0
- package/bundled/templates/gates/check-error-exit.mjs +309 -0
- package/bundled/templates/mcp-config.json +10 -0
- package/bundled/templates/methodology-template.yaml +209 -0
- package/bundled/templates/migration-template.md +408 -0
- package/bundled/templates/requirement-checklist.md +410 -0
- package/bundled/templates/requirement-document-template.md +591 -0
- package/bundled/templates/requirement-template.md +881 -0
- package/bundled/templates/reverse-spec-template.md +409 -0
- package/bundled/templates/test-case-template.md +74 -0
- package/bundled/templates/test-plan-template.md +74 -0
- package/package.json +9 -5
- package/src/commands/audit.js +82 -0
- package/src/commands/check.js +66 -10
- package/src/commands/init.js +161 -16
- package/src/commands/lint.js +96 -0
- package/src/commands/quickstart.js +16 -13
- package/src/commands/update.js +286 -14
- package/src/compilers/claude-code-compiler.js +4 -1
- package/src/config/ai-agent-paths.js +62 -17
- package/src/core/constants.js +42 -11
- package/src/core/manifest.js +201 -3
- package/src/core/paths.js +2 -2
- package/src/i18n/messages.js +9 -32
- package/src/installers/hooks-installer.js +167 -75
- package/src/installers/integration-installer.js +9 -5
- package/src/prompts/init.js +14 -14
- package/src/reconciler/actual-state-scanner.js +14 -3
- package/src/utils/detector.js +21 -1
- package/src/utils/effect-boundary.js +1093 -0
- package/src/utils/hasher.js +229 -9
- package/src/utils/hook-stats.js +1 -1
- package/src/utils/integration-generator.js +100 -4
- package/src/utils/reference-sync.js +4 -1
- package/src/utils/skills-installer.js +17 -3
- package/src/utils/spec-linter.js +35 -76
- package/src/utils/yaml-generator.js +51 -9
- package/standards-registry.json +31 -8
- package/src/commands/sync.js +0 -133
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Traditional Chinese locale pack for the turn-completion check.
|
|
3
|
+
*
|
|
4
|
+
* Ported from a Python implementation that ran for two weeks on two machines
|
|
5
|
+
* and was defeated five times by its own lesson before settling:
|
|
6
|
+
* 1. enumerated phrases -> missed a phrase
|
|
7
|
+
* 2. enumerated verbs -> missed a verb
|
|
8
|
+
* 3. matched its own comment -> comments stripped
|
|
9
|
+
* 4. matched its own backticked examples -> quoting stripped (shared layer)
|
|
10
|
+
* 5. matched a negated clause -> judgement moved to sentence scope
|
|
11
|
+
*
|
|
12
|
+
* The patterns below are the fifth version. Three of the five defects were
|
|
13
|
+
* caught by the corpus before shipping; the two that shipped were the ones no
|
|
14
|
+
* case covered. That asymmetry is the argument for R7.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately NOT ported: a detector for the phrase "要你決定什麼 / 沒有"
|
|
17
|
+
* ("what you need to decide / nothing"). That keys on one project's report
|
|
18
|
+
* template, not on any language, and shipping it would fire never or wrongly
|
|
19
|
+
* for everyone else.
|
|
20
|
+
*
|
|
21
|
+
* @see core/turn-completion-integrity.md
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// A request to REPORT BACK is also a request: "tell me when it's done and I will
|
|
25
|
+
// verify" is conditional, and its precondition is the human's action. Measured
|
|
26
|
+
// 2026-09-09 — the guard blocked exactly that sentence because it only knew how
|
|
27
|
+
// to spot requests for information.
|
|
28
|
+
//
|
|
29
|
+
// Widening this is the dangerous direction (it misses real unkept commitments),
|
|
30
|
+
// so the pattern is narrow: a completion word immediately followed by a
|
|
31
|
+
// report-back word. A bare "tell me" does not qualify.
|
|
32
|
+
const ASKING = new RegExp(
|
|
33
|
+
'(告訴我|給我|貼一段|貼上|提供|你是在哪|在哪裡看到|哪一個|是哪|需要知道' +
|
|
34
|
+
'|請你|麻煩你|等你(裁決|回覆|決定|確認)|要你自己|要你.{0,6}(動手|執行|跑|做)|由你' +
|
|
35
|
+
'|(做完|跑完|試完|裝完|驗完|改完|弄完|完成後|好了|有結果|通了)' +
|
|
36
|
+
'[,,]?.{0,6}(跟我說|告訴我|回報|讓我知道|再說)' +
|
|
37
|
+
// Asking for a one-word reply is the same kind of request: 「回『全甲』就好」.
|
|
38
|
+
// Narrow: 回 + an optional short quoted string + 就好/就可以/就行. A bare 回 does not qualify.
|
|
39
|
+
'|回(一句)?[「"“]?[^」"”\\n]{0,10}[」"”]?[,,]?.{0,2}就(好|可以|行)' +
|
|
40
|
+
// 「看到開始跑就跟我說,我去檢查」 — the precondition words are unbounded, so listing
|
|
41
|
+
// them (看到, 開始跑, ...) would miss the next one. The grammar is what marks it:
|
|
42
|
+
// 就 followed within two characters by a report-back phrase. A bare 就 does not qualify.
|
|
43
|
+
'|就.{0,2}(跟我說|告訴我|回報我|讓我知道)' +
|
|
44
|
+
// 「跟我說一聲,我會到 PC15 上確認」 — the precondition sat in a heading one paragraph up, so
|
|
45
|
+
// the paragraph opens with the request. A report-back phrase, a comma, then 我 at once is
|
|
46
|
+
// "you tell me, then I act". A report-back phrase alone does not qualify.
|
|
47
|
+
'|(跟我說|告訴我|回報我|讓我知道)(一聲)?[,,]\\s*我)'
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// First person + future marker + action verb, within one sentence.
|
|
51
|
+
// The window between marker and verb is 24 characters: Chinese objects can be
|
|
52
|
+
// long, and a 6-character window (chosen by feel) missed a real commitment
|
|
53
|
+
// whose verb sat 11 characters away.
|
|
54
|
+
const FUTURE = '(接著|接下來|繼續|下一步|等一下|待會|再|會|要|來|去|先)';
|
|
55
|
+
const ACTION =
|
|
56
|
+
'(做|辦|處理|推進|接手|進行|查|修|補|寫|跑|建|驗|測|實作|落地|完成|開始|送出|合併|部署' +
|
|
57
|
+
'|走|看|讀|確認|釐清|整理|標|記|盤|清|接|換|補上|收尾|重跑|重寫)';
|
|
58
|
+
// A subject's predicate ends where the same subject appears again: the window may not
|
|
59
|
+
// cross another 我. Measured: 「我先判斷成…,因為我用的是標準輸入」 read the 標 of 標準
|
|
60
|
+
// as the first 我's verb.
|
|
61
|
+
const COMMIT = new RegExp(`我([^我]{0,4})${FUTURE}[^我]{0,24}${ACTION}`, 'g');
|
|
62
|
+
|
|
63
|
+
// Between "我" and the future marker: a reporting verb means the sentence
|
|
64
|
+
// describes a commitment ("我說了下一步"), a negation means it declares the
|
|
65
|
+
// opposite ("我不會做").
|
|
66
|
+
const REPORTING = /(說|寫|講|提|記|標|引用|舉例|回報|報告)/;
|
|
67
|
+
const NEGATION = /(不|沒|未|別|無需|毋須|無須)/;
|
|
68
|
+
// A result clause AFTER the match means the step already happened: 「我先確認…,結果發現…」.
|
|
69
|
+
// Only text after the match counts — 「查了一輪結果發現前提不對,我先去確認落點」 is still a commitment.
|
|
70
|
+
const PAST_RESULT = /(結果|才|後來|於是|然後)[^,,。]{0,3}(發現|查到|看到|知道|證實|確認)/;
|
|
71
|
+
|
|
72
|
+
export function isCommitment(sentence) {
|
|
73
|
+
COMMIT.lastIndex = 0;
|
|
74
|
+
let m;
|
|
75
|
+
while ((m = COMMIT.exec(sentence)) !== null) {
|
|
76
|
+
const gap = m[1];
|
|
77
|
+
if (REPORTING.test(gap) || NEGATION.test(gap)) continue;
|
|
78
|
+
if (PAST_RESULT.test(sentence.slice(m.index + m[0].length))) continue;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function isAsking(text) {
|
|
85
|
+
return ASKING.test(text);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The human asking for the turn to end. Kept narrow on purpose: a false
|
|
90
|
+
* positive disables the check for the rest of the session.
|
|
91
|
+
*/
|
|
92
|
+
const STOP_REQUEST =
|
|
93
|
+
// 🔴 `先停` 曾寫成裸的,而語料當場抓到「先**停用**那份硬編碼清單」——
|
|
94
|
+
// 一句要求做事的指令被讀成叫我停。這個方向的誤判會把守衛整場關掉,
|
|
95
|
+
// 所以 `停` 後面接得出動詞的字一律排除。
|
|
96
|
+
/(先暫停|暫停一下|先停(?![用止掉住])|停一下|先不要(做|動)|不用繼續|今天(先)?到這|先這樣|收工|下班|我要回家|明天再(說|弄|做)|改天再|先擱著|睡了|晚安)/;
|
|
97
|
+
|
|
98
|
+
export function isStopRequest(text) {
|
|
99
|
+
return STOP_REQUEST.test(text);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const id = 'zh-TW';
|
|
103
|
+
export const label = '繁體中文';
|
|
104
|
+
|
|
105
|
+
export const corpus = [
|
|
106
|
+
[true, '我接著做兩件不需要你的',
|
|
107
|
+
'我接著做兩件不需要你的:先把那幾格作廢的數字在規格裡逐一標掉,再回去處理那份硬編碼的清單。'],
|
|
108
|
+
[true, '動詞在表外:走',
|
|
109
|
+
'我接著往同一個類別的下一個走:那支腳本裡有一行硬編碼的清單,pre-commit 自己就在警告它漏掉兩個。'],
|
|
110
|
+
[true, '受詞很長,動詞隔了 11 個字',
|
|
111
|
+
'我接著把今天這一輪的三個記憶寫進記憶檔——這三個今天各自撞了不只一次。'],
|
|
112
|
+
[true, '否定句旁邊仍有真承諾',
|
|
113
|
+
'那一項我不會動它。我接著把剩下那份清單整理好,然後回報。'],
|
|
114
|
+
[false, '條件式承諾:要資訊才動得了',
|
|
115
|
+
'我需要知道你是在哪一頁看到那個數字的。給我檔名或貼一段,我去查。'],
|
|
116
|
+
[false, '談論承諾,不是做出承諾',
|
|
117
|
+
'本 session 的守衛不用手動重設就已經恢復。下一次我說了下一步卻沒做,它會擋。'],
|
|
118
|
+
[false, '否定句:宣告不做',
|
|
119
|
+
'那個數字會因為引擎自己恢復而變動,與任何改動無關。我不會拿它做任何判斷。'],
|
|
120
|
+
[false, '合法的停止:事情在使用者手上',
|
|
121
|
+
'只剩那一跑要你自己在終端機跑,探測 repo 和判定腳本都備好了。'],
|
|
122
|
+
// 🔴 條件式承諾的第二種形狀:要求回報。前提在使用者手上,所以不是未兌現的承諾。
|
|
123
|
+
[false, '做完跟我說,我再驗',
|
|
124
|
+
'reload 之後不要關掉那個視窗。做完跟我說,我這邊會再獨立驗一次。'],
|
|
125
|
+
[false, '弄完讓我知道',
|
|
126
|
+
'第二行印出 no 才算數。弄完讓我知道,我接著把設定寫回 repo。'],
|
|
127
|
+
[false, '看到開始跑就跟我說,我去檢查——前提在使用者手上',
|
|
128
|
+
'步驟:\n1. 開 workbench 網頁並登入。\n2. 送出一句需求。\n3. 看到開始跑就跟我說,我去 PC15 檢查。'],
|
|
129
|
+
[false, '跟我說一聲,我會到 PC15 上確認——請求在段首',
|
|
130
|
+
'跟我說一聲,我會到 PC15 上確認三件事:\n- 規格檔在這個專案自己的資料夾裡。\n- workbench 的程式資料夾沒有多出任何檔案。'],
|
|
131
|
+
[true, '「跟我說」是敘述不是請求,後面的承諾仍必須擋',
|
|
132
|
+
'他跟我說過了。我接著去 PC15 確認部署有沒有生效。'],
|
|
133
|
+
[true, '有「就」但沒有要求回報的承諾(仍必須擋)',
|
|
134
|
+
'設定改好就推上去了。我接著去 PC15 檢查部署有沒有生效。'],
|
|
135
|
+
[false, '請使用者回覆「全甲」是條件式',
|
|
136
|
+
'三題都照建議的話,回「全甲」就好。這三題的代號各自不同(丙/甲/甲),不過我會照建議的組合理解。'],
|
|
137
|
+
[true, '回覆請求在另一段,不得豁免這一段的承諾',
|
|
138
|
+
'回「全甲」就好。\n\n我接著把清單整理好。'],
|
|
139
|
+
[false, '窗越過下一個「我」:先判斷成…因為我用的是標準',
|
|
140
|
+
'有一處我自己的判斷一度錯了,要說清楚:lint 報了兩個錯,我先判斷成「原本就壞的」,因為我用的是標準輸入的比對方式,而那個方式給錯答案。'],
|
|
141
|
+
[true, '同一主語內的承諾,後面接另一個「我」也照樣擋',
|
|
142
|
+
'我接著把清單整理好,因為我已經看過了。'],
|
|
143
|
+
[false, '過去的順序敘述:我先確認…,結果發現…',
|
|
144
|
+
'起草之前我先確認這筆設計要落在哪裡,結果發現 DEC-084 的前提有兩處跟程式碼對不上,所以要你決定的事從三題變成四題。'],
|
|
145
|
+
[true, '同一句拿掉結果子句——那就是還沒做的承諾(仍必須擋)',
|
|
146
|
+
'起草之前我先確認這筆設計要落在哪裡。'],
|
|
147
|
+
[true, '結果子句在承諾之前:後半句仍是承諾(仍必須擋)',
|
|
148
|
+
'查了一輪結果發現前提不對,我先去確認落點。'],
|
|
149
|
+
[true, '「發現」出現在承諾的受詞裡,不是結果子句(仍必須擋)',
|
|
150
|
+
'我先去確認有沒有新的發現。'],
|
|
151
|
+
[true, '沒有要求回報的承諾(仍必須擋)',
|
|
152
|
+
'設定檔已經改好了。我接著把驗證結果寫進規格,然後回報。'],
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 使用者的訊息,以及它是不是「叫我停」。
|
|
157
|
+
* 標 true 必須豁免;標 false 必須不豁免——**提到停止不等於叫我停止**。
|
|
158
|
+
*/
|
|
159
|
+
export const stopCorpus = [
|
|
160
|
+
[true, '直接叫停', '先暫停, 我要回家了. 我不會退出程式. 就先暫停'],
|
|
161
|
+
[true, '今天到這', '今天先到這,明天再弄。'],
|
|
162
|
+
[true, '收工', '收工吧,我下班了。'],
|
|
163
|
+
[false, '提到停止但不是叫停', '解釋一下這支 hook 為什麼會擋下回合。'],
|
|
164
|
+
[false, '要求做事而句中有停', '先停用那份硬編碼清單,改成走訪註冊表。'],
|
|
165
|
+
[false, '一般指令', '把偵測器修好然後推上去。'],
|
|
166
|
+
];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* UDS Hook: Commit Message Format Validator
|
|
4
|
+
*
|
|
5
|
+
* Validates commit messages against Conventional Commits format.
|
|
6
|
+
* Exit code: 0 = valid, 1 = invalid
|
|
7
|
+
*
|
|
8
|
+
* Two callers, two contracts:
|
|
9
|
+
* - git hook / CLI: node validate-commit-msg.mjs "feat(scope): msg"
|
|
10
|
+
* or a raw message on stdin. Exit 1 when invalid.
|
|
11
|
+
* - Claude Code PreToolUse(Bash): the hook payload arrives as JSON on stdin.
|
|
12
|
+
* Exit 2 blocks the tool call; anything that is not a
|
|
13
|
+
* `git commit -m` is none of this hook's business.
|
|
14
|
+
*
|
|
15
|
+
* 🔴 It was registered on UserPromptSubmit and read stdin as a raw commit
|
|
16
|
+
* message, so in an adopter's session it ran on EVERY prompt, failed to parse
|
|
17
|
+
* the hook payload as Conventional Commits, and exited 1 every time. Found by
|
|
18
|
+
* check-hook-delivery.ts, which executes each installed hook rather than
|
|
19
|
+
* checking that the file exists.
|
|
20
|
+
*
|
|
21
|
+
* Performance target: < 500ms
|
|
22
|
+
*
|
|
23
|
+
* @see docs/specs/SPEC-HOOKS-001-core-standard-hooks.md (REQ-1)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const VALID_TYPES = [
|
|
27
|
+
'feat', 'fix', 'docs', 'chore', 'test',
|
|
28
|
+
'refactor', 'style', 'perf', 'ci', 'build', 'revert',
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const COMMIT_PATTERN = new RegExp(
|
|
32
|
+
`^(${VALID_TYPES.join('|')})(\\(.+\\))?:\\s.+`
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validate a commit message against Conventional Commits format.
|
|
37
|
+
* @param {string} msg - The commit message to validate
|
|
38
|
+
* @returns {boolean} true if valid
|
|
39
|
+
*/
|
|
40
|
+
export function validateCommitMessage(msg) {
|
|
41
|
+
if (!msg || typeof msg !== 'string') return false;
|
|
42
|
+
return COMMIT_PATTERN.test(msg.trim());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// CLI mode.
|
|
46
|
+
function complain(msg) {
|
|
47
|
+
console.error(`❌ Invalid commit message format: "${msg}"`);
|
|
48
|
+
console.error(` Expected: <type>(<scope>): <subject>`);
|
|
49
|
+
console.error(` Valid types: ${VALID_TYPES.join(', ')}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The message of a `git commit -m ...`, or null when this is not one.
|
|
54
|
+
*
|
|
55
|
+
* The command must BE a git commit, not merely mention one: a substring test
|
|
56
|
+
* pulled `fake"` out of `echo "git commit -m fake"`. Global options are allowed
|
|
57
|
+
* between `git` and `commit` (`git -C /tmp/repo commit -m ...`), which a
|
|
58
|
+
* flags-only pattern rejected. Both were caught by this function's own tests.
|
|
59
|
+
*/
|
|
60
|
+
export function commitMessageFrom(command) {
|
|
61
|
+
if (typeof command !== 'string') return null;
|
|
62
|
+
const segment = command
|
|
63
|
+
.split(/&&|\|\||[;|\n]/)
|
|
64
|
+
.find((s) => /^\s*git\b/.test(s) && /\bcommit\b/.test(s));
|
|
65
|
+
if (!segment) return null;
|
|
66
|
+
const quoted = segment.match(/-m\s+(["'])([\s\S]*?)\1/);
|
|
67
|
+
if (quoted) return quoted[2];
|
|
68
|
+
const bare = segment.match(/-m\s+(\S+)/);
|
|
69
|
+
return bare ? bare[1] : null; // -F, heredoc, or no -m: nothing to inspect
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (process.argv[1] && process.argv[1].endsWith('validate-commit-msg.mjs')) {
|
|
73
|
+
const arg = process.argv[2];
|
|
74
|
+
if (arg) {
|
|
75
|
+
if (validateCommitMessage(arg)) process.exit(0);
|
|
76
|
+
complain(arg);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
} else {
|
|
79
|
+
let data = '';
|
|
80
|
+
process.stdin.setEncoding('utf-8');
|
|
81
|
+
process.stdin.on('data', (chunk) => { data += chunk; });
|
|
82
|
+
process.stdin.on('end', () => {
|
|
83
|
+
const raw = data.trim();
|
|
84
|
+
if (!raw) process.exit(0);
|
|
85
|
+
|
|
86
|
+
let payload = null;
|
|
87
|
+
try { payload = JSON.parse(raw); } catch { /* not a hook payload */ }
|
|
88
|
+
|
|
89
|
+
if (payload && typeof payload === 'object') {
|
|
90
|
+
// Claude Code PreToolUse. Silence unless this really is a commit.
|
|
91
|
+
const msg = commitMessageFrom(payload?.tool_input?.command);
|
|
92
|
+
if (msg === null) process.exit(0);
|
|
93
|
+
if (validateCommitMessage(msg)) process.exit(0);
|
|
94
|
+
complain(msg);
|
|
95
|
+
process.exit(2); // 2 is what blocks a tool call
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Legacy: a raw commit message piped in by a git hook.
|
|
99
|
+
if (validateCommitMessage(raw)) process.exit(0);
|
|
100
|
+
complain(raw);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../CHANGELOG.md
|
|
3
|
-
source_version: 6.
|
|
4
|
-
translation_version: 6.
|
|
5
|
-
last_synced: 2026-
|
|
3
|
+
source_version: 6.9.0
|
|
4
|
+
translation_version: 6.9.0
|
|
5
|
+
last_synced: 2026-09-14
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -17,6 +17,68 @@ status: current
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [6.9.0] - 2026-09-14
|
|
21
|
+
|
|
22
|
+
### 采用者升级注意
|
|
23
|
+
|
|
24
|
+
- **uds update 不再自动删除文件;会列出可移除的 UDS 旧文件,加 --prune 才会删,且只删 UDS 自己写过的文件。原本依赖自动清理文件的流程请加上 --prune。**(#168、#165,详见「修正」)
|
|
25
|
+
- **--content-mode 给了无法识别的值,现在会打印警告并照旧使用 index(6.8.0 也是生成 index 的内容);7.0.0 起会改为直接报错。** `--content-mode full` 已弃用,会解析为 `index` 并附说明。(详见「弃用」)
|
|
26
|
+
- **以 `uds init -y` 安装的 Codex、OpenCode 等非 Claude 工具,技能现在会装进它们自己的目录**(例如 Codex 是 `.agents/skills/`),不再装进 `.claude/skills/`。已有安装运行 `uds update` 会自动迁移。(详见「修正」)
|
|
27
|
+
- **Antigravity 现在会得到 `.agents/skills/` 与 `.agents/AGENTS.md`**,以前是什么都没有、指令文件写成 `INSTRUCTIONS.md`。Antigravity 只在该目录是已登记的项目时才会读取 `.agents/`,`uds init` 会打印这个提示。
|
|
28
|
+
- **6.8.0 及以前 uds init --with-hooks 写进 .claude/settings.json 的 hook 是从未执行的字符串格式,uds update 不会处理 hook,重跑 uds init --with-hooks 也不会删除旧条目与 scripts/hooks/*.js。要获得可用的 hook,请重跑 uds init --with-hooks,并可手动删除旧的 .js 条目。**
|
|
29
|
+
|
|
30
|
+
### 修正
|
|
31
|
+
|
|
32
|
+
- **`uds update` 不再靠「查一张哈希表」来决定文件是谁的(XSPEC-384,issue [#165](https://github.com/AsiaOstrich/universal-dev-standards/issues/165) 与 [#168](https://github.com/AsiaOstrich/universal-dev-standards/issues/168))。** 两位使用者对同一支命令报告了方向相反的缺陷:它删掉了使用者手写放在 `.standards/` 下的项目文件,没有警告、没有 diff、没有询问、没有备份(#168,是逐行比对 `git status` 才发现的);同时它把 registry 已经移除的标准留在 manifest 与磁盘上,而 `upstream.version` 照样前进到「最新」(#165)。两者都源自同一个布尔值在回答两个彼此独立的问题——**这个文件是不是 UDS 写的**、**它现在还是不是现行标准**——而每个 issue 各撞上这个超载轴的一端。所有权现在改成在 UDS 写入的当下记录,存进 manifest 新增的 `provenance` 字段,并以复制动作实际返回的路径为键,而不是从来源文件名重新推算的路径(正是那个重新推算,让 `fileHashes` 里出现五条 `.standards/options/<name>.ai.yaml`,而真正的文件住在 `options/<category>/<name>.ai.yaml`)。provenance 是只增的,`fileHashes` 是当前状态;若两者同进同退,provenance 会在同一刻一起失效,也就毫无作用。删除现在必须两件事同时成立,其余每一种组合一律保留,**并打印保留的理由**。无法判定所有权时归向保留——那正是旧程序不肯选的那一边。既有安装没有 provenance,因此首次升级无从归属、也不会删任何东西;provenance 只在一次完整写入全套标准的执行结束时才建立。删除另外需要新的 `--prune` 标志,刻意不用 `--yes`:`--yes` 会被设在 CI 里,让它一并授权删除,等于正好在没有人看得到的地方把破坏性路径打开。「默认就删」的分阶段策略放在单一具名常量(`PRUNE_POLICY`),因为 XSPEC-384 §4 尚未裁决。每一份删除报告都打印分母——检查了几个、我方拥有几个、非我方几个、判不了几个、排除几个以及为什么——因为一份只列出动作对象的报告,与「它只看到这几个」无从分辨。两个 issue 都由先证明会红的测试钉住。
|
|
33
|
+
- **九个工具里有八个,技能被装进它们不会读的目录。** 非交互路径(`uds init -y`)下,除 Claude Code 以外每个能装技能的工具,技能都被写进 `.claude/skills/`;一个 codex 仓库执行 `--mode skills -y` 会得到零个技能、零条提示。现在「能否装技能」与「是否走 marketplace」都改为查询路径表;检测到但没有经过验证路径的工具什么都不装,并且会给出提示;`uds update` 转换旧 manifest 时会重新推导工具,不再假设 `claude-code`。Codex 那条未经验证的 `fallbackSkillsPath: '.claude/skills/'` 已移除。交互流程从未受影响。
|
|
34
|
+
- **Roo Code 永远装不上。** 路径表里有它,检测器里没有;它的标识符在一张表里叫 `roo`、其他地方都叫 `roo-code`,于是 `uds init` 把指令写进根目录的 `roo-code.md`。检测改用 `.roo/` 与 `.roorules`(刻意不用 `.clinerules`,那是 Cline 自己的标记);技能也不再退回 `.claude/skills/`,因为 Roo Code 文档列出的位置里没有它。依据是 Roo Code 的文档,未在真实的 Roo Code 上实测。
|
|
35
|
+
- **Antigravity:UDS 六个月来什么都没为它安装,而且写的指令文件是它不会读的那一份(XSPEC-355 OQ6)。** 技能改装进 `.agents/skills/`、指令改写进 `.agents/AGENTS.md`,由工具的二进制文件、随附说明文档、以及一次带诱饵路径的实跑三方确认。它的 tier 从 `minimal` 升为 `partial`。
|
|
36
|
+
- **UDS 至今发布的每一个 hook 都是失效的,而采用者拿到四个坏掉的 hook。** hook 条目写成裸字符串(只有对象形式会运行);`scripts/hooks` 没有进入 npm 包;hook 是 ESM `.js`,在 `"type": "commonjs"` 下会失败(改为 `.mjs`);commit message 校验挂在 `UserPromptSubmit`,每输入一句话就运行一次、每次 exit 1(改挂 `PreToolUse(Bash)`,只检查真正的 `git commit -m`)。
|
|
37
|
+
- **`uds check` 的还原会用一份过期模板覆盖生成的集成文件。** Claude Code 那份是 140 行、最后修改于 2026-03-25 的文件。还原现在改用安装器记录的配置重新生成,受管区块外的内容不动;Antigravity 与 Gemini CLI 第一次有了还原路径,Codex 的后备来源也不再指向不存在的目录。
|
|
38
|
+
- **Codex/OpenCode 的 `AGENTS.md` 没有披露语句。** 2026-08-18 的披露修正只覆盖了两个生成器中的一个;选择 codex 或 opencode 时,`AGENTS.md` 走的是另一个。两种语言、两种输出格式均已修正。
|
|
39
|
+
- **cline、windsurf、roo-code 与 Antigravity 的集成文件只写「遵循 commit-message 规则」,没有写出规则本身。** 格式与合法类型现在直接写在文件里,与 Codex 那份原本的做法相同。
|
|
40
|
+
|
|
41
|
+
### 新增
|
|
42
|
+
|
|
43
|
+
- **`turn-completion-integrity`——agent 不得在说了下一步之后、没做就结束回合。** 由 Stop hook 在回合结束时执行,而不是写成指令。检测器附英文与 zh-TW 语言包及经过变异测试的语料;它会读取用户的最后一条消息,所以被叫停不会被当作未兑现的承诺;逐项列出「谁卡在谁身上」的清单被识别为合法的结束方式;「做完跟我说,我再验」被视为条件式。`uds init --with-hooks` 现在会在你的语言没有语言包时警告,因为在未列出的语言下,hook 装好了却不可能触发。含 zh-TW 与 zh-CN 翻译。
|
|
44
|
+
- **`deferred-item-exit`——六条标准会产出延后项目,而没有一条说那些项目要去哪(XSPEC-391)。** 一位采用者的一次设计工作产出了一份 ADR 与一份规格,其中带有五个标为「待决定」/「另案处理」/「不在 v1」的项目,而**五项全都没有进入任何追踪系统**。原因不是健忘。对会产出这类项目的六条标准——`adr-standards`、`spec-driven-development`、`retrospective-standards`、`feature-discovery-standards`、`code-review-checklist`、`acceptance-criteria-traceability`——grep `issue|tracker|backlog|task id|work item` 共 13 个命中,而**没有任何一个是出口**:ADR 的 `Technical Story` 是输入参照、retrospective 把 tracker 当指标来源、feature-discovery 把工单当需求输入、AC-traceability 只对外部阻塞的覆盖要求链接,而 code-review 的 8 个命中全是英文单字 "issues",意思是「问题」。每条标准都说明如何把自己的文档写好;文档写完就是终点。新标准把缺少的那个关系陈述一次——延后项目在文档之外有一个可追溯的出口,而文档带着那个出口的识别码——六条产出端标准加上 `brainstorm-assistant` skill 各自取得**一行指向它的指针,而不是一份副本**,因为同一条规则的六份副本会往六个方向腐坏。**载体刻意不指定**:issue、受追踪的 TODO、manifest 的一列、backlog 文件里的一行都符合,判准是「这个项目离开文档了吗」,永远不是「用了哪个工具」。三个发现决定了条文。第一,出口必须在产出该文档的那次变更落地*之后*仍然解析得到——两个观察到的泄漏满足其他所有条件,仍然遗失了项目(待办写进一个会被本次合并关闭的 issue;待办写进出口的留言,被后续留言推出视线)。第二,**链接存在不等于链接有效**:回报者自己的闸门会放行他最强的那个例子——一份写着「与 issue #19 一并决定」的文档,而 #19 里根本没有这件事——所以 DEX-005/006 要求「有链接且内容已验证」与「有链接、内容未验证」永远不得印出同一个绿,因为一个被回报成通过的未知,比一个被回报成未知的未知更糟。第三,锚点是文档的**结构**(ADR 的 `Consequences`、规格的范围外章节、retrospective 的 `Action Items`),不是它的措辞:结构可以穷举,措辞清单不行,所以 DEX-008 要求任何措辞清单都要声明其涵盖率未知,DEX-009 要求任何窗口大小(「3 行以内」)都要载明来历,否则标为未校准。依 DEC-049,这条标准完全写成「必须存在的关系」,绝不写成「必须维持它的机制」——而且它在自己的本文里明白写出 **UDS 不为它提供任何闸门**,因为一条陈述了规则却没有东西运行它的标准,不承认这一点时比承认时更糟。`adr-standards` 另外补上一条它从未陈述过的边界(对它 grep `acceptance criteria|\bAC\b|驗收` 得到**零**命中,对照组 `acceptance-criteria-traceability` 为 84 个命中):**验收标准只在一处维护——SPEC**,ADR 以链接指向它——被拷贝的清单有两个拥有者,其中一个永远不会被更新,实测后果是工作出货后 ADR 里的勾选框全部仍是未勾选,而只读规格的覆盖率工具看不到它。
|
|
45
|
+
- **`AUTH_SCOPE_EXTRACTION`——租户界限是一个 `WHERE` 子句,而迁移流程里没有任何东西强迫你去找它(`reverse-engineering-standards` 1.3.0,issue [#166](https://github.com/AsiaOstrich/universal-dev-standards/issues/166))。** 一次真实的 PHP → C# 迁移中,一个以租户为界的账号列表 endpoint 在重写过程中弄丢了它的隔离谓词:依角色限缩范围被换成粗糙的「这个账号是不是任何一个已启用的管理员?」检查,于是不论是谁在问,它都返回数据库里的每一个账号。它出货了、通过了所有既有测试(那个方法一个测试都没有),最后是客户反馈「我看到了不该看到的账号信息」才浮现。`test-completeness-dimensions` 的维度 4 早就点名跨租户访问,所以缺的从来不是维度,缺的是一个在迁移当下强迫想起它的步骤。有三个性质让这一类缺陷穿过每一道闸门:那条安全关键的代码因为住在查询里而非请求/响应契约里,读起来就像众多过滤条件之一;基于形状的断言看不见范围,所以「200 加非空列表」在子句被删掉之后照样通过;而代码库别处存在一支共用 scope resolver 会被读成覆盖,同时一个新的 call site 正在不调用它地重写这个查询。新阶段与隐含规则扫描并行,机械化地推导出每一个以操作者自身身份为界的谓词——包含由 ORM global scope、repository 基类、RLS 策略、注入过滤条件的 middleware 在 SQL 之外执行的范围,因为只 grep SQL 会报告一个比实际更小的集合,而在这里更小的集合读起来恰好就像更安全的集合。每个命中都记下 `file:line`、自我绑定与触发分支;oracle 是「每个角色分支、逐 call site 的谓词等价性」,不是输出形状。RE-AUTH-001 要求一个断言另一操作者记录**不存在**的负向测试(附自我检查:在暂存副本里把谓词删掉,若测试还是通过,那它从来就不是在测范围);RE-AUTH-002 则对任何「移植后等价物未经验证」的谓词 block cutover。
|
|
46
|
+
- **写下来的日期现在必须代表某件事(`tech-debt-standards` 1.1.0、`governance-layer` 1.1.0)。** 登记表模板从 1.0.0 起就要求 `Owner` 与 `Target Resolution Date`,而两份标准里没有任何一处说那个日期过了会怎样——对 `core/tech-debt-standards.md` grep `overdue|past due|expired|exceed` 零命中,而对照组 grep `Owner` 有命中,证明那个「查无」是真的、不是查询工具坏掉。更严重的是 `Registry Storage Options` 把「专用电子表格」列为完全合法:一份没有任何程序读得到的表格满足本节其余每一条要求,它没有任何地方是错的——直到日期过了,然后什么都没发生。`tech-debt-standards` 新增**到期处置**——到期时只有三种合法处置(做掉/撤销/延期并写明理由)、TD-EXP-001..006、明文禁止把到期实现成自动延期或自动关闭(两者都让时钟停止,且都不留下停了的痕迹),以及给跑不动检查的团队的合规替代方案**无人看管声明**。每个存储选项现在都带着「在什么条件下它才合法」;电子表格刻意保留,因为它常是出钱的人唯一会打开的格式。`governance-layer` 新增风险接受条款的 `review_by`(`review_by` 已过的接受不是有效条款,pipeline 必须 fail closed,与没有条款时一样)、**待裁决事项**(GOV-PD-001..004——待裁决是一种带时钟、带固定列举标记的受治理状态,不是自由书写的散文)、**汇总报告**(GOV-RPT-001..005——通过/失败/**判不了**分开打印、写出分母与其推导方式、不得合并成单一分数,因为一个「什么都不做」与「把工作做完」得分相同的指标,量的不是那份工作),以及**新鲜度指标**(GOV-FRESH-001..004——指标必须指名自己读的是编辑时间还是对账时间,两者不得共用字段;一份今天刚编辑、从未与现实对过的文件,在其中一个时钟上是零天、在另一个上是无上限)。两份标准都在标准正文里明白写出 UDS 对这些规则不提供任何检查器:最低标准不是「去建一支检查器」,而是「绝不让一条记载在无声中变成无人看管」。
|
|
47
|
+
- **`uds audit --effects` —— 一道去问「这个回报成功的组件,到底做了什么没有」的闸门(XSPEC-383 R8)。** 形状 D:可达、被调用、跑得动、回传 `{ok: true}`,而它什么都没碰。R3 的可达性闸门看不见它——**可达性问的是入边(谁调用它),形状 D 的病灶在出边(它最终碰到什么),方向相反**。根因是**宣称与证据共用同一个作者**:回传值既是「我做了什么」也是唯一的证据,而类型系统验的那个形状,对真实作与空壳**完全同构**。本闸门走访每个宣告的实作的调用图,量它是否触及跨进程边界。**边界集合从 runtime 自读**——由家族根名规则走访 `builtinModules` 展开(`fs`、`child_process`、`net`/`dgram`/`tls`、`http`/`https`/`http2`、`dns`、`worker_threads`),不是手打清单,因此 `fs/promises` 与未来任何子路径都不需要改代码;且**每条规则都印出自己展开了几个**,展开 0 个就是规则过期了。免 import 的全局 API(`fetch`、`WebSocket`、`process.dlopen`)先探测当前 runtime 才纳入,这个 Node 没有的那些也一并印出来。家族**用 glob 宣告**在 `.uds/effect-boundary.json`,**不用文件名清单**——文件名清单在有人加上第七个 adapter 的那一刻就不再为真,而那正是本闸门存在的理由。判定三态:零命中判 RED(家族中位数 > 0 时带「兄弟有对照组」的佐证;整个家族全为零时**组内比较集体沉默**,报告会明说这个 RED 只由绝对零判准支撑);零命中但带着无法分类的外部依赖则是 **UNDECIDABLE 并 exit 2**——判成绿是 fail-open,判成红是诬告。依 R7-b,**宣告 `NOT_IMPLEMENTED` 且从不回传成功形状的实作是合法的,不需要白名单**——这个连言很重要:只认关键字的话,那个字就是每个空壳将来要走的洞,而两者同时出现的文件会被**指名判 RED**。R7-c 抽出字符串拼接产生的域名(模板内插与 `+` 串接一律折成 `*`,所以 `` `https://${env}.api.acme.example` `` 仍可判定,`` `https://api.${tld}` `` 不可判定),对照**来源可插拔**的持有清单:文件、环境变量,或**命令**——那正是接注册商或云账户 DNS zone API 的位置。**宣告了却读不到 → exit 2**,绝不当成「清单为空所以什么都合法」。基线是 **TSV,每列一个到期日**(§7.11.2),格式坏掉的列 exit 2,因为**坏掉的基线不是「没有基线」**。做的过程中它第一次自测就抓到自己的真缺陷:**type-only import 被当成调用图的边**,于是空壳继承了接口文件的边界命中而判绿——类型 import 编译后整行消失,把它算成命中是**凭空多出来的绿灯**。那个案例现在由一支专属对照臂钉住。**它证明不了什么**:碰到的那个边界是不是**对的**那一个——打一发装饰性 log 请求就能过关。那是 R9,本轮未做。UDS 自己没有效果家族,所以不带 config 直接跑会 exit 2,这是设计而非故障;CI 跑的是 `--self-test`,十七臂(五个探针对照组、分母、绿、红、R7-b 滥用、R7-b 豁免、跨文件调用图、边界金丝雀、域名金丝雀、读不到清单、空集合、不可判定、探针失效)在一份为本 repo 自己写的合成语料上各自证明得出来。
|
|
48
|
+
- **一道采用者跑得动的错误出口闸门。** `templates/gates/check-error-exit.mjs` 现在随包发布。`uds check` 会在有 `src/` 却没有这道闸门的项目上报告,但从不写入;`uds update` 会说明它是什么并提议写入,默认答案是**不要**,文件已存在时绝不覆盖。闸门允许一个文件格式化错误信息,第二个出现时才判红;配置好之前一律 exit 2。
|
|
49
|
+
- **`brainstorm-assistant`:判官现在需要心智,不只需要座位(XSPEC-388)。** BQS D4 必须同时具备独立 context 与声明的模型层级才算通过,模型层级只能用 `core/model-selection.md` 的厂商中立标签表达,指名具体厂商模型即违规。CONVERGE 评审提示改写为「目标+约束」。没有移除任何 v3 机制。
|
|
50
|
+
- **`llms.txt` 改为生成,不再手写。** 由 `uds-manifest.json`、`core/`、`skills/`、`integrations/REGISTRY.json` 与 `cli/package.json` 推导,`--check` 在已提交的文件差一个字节时即失败。
|
|
51
|
+
|
|
52
|
+
### 变更
|
|
53
|
+
|
|
54
|
+
- **P1 与 P3 回到探针集,而它们当初被砍的理由,现在成了另一种错误的实例(XSPEC-408)。** 两者都在 2026-07-23 以「基线已通过」为由退役:在没有安装 UDS 的情况下对 Antigravity CLI 1.0.14 运行,模型会先读档再回答(P1),也会主动给出自己的推荐(P3)。这些观察仍然成立;站不住的是退役这个结论。**每一支探针量的是两件事——一个行为与一个声明的标记——而被推翻的只有行为。** P1 的退役纪录自己就写出了这一点(「剩下的是:UDS 要求明确的 `[Source: <path>]` 标注,而基线用的是 markdown 文件链接」),接着却引用 §2.2「探针断言结构,不断言用词」把剩下的部分丢掉。那个读法不可能正确,因为 **P2 正是靠比对四个字面标签存活**,而且是整组里最耐用的探针;§4 自己的总结也早已得出「always-read 层耐用的部分看起来是声明的形式与内部惯例,而不是知识」,而两支声明形式的探针就被砍在它下面几段。§2.2 现在写出它本来就该承载的区分:比对模型碰巧写出的句子,量到的是运气;比对**标准要求模型印出的标记**,量到的是标准有没有送达。P1 与 P3 改写成只问这个较窄的问题,而且两者现在都会在答案*事实正确但没有标记*时明确失败——那正是它们存在要抓的情形。它们的 §2.3 入场基线不花任何一次新运行:留存的 2026-07-23 逐字稿重新计分后,`[Source:` 出现 **0 次**、`[Recommended]` 出现 **0 次**,各自都对照同一个读取器在同一份文件里找到的阳性控制字符串,所以那个 0 是「不存在」,而不是搜索坏掉。`scripts/check-reinstated-probe-baselines.ts` 在每次 CI 运行时重新推导这两个数字——一个读过一次就打进文档的 0 是一枚戳,而这个 repo 已经记录过戳会发生什么事——其 `--self-test` 臂涵盖标记出现(红)、控制字符串缺失(判不了,绝不是绿)与空逐字稿(判不了),三者皆经突变确认。**这件事没有做到的**:提高 n。每支探针一次运行、一个工具、一个前沿模型、重读一遍。`DELTA-TREND.md` 把这次重新计分记在它自己的子表里,并明文禁止并入上方的总表;Codex 那一列加注其 50% 指的是*已退役*的 P1/P3——Codex 没有留存任何 P1/P3 逐字稿,所以不像 Antigravity 有东西可以重新计分。当初让这些探针被退役的那群对象——采用者在 aider 与 continue-dev 下运行的本机与量化模型——至今仍未被量测过,而一支探针的全部价值,就是在那群对象不再需要这条规则时告诉你。复原探针是把传感器装回去;它没有说它会读到什么。
|
|
55
|
+
- **技能:每一个配套文件现在都能从自己的 `SKILL.md` 一跳到达。** 原本有 13 个配套文件(3,193 行)没有任何东西指向它们,另有 56 个只能经由另一个配套文件到达;`skills/` 与各语言树的 168 个配套文件现在全部是一跳,每一条指引都写明文件内容与何时该读。这消除的是结构风险,并不证明配套文件真的会被读取。
|
|
56
|
+
- **发布的 `.ai.yaml` 的 `meta.updated` 改取自源文件的 git 历史**;git 查无记录时直接省略该字段,不再使用手写日期或 transform 执行当天的日期。
|
|
57
|
+
- **`governance-layer`:Enforcement Reality 一节现在也点名较旧的风险接受字段**(`review_by`、`risks_accepted`、`gates_bypassed`)没有任何程序在读取。
|
|
58
|
+
- **依赖:** `chalk` 5.6.2 → 6.0.0、`js-yaml` 5.2.1 → 5.2.3(CLI 运行时);`eslint`、`globals`、`lint-staged`、`tsx`(开发用)。
|
|
59
|
+
- **仓库内部验证(不影响采用者拿到的内容):** 实跑 `uds init` 的采用者指令文件检查;遍历路径表每个工具的安装路径闸门;实际执行已安装 Stop hook 的 hook 投递闸门;比对内容的 bundle parity;skill 触发面闸门;发布戳一致性检查器;翻译 `source_hash` 棘轮;名称提及分类器;STATUS.md 矛盾闸门;本仓库的 `.claude/skills` 副本改为生成;skill 金丝雀仪器(XSPEC-408 R2)及其首批实跑;P7 探针砍除;bump/sync 往返检查移到每次 CI;测试套件不再受机器语言环境影响。
|
|
60
|
+
|
|
61
|
+
### 弃用
|
|
62
|
+
|
|
63
|
+
- **`contentMode: 'full'`——一个既有模式的第二个名字(XSPEC-357 R7)。** manifest schema 接受它、`--content-mode` 提供它、init 提示把它包装成「拿 context 预算换合规」的取舍(「完整嵌入所有规则、约 10-15 KB、合规率最高」),而且每一个 `partial` 层级的工具都被自动指派它。这些一项都没有被实现:生成器对模式的唯一判断是 `=== 'minimal'`,因此 `full` 与 `index` 走同一条分支,**在实测的 24 组(工具 × 语言)组合中写出逐位相同的文件**,且对照组证明该比较确实抓得到差异(`full` 对 `minimal` 在 24 组中全部不同)。它也不可能按宣称的方式运作——`.standards/` 约 248k token,远超过任何集成文件装得下的量。采用者是在两个标签之间选择同一种行为,而那个标签承诺了一个不存在的差异;文档甚至以法规理由建议银行核心系统采用 `full`。**这次弃用对采用者的代价是零**:`--content-mode full` 仍然接受并解析为 `index`(附说明),manifest 中记录的 `full` 会在下次读取时改写为 `index`,而由于两个模式本来就产生相同的字节,**任何项目生成的文件都不会改变**。无法识别的模式仍然解析为 `index`,但现在会打印警告并写明那个值;7.0.0 起会改为直接报错。`check-adopter-instruction-files.ts` 里的 `content-mode=full` 情境——正是它「8 个文件全部逐位相同」的发现促成了这次移除——一并移除,而不是留着拿 `index` 跟 `index` 比、然后永远报告「相同」。
|
|
64
|
+
## [6.8.0] - 2026-08-20
|
|
65
|
+
|
|
66
|
+
### 新增
|
|
67
|
+
|
|
68
|
+
- **一道去问「这条 `uds <cmd>` 指示真的跑得动吗」的闸门(XSPEC-383 R4)。** 2026-08-19 查到三个顶层命令(`uds install`、`uds lint`、`uds sync`)与两个旗标(`uds check --spec-size`、`uds spec create --boost`)出现在出货的指引里而**它们都不存在**——落点包括 `quickstart.js`(它的整个工作就是「快速找到对的命令」)与 `integration-generator.js`(它把命令**写进每一个采用者的 `CLAUDE.md`/`AGENTS.md`**)。两处早已修掉(`465335e4`),而**没有任何东西在确认那个修正会维持**。`check-command-existence.mjs` 走访 `core/`、`locales/`、`ai/standards/`、`cli/src/`、`skills/`、`docs/` 与 repo 根目录的 `*.md`,抽出每一个 `uds <cmd>` 样式,用 `uds <path> --definitely-not-a-real-flag` 对本次 commit 自己的 CLI 探测——**不是 `--help`**:commander 对**未知**命令会回答通用命令表而不是报错,而那正是 `uds lint`/`uds sync` 在第一轮检查中存活的原因。
|
|
69
|
+
- **同一支探针对现况再跑一次,翻出第一次事故的修正从未碰到的漂移。** `uds workflow`(v6.0.0 移除)在 `docs/user/CHEATSHEET.md`、`docs/reference/FEATURE-REFERENCE.md`、`skills/workflows/README.md`(及 zh-TW/zh-CN 镜像)**被当成现行命令展示了五个月**,而 `docs/MIGRATION-v6.md` 自己就给了能抓到它的那条 grep。`uds config --lang`/`--mode` 从未存在(root `README.md`、两份 locale、`docs/reference/INTEGRATION-VERIFICATION.md`)。`uds agent install --all` 把位置参数写成旗标。`uds reverse-tdd` 是为了一段 GitHub Actions 范例**虚构出来的 CLI**。`uds check --interactive` 不存在,因为交互模式本来就是默认。**29 个发现,29 个修好,0 个残留。**
|
|
70
|
+
- **一道去问「有没有人到得了这段代码」的闸门(XSPEC-383 R3)。** 单元测试证明函数是对的,对「有没有使用者叫得到」一个字都没说。2026-04-07 有一次 commit 加了 `spec-linter.js`(172 行、14 个测试全过)与 `sync.js`(133 行)——**两者都从未被注册**,而同一天有下游产品把自己接上 `npx uds lint --json`,一个因此永远不会存在的命令。四个半月,两边全绿,中间没有一条通的路。`check-module-reachability.mjs` 从 package.json 的 `bin` 与 `main` 出发做 BFS,**手查找到 2 个,走访找到 24 个**,含整个九模块的 `src/flow/` 子系统。
|
|
71
|
+
- **`uds lint`(XSPEC-383 R5)。** 注册那个 linter 自 2026-04-07 起就在等的命令,带着两项禁得起真实 spec 考验的检查:依赖有效性与篇幅。
|
|
72
|
+
|
|
73
|
+
### 变更
|
|
74
|
+
|
|
75
|
+
- **哈希前先规范化行尾(#155)。** `uds check` 比对的是磁盘上的原始 bytes,于是 Windows 在 `core.autocrlf=true` 下的 checkout 把每个 LF 换成 CRLF,**每一个哈希都不再吻合**——而「N 个文件已修改」这句话,无论是有人改了 N 个文件还是平台改写了每一个换行,读起来完全一样。走访另外找到两套从不经过 `hasher.js` 的哈希实现,四处全修。新增 21 个测试,含负向对照:真实内容差异与尾随空白差异,在 CRLF checkout 上仍须检测得到。`uds check --force` 的输出前后逐字节相同,既有 manifest 不需要重新盖章。
|
|
76
|
+
- **使用说明生成器改为问 CLI,而不是背诵一份清单。** `scanCliCommands` 把 `cli/bin/uds.js` 读进一个变量然后忽略它,改用一份注记着「based on uds.js analysis」的手写数组。于是**每一次重新生成都把已移除的 `uds workflow` 写回文档**,也从来不会加入 `uds lint`。现在它解析 `uds --help`——CLI 对自己有哪些命令的权威回答,涵盖任何单文件解析看不到的注册写法(`mcp` 完全由另一个模块注册)。涵盖率从 19/24 变成 **23/23**。
|
|
77
|
+
|
|
78
|
+
### 移除
|
|
79
|
+
|
|
80
|
+
- **`uds sync` 与 AC 覆盖检查(XSPEC-383 R5,选项 E)。** `sync.js` 零消费者。AC 覆盖检查对 93 份真实 spec 测量,报告 98 条验收条件中 0 条被覆盖——**不是因为它们没有测试**,而是因为它用**位置**生成 AC 标识符(`AC-1`、`AC-2`)而不是读规格声明的那些,再用写死的 `@` 前缀去找。一个写 `AC-045-001` 并且标注不带 `@` 的项目,无论追溯做得多完整都会得到零覆盖。**它报的不是「这个项目没有追溯」,而是「我用我自己的惯例去找,找不到」,而这两句话打印出来一模一样。** 它是移除而不是留着不接:它是一个正确实现了一个唯一已知消费者并不使用的惯例的东西,躺在树上等着被人重新接上。跨 repo 的 AC 标识符惯例调解是协商,不是补丁,另案处理。
|
|
81
|
+
|
|
20
82
|
## [6.7.5] - 2026-08-18
|
|
21
83
|
|
|
22
84
|
### 变更
|
|
@@ -14,7 +14,7 @@ status: current
|
|
|
14
14
|
|
|
15
15
|
Universal Development Standards 是一个语言无关、框架无关的文件化标准框架。它提供:
|
|
16
16
|
|
|
17
|
-
- **核心规范** (`core/`):
|
|
17
|
+
- **核心规范** (`core/`):152 个基础开发标准
|
|
18
18
|
- **AI 技能** (`skills/`):用于 AI 辅助开发的 Claude Code 技能
|
|
19
19
|
- **CLI 工具** (`cli/`):用于采用标准的 Node.js CLI
|
|
20
20
|
- **整合** (`integrations/`):各种 AI 工具的配置
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
source: ../../README.md
|
|
3
3
|
source_version: 6.0.0
|
|
4
4
|
translation_version: 6.0.0
|
|
5
|
-
last_synced: 2026-
|
|
6
|
-
source_hash:
|
|
5
|
+
last_synced: 2026-08-19
|
|
6
|
+
source_hash: d978c5775a25
|
|
7
7
|
status: current
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -15,7 +15,7 @@ status: current
|
|
|
15
15
|
|
|
16
16
|
> **语言**: [English](../../README.md) | [繁體中文](../zh-TW/README.md) | 简体中文
|
|
17
17
|
|
|
18
|
-
**版本**: 6.
|
|
18
|
+
**版本**: 6.9.0 | **发布日期**: 2026-09-14 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
|
|
19
19
|
|
|
20
20
|
语言无关、框架无关的软件项目文档标准。通过 AI 原生工作流,确保不同技术栈之间的一致性、质量和可维护性。
|
|
21
21
|
|
|
@@ -76,10 +76,10 @@ npx universal-dev-standards init
|
|
|
76
76
|
<!-- UDS_STATS_TABLE_START -->
|
|
77
77
|
| 类别 | 数量 | 说明 |
|
|
78
78
|
|----------|-------|-------------|
|
|
79
|
-
| **核心标准** |
|
|
79
|
+
| **核心标准** | 152 | 通用开发准则 |
|
|
80
80
|
| **AI Skills** | 55 | 互动式技能 |
|
|
81
81
|
| **斜线命令** | 51 | 快速操作 |
|
|
82
|
-
| **CLI 命令** |
|
|
82
|
+
| **CLI 命令** | 23 | 项目设置与维护 |
|
|
83
83
|
<!-- UDS_STATS_TABLE_END -->
|
|
84
84
|
|
|
85
85
|
> **5.0 新功能?** 请参阅[预发布说明](../../docs/PRE-RELEASE.md)了解新功能详情。
|
|
@@ -198,9 +198,9 @@ uds uninstall # 从项目移除标准
|
|
|
198
198
|
|
|
199
199
|
| 参数 | 命令 | 说明 |
|
|
200
200
|
| :--- | :--- | :--- |
|
|
201
|
-
| **提交语言** | `uds config
|
|
201
|
+
| **提交语言** | `uds config set output_language simplified-chinese` | 设置 AI 提交消息的偏好语言 |
|
|
202
202
|
| **标准** | `uds init` | 安装所有可用标准 |
|
|
203
|
-
| **工具模式** | `uds config --
|
|
203
|
+
| **工具模式** | `uds config --type content_mode` | 在 Skills、Standards 或两者之间切换 |
|
|
204
204
|
|
|
205
205
|
---
|
|
206
206
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
source: ../../../core/ai-instruction-standards.md
|
|
3
|
-
source_version: 1.1.
|
|
4
|
-
translation_version: 1.1.
|
|
5
|
-
last_synced: 2026-
|
|
3
|
+
source_version: 1.1.1
|
|
4
|
+
translation_version: 1.1.1
|
|
5
|
+
last_synced: 2026-08-19
|
|
6
6
|
status: current
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -213,7 +213,7 @@ translation_version: {本翻译的版本}
|
|
|
213
213
|
|------|------|--------|
|
|
214
214
|
| **Canonical 拥有者** | `core/{name}.md` 等 | 维持 L1/L2/L3/L4 为英文;breaking change 时 bump `source_version` |
|
|
215
215
|
| **Locale 维护者** | `locales/{lang}/...` | `translation_version` 对齐 `source_version`;翻译 L1(必)、L2(选)、L3(必)、L4(建议)|
|
|
216
|
-
| **采用者** | 自己的 `.claude/skills/`、`CLAUDE.md` | 用 `uds
|
|
216
|
+
| **采用者** | 自己的 `.claude/skills/`、`CLAUDE.md` | 用 `uds init --locale {lang}`(首次)或 `uds update --locale {lang}`(重新同步)安装;**绝不**手动修改 canonical |
|
|
217
217
|
|
|
218
218
|
### Chimera 防范
|
|
219
219
|
|
|
@@ -229,7 +229,8 @@ translation_version: {本翻译的版本}
|
|
|
229
229
|
### 采用者安装
|
|
230
230
|
|
|
231
231
|
```bash
|
|
232
|
-
uds
|
|
232
|
+
uds init --locale zh-cn # 首次以简体中文安装 skills 与 standards
|
|
233
|
+
uds update --locale zh-cn # 对既有采用重新同步
|
|
233
234
|
```
|
|
234
235
|
|
|
235
236
|
**Locale 解析优先顺序**:`--locale` flag > `.uds/install.yaml` > `UDS_LOCALE` env > fallback `en`
|
|
@@ -239,7 +240,7 @@ Locale 不存在时 fallback 到 canonical + WARN,**不**阻断安装。
|
|
|
239
240
|
### 迁移:已有 chimera 的采用者
|
|
240
241
|
|
|
241
242
|
1. **辨识 chimera**:比对采用者档案与 UDS canonical / locale 变体
|
|
242
|
-
2. **安装正确变体**:`uds
|
|
243
|
+
2. **安装正确变体**:`uds update --locale {lang}`
|
|
243
244
|
3. **保留专案级客制**:抽出为 overlay
|
|
244
245
|
4. **丢弃纯翻译**:locale 变体取代之
|
|
245
246
|
|
|
@@ -251,8 +252,9 @@ Locale 不存在时 fallback 到 canonical + WARN,**不**阻断安装。
|
|
|
251
252
|
| 更新 canonical | 改进英文 source | Bump `source_version` |
|
|
252
253
|
| 翻译 / 同步 locale | 新增或更新 locale 内容 | Bump `translation_version` |
|
|
253
254
|
| 检查覆盖率 | 定期 review | `locales/COVERAGE.md` |
|
|
254
|
-
| 带 locale 安装 | 采用者初设 | `uds
|
|
255
|
-
|
|
|
255
|
+
| 带 locale 安装 | 采用者初设 | `uds init --locale {lang}` |
|
|
256
|
+
| 带 locale 重新同步 | 既有采用 | `uds update --locale {lang}` |
|
|
257
|
+
| 跑 i18n lint | Commit 前 / CI | `uds check --i18n` |
|
|
256
258
|
|
|
257
259
|
---
|
|
258
260
|
|