universal-dev-standards 6.8.0 → 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.
Files changed (194) hide show
  1. package/bin/uds.js +12 -2
  2. package/bundled/ai/standards/acceptance-criteria-traceability.ai.yaml +14 -2
  3. package/bundled/ai/standards/adr-standards.ai.yaml +14 -2
  4. package/bundled/ai/standards/code-review.ai.yaml +13 -3
  5. package/bundled/ai/standards/commit-message.ai.yaml +8 -4
  6. package/bundled/ai/standards/deferred-item-exit.ai.yaml +225 -0
  7. package/bundled/ai/standards/feature-discovery-standards.ai.yaml +14 -2
  8. package/bundled/ai/standards/governance-layer.ai.yaml +128 -2
  9. package/bundled/ai/standards/logging.ai.yaml +2 -2
  10. package/bundled/ai/standards/retrospective-standards.ai.yaml +14 -2
  11. package/bundled/ai/standards/reverse-engineering-standards.ai.yaml +73 -2
  12. package/bundled/ai/standards/security-standards.ai.yaml +2 -2
  13. package/bundled/ai/standards/spec-driven-development.ai.yaml +14 -2
  14. package/bundled/ai/standards/tech-debt-standards.ai.yaml +87 -3
  15. package/bundled/ai/standards/turn-completion-integrity.ai.yaml +131 -0
  16. package/bundled/core/acceptance-criteria-traceability.md +5 -2
  17. package/bundled/core/adr-standards.md +26 -2
  18. package/bundled/core/code-review-checklist.md +5 -2
  19. package/bundled/core/context-aware-loading.md +1 -1
  20. package/bundled/core/deferred-item-exit.md +254 -0
  21. package/bundled/core/feature-discovery-standards.md +5 -1
  22. package/bundled/core/governance-layer.md +114 -2
  23. package/bundled/core/retrospective-standards.md +4 -2
  24. package/bundled/core/reverse-engineering-standards.md +81 -2
  25. package/bundled/core/spec-driven-development.md +8 -2
  26. package/bundled/core/tech-debt-standards.md +67 -8
  27. package/bundled/core/turn-completion-integrity.md +196 -0
  28. package/bundled/hooks/check-dangerous-cmd.mjs +60 -0
  29. package/bundled/hooks/check-logging-standard.mjs +59 -0
  30. package/bundled/hooks/check-turn-completion.mjs +233 -0
  31. package/bundled/hooks/inject-standards.mjs +183 -0
  32. package/bundled/hooks/telemetry-wrapper.mjs +77 -0
  33. package/bundled/hooks/turn-completion/detect.mjs +99 -0
  34. package/bundled/hooks/turn-completion/locales/en.mjs +159 -0
  35. package/bundled/hooks/turn-completion/locales/zh-TW.mjs +166 -0
  36. package/bundled/hooks/validate-commit-msg.mjs +104 -0
  37. package/bundled/locales/zh-CN/CHANGELOG.md +47 -3
  38. package/bundled/locales/zh-CN/CLAUDE.md +1 -1
  39. package/bundled/locales/zh-CN/README.md +2 -2
  40. package/bundled/locales/zh-CN/SECURITY.md +1 -1
  41. package/bundled/locales/zh-CN/core/adr-standards.md +1 -1
  42. package/bundled/locales/zh-CN/core/governance-layer.md +118 -6
  43. package/bundled/locales/zh-CN/core/retrospective-standards.md +1 -1
  44. package/bundled/locales/zh-CN/core/tech-debt-standards.md +71 -4
  45. package/bundled/locales/zh-CN/core/turn-completion-integrity.md +190 -0
  46. package/bundled/locales/zh-CN/docs/CHEATSHEET.md +8 -1
  47. package/bundled/locales/zh-CN/docs/CLI-INIT-OPTIONS.md +29 -68
  48. package/bundled/locales/zh-CN/docs/FEATURE-REFERENCE.md +25 -15
  49. package/bundled/locales/zh-CN/docs/USAGE-MODES-COMPARISON.md +1 -2
  50. package/bundled/locales/zh-CN/integrations/google-antigravity/{INSTRUCTIONS.md → AGENTS.md} +1 -1
  51. package/bundled/locales/zh-CN/integrations/google-antigravity/README.md +3 -3
  52. package/bundled/locales/zh-CN/skills/atdd-assistant/SKILL.md +2 -0
  53. package/bundled/locales/zh-CN/skills/bdd-assistant/SKILL.md +2 -0
  54. package/bundled/locales/zh-CN/skills/brainstorm-assistant/SKILL.md +22 -12
  55. package/bundled/locales/zh-CN/skills/brainstorm-assistant/guide.md +12 -9
  56. package/bundled/locales/zh-CN/skills/code-review-assistant/SKILL.md +1 -0
  57. package/bundled/locales/zh-CN/skills/commands/brainstorm.md +17 -13
  58. package/bundled/locales/zh-CN/skills/commands/config.md +0 -1
  59. package/bundled/locales/zh-CN/skills/commands/init.md +1 -2
  60. package/bundled/locales/zh-CN/skills/commit-standards/SKILL.md +2 -0
  61. package/bundled/locales/zh-CN/skills/contract-test-assistant/SKILL.md +1 -0
  62. package/bundled/locales/zh-CN/skills/dev-methodology/SKILL.md +2 -0
  63. package/bundled/locales/zh-CN/skills/observability-assistant/SKILL.md +1 -0
  64. package/bundled/locales/zh-CN/skills/project-structure-guide/SKILL.md +1 -0
  65. package/bundled/locales/zh-CN/skills/release-standards/SKILL.md +3 -0
  66. package/bundled/locales/zh-CN/skills/requirement-assistant/SKILL.md +2 -0
  67. package/bundled/locales/zh-CN/skills/reverse-engineer/SKILL.md +3 -0
  68. package/bundled/locales/zh-CN/skills/runbook-assistant/SKILL.md +1 -0
  69. package/bundled/locales/zh-CN/skills/slo-assistant/SKILL.md +1 -0
  70. package/bundled/locales/zh-CN/skills/tdd-assistant/SKILL.md +2 -0
  71. package/bundled/locales/zh-TW/CHANGELOG.md +47 -3
  72. package/bundled/locales/zh-TW/CLAUDE.md +1 -1
  73. package/bundled/locales/zh-TW/README.md +2 -2
  74. package/bundled/locales/zh-TW/SECURITY.md +1 -1
  75. package/bundled/locales/zh-TW/core/acceptance-criteria-traceability.md +2 -0
  76. package/bundled/locales/zh-TW/core/adr-standards.md +26 -5
  77. package/bundled/locales/zh-TW/core/code-review-checklist.md +2 -0
  78. package/bundled/locales/zh-TW/core/container-image-standards.md +2 -2
  79. package/bundled/locales/zh-TW/core/contract-testing-standards.md +2 -2
  80. package/bundled/locales/zh-TW/core/cross-flow-regression.md +8 -7
  81. package/bundled/locales/zh-TW/core/data-contract.md +2 -2
  82. package/bundled/locales/zh-TW/core/data-migration-testing.md +2 -2
  83. package/bundled/locales/zh-TW/core/data-pipeline.md +2 -2
  84. package/bundled/locales/zh-TW/core/deferred-item-exit.md +251 -0
  85. package/bundled/locales/zh-TW/core/documentation-writing-standards.md +228 -3
  86. package/bundled/locales/zh-TW/core/full-coverage-testing.md +15 -2
  87. package/bundled/locales/zh-TW/core/governance-layer.md +118 -5
  88. package/bundled/locales/zh-TW/core/iac-design-principles.md +2 -2
  89. package/bundled/locales/zh-TW/core/incident-response.md +2 -2
  90. package/bundled/locales/zh-TW/core/model-provenance.md +4 -2
  91. package/bundled/locales/zh-TW/core/pii-classification.md +42 -6
  92. package/bundled/locales/zh-TW/core/prd-standards.md +4 -2
  93. package/bundled/locales/zh-TW/core/product-metrics-standards.md +4 -2
  94. package/bundled/locales/zh-TW/core/release-readiness-gate.md +2 -2
  95. package/bundled/locales/zh-TW/core/resource-cost-boundary.md +2 -2
  96. package/bundled/locales/zh-TW/core/retrospective-standards.md +5 -3
  97. package/bundled/locales/zh-TW/core/reverse-engineering-standards.md +83 -5
  98. package/bundled/locales/zh-TW/core/runbook.md +2 -2
  99. package/bundled/locales/zh-TW/core/schema-evolution.md +2 -2
  100. package/bundled/locales/zh-TW/core/secret-management-standards.md +2 -2
  101. package/bundled/locales/zh-TW/core/slo-sli.md +2 -2
  102. package/bundled/locales/zh-TW/core/spec-driven-development.md +2 -0
  103. package/bundled/locales/zh-TW/core/tech-debt-standards.md +71 -4
  104. package/bundled/locales/zh-TW/core/turn-completion-integrity.md +190 -0
  105. package/bundled/locales/zh-TW/core/user-journey-testing.md +2 -2
  106. package/bundled/locales/zh-TW/core/user-story-mapping.md +2 -2
  107. package/bundled/locales/zh-TW/core/verification-oracle.md +2 -2
  108. package/bundled/locales/zh-TW/docs/CHEATSHEET.md +8 -1
  109. package/bundled/locales/zh-TW/docs/CLI-INIT-OPTIONS.md +29 -68
  110. package/bundled/locales/zh-TW/docs/FEATURE-REFERENCE.md +25 -15
  111. package/bundled/locales/zh-TW/docs/USAGE-MODES-COMPARISON.md +1 -2
  112. package/bundled/locales/zh-TW/integrations/google-antigravity/{INSTRUCTIONS.md → AGENTS.md} +1 -1
  113. package/bundled/locales/zh-TW/integrations/google-antigravity/README.md +3 -3
  114. package/bundled/locales/zh-TW/skills/adr-assistant/SKILL.md +1 -1
  115. package/bundled/locales/zh-TW/skills/atdd-assistant/SKILL.md +2 -0
  116. package/bundled/locales/zh-TW/skills/bdd-assistant/SKILL.md +2 -0
  117. package/bundled/locales/zh-TW/skills/brainstorm-assistant/SKILL.md +22 -12
  118. package/bundled/locales/zh-TW/skills/brainstorm-assistant/guide.md +12 -9
  119. package/bundled/locales/zh-TW/skills/code-review-assistant/SKILL.md +1 -0
  120. package/bundled/locales/zh-TW/skills/commands/brainstorm.md +17 -13
  121. package/bundled/locales/zh-TW/skills/commands/config.md +0 -1
  122. package/bundled/locales/zh-TW/skills/commands/init.md +1 -2
  123. package/bundled/locales/zh-TW/skills/commit-standards/SKILL.md +2 -0
  124. package/bundled/locales/zh-TW/skills/contract-test-assistant/SKILL.md +2 -1
  125. package/bundled/locales/zh-TW/skills/dev-methodology/SKILL.md +2 -0
  126. package/bundled/locales/zh-TW/skills/dev-workflow-guide/SKILL.md +1 -1
  127. package/bundled/locales/zh-TW/skills/knowledge-graph/guide.md +2 -2
  128. package/bundled/locales/zh-TW/skills/migration-assistant/SKILL.md +1 -1
  129. package/bundled/locales/zh-TW/skills/observability-assistant/SKILL.md +1 -0
  130. package/bundled/locales/zh-TW/skills/project-discovery/SKILL.md +1 -0
  131. package/bundled/locales/zh-TW/skills/project-structure-guide/SKILL.md +1 -0
  132. package/bundled/locales/zh-TW/skills/release-standards/SKILL.md +3 -0
  133. package/bundled/locales/zh-TW/skills/requirement-assistant/SKILL.md +2 -0
  134. package/bundled/locales/zh-TW/skills/reverse-engineer/SKILL.md +3 -0
  135. package/bundled/locales/zh-TW/skills/runbook-assistant/SKILL.md +1 -0
  136. package/bundled/locales/zh-TW/skills/slo-assistant/SKILL.md +1 -0
  137. package/bundled/locales/zh-TW/skills/tdd-assistant/SKILL.md +2 -0
  138. package/bundled/skills/atdd-assistant/SKILL.md +2 -0
  139. package/bundled/skills/bdd-assistant/SKILL.md +2 -0
  140. package/bundled/skills/brainstorm-assistant/SKILL.md +31 -13
  141. package/bundled/skills/brainstorm-assistant/guide.md +9 -6
  142. package/bundled/skills/code-review-assistant/SKILL.md +1 -0
  143. package/bundled/skills/commands/brainstorm.md +12 -9
  144. package/bundled/skills/commands/config.md +0 -1
  145. package/bundled/skills/commands/init.md +2 -3
  146. package/bundled/skills/commit-standards/SKILL.md +2 -0
  147. package/bundled/skills/contract-test-assistant/SKILL.md +1 -0
  148. package/bundled/skills/dev-methodology/SKILL.md +4 -0
  149. package/bundled/skills/observability-assistant/SKILL.md +1 -0
  150. package/bundled/skills/project-discovery/SKILL.md +1 -0
  151. package/bundled/skills/project-structure-guide/SKILL.md +1 -0
  152. package/bundled/skills/release-standards/SKILL.md +3 -0
  153. package/bundled/skills/requirement-assistant/SKILL.md +2 -0
  154. package/bundled/skills/reverse-engineer/SKILL.md +3 -0
  155. package/bundled/skills/runbook-assistant/SKILL.md +1 -0
  156. package/bundled/skills/slo-assistant/SKILL.md +1 -0
  157. package/bundled/skills/tdd-assistant/SKILL.md +2 -0
  158. package/bundled/templates/.ai-context.yaml.template +194 -0
  159. package/bundled/templates/CLAUDE.md.template +145 -0
  160. package/bundled/templates/DESIGN.md +237 -0
  161. package/bundled/templates/SKILL-BRIEF-TEMPLATE.md +57 -0
  162. package/bundled/templates/SKILL-CANDIDATES.md +39 -0
  163. package/bundled/templates/gates/check-error-exit.mjs +309 -0
  164. package/bundled/templates/mcp-config.json +10 -0
  165. package/bundled/templates/methodology-template.yaml +209 -0
  166. package/bundled/templates/migration-template.md +408 -0
  167. package/bundled/templates/requirement-checklist.md +410 -0
  168. package/bundled/templates/requirement-document-template.md +591 -0
  169. package/bundled/templates/requirement-template.md +881 -0
  170. package/bundled/templates/reverse-spec-template.md +409 -0
  171. package/bundled/templates/test-case-template.md +74 -0
  172. package/bundled/templates/test-plan-template.md +74 -0
  173. package/package.json +7 -5
  174. package/src/commands/audit.js +82 -0
  175. package/src/commands/check.js +66 -10
  176. package/src/commands/init.js +161 -16
  177. package/src/commands/update.js +286 -14
  178. package/src/compilers/claude-code-compiler.js +4 -1
  179. package/src/config/ai-agent-paths.js +62 -17
  180. package/src/core/constants.js +42 -11
  181. package/src/core/manifest.js +201 -3
  182. package/src/core/paths.js +2 -2
  183. package/src/i18n/messages.js +6 -29
  184. package/src/installers/hooks-installer.js +167 -75
  185. package/src/installers/integration-installer.js +9 -5
  186. package/src/prompts/init.js +14 -14
  187. package/src/utils/detector.js +21 -1
  188. package/src/utils/effect-boundary.js +1093 -0
  189. package/src/utils/hasher.js +166 -1
  190. package/src/utils/hook-stats.js +1 -1
  191. package/src/utils/integration-generator.js +79 -1
  192. package/src/utils/reference-sync.js +4 -1
  193. package/src/utils/yaml-generator.js +51 -9
  194. package/standards-registry.json +31 -8
@@ -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.8.0
4
- translation_version: 6.8.0
5
- last_synced: 2026-08-19
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,50 @@ 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` 比、然后永远报告「相同」。
20
64
  ## [6.8.0] - 2026-08-20
21
65
 
22
66
  ### 新增
@@ -14,7 +14,7 @@ status: current
14
14
 
15
15
  Universal Development Standards 是一个语言无关、框架无关的文件化标准框架。它提供:
16
16
 
17
- - **核心规范** (`core/`):150 个基础开发标准
17
+ - **核心规范** (`core/`):152 个基础开发标准
18
18
  - **AI 技能** (`skills/`):用于 AI 辅助开发的 Claude Code 技能
19
19
  - **CLI 工具** (`cli/`):用于采用标准的 Node.js CLI
20
20
  - **整合** (`integrations/`):各种 AI 工具的配置
@@ -15,7 +15,7 @@ status: current
15
15
 
16
16
  > **语言**: [English](../../README.md) | [繁體中文](../zh-TW/README.md) | 简体中文
17
17
 
18
- **版本**: 6.8.0 | **发布日期**: 2026-08-20 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
18
+ **版本**: 6.9.0 | **发布日期**: 2026-09-14 | **授权**: [双重授权](../../LICENSE) (CC BY 4.0 + MIT)
19
19
 
20
20
  语言无关、框架无关的软件项目文档标准。通过 AI 原生工作流,确保不同技术栈之间的一致性、质量和可维护性。
21
21
 
@@ -76,7 +76,7 @@ npx universal-dev-standards init
76
76
  <!-- UDS_STATS_TABLE_START -->
77
77
  | 类别 | 数量 | 说明 |
78
78
  |----------|-------|-------------|
79
- | **核心标准** | 150 | 通用开发准则 |
79
+ | **核心标准** | 152 | 通用开发准则 |
80
80
  | **AI Skills** | 55 | 互动式技能 |
81
81
  | **斜线命令** | 51 | 快速操作 |
82
82
  | **CLI 命令** | 23 | 项目设置与维护 |
@@ -13,7 +13,7 @@ status: current
13
13
  <!-- UDS_SUPPORTED_VERSIONS_START -->
14
14
  | 版本 | 支持状态 |
15
15
  |------|--------|
16
- | 6.8.0 | ✅ 最新正式版 |
16
+ | 6.9.0 | ✅ 最新正式版 |
17
17
  | < 6.0.0 | ❌ 已终止支持 |
18
18
  <!-- UDS_SUPPORTED_VERSIONS_END -->
19
19
 
@@ -3,7 +3,7 @@ source: ../../../core/adr-standards.md
3
3
  source_version: 1.0.0
4
4
  translation_version: 1.0.0
5
5
  last_synced: 2026-03-26
6
- status: current
6
+ status: stale
7
7
  ---
8
8
 
9
9
  # 架构决策记录(ADR)
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  source: ../../../core/governance-layer.md
3
- source_version: 1.0.0
4
- translation_version: 1.0.0
5
- last_synced: 2026-06-10
6
- source_hash: faff51e79a15
3
+ source_version: 1.1.0
4
+ translation_version: 1.1.0
5
+ last_synced: 2026-08-20
6
+ source_hash: 15ca18717240
7
7
  status: current
8
8
  ---
9
9
 
@@ -11,8 +11,8 @@ status: current
11
11
 
12
12
  > **语言**: [English](../../../core/governance-layer.md) | [繁體中文](../../zh-TW/core/governance-layer.md) | 简体中文
13
13
 
14
- **版本**: 1.0.0
15
- **最后更新**: 2026-05-07
14
+ **版本**: 1.1.0
15
+ **最后更新**: 2026-08-20
16
16
  **适用范围**: 所有具有多 Agent 或多角色 AI 工作流程的软件项目
17
17
  **范畴**: universal
18
18
  **产业标准**: 无(UDS 原创)
@@ -131,9 +131,79 @@ Vision(方向)→ Mission(边界 + 红线)→ Goals(可量测的 KPI
131
131
  | `signatory` | 接受风险的人员或角色 |
132
132
  | `gates_bypassed` | 列举所有绕过的人工闸门 |
133
133
  | `risks_accepted` | 明确描述已接受的风险 |
134
+ | `review_by` | 本次接受失效、必须重新做一次判断的日期 |
134
135
 
135
136
  若无有效的风险接受条款,pipeline **必须拒绝启动(fail-closed)**。
136
137
 
138
+ ### 接受到期
139
+
140
+ `review_by` 已过的条款**不是有效条款**。pipeline 必须 fail closed,与完全没有条款时一模一样。
141
+
142
+ `date` 记录的是「何时接受了这个风险」,不是「何时该重新判断」。没有 `review_by`,签过一次的接受就永远有效——当初支持它的条件可能已经改变、签署人可能已经离开项目,而条款里每一个字段读起来仍然完全正确。
143
+
144
+ 到期时,必须施用且只能施用下列三种处置之一,与[技术债标准 → 到期处置](tech-debt-standards.md#到期处置)所定义的三种相同:
145
+
146
+ | 处置 | 含义 |
147
+ |------|------|
148
+ | **重新接受** | 由当下的签署人重新签署,并给出新的 `review_by` |
149
+ | **撤销** | 移除该绕过,恢复人工闸门 |
150
+ | **延期** | 新的 `review_by` **与**书面理由,一起记下 |
151
+
152
+ **禁止自动延长 `review_by`。** 那会把一道 fail-closed 的闸门变成 fail-open,而所有字段看起来都还是对的——失效之所以隐形,正是因为条款仍然验证得过。
153
+
154
+ ---
155
+
156
+ ## 待裁决事项
157
+
158
+ 「还没决定」是一种治理状态,不是治理的缺席。规格里的未决问题、提出但未批准的红线、没有 owner 的 KPI——每一项都是有人被期待要做的决定,而每一项对「只读已做成决定」的检查都是隐形的。
159
+
160
+ 待裁决事项与已接受风险**同级受治理**:它们带时钟,而且必须可被列举。
161
+
162
+ **规则 GOV-PD-001(必要)**——项目必须声明待裁决事项**记在哪里**,以及**什么标记代表一项待裁决**:一个固定的 token(状态值、标签、字面标记字符串),不得是自由书写的散文。列举不该取决于读者猜中当初用了哪些字。三份分别写「TBD」「待拍板」「待确认」的文件,是三份无法被列举的文件;一个声明过的标记让三份都找得到。
163
+
164
+ **规则 GOV-PD-002(必要)**——列举待裁决事项时,必须同时报告总数**与**无法解析的来源份数(见[汇总报告](#汇总报告))。「查无待裁决事项」在不知道走访集合有多大时,不带任何信息。
165
+
166
+ **规则 GOV-PD-003(必要)**——每一项待裁决事项都带一个**裁决期限日期**。到期时适用与逾期技术债相同的三种处置——**做出决定**、**撤回这个问题**、或**延期并写明理由**。禁止自动延期。
167
+
168
+ **规则 GOV-PD-004(必要)**——若没有任何东西在排程上列举待裁决事项,项目必须带一份**无人看管声明**,写明负责人、复查频率与最后复查日期——与技术债登记表被要求的两态规则相同。没有被列举是可接受的;没有被列举又没有声明则不可接受。
169
+
170
+ > 一项没有日期的待裁决事项,在行为上与「决定不做」完全相同。差别只在于待裁决的形式让人以为还有人会去看它。
171
+
172
+ ---
173
+
174
+ ## 汇总报告
175
+
176
+ 每一份治理报告——合规摘要、闸门报告、KPI 汇总、红线扫描——都是对某个集合提出的宣称。这个宣称的价值,恰好等于它对「自己判不了什么」的交代的价值。
177
+
178
+ **规则 GOV-RPT-001(必要)**——报告必须打印三个数字,不能只打印两个:**通过**、**失败**、**判不了**(无法解析的文件、缺字段、来源不可达、不支持的格式)。
179
+
180
+ **规则 GOV-RPT-002(必要)**——「判不了」**不得**并入「通过」,也**不得**省略。一份解析不了的文件不是一份干净的文件。只打印「N 项检查通过」的报告,不论 N 是多少都不合规。
181
+
182
+ **规则 GOV-RPT-003(必要)**——报告必须写出自己的**分母**以及分母是怎么推导出来的。范围来自硬编码清单的报告,是一份关于那份清单的报告,不是关于这个项目的报告:清单之外的东西全部腐坏,它照样是绿的。要用「走访并排除」推导集合,不要用列举——见[类别层级修正](../../../core/class-level-fix.md)。
183
+
184
+ **规则 GOV-RPT-004(必要)**——正向与负向计数分开报告;绝不合并成单一的合规分数。**一个「什么都不做」与「把工作做完」得分相同的指标,量的不是那份工作。**「11 项中通过 5 项」与「检查器从未启动」产生同一个数字,而单一分数分不出这两者。
185
+
186
+ **规则 GOV-RPT-005(建议)**——当报告的正确性取决于它自己的工具能运作时,加一只金丝雀:一个输入已知会失败、因此**必须**失败的检查。若金丝雀通过了,整份报告不可信,必须整份报告为「判不了」,而不是绿灯。
187
+
188
+ ---
189
+
190
+ ## 新鲜度指标
191
+
192
+ **规则 GOV-FRESH-001(必要)**——任何新鲜度/停滞指标都必须指名它读的是下列哪一个时钟:
193
+
194
+ | 时钟 | 回答的问题 | 可以从哪里读 |
195
+ |------|-----------|-------------|
196
+ | **编辑时间** | 这份产物上次被改动是多久以前? | 文件 mtime、最后动到它的 commit、「最后更新」字段 |
197
+ | **对账时间** | 这份产物上次与它宣称在描述的真实来源做比对是多久以前? | 那次比对被记下的日期——没有别的东西能提供它 |
198
+
199
+ **规则 GOV-FRESH-002(必要)**——两者**不得**共用同一个字段或同一个字段标题。它们回答不同的问题,而同一份产物可以在其中一个上满分、在另一个上任意地旧:一份今天刚编辑、内容从未与现实对过的文件,以编辑时间算是零天,以对账时间算是无上限。
200
+
201
+ **规则 GOV-FRESH-003(必要)**——只有编辑时间可取得时,报告必须把该栏标示为编辑时间,**并且**把对账时间报告为「判不了」(GOV-RPT-001)——绝不能标成新鲜,也绝不能省略不提。
202
+
203
+ **规则 GOV-FRESH-004(建议)**——对账时间只有在「由执行该比对的东西自己记下」时才有意义。事后由人手动填入的日期是一项断言,不是一次量测;请如实标示。
204
+
205
+ > 这是「单轴装多维」的失败:一个字段,被两个不同的问题读取。这个字段永远不会被抓到是错的,因为从来没有人问过它在回答哪一个问题。
206
+
137
207
  ---
138
208
 
139
209
  ## 治理文件结构
@@ -157,4 +227,46 @@ governance/
157
227
  - [ ] Goals 清单存在,每个 KPI 均含:id、metric_name、threshold、measurement_method
158
228
  - [ ] 没有任何 KPI 使用模糊词汇(「改善」、「提升」、「更好」)
159
229
  - [ ] 若 `gate.mode = trace_only`,`mission.md` 中存在风险接受条款
230
+ - [ ] 每一份风险接受条款都有 `review_by` 日期,且没有任何一份已经过期
231
+ - [ ] 项目已声明待裁决事项记在哪里、以及哪一个固定标记代表一项待裁决
232
+ - [ ] 每一项待裁决事项都有裁决期限日期
233
+ - [ ] 待裁决事项要么被某个会执行的东西列举,要么被无人看管声明涵盖
234
+ - [ ] 每一份治理报告都分开打印「通过/失败/**判不了**」,并写出分母与分母的推导方式
235
+ - [ ] 没有任何报告把正向与负向计数合并成单一分数
236
+ - [ ] 每一个新鲜度指标都指名自己读的是编辑时间或对账时间,且两者不共用字段
160
237
  - [ ] 所有 AI 评估器以 0.4/0.3/0.3 权重评分,且任一轴 < 0.3 即不通过
238
+
239
+ ---
240
+
241
+ ## 执行现实
242
+
243
+ > **本标准对它的任何一条规则都不提供检查器——不只是 1.1.0 新增的那些,也包括自 1.0.0 起就在里面的那条 fail-closed 风险接受要求。这是已知代价,写在这里,而不是留给采用者自己撞到。**
244
+ >
245
+ > 2026-08-20 实测:`review_by`、`risks_accepted`、`gates_bypassed` **没有出现在任何程序里**——UDS CLI 没有,任何消费端也没有。那句写着 pipeline「必须拒绝启动」的条款,在它被写下来的三个半月里,**从来没有让任何一条 pipeline 拒绝启动过**。把这件事讲明白不是外加的但书,它就是本节自己的规则套用在本节身上;而本节的初稿只列出新规则为未执行,那会让人以为旧的那条有在执行。
246
+ >
247
+ > UDS 定义的是这些要求,它不提供执行这些要求的程序。想要它们被执行的采用者必须自己写那支列举器、那支三态计数报告器、那个对账日期记录器——而多数人不会写。那正是本标准所描述的失败,现在同样适用于本标准自己。
248
+ >
249
+ > 所以最低标准**不是**「去把工具做出来」,而是:**任何被记载为待裁决、已接受、或新鲜的东西,要么指向一个会执行的检查,要么明白说出没有东西在看它。** 声明「无人看管」是合规的。无人看管却不声明,才是这些规则真正禁止的唯一结果,因为只有它会让读者对「有没有东西在看」产生误解。
250
+
251
+ ---
252
+
253
+ ## 版本历史
254
+
255
+ | 版本 | 日期 | 变更 |
256
+ |------|------|------|
257
+ | 1.1.0 | 2026-08-20 | 新增:风险接受条款的 `review_by` 字段 + 接受到期的三种处置与禁止自动延期;待裁决事项(GOV-PD-001..004);汇总报告(GOV-RPT-001..005——通过/失败/判不了、分母推导、不得合并成单一分数、金丝雀);新鲜度指标(GOV-FRESH-001..004——编辑时间与对账时间不得共用字段);执行现实说明;合规检查清单扩充 |
258
+ | 1.0.0 | 2026-05-07 | 初始版本:Vision/Mission/Goals 三层架构、红线格式、评估器整合、风险接受条款、合规检查清单 |
259
+
260
+ ---
261
+
262
+ ## 相关标准
263
+
264
+ - [技术债标准](tech-debt-standards.md) — 「到期处置」定义了本标准沿用的三种处置
265
+ - [类别层级修正](../../../core/class-level-fix.md) — 以走访并排除而非列举推导集合(GOV-RPT-003)
266
+ - [验证证据](verification-evidence.md) — 为何绿灯必须被证明来自一个真的在运作的检查(GOV-RPT-005)
267
+
268
+ ---
269
+
270
+ ## 授权
271
+
272
+ 本标准以 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) 发布。
@@ -3,7 +3,7 @@ source: ../../../core/retrospective-standards.md
3
3
  source_version: 1.0.0
4
4
  translation_version: 1.0.0
5
5
  last_synced: 2026-03-26
6
- status: current
6
+ status: stale
7
7
  ---
8
8
 
9
9
  # 回顾标准