universal-dev-standards 6.13.1 → 6.14.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/bin/uds.js +37 -0
  2. package/bundled/ai/standards/open-work-tracking.ai.yaml +71 -4
  3. package/bundled/ai/standards/turn-completion-integrity.ai.yaml +14 -7
  4. package/bundled/core/open-work-tracking.md +111 -8
  5. package/bundled/core/turn-completion-integrity.md +58 -11
  6. package/bundled/hooks/check-turn-completion-agy.mjs +147 -0
  7. package/bundled/hooks/turn-completion/locales/en.mjs +54 -5
  8. package/bundled/hooks/turn-completion/locales/zh-TW.mjs +37 -6
  9. package/bundled/locales/zh-CN/CHANGELOG.md +33 -3
  10. package/bundled/locales/zh-CN/README.md +2 -2
  11. package/bundled/locales/zh-CN/SECURITY.md +1 -0
  12. package/bundled/locales/zh-CN/core/turn-completion-integrity.md +46 -13
  13. package/bundled/locales/zh-CN/docs/CHEATSHEET.md +6 -1
  14. package/bundled/locales/zh-CN/docs/CLI-INIT-OPTIONS.md +33 -8
  15. package/bundled/locales/zh-CN/docs/FEATURE-REFERENCE.md +17 -7
  16. package/bundled/locales/zh-TW/CHANGELOG.md +33 -3
  17. package/bundled/locales/zh-TW/README.md +2 -2
  18. package/bundled/locales/zh-TW/SECURITY.md +1 -0
  19. package/bundled/locales/zh-TW/core/open-work-tracking.md +88 -9
  20. package/bundled/locales/zh-TW/core/turn-completion-integrity.md +46 -13
  21. package/bundled/locales/zh-TW/docs/CHEATSHEET.md +6 -1
  22. package/bundled/locales/zh-TW/docs/CLI-INIT-OPTIONS.md +33 -8
  23. package/bundled/locales/zh-TW/docs/FEATURE-REFERENCE.md +17 -7
  24. package/package.json +1 -1
  25. package/src/commands/init.js +17 -2
  26. package/src/commands/open-work.js +60 -0
  27. package/src/commands/uninstall.js +1 -1
  28. package/src/commands/update.js +91 -0
  29. package/src/i18n/messages.js +3 -0
  30. package/src/installers/hooks-installer.js +276 -11
  31. package/src/uninstallers/hook-uninstaller.js +107 -4
  32. package/src/utils/detector.js +46 -1
  33. package/src/utils/open-work-tracking.mjs +693 -0
  34. package/standards-registry.json +8 -8
@@ -1,7 +1,7 @@
1
1
  # UDS 功能參考手冊
2
2
 
3
3
  > Universal Development Standards - 完整功能文件
4
- > Auto-generated | Last updated: 2026-09-23
4
+ > Auto-generated | Last updated: 2026-09-29
5
5
 
6
6
  **Language**: [English](../../../docs/reference/FEATURE-REFERENCE.md) | 繁體中文 | [简体中文](../../zh-CN/docs/FEATURE-REFERENCE.md)
7
7
 
@@ -9,15 +9,15 @@
9
9
 
10
10
  ## 目錄
11
11
 
12
- 1. [CLI 指令](#cli-commands) (23)
12
+ 1. [CLI 指令](#cli-commands) (24)
13
13
  2. [斜線命令](#slash-commands) (51)
14
14
  3. [技能](#skills) (55)
15
15
  4. [代理](#agents) (5)
16
16
  5. [工作流程](#workflows) (5)
17
17
  6. [核心規範](#core-standards) (153)
18
- 7. [腳本](#scripts) (59)
18
+ 7. [腳本](#scripts) (63)
19
19
 
20
- **Total Features: 351**
20
+ **Total Features: 356**
21
21
 
22
22
  ---
23
23
 
@@ -158,6 +158,8 @@
158
158
  | `--rollback` | Rollback to the most recent backup |
159
159
  | `--claude-target` | Switch an existing install to a different Claude Code integration target: project (CLAUDE.md) or local (CLAUDE.local.md) — moves the UDS block, keeps your content, no reinstall |
160
160
  | `--locale` | Override locale for skills install (zh-tw, zh-cn, en); also reads .uds/install.yaml + UDS_LOCALE env |
161
+ | `--with-hooks` | Install the enforcement hooks that are missing from this already-initialized project (re-detects tools; hooks already there and your own hooks are not touched; with --plan, writes nothing; --force also overwrites edited hook scripts) |
162
+ | `--ai-tool` | With --with-hooks: comma-separated tools to install hooks for (claude-code, codex, gemini-cli, antigravity) instead of detecting them |
161
163
 
162
164
  ### `uds skills`
163
165
 
@@ -276,6 +278,10 @@
276
278
 
277
279
  **說明**: MCP server commands for AI tool integration
278
280
 
281
+ ### `uds open-work`
282
+
283
+ **說明**: Reference checks for open-work-tracking (OWT-017/018/019). Exit 0 no violation, 1 violation, 2 cannot decide (not a pass)
284
+
279
285
  ### `uds run`
280
286
 
281
287
  **說明**: Run a project command by intent (test/lint/build/security) via uds.project.yaml
@@ -478,7 +484,7 @@
478
484
  | `deployment-standards` | 1.1.0 | This standard defines guidelines for safely deploying software to production, co |
479
485
  | `deprecation-standards` | 1.1.0 | |
480
486
  | `design-document-standards` | 1.0.0 | |
481
- | `developer-memory` | 1.1.1 | This standard defines a structured system for capturing, retrieving, and surfaci |
487
+ | `developer-memory` | 1.2.0 | This standard defines a structured system for capturing, retrieving, and surfaci |
482
488
  | `disaster-recovery-drill` | - | |
483
489
  | `documentation-lifecycle` | 1.0.0 | This standard defines **when** to update documentation, **when** to check it, an |
484
490
  | `documentation-structure` | 1.5.0 | This standard defines a consistent documentation structure for software projects |
@@ -516,7 +522,7 @@
516
522
  | `mutation-testing` | 1.1.0 | Mutation testing evaluates test suite effectiveness by injecting artificial bugs |
517
523
  | `no-cicd-deployment` | - | |
518
524
  | `observability-standards` | 1.0.0 | |
519
- | `open-work-tracking` | 1.0.0 | The deferred-item-exit standard requires that a deferred item leave its document |
525
+ | `open-work-tracking` | 1.1.0 | The deferred-item-exit standard requires that a deferred item leave its document |
520
526
  | `packaging-standards` | 1.1.0 | This standard defines a Recipe-based packaging framework that enables user proje |
521
527
  | `performance-standards` | 1.2.0 | This standard defines comprehensive guidelines for software performance engineer |
522
528
  | `pii-classification` | 1.1.0 | **Status**: Active | **Updated**: 2026-06-19 | |
@@ -574,7 +580,7 @@
574
580
  | `timeout-standards` | - | |
575
581
  | `token-budget` | - | |
576
582
  | `translation-lifecycle-standards` | 1.0.1 | Translation lifecycle standards: MISSING vs OUTDATED distinction, semver-aware s |
577
- | `turn-completion-integrity` | 1.3.0 | An agent writes *"I'll do X next"* and then ends the turn without doing X. |
583
+ | `turn-completion-integrity` | 1.5.0 | An agent writes *"I'll do X next"* and then ends the turn without doing X. |
578
584
  | `user-journey-testing` | - | |
579
585
  | `user-story-mapping` | 1.0.0 | **Status**: Active | **Updated**: 2026-06-17 | |
580
586
  | `verification-evidence` | 1.3.0 | Establish an "Iron Law" that no task can be claimed as complete without verifica |
@@ -610,8 +616,11 @@
610
616
  | `check-docs-sync.sh` | Documentation Sync Checker |
611
617
  | `check-error-exit.mjs` | 🔴 沒填就是沒設定,而沒設定會 exit 2, |
612
618
  | `check-external-references.mjs` | External Reference Checker (SPEC-SELFDIAG-001 REQ-5, AC-7) |
619
+ | `check-home-untouched.mjs` | check-home-untouched — did this run write anywhere UDS writes under HOME? |
620
+ | `check-open-work-tracking.mjs` | Open-work-tracking reference checks for OWT-017 / OWT-018 / OWT-019 — repo entry point. |
613
621
  | `check-orphan-specs.ps1` | Check Orphan Specs |
614
622
  | `check-orphan-specs.sh` | Orphan Spec Detection Script |
623
+ | `check-prompt-footprint.mjs` | Prompt Footprint Ratchet — DEC-117 D2/L2 |
615
624
  | `check-scope-sync.ps1` | Check Scope Sync |
616
625
  | `check-scope-sync.sh` | Scope Consistency Check Script |
617
626
  | `check-skill-next-steps-sync.ps1` | Check Skill Next Steps Sync |
@@ -625,6 +634,7 @@
625
634
  | `check-translation-hash-ratchet.sh` | XSPEC-392 R6 棘輪:新的翻譯必須帶 source_hash,既有的欠債冷凍為基線。 |
626
635
  | `check-translation-sync.ps1` | Check Translation Sync |
627
636
  | `check-translation-sync.sh` | Translation Sync Checker |
637
+ | `check-upgrade-fidelity.sh` | Upgrade Fidelity Checker |
628
638
  | `check-usage-docs-sync.ps1` | Check if usage documentation needs to be regenerated |
629
639
  | `check-usage-docs-sync.sh` | check-usage-docs-sync.sh |
630
640
  | `check-version-sync.ps1` | Check Version Sync |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-dev-standards",
3
- "version": "6.13.1",
3
+ "version": "6.14.0-beta.2",
4
4
  "description": "CLI tool for adopting Universal Development Standards",
5
5
  "keywords": [
6
6
  "documentation",
@@ -52,6 +52,8 @@ export async function initCommand(options) {
52
52
  if (isInitialized(projectPath)) {
53
53
  console.log(chalk.yellow(msg.alreadyInitialized));
54
54
  console.log(chalk.gray(` ${msg.useUpdateOrDelete}`));
55
+ // `init` cannot run twice, so `--with-hooks` has no effect here; say where the door is.
56
+ if (options.withHooks) console.log(chalk.yellow(` ${msg.useUpdateWithHooks}`));
55
57
  return;
56
58
  }
57
59
 
@@ -281,8 +283,8 @@ export async function initCommand(options) {
281
283
  }
282
284
  }
283
285
 
284
- // turn-completion-integrity is also extended to Codex and Gemini CLI
285
- // (2026-09-25), each with its own config file and output contract — see
286
+ // turn-completion-integrity is also extended to Codex, Gemini CLI and
287
+ // Antigravity CLI (2026-09-25; agy 2026-09-29), each with its own config file and output contract — see
286
288
  // installCodexHooks/installGeminiHooks in hooks-installer.js. Gated on the
287
289
  // tools the adopter actually selected: writing a hooks.json into every
288
290
  // project's .codex/ regardless of whether Codex is used would be noise,
@@ -311,6 +313,19 @@ export async function initCommand(options) {
311
313
  console.log(chalk.yellow(` ⚠ Gemini CLI hook not installed — ${geminiResult.reason}`));
312
314
  }
313
315
  }
316
+ if (selectedTools.includes('antigravity')) {
317
+ const { installAgyHooks } = await import('../installers/hooks-installer.js');
318
+ const agyResult = installAgyHooks(projectPath);
319
+ if (agyResult.installed) {
320
+ console.log(chalk.green(' ✓ Antigravity CLI Stop hook installed (turn-completion-integrity; .agents/hooks.json)'));
321
+ // Verified 2026-09-29 (agy 1.2.12): single turn, no tool calls, `agy -p`.
322
+ // Multi-turn, tool-call turns and interactive mode are not verified —
323
+ // say so here, where the adopter believes it now works everywhere.
324
+ console.log(chalk.yellow(' ⚠ Verified against a real agy session for a single turn without tool calls in `agy -p` mode only; multi-turn, tool-call turns and interactive mode are not yet verified.'));
325
+ } else {
326
+ console.log(chalk.yellow(` ⚠ Antigravity CLI hook not installed — ${agyResult.reason}`));
327
+ }
328
+ }
314
329
  }
315
330
 
316
331
  // 5. Setup Pre-commit Hook
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `uds open-work` — the open-work-tracking reference checks (OWT-017 / 018 / 019)
3
+ * as a command, so an adopter can run them from the npm package.
4
+ *
5
+ * This file holds no rules. The one body of them is
6
+ * `../utils/open-work-tracking.mjs`; this only turns commander's parsed
7
+ * arguments back into the argv that module's `main()` reads, so the command and
8
+ * `node scripts/check-open-work-tracking.mjs` cannot disagree.
9
+ *
10
+ * Exit codes are the module's and are not translated: 0 no violation, 1
11
+ * violation, 2 cannot decide (no structure found, git failed, or the checker's
12
+ * own self-test arms failed). 2 is NOT a pass. `process.exitCode` is set rather
13
+ * than calling `process.exit()`, so commander's post-action hook still runs.
14
+ *
15
+ * It is a reference decision procedure offered as evidence (OWT-015), not a
16
+ * gate, and its coverage is unknown and uncalibrated (OWT-011, OWT-016); the
17
+ * module prints both statements on every run.
18
+ *
19
+ * @module commands/open-work
20
+ */
21
+
22
+ import { main } from '../utils/open-work-tracking.mjs';
23
+
24
+ /** Append `--name value` when the option was given. */
25
+ function withOption(argv, name, value) {
26
+ if (value !== undefined && value !== null) argv.push(name, String(value));
27
+ return argv;
28
+ }
29
+
30
+ function run(argv) {
31
+ process.exitCode = main(argv);
32
+ }
33
+
34
+ /** uds open-work next-action [files...] [--root DIR] [--id-pattern RE] — OWT-019 */
35
+ export function openWorkNextActionCommand(files = [], options = {}) {
36
+ const argv = ['next-action'];
37
+ withOption(argv, '--root', options.root);
38
+ withOption(argv, '--id-pattern', options.idPattern);
39
+ run([...argv, ...files]);
40
+ }
41
+
42
+ /** uds open-work revision (--file PATH --base REV | --before FILE --after FILE) — OWT-018 */
43
+ export function openWorkRevisionCommand(options = {}) {
44
+ const argv = ['revision'];
45
+ withOption(argv, '--file', options.file);
46
+ withOption(argv, '--base', options.base);
47
+ withOption(argv, '--before', options.before);
48
+ withOption(argv, '--after', options.after);
49
+ run(argv);
50
+ }
51
+
52
+ /** uds open-work separation [files...] — OWT-017 */
53
+ export function openWorkSeparationCommand(files = []) {
54
+ run(['separation', ...files]);
55
+ }
56
+
57
+ /** uds open-work self-test — run the checker's own arms and nothing else */
58
+ export function openWorkSelfTestCommand() {
59
+ run(['--self-test']);
60
+ }
@@ -56,7 +56,7 @@ export async function uninstallCommand(options) {
56
56
  const categories = await checkbox({
57
57
  message: msg.selectCategories,
58
58
  choices: [
59
- { name: `${msg.categoryHooks} (.husky/pre-commit, .claude/settings.json, .codex/hooks.json, .gemini/settings.json)`, value: 'hooks', checked: true },
59
+ { name: `${msg.categoryHooks} (.husky/pre-commit, .claude/settings.json, .codex/hooks.json, .gemini/settings.json, .agents/hooks.json)`, value: 'hooks', checked: true },
60
60
  { name: `${msg.categorySkills} (skills, commands)`, value: 'skills', checked: true },
61
61
  { name: `${msg.categoryIntegrations} (CLAUDE.md, .cursorrules, ...)`, value: 'integrations', checked: true },
62
62
  { name: `${msg.categoryStandards} (.standards/)`, value: 'standards', checked: true }
@@ -46,6 +46,7 @@ import {
46
46
  } from '../config/ai-agent-paths.js';
47
47
  import { getMarketplaceSkillsInfo } from '../utils/github.js';
48
48
  import { detectAITools } from '../utils/detector.js';
49
+ import { HOOK_CAPABLE_TOOLS, resolveHookTools, installMissingHooks } from '../installers/hooks-installer.js';
49
50
  import {
50
51
  promptSkillsInstallLocation,
51
52
  promptCommandsInstallation
@@ -451,6 +452,15 @@ export async function updateCommand(options) {
451
452
  return;
452
453
  }
453
454
 
455
+ // Handle --with-hooks (added 2026-09-29): install the enforcement hooks that are
456
+ // MISSING from an already-initialized project — the door `uds init --with-hooks`
457
+ // cannot be, because `uds init` refuses to run twice. Standalone like
458
+ // --claude-target and --sync-refs; and like them it honours --plan by writing nothing.
459
+ if (options.withHooks) {
460
+ await updateHooksOnly(projectPath, manifest, options);
461
+ return;
462
+ }
463
+
454
464
  // Handle --sync-refs option.
455
465
  // `--plan` is honoured here too. This branch is above the mode dispatch
456
466
  // because sync-refs is its own operation rather than a scope of the
@@ -1827,6 +1837,87 @@ async function switchClaudeTarget(projectPath, manifest, target, options) { // e
1827
1837
  * @param {Object} manifest - Manifest object (will be mutated with updated hashes)
1828
1838
  * @returns {{success: boolean, updated: string[], errors: string[]}}
1829
1839
  */
1840
+ /**
1841
+ * `uds update --with-hooks [--ai-tool <list>] [--plan] [--force]`
1842
+ *
1843
+ * Adds the enforcement hooks that are missing; a hook that is already there is not
1844
+ * touched, and the adopter's own hooks are never touched (see installMissingHooks).
1845
+ * Exit code 1 only when there is no hook-capable tool to act on, or an install failed:
1846
+ * "nothing to do" is 0, "could not tell which tool" is not.
1847
+ *
1848
+ * @param {string} projectPath
1849
+ * @param {object} manifest
1850
+ * @param {{ plan?: boolean, force?: boolean, aiTool?: string, yes?: boolean }} options
1851
+ * @returns {Promise<void>}
1852
+ */
1853
+ export async function updateHooksOnly(projectPath, manifest, options = {}) {
1854
+ const ignored = ['skills', 'commands', 'syncRefs', 'integrationsOnly', 'standardsOnly', 'apply', 'rollback', 'prune']
1855
+ .filter((k) => options[k]).map((k) => `--${k.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase())}`);
1856
+ if (ignored.length) {
1857
+ console.log(chalk.yellow(` ! --with-hooks does one thing and does not compose; ${ignored.join(', ')} ignored.`));
1858
+ console.log();
1859
+ }
1860
+
1861
+ const capable = HOOK_CAPABLE_TOOLS.join(', ');
1862
+ const resolved = resolveHookTools(projectPath, manifest, { aiTool: options.aiTool });
1863
+
1864
+ if (resolved.unknown.length) {
1865
+ console.log(chalk.red(` ✗ No hook installer for: ${resolved.unknown.join(', ')}`));
1866
+ console.log(chalk.gray(` Tools with hooks: ${capable}`));
1867
+ console.log();
1868
+ process.exitCode = 1;
1869
+ return;
1870
+ }
1871
+ if (resolved.tools.length === 0) {
1872
+ // Both non-interactive and interactive get the same message: there is no prompt to
1873
+ // fall back to here, so the way to say which tool is spelled out instead.
1874
+ console.log(chalk.yellow(' ⚠ Could not tell which AI tool to install hooks for.'));
1875
+ console.log(chalk.gray(' Neither this project\'s manifest nor its files name one of: ' + capable + '.'));
1876
+ console.log(chalk.gray(' Say which one: uds update --with-hooks --ai-tool <tool>[,<tool>...]'));
1877
+ console.log(chalk.gray(' e.g. uds update --with-hooks --ai-tool antigravity'));
1878
+ console.log(chalk.gray(' What is detected: claude-code (.claude/ or CLAUDE.md) · codex (root AGENTS.md) · gemini-cli (GEMINI.md)'));
1879
+ console.log(chalk.gray(' antigravity (.agents/AGENTS.md, .agents/rules/, .agents/workflows/, .agents/plugins/ or .agents/hooks.json; .agents/skills/ is shared with Codex and does not count)'));
1880
+ console.log();
1881
+ process.exitCode = 1;
1882
+ return;
1883
+ }
1884
+
1885
+ console.log(chalk.bold(options.plan ? 'Hooks — plan (nothing is written)' : 'Hooks'));
1886
+ for (const tool of resolved.tools) {
1887
+ console.log(chalk.gray(` ${tool}: ${resolved.sources[tool].join(', ')}`));
1888
+ }
1889
+
1890
+ const { results, scripts } = installMissingHooks(projectPath, resolved.tools, {
1891
+ plan: !!options.plan,
1892
+ overwriteScripts: !!options.force,
1893
+ });
1894
+
1895
+ let failed = false;
1896
+ for (const r of results) {
1897
+ const rel = r.path ? relative(projectPath, r.path) || r.path : '';
1898
+ if (r.outcome === 'installed') console.log(chalk.green(` ✓ ${r.tool}: installed${r.repaired ? ' (replaced an out-of-date UDS entry)' : ''} — ${rel}`));
1899
+ else if (r.outcome === 'would-install') console.log(chalk.cyan(` + ${r.tool}: would install${r.repaired ? ' (replacing an out-of-date UDS entry)' : ''} — ${rel}`));
1900
+ else if (r.outcome === 'unchanged') console.log(chalk.gray(` · ${r.tool}: already installed, not touched — ${rel}`));
1901
+ else { failed = true; console.log(chalk.yellow(` ⚠ ${r.tool}: not installed — ${r.why}`)); }
1902
+ }
1903
+ const installedAny = results.some((r) => r.outcome === 'installed' || r.outcome === 'would-install');
1904
+ if (installedAny && scripts.kept.length) {
1905
+ console.log(chalk.yellow(` ! ${scripts.kept.length} hook script(s) in scripts/hooks/ differ from this UDS version and were kept: ${scripts.kept.slice(0, 5).join(', ')}${scripts.kept.length > 5 ? ', ...' : ''}`));
1906
+ console.log(chalk.gray(' Add --force to overwrite them with the shipped versions.'));
1907
+ }
1908
+ if (results.some((r) => r.tool === 'antigravity' && r.outcome === 'installed')) {
1909
+ console.log(chalk.yellow(' ⚠ Verified against a real agy session for a single turn without tool calls in `agy -p` mode only; multi-turn, tool-call turns and interactive mode are not yet verified.'));
1910
+ }
1911
+ if (results.some((r) => r.tool === 'codex' && r.outcome === 'installed')) {
1912
+ console.log(chalk.yellow(' ⚠ Codex will not run it until you trust it: open Codex in this project, trust the project, then run /hooks and trust this hook.'));
1913
+ }
1914
+ if (!results.some((r) => r.outcome === 'installed' || r.outcome === 'would-install')) {
1915
+ console.log(chalk.gray(' Nothing to add.'));
1916
+ }
1917
+ console.log();
1918
+ if (failed) process.exitCode = 1;
1919
+ }
1920
+
1830
1921
  export function regenerateIntegrations(projectPath, manifest) {
1831
1922
  const aiTools = manifest.aiTools || [];
1832
1923
 
@@ -930,6 +930,7 @@ export const messages = {
930
930
  title: 'Universal Development Standards - Initialize',
931
931
  alreadyInitialized: '⚠ Standards already initialized in this project.',
932
932
  useUpdateOrDelete: 'Use `uds update` to update, or delete .standards/ to reinitialize.',
933
+ useUpdateWithHooks: 'To add enforcement hooks to this project (including for tools UDS began supporting after you initialized), run `uds update --with-hooks`.',
933
934
  // Detection
934
935
  detectingProject: 'Detecting project characteristics...',
935
936
  analysisComplete: 'Project analysis complete',
@@ -2188,6 +2189,7 @@ export const messages = {
2188
2189
  title: '通用開發標準 - 初始化',
2189
2190
  alreadyInitialized: '⚠ 此專案已初始化標準。',
2190
2191
  useUpdateOrDelete: '使用 `uds update` 更新,或刪除 .standards/ 重新初始化。',
2192
+ useUpdateWithHooks: '要為這個專案補裝執行關卡(含 UDS 在你初始化之後才支援的工具),請執行 `uds update --with-hooks`。',
2191
2193
  // Detection
2192
2194
  detectingProject: '正在偵測專案特性...',
2193
2195
  analysisComplete: '專案分析完成',
@@ -3158,6 +3160,7 @@ export const messages = {
3158
3160
  title: '通用开发标准 - 初始化',
3159
3161
  alreadyInitialized: '⚠ 此项目已初始化标准。',
3160
3162
  useUpdateOrDelete: '使用 `uds update` 更新,或删除 .standards/ 重新初始化。',
3163
+ useUpdateWithHooks: '要为这个项目补装执行关卡(含 UDS 在你初始化之后才支持的工具),请执行 `uds update --with-hooks`。',
3161
3164
  // Detection
3162
3165
  detectingProject: '正在检测项目特性...',
3163
3166
  analysisComplete: '项目分析完成',