@fenglimg/fabric-shared 2.0.0-rc.34 → 2.0.0-rc.36

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.
@@ -1,6 +1,6 @@
1
1
  // src/i18n/locales/en.ts
2
2
  var enMessages = {
3
- "cli.main.description": "Fabric CLI - AI agent collaboration framework.\n\nThree-step mental model:\n Install (\u88C5) - fab install one-shot project setup\n Configure (\u914D) - fab config interactive configuration panel\n Run (\u8DD1) - fab serve launch the local MCP HTTP service\n fab doctor run target-state diagnostics\n\nExamples:\n fab install install Fabric in the current project\n fab config open the interactive configuration panel\n fab serve --port 7373 start the MCP HTTP service\n fab doctor --fix repair derived Fabric state\n fab uninstall --dry-run preview uninstall without removing files",
3
+ "cli.main.description": "Fabric CLI - AI agent collaboration framework.\n\nThree-step mental model:\n Install (\u88C5) - fabric install one-shot project setup\n Configure (\u914D) - fabric config interactive configuration panel\n Run (\u8DD1) - fabric serve launch the local MCP HTTP service\n fabric doctor run target-state diagnostics\n\nExamples:\n fabric install install Fabric in the current project\n fabric config open the interactive configuration panel\n fabric serve --port 7373 start the MCP HTTP service\n fabric doctor --fix repair derived Fabric state\n fabric uninstall --dry-run preview uninstall without removing files",
4
4
  "cli.shared.created": "Created",
5
5
  "cli.shared.skipped": "Skipped",
6
6
  "cli.shared.next": "Next",
@@ -38,7 +38,7 @@ var enMessages = {
38
38
  "cli.bootstrap.install.skipped-header": "Skipped {path}: Fabric Bootstrap header already present.",
39
39
  "cli.bootstrap.install.prepended": "Prepended {path}",
40
40
  "cli.bootstrap.errors.unknown-client": 'Unknown client "{client}". Use a comma-separated list such as claude,cursor,codex.',
41
- "cli.config.description": "Open the interactive Fabric configuration panel (language, knowledge layer, audit mode, hint windows, MCP client wiring, etc.).\n\nExamples:\n fab config open the interactive panel\n fab config --target /path edit configuration for a specific project",
41
+ "cli.config.description": "Open the interactive Fabric configuration panel (language, knowledge layer, audit mode, hint windows, MCP client wiring, etc.).\n\nExamples:\n fabric config open the interactive panel\n fabric config --target /path edit configuration for a specific project",
42
42
  "cli.config.args.target.description": "Target project directory (defaults to cwd).",
43
43
  "cli.config.clients.claude": "Claude Code CLI",
44
44
  "cli.config.install.description": "Install Fabric MCP server entries into detected client configs.",
@@ -50,14 +50,14 @@ var enMessages = {
50
50
  "cli.config.install.no-config-path": "Skipping {client}: no config path detected.",
51
51
  "cli.config.install.dry-run": "[dry-run] {client}: would write {path}",
52
52
  "cli.config.install.wrote": "{client}: wrote {path}",
53
- // rc.16 TASK-006 (F1-panel): clack-driven `fab config` interactive panel.
53
+ // rc.16 TASK-006 (F1-panel): clack-driven `fabric config` interactive panel.
54
54
  // Keys consumed by packages/cli/src/commands/config.ts (menu loop +
55
55
  // per-field prompts) and by getPanelFields() (label_i18n_key references).
56
56
  "cli.config.intro": "Fabric Configuration",
57
57
  "cli.config.outro": "Configuration saved.",
58
58
  "cli.config.outro-no-changes": "No changes made.",
59
59
  "cli.config.cancel": "Cancelled.",
60
- "cli.config.non-tty-notice": "fab config requires an interactive terminal. Run it from a TTY to edit configuration fields.",
60
+ "cli.config.non-tty-notice": "fabric config requires an interactive terminal. Run it from a TTY to edit configuration fields.",
61
61
  "cli.config.menu.field-select": "Select a field to edit:",
62
62
  "cli.config.menu.exit": "Exit",
63
63
  "cli.config.value.current": "current: {value}",
@@ -66,7 +66,7 @@ var enMessages = {
66
66
  "cli.config.prompt.text": "Enter a new value for {key} (current: {current}):",
67
67
  "cli.config.write.success": "Saved {key} = {value}",
68
68
  "cli.config.write.failure": "Failed to write fabric-config.json: {message}",
69
- "cli.config.errors.uninit-workspace.message": "Workspace not initialized. Run `fab install` first.",
69
+ "cli.config.errors.uninit-workspace.message": "Workspace not initialized. Run `fabric install` first.",
70
70
  "cli.config.errors.invalid-int": "Must be a positive integer.",
71
71
  "cli.config.errors.unknown-field": "Unknown field selection \u2014 skipping.",
72
72
  "cli.config.errors.no-enum-options": "No enum options available for this field \u2014 skipping.",
@@ -93,14 +93,14 @@ var enMessages = {
93
93
  "cli.config.fields.maintenance_hint_cooldown_days.description": "Cooldown (in days) before the maintenance hint can fire again.",
94
94
  "cli.config.fields.audit_mode.label": "Audit mode",
95
95
  "cli.config.fields.audit_mode.description": "Audit verbosity for human-lock + drift detection (strict / warn / off).",
96
- "cli.doctor.description": "Run Fabric target-state diagnostics (meta sync, knowledge index, bootstrap, events ledger, human-lock drift).\n\nExamples:\n fab doctor read-only diagnostics report\n fab doctor --fix repair derived state (meta + indexes)\n fab doctor --fix-knowledge apply lint mutations (demote / archive)\n fab doctor --json --strict machine-readable output, warnings as errors",
96
+ "cli.doctor.description": "Run Fabric target-state diagnostics (meta sync, knowledge index, bootstrap, events ledger, human-lock drift).\n\nExamples:\n fabric doctor read-only diagnostics report\n fabric doctor --fix repair derived state (meta + indexes)\n fabric doctor --fix-knowledge apply lint mutations (demote / archive)\n fabric doctor --json --strict machine-readable output, warnings as errors",
97
97
  "doctor.section.fixable": "Fixable errors:",
98
98
  "doctor.section.manual": "Manual errors:",
99
99
  "doctor.section.warnings": "Warnings:",
100
100
  "doctor.section.fix-knowledge-mutations": "Fix-knowledge mutations:",
101
101
  // v2.0.0-rc.29 REVIEW (codex LOW-2): F2's payload-limit defaults reach the JSON
102
102
  // envelope but never surfaced in the human renderer, so operators tuning
103
- // `mcpPayloadLimits` had no fast `fab doctor` confirmation that their config
103
+ // `mcpPayloadLimits` had no fast `fabric doctor` confirmation that their config
104
104
  // override took effect. Two strings: a section header + a one-liner row.
105
105
  "doctor.section.payload-limits": "MCP payload limits:",
106
106
  "doctor.payload-limits.line": "warn={warnKb} KB, hard={hardKb} KB (source: {source})",
@@ -137,7 +137,7 @@ var enMessages = {
137
137
  "cite-coverage.contract.cite_id_unresolved": "Unresolved cite IDs",
138
138
  "cite-coverage.contract.skip_count": "Skip bucket",
139
139
  "cite-coverage.contract.status.ok": "ok",
140
- "cite-coverage.contract.status.skipped_bootstrap_drift": "skipped (bootstrap drift \u2014 run `fab install`)",
140
+ "cite-coverage.contract.status.skipped_bootstrap_drift": "skipped (bootstrap drift \u2014 run `fabric install`)",
141
141
  "cite-coverage.contract.status.awaiting_marker": "awaiting first marker emit",
142
142
  // Plural knowledge-type labels (rc.29 BUG-C1: verbatim alignment with
143
143
  // canonical KnowledgeTypeSchema) plus the sixth "unresolved" bucket.
@@ -166,6 +166,9 @@ var enMessages = {
166
166
  "cli.doctor.args.strict.description": "Treat warnings as failures.",
167
167
  "cli.doctor.args.fix-knowledge.description": "Apply knowledge lint mutations: demote orphaned canonical entries, archive stale drafts, and bump drifted index counters. Default doctor run remains report-only.",
168
168
  "cli.doctor.args.yes.description": "Skip the --fix-knowledge safety confirm. Required for non-tty invocations unless FABRIC_NONINTERACTIVE=1 is set in the environment.",
169
+ // rc.35 TASK-12 (P0-11): --verbose unfolds maintainer-audience hints.
170
+ "cli.doctor.args.verbose.description": "Show all action hints including maintainer-audience ones (Fabric contributors editing the source tree). By default these are folded for npm end users.",
171
+ "doctor.maintainer-hint-folded": "(maintainer-only remediation \u2014 re-run with `fabric doctor --verbose` to see)",
169
172
  "cli.doctor.errors.fix-knowledge-fix-mutually-exclusive": "--fix-knowledge and --fix cannot be combined. --fix-knowledge mutates user knowledge state (demote/archive); --fix repairs derived state (meta/index). Run them separately.",
170
173
  // rc.20 TASK-05: --cite-coverage report flags. Read-only; mutually exclusive with --fix/--fix-knowledge.
171
174
  "cli.doctor.args.cite-coverage.description": "Generate cite policy adherence report (read-only; skips standard inspections)",
@@ -183,7 +186,7 @@ var enMessages = {
183
186
  "cli.doctor.args.auto.description": "With --enrich-descriptions: write deterministic stub values for missing fields. Without --auto, the run is read-only.",
184
187
  "cli.doctor.args.dry-run.description": "With --enrich-descriptions --auto or --fix: preview the planned changes without writing to disk. The fix-dry-run output mirrors --fix's fixable_errors list but executes no mutations.",
185
188
  // v2.0.0-rc.33 W4-B1 (T6 P2): --fix --dry-run banner — printed before the standard report so users see no mutations were applied.
186
- "cli.doctor.fix-dry-run-banner": "[dry-run] No mutations were applied. The fixable_errors list below shows what `fab doctor --fix` would address; rerun without --dry-run to actually fix.",
189
+ "cli.doctor.fix-dry-run-banner": "[dry-run] No mutations were applied. The fixable_errors list below shows what `fabric doctor --fix` would address; rerun without --dry-run to actually fix.",
187
190
  "cli.doctor.errors.enrich-descriptions-mutex": "--enrich-descriptions cannot be combined with --fix, --fix-knowledge, or --cite-coverage. Run them separately.",
188
191
  "doctor.enrich.allComplete": "All canonical knowledge entries already declare intent_clues / tech_stack / impact / must_read_if.",
189
192
  // rc.26 TASK-02a: doctor foundation-batch check messages.
@@ -191,21 +194,21 @@ var enMessages = {
191
194
  "doctor.check.bootstrap_marker_migration.ok": "No legacy fabric:knowledge-base markers detected in bootstrap target files.",
192
195
  "doctor.check.bootstrap_marker_migration.message.singular": "{count} file still carry the legacy fabric:knowledge-base bootstrap marker: {list}.",
193
196
  "doctor.check.bootstrap_marker_migration.message.plural": "{count} files still carry the legacy fabric:knowledge-base bootstrap marker: {list}.",
194
- "doctor.check.bootstrap_marker_migration.remediation": "Run `fab doctor --fix` to migrate to fabric:bootstrap marker",
197
+ "doctor.check.bootstrap_marker_migration.remediation": "Run `fabric doctor --fix` to migrate to fabric:bootstrap marker",
195
198
  "doctor.check.bootstrap_snapshot_drift.name": "Bootstrap snapshot drift",
196
199
  "doctor.check.bootstrap_snapshot_drift.message.drift": ".fabric/AGENTS.md content diverges byte-for-byte from BOOTSTRAP_CANONICAL.",
197
- "doctor.check.bootstrap_snapshot_drift.remediation.drift": "Run `fab doctor --fix` to restore canonical bootstrap snapshot",
200
+ "doctor.check.bootstrap_snapshot_drift.remediation.drift": "Run `fabric doctor --fix` to restore canonical bootstrap snapshot",
198
201
  "doctor.check.bootstrap_snapshot_drift.ok.ok": ".fabric/AGENTS.md byte-equals BOOTSTRAP_CANONICAL.",
199
202
  "doctor.check.bootstrap_snapshot_drift.ok.missing_delegated": ".fabric/AGENTS.md absent \u2014 delegated to bootstrap_anchor_missing.",
200
203
  "doctor.check.managed_block_drift.name": "Managed block drift",
201
204
  "doctor.check.managed_block_drift.message.singular": "{count} three-end managed block diverge from expected body (snapshot + optional project-rules concat): {list}.",
202
205
  "doctor.check.managed_block_drift.message.plural": "{count} three-end managed blocks diverge from expected body (snapshot + optional project-rules concat): {list}.",
203
- "doctor.check.managed_block_drift.remediation": "Run `fab doctor --fix` to restore three-end managed blocks from canonical",
206
+ "doctor.check.managed_block_drift.remediation": "Run `fabric doctor --fix` to restore three-end managed blocks from canonical",
204
207
  "doctor.check.managed_block_drift.ok.ok": "Three-end managed blocks byte-equal expectedBody.",
205
208
  "doctor.check.managed_block_drift.ok.no_managed_block": "No three-end managed blocks detected \u2014 propagation pending or legacy-marker state.",
206
209
  "doctor.check.bootstrap_anchor.name": "Bootstrap anchor",
207
210
  "doctor.check.bootstrap_anchor.message.missing": "Neither AGENTS.md nor CLAUDE.md exists at the repo root. Fabric requires a bootstrap anchor file at the project root.",
208
- "doctor.check.bootstrap_anchor.remediation.missing": "Run `fab install` to generate the AGENTS.md / CLAUDE.md bootstrap anchor at the repo root.",
211
+ "doctor.check.bootstrap_anchor.remediation.missing": "Run `fabric install` to generate the AGENTS.md / CLAUDE.md bootstrap anchor at the repo root.",
209
212
  "doctor.check.bootstrap_anchor.ok": "Bootstrap anchor present at repo root: {present}.",
210
213
  "doctor.check.baseline_filename_format.name": "Baseline filename format",
211
214
  "doctor.check.baseline_filename_format.ok": "All baseline knowledge files use the canonical `${id}--${slug}.md` filename format.",
@@ -216,60 +219,64 @@ var enMessages = {
216
219
  "doctor.check.knowledge_dir_missing.name": "Knowledge layout",
217
220
  "doctor.check.knowledge_dir_missing.message.singular": "{count} required knowledge subdir is missing: {list}.",
218
221
  "doctor.check.knowledge_dir_missing.message.plural": "{count} required knowledge subdirs are missing: {list}.",
219
- "doctor.check.knowledge_dir_missing.remediation": "Run `fab doctor --fix` to create the missing .fabric/knowledge/* subdirectories.",
222
+ "doctor.check.knowledge_dir_missing.remediation": "Run `fabric doctor --fix` to create the missing .fabric/knowledge/* subdirectories.",
220
223
  "doctor.check.knowledge_dir_missing.ok": "All {count} required .fabric/knowledge/* subdirectories exist.",
221
224
  "doctor.check.forensic.name": "Scan evidence",
222
225
  "doctor.check.forensic.message.missing.singular": "{error} Live scan detects {frameworkKind} with {count} entry point.",
223
226
  "doctor.check.forensic.message.missing.plural": "{error} Live scan detects {frameworkKind} with {count} entry points.",
224
227
  "doctor.check.forensic.message.missing-default": ".fabric/forensic.json is missing.",
225
228
  "doctor.check.forensic.message.invalid-default": ".fabric/forensic.json is invalid.",
226
- "doctor.check.forensic.remediation": "Run `fab install` to regenerate .fabric/forensic.json.",
229
+ "doctor.check.forensic.remediation": "Run `fabric install` to regenerate .fabric/forensic.json.",
227
230
  "doctor.check.forensic.ok": ".fabric/forensic.json is valid for {frameworkKind}.",
228
231
  "doctor.check.agents_meta.name": "Agents metadata",
229
232
  "doctor.check.agents_meta.message.missing": ".fabric/agents.meta.json is missing.",
230
- "doctor.check.agents_meta.remediation.missing": "Run `fab doctor --fix` to rebuild agents.meta.json from .fabric/knowledge/.",
233
+ "doctor.check.agents_meta.remediation.missing": "Run `fabric doctor --fix` to rebuild agents.meta.json from .fabric/knowledge/.",
231
234
  "doctor.check.agents_meta.message.invalid-default": ".fabric/agents.meta.json is invalid.",
232
- "doctor.check.agents_meta.remediation.invalid": "Run `fab doctor --fix` to let reconcile rebuild agents.meta.json from the .fabric/knowledge/ disk ground-truth (rc.31+ auto-migrates legacy singular knowledge_type values to canonical plural; do NOT manually delete agents.meta.json \u2014 you would lose counters envelope and promote-ledger associations).",
235
+ // rc.35 TASK-09 (P0-14): humanised parse-failure messages.
236
+ "doctor.check.agents_meta.message.invalid-zod": ".fabric/agents.meta.json fails schema validation \u2014 {issues}. The file was likely written by an incompatible fabric CLI version, or hand-edited.",
237
+ "doctor.check.agents_meta.message.invalid-from-old-cli": ".fabric/agents.meta.json fails schema validation because the GLOBAL `fabric` CLI on PATH ({version}) is older than the minimum-supported {minVersion}. The schema gained backward-compatible singular\u2192plural normalisation in rc.31; older CLIs cannot parse the result they themselves write back.",
238
+ "doctor.check.agents_meta.remediation.invalid": "Run `fabric doctor --fix` to let reconcile rebuild agents.meta.json from the .fabric/knowledge/ disk ground-truth (rc.31+ auto-migrates legacy singular knowledge_type values to canonical plural; do NOT manually delete agents.meta.json \u2014 you would lose counters envelope and promote-ledger associations).",
233
239
  "doctor.check.agents_meta.message.stale": ".fabric/agents.meta.json revision {revision} does not match .fabric/knowledge derived revision {computedRevision}.",
234
- "doctor.check.agents_meta.remediation.stale": "Benign \u2014 engine auto-heals on next plan-context/get-sections call. Run `fab doctor --fix` for explicit reconciliation.",
240
+ "doctor.check.agents_meta.message.stale_hash_equal": ".fabric/agents.meta.json content is aligned with .fabric/knowledge (revision {revision}) but the mtime/counters derived state is out of date. Benign.",
241
+ "doctor.check.agents_meta.remediation.stale": "Benign \u2014 engine auto-heals on next plan-context/get-sections call. Run `fabric doctor --fix` for explicit reconciliation.",
235
242
  "doctor.check.agents_meta.ok": ".fabric/agents.meta.json revision {revision} is aligned with .fabric/knowledge.",
236
243
  "doctor.check.rule_content_refs.name": "Rule content refs",
237
244
  "doctor.check.rule_content_refs.message.unavailable": "Cannot inspect content_ref entries until agents.meta.json is valid.",
238
- "doctor.check.rule_content_refs.remediation.unavailable": "Fix agents.meta.json first: run `fab doctor --fix`.",
245
+ "doctor.check.rule_content_refs.remediation.unavailable": "Fix agents.meta.json first: run `fabric doctor --fix`.",
239
246
  "doctor.check.rule_content_refs.message.outside.singular": "{count} content_ref entry is outside .fabric/knowledge.",
240
247
  "doctor.check.rule_content_refs.message.outside.plural": "{count} content_ref entries are outside .fabric/knowledge.",
241
248
  // v2.0.0-rc.33 W3-2 (T6 #12): project rules forbid hand-editing agents.meta.json (see .fabric/AGENTS.md). Direct users through doctor --fix reconcile path instead.
242
- "doctor.check.rule_content_refs.remediation.outside": "Run `fab doctor --fix` to let reconcile auto-prune external content_refs (rc.31+ compatible). Do NOT hand-edit agents.meta.json \u2014 the engine reconciles automatically.",
243
- "doctor.check.rule_content_refs.message.missing.singular": "{count} content_ref target is missing. Run `fab doctor --fix` to reconcile.",
244
- "doctor.check.rule_content_refs.message.missing.plural": "{count} content_ref targets are missing. Run `fab doctor --fix` to reconcile.",
245
- "doctor.check.rule_content_refs.remediation.missing": "Run `fab doctor --fix` to reconcile agents.meta.json with the files present in .fabric/knowledge/.",
249
+ "doctor.check.rule_content_refs.remediation.outside": "Run `fabric doctor --fix` to let reconcile auto-prune external content_refs (rc.31+ compatible). Do NOT hand-edit agents.meta.json \u2014 the engine reconciles automatically.",
250
+ "doctor.check.rule_content_refs.message.missing.singular": "{count} content_ref target is missing. Run `fabric doctor --fix` to reconcile.",
251
+ "doctor.check.rule_content_refs.message.missing.plural": "{count} content_ref targets are missing. Run `fabric doctor --fix` to reconcile.",
252
+ "doctor.check.rule_content_refs.remediation.missing": "Run `fabric doctor --fix` to reconcile agents.meta.json with the files present in .fabric/knowledge/.",
246
253
  "doctor.check.rule_content_refs.ok": "All content_ref entries resolve to .fabric/knowledge files.",
247
254
  "doctor.check.knowledge_test_index.name": "Knowledge-test index",
248
- "doctor.check.knowledge_test_index.remediation.missing": "Run `fab doctor --fix` to rebuild .fabric/.cache/knowledge-test.index.json.",
249
- "doctor.check.knowledge_test_index.remediation.invalid": "Delete .fabric/.cache/knowledge-test.index.json and run `fab doctor --fix` to regenerate it.",
255
+ "doctor.check.knowledge_test_index.remediation.missing": "Run `fabric doctor --fix` to rebuild .fabric/.cache/knowledge-test.index.json.",
256
+ "doctor.check.knowledge_test_index.remediation.invalid": "Delete .fabric/.cache/knowledge-test.index.json and run `fabric doctor --fix` to regenerate it.",
250
257
  "doctor.check.knowledge_test_index.message.stale": ".fabric/.cache/knowledge-test.index.json is stale.",
251
- "doctor.check.knowledge_test_index.remediation.stale": "Run `fab doctor --fix` to rebuild the knowledge-test index.",
258
+ "doctor.check.knowledge_test_index.remediation.stale": "Run `fabric doctor --fix` to rebuild the knowledge-test index.",
252
259
  "doctor.check.knowledge_test_index.ok.link_singular.orphan_singular": "{linkCount} link and {orphanCount} orphan annotation indexed.",
253
260
  "doctor.check.knowledge_test_index.ok.link_singular.orphan_plural": "{linkCount} link and {orphanCount} orphan annotations indexed.",
254
261
  "doctor.check.knowledge_test_index.ok.link_plural.orphan_singular": "{linkCount} links and {orphanCount} orphan annotation indexed.",
255
262
  "doctor.check.knowledge_test_index.ok.link_plural.orphan_plural": "{linkCount} links and {orphanCount} orphan annotations indexed.",
256
263
  "doctor.check.event_ledger.name": "Event ledger",
257
264
  "doctor.check.event_ledger.message.missing": ".fabric/events.jsonl is missing.",
258
- "doctor.check.event_ledger.remediation.missing": "Run `fab doctor --fix` to create .fabric/events.jsonl.",
265
+ "doctor.check.event_ledger.remediation.missing": "Run `fabric doctor --fix` to create .fabric/events.jsonl.",
259
266
  "doctor.check.event_ledger.message.not_writable-default": ".fabric/events.jsonl is not writable.",
260
267
  "doctor.check.event_ledger.remediation.not_writable": "Check file permissions on .fabric/events.jsonl and ensure no other process holds a write lock.",
261
268
  "doctor.check.event_ledger.message.invalid-default": ".fabric/events.jsonl is invalid.",
262
269
  // v2.0.0-rc.33 W3-1 (P0-6): archive-history mode — direct users to mv the broken ledger into events.archive/ before recreating, preserving history rather than rm'ing it. Mirrors rotateEventLedgerIfNeeded's events-rotated-YYYY-MM-DD.jsonl naming convention (events-corrupted-YYYY-MM-DD.jsonl distinguishes this archive cause from sliding-window rotation).
263
- "doctor.check.event_ledger.remediation.invalid": "Archive history first (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-corrupted-$(date +%Y-%m-%d).jsonl`), then run `fab doctor --fix` to create a new empty ledger. Historical events are preserved under events.archive/.",
270
+ "doctor.check.event_ledger.remediation.invalid": "Archive history first (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-corrupted-$(date +%Y-%m-%d).jsonl`), then run `fabric doctor --fix` to create a new empty ledger. Historical events are preserved under events.archive/.",
264
271
  "doctor.check.event_ledger.ok": ".fabric/events.jsonl exists, is writable, and is parseable.",
265
272
  "doctor.check.mcp_config_in_wrong_file.name": "Claude MCP config location",
266
- "doctor.check.mcp_config_in_wrong_file.message": ".claude/settings.json contains mcpServers.fabric \u2014 this file is for hooks/permissions only. Run --fix to remove it, then re-run fab install to write .mcp.json.",
267
- "doctor.check.mcp_config_in_wrong_file.remediation": "Run `fab doctor --fix` to remove mcpServers.fabric from .claude/settings.json, then run `fab install` to write .mcp.json.",
273
+ "doctor.check.mcp_config_in_wrong_file.message": ".claude/settings.json contains mcpServers.fabric \u2014 this file is for hooks/permissions only. Run --fix to remove it, then re-run fabric install to write .mcp.json.",
274
+ "doctor.check.mcp_config_in_wrong_file.remediation": "Run `fabric doctor --fix` to remove mcpServers.fabric from .claude/settings.json, then run `fabric install` to write .mcp.json.",
268
275
  "doctor.check.mcp_config_in_wrong_file.ok": "mcpServers.fabric is not in .claude/settings.json.",
269
276
  "doctor.check.event_ledger_partial_write.name": "Event ledger partial write",
270
277
  "doctor.check.event_ledger_partial_write.ok.skipped": "No partial-write check needed (ledger missing or not writable).",
271
278
  "doctor.check.event_ledger_partial_write.message": "events.jsonl has a partial write at byte offset {byteOffset} ({byteLength} corrupted bytes). Run --fix to truncate and preserve corrupted bytes.",
272
- "doctor.check.event_ledger_partial_write.remediation": "Run `fab doctor --fix` to truncate the partial write and restore events.jsonl to a valid state.",
279
+ "doctor.check.event_ledger_partial_write.remediation": "Run `fabric doctor --fix` to truncate the partial write and restore events.jsonl to a valid state.",
273
280
  "doctor.check.event_ledger_partial_write.ok.clean": "events.jsonl has no partial trailing write.",
274
281
  // v2.0.0-rc.27 TASK-010 (audit §2.24): schema-compat forward-warn category.
275
282
  "doctor.check.event_ledger_schema_compat.name": "Event ledger schema compat",
@@ -278,48 +285,58 @@ var enMessages = {
278
285
  "doctor.check.event_ledger_schema_compat.message.schema_version": "events.jsonl has {count} row(s) with unsupported `schema_version` (samples: {samples}).",
279
286
  "doctor.check.event_ledger_schema_compat.message.event_type": "events.jsonl has {count} row(s) with unknown `event_type` (samples: {samples}).",
280
287
  // v2.0.0-rc.33 W3-1 (P0-6): archive-history mode — same as event_ledger.invalid above. Explicit "archive" wording (rather than "back up") makes it clear the old ledger is preserved under events.archive/, not discarded.
281
- "doctor.check.event_ledger_schema_compat.remediation": "Preferred: upgrade the fab CLI to a server-compatible version. Otherwise archive history first (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-schema-mismatch-$(date +%Y-%m-%d).jsonl`), then run `fab doctor --fix` to create a new empty ledger. Historical events stay under events.archive/ for later manual migration.",
288
+ "doctor.check.event_ledger_schema_compat.remediation": "Preferred: upgrade the fabric CLI to a server-compatible version. Otherwise archive history first (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-schema-mismatch-$(date +%Y-%m-%d).jsonl`), then run `fabric doctor --fix` to create a new empty ledger. Historical events stay under events.archive/ for later manual migration.",
282
289
  // v2.0.0-rc.28 TASK-04 (audit §3.1): SKILL ref/ mirror parity check.
283
290
  "doctor.check.skill_ref_mirror.name": "Skill ref mirror parity",
284
291
  "doctor.check.skill_ref_mirror.ok": "All `.claude/skills/<slug>/ref/` and `.codex/skills/<slug>/ref/` files are byte-identical.",
285
292
  "doctor.check.skill_ref_mirror.message": "{count} skill ref file(s) differ between `.claude/skills/` and `.codex/skills/` (paths: {list}). One client was hand-edited or partially installed.",
286
- "doctor.check.skill_ref_mirror.remediation": "Run `fab install` to rewrite both client subtrees from the canonical templates and restore parity.",
293
+ "doctor.check.skill_ref_mirror.remediation": "Run `fabric install` to rewrite both client subtrees from the canonical templates and restore parity.",
287
294
  // v2.0.0-rc.33 W3-6 (P1-13): SKILL.md token budget lint. warn > 5K / error > 10K tokens (chars/3 estimate). Anthropic recommends SKILL.md hot path stay ~3K; over 5K hurts progressive disclosure; over 10K is blocking (wasted model context + load latency).
288
295
  "doctor.check.skill_token_budget.name": "Skill token budget",
289
296
  "doctor.check.skill_token_budget.ok": "All .claude/skills/<slug>/SKILL.md files are within token budget (warn 5K / error 10K).",
290
297
  "doctor.check.skill_token_budget.message.singular": "{count} SKILL.md exceeds the token budget: {list}. Sink detail into ref/ for progressive disclosure.",
291
298
  "doctor.check.skill_token_budget.message.plural": "{count} SKILL.md files exceed the token budget: {list}. Sink detail into ref/ for progressive disclosure.",
292
- "doctor.check.skill_token_budget.remediation": "Move detailed phase / worked-examples / decision tables out of the SKILL.md hot path into `templates/skills/<slug>/ref/*.md`. Keep SKILL.md focused on trigger-gate + key-phase summaries; see W1 progressive disclosure split. Re-run `fab install` to sync both client subtrees.",
299
+ "doctor.check.skill_token_budget.remediation": "Move detailed phase / worked-examples / decision tables out of the SKILL.md hot path into `templates/skills/<slug>/ref/*.md`. Keep SKILL.md focused on trigger-gate + key-phase summaries; see W1 progressive disclosure split. Re-run `fabric install` to sync both client subtrees.",
293
300
  // v2.0.0-rc.33 W3-7 (P1-14): SKILL.md description structural lint. Proxy for trigger-recall (a live-LLM recall test requires a model — W1 ran gemini for that). This lint catches regression: missing description / >60 tokens / no Chinese trigger / no English trigger.
294
301
  "doctor.check.skill_description.name": "Skill description quality",
295
302
  "doctor.check.skill_description.ok": "All SKILL.md description fields are well-structured (non-empty, <60 tokens, bilingual triggers).",
296
303
  "doctor.check.skill_description.message.singular": "{count} SKILL.md description structural issue: {list}. The description field is the host's primary auto-invoke matching signal.",
297
304
  "doctor.check.skill_description.message.plural": "{count} SKILL.md description structural issues: {list}. The description field is the host's primary auto-invoke matching signal.",
298
- "doctor.check.skill_description.remediation": "Edit the `description:` field in `packages/cli/templates/skills/<slug>/SKILL.md` frontmatter: (1) non-empty; (2) <60 tokens (chars/3 estimate, ~180 chars); (3) at least one Chinese trigger phrase; (4) at least one English trigger phrase. See W1 description rewrite style. Re-run `fab install` to sync both client subtrees. For recall verification, run the W1 gemini delegate (see .workflow/.scratchpad/rc33-plan/W1-VERIFY-RESULT.md).",
305
+ "doctor.check.skill_description.remediation": "Edit the `description:` field in `packages/cli/templates/skills/<slug>/SKILL.md` frontmatter: (1) non-empty; (2) <60 tokens (chars/3 estimate, ~180 chars); (3) at least one Chinese trigger phrase; (4) at least one English trigger phrase. See W1 description rewrite style. Re-run `fabric install` to sync both client subtrees. For recall verification, run the W1 gemini delegate (see .workflow/.scratchpad/rc33-plan/W1-VERIFY-RESULT.md).",
299
306
  // v2.0.0-rc.33 W3-3 (P1-3): cite-policy Goodhart pattern detection. Scans 7d of assistant_turn_observed events for 4 anti-patterns (G1 ritual / G2 dismissal abuse / G3 chained-from misuse / G5 placeholder cite). Warning severity — heuristics can false-positive; advisory only.
300
307
  "doctor.check.cite_goodhart.name": "Cite-policy Goodhart",
301
308
  "doctor.check.cite_goodhart.ok": "No cite-policy Goodhart patterns detected over the last 7 days.",
302
309
  "doctor.check.cite_goodhart.message.singular": "Detected {count} cite-policy Goodhart pattern: {list}.",
303
310
  "doctor.check.cite_goodhart.message.plural": "Detected {count} cite-policy Goodhart patterns: {list}.",
304
- "doctor.check.cite_goodhart.remediation": "Review the fired patterns: G1 ritual \u2192 the same id repeated as [recalled] suggests the KB should land into a contract instead; G2 dismissal abuse \u2192 > 60% of recalled cites used skip: bypasses contract enforcement, audit skip-reason validity; G3 chained-from misuse \u2192 chained-from tag with no commitment (operators=[] + skip_reason=null), add operators or use a different tag; G5 placeholder cite \u2192 too many bare 'KB: none' / [unspecified], prefer specific sentinels like [no-relevant] / [not-applicable]. For raw data, run `fab doctor --cite-coverage --since=7d`.",
311
+ "doctor.check.cite_goodhart.remediation": "Review the fired patterns: G1 ritual \u2192 the same id repeated as [recalled] suggests the KB should land into a contract instead; G2 dismissal abuse \u2192 > 60% of recalled cites used skip: bypasses contract enforcement, audit skip-reason validity; G3 chained-from misuse \u2192 chained-from tag with no commitment (operators=[] + skip_reason=null), add operators or use a different tag; G5 placeholder cite \u2192 too many bare 'KB: none' / [unspecified], prefer specific sentinels like [no-relevant] / [not-applicable]. For raw data, run `fabric doctor --cite-coverage --since=7d`.",
305
312
  // v2.0.0-rc.33 W4-A4 (T5 P2): draft-backlog lint. rc.32 baseline showed 92% of entries stuck at draft, signaling a broken promote loop. Warns when > 50% draft (workspace must have >= 10 entries to compute the ratio — small corpora are noisy).
306
313
  "doctor.check.draft_backlog.name": "Knowledge draft backlog",
307
314
  "doctor.check.draft_backlog.ok": "draft-maturity entry ratio is healthy (< 50%, or workspace too small to compute).",
308
315
  "doctor.check.draft_backlog.message": "{draftCount}/{totalCount} ({pct}%) canonical knowledge entries are stuck at draft maturity \u2014 promote loop is broken (rc.32 baseline was 92%).",
309
316
  "doctor.check.draft_backlog.remediation": "Run `/fabric-review` to triage drafts: approve to promote to verified/proven, reject to drop, modify to fix. A long-standing draft backlog usually means archive produces drafts faster than review can promote them.",
317
+ // rc.36 TASK-05 (P0-8): empty-tags ratio warn.
318
+ "doctor.check.knowledge_tags_empty.name": "Knowledge tags coverage",
319
+ "doctor.check.knowledge_tags_empty.ok": "empty-tag ratio is healthy (\u2264 50%, or workspace too small to compute).",
320
+ "doctor.check.knowledge_tags_empty.message": "{emptyCount}/{totalCount} ({pct}%) canonical knowledge entries have empty `tags:` \u2014 topical clustering and cross-entry retrieval degrade. The fabric-archive / fabric-import skills should produce 2-4 tags per entry.",
321
+ "doctor.check.knowledge_tags_empty.remediation": "On the next archive/import run, populate `tags:` in the frontmatter with 2-4 kebab-case keywords. To backfill existing entries in bulk, use `/fabric-review` with the modify flow.",
322
+ // rc.36 TASK-09 (P1-NEW1): drift_detected events unconsumed by demote.
323
+ "doctor.check.drift_unconsumed.name": "Knowledge drift unconsumed",
324
+ "doctor.check.drift_unconsumed.ok": "knowledge_drift_detected events in the last 30 days have been consumed by paired knowledge_demoted, or event volume is too low to compute.",
325
+ "doctor.check.drift_unconsumed.message": "{driftCount} knowledge_drift_detected events in the last 30 days, but only {demoteCount} knowledge_demoted. Drift > demote by \u2265 5 means part of the drift is going unconsumed \u2014 KB slowly stales.",
326
+ "doctor.check.drift_unconsumed.remediation": "rc.36 has no auto-demote pipeline; act manually: run `fabric doctor --fix` to trigger orphan-demote / stale-archive auto-heal, or invoke `/fabric-review` to manually triage drift-flagged entries. Automatic 14-day demote is planned for rc.37.",
310
327
  "doctor.check.meta_manually_diverged.name": "Meta manual divergence",
311
328
  "doctor.check.meta_manually_diverged.ok.unreadable": "agents.meta.json not readable; skipping divergence check.",
312
329
  "doctor.check.meta_manually_diverged.message.extra.singular": "agents.meta.json has {count} entry with no backing file on disk. Run --fix to reconcile.",
313
330
  "doctor.check.meta_manually_diverged.message.extra.plural": "agents.meta.json has {count} entries with no backing file on disk. Run --fix to reconcile.",
314
- "doctor.check.meta_manually_diverged.remediation.extra": "Run `fab doctor --fix` to reconcile agents.meta.json with the rule files currently on disk.",
331
+ "doctor.check.meta_manually_diverged.remediation.extra": "Run `fabric doctor --fix` to reconcile agents.meta.json with the rule files currently on disk.",
315
332
  "doctor.check.meta_manually_diverged.message.hash.singular": "agents.meta.json has {count} entry whose hash does not match the file on disk. Run --fix to reconcile.",
316
333
  "doctor.check.meta_manually_diverged.message.hash.plural": "agents.meta.json has {count} entries whose hash does not match the file on disk. Run --fix to reconcile.",
317
- "doctor.check.meta_manually_diverged.remediation.hash": "Run `fab doctor --fix` to reconcile agents.meta.json with the current rule file contents.",
334
+ "doctor.check.meta_manually_diverged.remediation.hash": "Run `fabric doctor --fix` to reconcile agents.meta.json with the current rule file contents.",
318
335
  "doctor.check.meta_manually_diverged.ok.consistent": "agents.meta.json is consistent with rule files on disk.",
319
336
  "doctor.check.knowledge_dir_unindexed.name": "Knowledge dir unindexed",
320
- "doctor.check.knowledge_dir_unindexed.message.singular": "{count} .md file in .fabric/knowledge/ not indexed in agents.meta.json. Run `fab doctor --fix` to index the missing knowledge files.",
321
- "doctor.check.knowledge_dir_unindexed.message.plural": "{count} .md files in .fabric/knowledge/ not indexed in agents.meta.json. Run `fab doctor --fix` to index the missing knowledge files.",
322
- "doctor.check.knowledge_dir_unindexed.remediation": "Run `fab doctor --fix` to index the missing knowledge files.",
337
+ "doctor.check.knowledge_dir_unindexed.message.singular": "{count} .md file in .fabric/knowledge/ not indexed in agents.meta.json. Run `fabric doctor --fix` to index the missing knowledge files.",
338
+ "doctor.check.knowledge_dir_unindexed.message.plural": "{count} .md files in .fabric/knowledge/ not indexed in agents.meta.json. Run `fabric doctor --fix` to index the missing knowledge files.",
339
+ "doctor.check.knowledge_dir_unindexed.remediation": "Run `fabric doctor --fix` to index the missing knowledge files.",
323
340
  "doctor.check.knowledge_dir_unindexed.ok": "All .fabric/knowledge/ .md files are indexed in agents.meta.json.",
324
341
  "doctor.check.stable_id_collision.name": "Stable ID collision",
325
342
  "doctor.check.stable_id_collision.message.singular": 'stable_id "{stableId}" is declared in {fileCount} files: {files}. Edit one of the knowledge files to use a unique stable_id.',
@@ -328,9 +345,9 @@ var enMessages = {
328
345
  "doctor.check.stable_id_collision.remediation": "Run `/fabric-review modify <one of the colliding ids from the message>` to let the canonical id allocator reassign it (updates frontmatter + counters + historical cross-refs atomically). Do NOT hand-edit id frontmatter \u2014 it will desync counters.",
329
346
  "doctor.check.stable_id_collision.ok": "No declared stable_id collisions found in .fabric/knowledge/.",
330
347
  "doctor.check.counter_desync.name": "Knowledge counter desync",
331
- "doctor.check.counter_desync.message.singular": "{count} knowledge counter desynced from observed stable_ids. {counterPath} = {current} but observed {observedId}. Run `fab doctor --fix` to bump counters.",
332
- "doctor.check.counter_desync.message.plural": "{count} knowledge counters desynced from observed stable_ids. {counterPath} = {current} but observed {observedId}. Run `fab doctor --fix` to bump counters.",
333
- "doctor.check.counter_desync.remediation": "Run `fab doctor --fix` to bump agents.meta.json counters to the maximum observed counter value.",
348
+ "doctor.check.counter_desync.message.singular": "{count} knowledge counter desynced from observed stable_ids. {counterPath} = {current} but observed {observedId}. Run `fabric doctor --fix` to bump counters.",
349
+ "doctor.check.counter_desync.message.plural": "{count} knowledge counters desynced from observed stable_ids. {counterPath} = {current} but observed {observedId}. Run `fabric doctor --fix` to bump counters.",
350
+ "doctor.check.counter_desync.remediation": "Run `fabric doctor --fix` to bump agents.meta.json counters to the maximum observed counter value.",
334
351
  "doctor.check.counter_desync.ok": "agents.meta.json counters envelope is consistent with observed stable_ids.",
335
352
  "doctor.check.preexisting_root_files.name": "Preexisting root markdown",
336
353
  "doctor.check.preexisting_root_files.ok": "No CLAUDE.md or AGENTS.md detected at project root.",
@@ -345,12 +362,12 @@ var enMessages = {
345
362
  "doctor.check.orphan_demote.ok": "No canonical knowledge entries exceed their maturity-keyed inactivity threshold.",
346
363
  "doctor.check.orphan_demote.message.singular": "{count} canonical knowledge entry exceeds their maturity-keyed inactivity threshold (stable={stableDays}d / endorsed={endorsedDays}d / draft={draftDays}d). First: {detail}.",
347
364
  "doctor.check.orphan_demote.message.plural": "{count} canonical knowledge entries exceed their maturity-keyed inactivity threshold (stable={stableDays}d / endorsed={endorsedDays}d / draft={draftDays}d). First: {detail}.",
348
- "doctor.check.orphan_demote.remediation": "Run `fab doctor --fix-knowledge` to demote orphan entries one maturity tier.",
365
+ "doctor.check.orphan_demote.remediation": "Run `fabric doctor --fix-knowledge` to demote orphan entries one maturity tier.",
349
366
  "doctor.check.stale_archive.name": "Knowledge stale archive",
350
367
  "doctor.check.stale_archive.ok": "No draft knowledge entries exceed the additional stale-archive quiet window.",
351
368
  "doctor.check.stale_archive.message.singular": "{count} draft knowledge entry is stale beyond the demote+{additionalDays}d additional quiet window. First: {detail}.",
352
369
  "doctor.check.stale_archive.message.plural": "{count} draft knowledge entries are stale beyond the demote+{additionalDays}d additional quiet window. First: {detail}.",
353
- "doctor.check.stale_archive.remediation": "Run `fab doctor --fix-knowledge` to move stale entries into `.fabric/.archive/<type>/`.",
370
+ "doctor.check.stale_archive.remediation": "Run `fabric doctor --fix-knowledge` to move stale entries into `.fabric/.archive/<type>/`.",
354
371
  "doctor.check.pending_overdue.name": "Knowledge pending overdue",
355
372
  "doctor.check.pending_overdue.ok": "No pending knowledge entries exceed the 14-day review threshold.",
356
373
  "doctor.check.pending_overdue.message.singular": "{count} pending knowledge entry has been awaiting review for more than {thresholdDays} days. First: {detail}.",
@@ -372,7 +389,7 @@ var enMessages = {
372
389
  "doctor.check.index_drift.ok": "agents.meta.json counters envelope is at or above the highest existing canonical counter for every (layer, type) pair.",
373
390
  "doctor.check.index_drift.message.singular": "{count} (layer, type) counter slot have drifted below the observed canonical maximum (next allocate would collide). First: {detail}.",
374
391
  "doctor.check.index_drift.message.plural": "{count} (layer, type) counter slots have drifted below the observed canonical maximum (next allocate would collide). First: {detail}.",
375
- "doctor.check.index_drift.remediation": "Run `fab doctor --fix-knowledge` to bump agents.meta.json counters to max_observed + 1.",
392
+ "doctor.check.index_drift.remediation": "Run `fabric doctor --fix-knowledge` to bump agents.meta.json counters to max_observed + 1.",
376
393
  "doctor.check.underseeded.name": "Knowledge underseeded",
377
394
  "doctor.check.underseeded.ok": "Knowledge corpus has {count} canonical entries (>= {threshold}).",
378
395
  "doctor.check.underseeded.message.singular": "Knowledge corpus has only {count} canonical entry (< {threshold} threshold). The plan_context retrieval surface is below its useful floor.",
@@ -406,7 +423,7 @@ var enMessages = {
406
423
  "doctor.check.session_hints_stale.ok": "No session-hints cache files older than {days} days under .fabric/.cache/.",
407
424
  "doctor.check.session_hints_stale.message.singular": "{count} session-hints cache file under .fabric/.cache/ is older than {days} days. First: {detail}.",
408
425
  "doctor.check.session_hints_stale.message.plural": "{count} session-hints cache files under .fabric/.cache/ are older than {days} days. First: {detail}.",
409
- "doctor.check.session_hints_stale.remediation": "Run `fab doctor --fix-knowledge` to delete stale session-hints cache files.",
426
+ "doctor.check.session_hints_stale.remediation": "Run `fabric doctor --fix-knowledge` to delete stale session-hints cache files.",
410
427
  "doctor.check.stale_serve_lock.name": "Serve lock",
411
428
  "doctor.check.stale_serve_lock.ok.no_lock": "No .fabric/.serve.lock present.",
412
429
  "doctor.check.stale_serve_lock.ok.live_pid": ".fabric/.serve.lock held by live PID {pid}.",
@@ -414,26 +431,39 @@ var enMessages = {
414
431
  "doctor.check.stale_serve_lock.age.day.plural": "{count} days ago",
415
432
  "doctor.check.stale_serve_lock.age.hour.singular": "{count} hour ago",
416
433
  "doctor.check.stale_serve_lock.age.hour.plural": "{count} hours ago",
417
- "doctor.check.stale_serve_lock.message.dead_pid": "[advisory] .fabric/.serve.lock holds dead PID {pid} (acquired {acquiredAgo}). Run `fab doctor --fix` to remove.",
418
- "doctor.check.stale_serve_lock.remediation.dead_pid": "Run `fab doctor --fix` to remove the stale .fabric/.serve.lock.",
434
+ "doctor.check.stale_serve_lock.message.dead_pid": "[advisory] .fabric/.serve.lock holds dead PID {pid} (acquired {acquiredAgo}). Run `fabric doctor --fix` to remove.",
435
+ "doctor.check.stale_serve_lock.remediation.dead_pid": "Run `fabric doctor --fix` to remove the stale .fabric/.serve.lock.",
419
436
  "doctor.check.relevance_fields_missing.name": "Knowledge relevance fields missing",
420
437
  "doctor.check.relevance_fields_missing.ok": "All pending entries declare both relevance_scope and relevance_paths.",
421
438
  "doctor.check.relevance_fields_missing.message.singular": "{count} pending entry is missing relevance_scope and/or relevance_paths in frontmatter. First: {detail}.",
422
439
  "doctor.check.relevance_fields_missing.message.plural": "{count} pending entries are missing relevance_scope and/or relevance_paths in frontmatter. First: {detail}.",
423
- "doctor.check.relevance_fields_missing.remediation": "Run `fab doctor --fix-knowledge` to back-fill the schema defaults (relevance_scope: broad, relevance_paths: []).",
440
+ "doctor.check.relevance_fields_missing.remediation": "Run `fabric doctor --fix-knowledge` to back-fill the schema defaults (relevance_scope: broad, relevance_paths: []).",
424
441
  // rc.31 BUG-M3/NEW-4: hooks_wired observability.
425
442
  "doctor.check.hooks_wired.name": "Claude Code hooks wired",
426
443
  "doctor.check.hooks_wired.ok.skipped": "Project does not use Claude Code (no .claude/ directory); hooks_wired check skipped.",
427
444
  "doctor.check.hooks_wired.ok.wired": ".claude/settings.json has the three fabric hooks wired: Stop:fabric-hint / SessionStart:knowledge-hint-broad / PreToolUse:knowledge-hint-narrow.",
428
- "doctor.check.hooks_wired.message.missing_settings": ".claude/ exists but .claude/settings.json is absent or unparseable; fab install may have never run successfully, or the file was wiped externally.",
429
- "doctor.check.hooks_wired.message.incomplete": ".claude/settings.json is missing fabric hook injections: {missing}. fab install dry-run report does not match actual state (rc.30 audit BUG-M3 / NEW-4).",
430
- "doctor.check.hooks_wired.remediation": "Run `fab install` to re-inject hooks (idempotent; only fills missing slots). If hooks config was accidentally wiped, back up .claude/settings.json before running.",
445
+ "doctor.check.hooks_wired.message.missing_settings": ".claude/ exists but .claude/settings.json is absent or unparseable; fabric install may have never run successfully, or the file was wiped externally.",
446
+ "doctor.check.hooks_wired.message.incomplete": ".claude/settings.json is missing fabric hook injections: {missing}. fabric install dry-run report does not match actual state (rc.30 audit BUG-M3 / NEW-4).",
447
+ "doctor.check.hooks_wired.remediation": "Run `fabric install` to re-inject hooks (idempotent; only fills missing slots). If hooks config was accidentally wiped, back up .claude/settings.json before running.",
431
448
  // rc.31 BUG-G2/G5: promote-ledger invariant check.
432
449
  "doctor.check.promote_ledger_invariant.name": "Promote ledger invariant",
433
450
  "doctor.check.promote_ledger_invariant.ok": "knowledge_proposed={proposed} >= knowledge_promote_started={started} >= knowledge_promoted={promoted}; ledger invariant holds.",
434
451
  "doctor.check.promote_ledger_invariant.message.proposed-lt-started": "knowledge_proposed={proposed} is less than knowledge_promote_started={started} (ledger invariant violated; some pending entries were approved without going through fab_extract_knowledge, so no propose event was emitted for them).",
435
452
  "doctor.check.promote_ledger_invariant.message.started-lt-promoted": "knowledge_promote_started={started} is less than knowledge_promoted={promoted} (ledger invariant violated; unpaired promoted events exist, possibly from doctor filesystem-edit fallback or external writers).",
436
- "doctor.check.promote_ledger_invariant.remediation": "Starting in rc.31, review.approve synthesizes a knowledge_proposed event to keep the invariant; re-run fab doctor after the next approve to settle. Historical imbalance is observability-only and does not affect KB function.",
453
+ "doctor.check.promote_ledger_invariant.remediation": "Starting in rc.31, review.approve synthesizes a knowledge_proposed event to keep the invariant; re-run fabric doctor after the next approve to settle. Historical imbalance is observability-only and does not affect KB function.",
454
+ // rc.35 TASK-04 (P0-9.b): global_cli_outdated.
455
+ "doctor.check.global_cli_outdated.name": "Global fabric CLI version",
456
+ "doctor.check.global_cli_outdated.ok": "Global `fabric` on PATH is {version}; compatible with the rc.31+ project schema.",
457
+ "doctor.check.global_cli_outdated.message.outdated": "Global `fabric` on PATH is {version}, older than the minimum-supported {minVersion}. rc.31 introduced an agents.meta.json schema fix; hooks installed by an outdated binary silently fail. Upgrade the global CLI to match the project.",
458
+ "doctor.check.global_cli_outdated.message.not_found": "No `fabric` binary on PATH. The CLI is required for `fabric install` / `fabric doctor`; install it globally.",
459
+ "doctor.check.global_cli_outdated.message.unparseable": "Could not parse `fabric -v` output ({detail}). Skipping outdated-version check.",
460
+ "doctor.check.global_cli_outdated.remediation": "Run `npm install -g @fenglimg/fabric-cli@latest`, then re-run `fabric install` in each fabric-managed project to resync hooks + SKILL.md.",
461
+ // rc.35 TASK-05 (P0-10.a): knowledge_summary_opaque.
462
+ "doctor.check.knowledge_summary_opaque.name": "Knowledge summary opacity",
463
+ "doctor.check.knowledge_summary_opaque.ok.skipped": "agents.meta.json is absent or invalid; summary-opacity check skipped.",
464
+ "doctor.check.knowledge_summary_opaque.ok": "{opaque}/{total} entries have summary == stable_id; opacity ratio is within the healthy band.",
465
+ "doctor.check.knowledge_summary_opaque.message.warn": "{opaque}/{total} entries ({pct}%) have description.summary equal to their stable_id, exceeding the {threshold}% threshold. Narrow-hint output renders as `<id> \xB7 <id>`, signaling nothing useful, and AI clients skip the fetch. First opaque: {sample}.",
466
+ "doctor.check.knowledge_summary_opaque.remediation": "Run the fabric-review skill to rewrite opaque summaries with one short human-readable phrase. The rc.35 hint renderer fallback (TASK-06) will also synthesize a temporary summary from the entry's `## Summary` section.",
437
467
  "doctor.check.skill_md_yaml_invalid.name": "Skill markdown YAML",
438
468
  "doctor.check.skill_md_yaml_invalid.ok": "All .claude/.codex SKILL.md frontmatter values parse as strict YAML.",
439
469
  "doctor.check.skill_md_yaml_invalid.message.singular": "{count} SKILL.md frontmatter value contains an unquoted ': ' that strict YAML parsers reject (Claude Code tolerates it; Codex CLI drops the skill at load). First: {detail}.",
@@ -470,11 +500,17 @@ var enMessages = {
470
500
  "cli.human-lint.table.location": "Location",
471
501
  "cli.human-lint.table.expected": "Expected",
472
502
  "cli.human-lint.table.got": "Got",
473
- "cli.install.description": "Install Fabric in the target project (scaffold .fabric/, bootstrap templates, MCP client wiring, git hooks).\n\nExamples:\n fab install interactive install in the current project\n fab install --yes accept defaults, skip the TTY wizard\n fab install --dry-run preview the install plan without writing files",
503
+ "cli.install.description": "Install Fabric in the target project (scaffold .fabric/, bootstrap templates, MCP client wiring, git hooks).\n\nExamples:\n fabric install interactive install in the current project\n fabric install --yes accept defaults, skip the TTY wizard\n fabric install --dry-run preview the install plan without writing files",
474
504
  "cli.install.args.target.description": "Target project path. Defaults to --target, then EXTERNAL_FIXTURE_PATH, then cwd.",
475
505
  "cli.install.args.debug.description": "Print target resolution details to stderr.",
476
506
  "cli.install.args.yes.description": "Accept the current install plan and run without the TTY wizard",
477
507
  "cli.install.args.dry-run.description": "Print the install plan without writing files or running follow-up stages",
508
+ // rc.35 TASK-08 (P0-5/6): --force-skills-only.
509
+ "cli.install.args.force-skills-only.description": "Skip bootstrap / MCP / hooks / settings; refresh ONLY the fabric Skill template copies (.claude/.codex/.cursor/skills/*).",
510
+ "cli.install.force-skills-only.banner": "Refreshing fabric Skill templates only",
511
+ "cli.install.force-skills-only.uninitialised.message": "fabric install --force-skills-only: project is not initialised (.fabric/agents.meta.json is missing).",
512
+ "cli.install.force-skills-only.uninitialised.hint": "Run `fabric install` (without --force-skills-only) first to lay down the base scaffold, then re-run with --force-skills-only for subsequent Skill refreshes.",
513
+ "cli.install.force-skills-only.summary": "Skills refresh complete \u2014 written: {written}, skipped: {skipped}, errors: {errors}",
478
514
  "cli.install.mcp.install.global": "Using globally-installed @fenglimg/fabric-server",
479
515
  "cli.install.mcp.install.local": "Installing @fenglimg/fabric-server to project devDependencies",
480
516
  "cli.install.mcp.local.installing": "Running {manager} add -D @fenglimg/fabric-server...",
@@ -549,7 +585,7 @@ var enMessages = {
549
585
  "cli.install.capabilities.follow-up.ready": "continue in client",
550
586
  "cli.install.capabilities.follow-up.install": "install client assets",
551
587
  "cli.install.capabilities.follow-up.manual": "manual step required",
552
- "cli.install.next-step.message": "run fab hooks install to add the Day 4 pre-commit pipeline.",
588
+ "cli.install.next-step.message": "run fabric hooks install to add the Day 4 pre-commit pipeline.",
553
589
  "cli.install.reason-message.installable-body": ".fabric/forensic.json is ready; some detected clients support Fabric follow-up but still need client assets installed.",
554
590
  "cli.install.reason-message.manual-body": ".fabric/forensic.json is ready; some detected clients still need manual follow-up because no Fabric skill is installed for them yet.",
555
591
  "cli.install.codex-hooks.created": "{label} {path} with Codex hooks config (requires features.codex_hooks = true).",
@@ -563,15 +599,15 @@ var enMessages = {
563
599
  "cli.install.claude-settings.invalid-json": "{label} {path}: invalid JSON ({reason}).",
564
600
  "cli.install.claude-settings.invalid-hooks": '{label} {path}: "hooks" must be a JSON object.',
565
601
  "cli.install.claude-settings.invalid-stop-array": '{label} {path}: "hooks.Stop" must be an array.',
566
- "cli.install.errors.abort-existing": "ABORT: {path} already exists. fab install is non-destructive.",
602
+ "cli.install.errors.abort-existing": "ABORT: {path} already exists. fabric install is non-destructive.",
567
603
  "cli.install.diff.canonical": "Workspace already canonical ({count} files verified).",
568
604
  "cli.install.diff.applying-missing": "Applying {count} missing pieces: {files}",
569
- "cli.install.diff.drift-abort": "Drift detected in {path}. Run `fab doctor` to inspect, or `fab uninstall && fab install` to reset.",
605
+ "cli.install.diff.drift-abort": "Drift detected in {path}. Run `fabric doctor` to inspect, or `fabric uninstall && fabric install` to reset.",
570
606
  "cli.install.diff.state.missing": "missing",
571
607
  "cli.install.diff.state.present-canonical": "canonical",
572
608
  "cli.install.diff.state.drifted": "drifted",
573
609
  "cli.install.diff.state.user-modified": "user-modified",
574
- "cli.uninstall.description": "Uninstall Fabric from the target project. .fabric/knowledge/ is always preserved; ~/.fabric/knowledge/ is never touched.\n\nExamples:\n fab uninstall interactive uninstall in the current project\n fab uninstall --yes accept defaults, skip the TTY wizard\n fab uninstall --dry-run preview the uninstall plan without removing files",
610
+ "cli.uninstall.description": "Uninstall Fabric from the target project. .fabric/knowledge/ is always preserved; ~/.fabric/knowledge/ is never touched.\n\nExamples:\n fabric uninstall interactive uninstall in the current project\n fabric uninstall --yes accept defaults, skip the TTY wizard\n fabric uninstall --dry-run preview the uninstall plan without removing files",
575
611
  "cli.uninstall.args.target.description": "Target project path. Defaults to --target, then EXTERNAL_FIXTURE_PATH, then cwd.",
576
612
  "cli.uninstall.args.debug.description": "Print target resolution details to stderr.",
577
613
  "cli.uninstall.args.yes.description": "Accept the current uninstall plan and run without the TTY wizard.",
@@ -622,7 +658,7 @@ var enMessages = {
622
658
  "cli.scan.args.target.description": "Target absolute path. Defaults to --target, then EXTERNAL_FIXTURE_PATH, then cwd.",
623
659
  "cli.scan.args.debug.description": "Print detection evidence in formatted output.",
624
660
  "cli.scan.args.json.description": "Print the diagnostic report as JSON.",
625
- "cli.scan.error.missing-forensic": "forensic.json not found at {path}; run `fab install` first to produce the deterministic project snapshot.",
661
+ "cli.scan.error.missing-forensic": "forensic.json not found at {path}; run `fabric install` first to produce the deterministic project snapshot.",
626
662
  "cli.scan.summary.created": "Wrote {count} knowledge entries to .fabric/knowledge/.",
627
663
  "cli.scan.summary.skipped": "No changes detected; {count} entries already up-to-date.",
628
664
  "cli.scan.report.title": "Fabric scan report",
@@ -637,20 +673,20 @@ var enMessages = {
637
673
  "cli.scan.report.recommendations": "Recommendations:",
638
674
  "cli.scan.readme-quality.ok": "ok",
639
675
  "cli.scan.readme-quality.stub": "stub",
640
- "cli.scan.recommendation.init": "L0: Run fab install to scaffold `.fabric/AGENTS.md` with the canonical Fabric bootstrap content.",
676
+ "cli.scan.recommendation.init": "L0: Run fabric install to scaffold `.fabric/AGENTS.md` with the canonical Fabric bootstrap content.",
641
677
  "cli.scan.recommendation.readme": "L0: Expand README.md before promoting project facts into Fabric references.",
642
678
  "cli.scan.recommendation.contributing": "L0: Add CONTRIBUTING.md or leave a bootstrap TODO reference for contribution flow.",
643
679
  "cli.scan.recommendation.unknown-framework": "L1: Add tech-stack TODOs manually because no framework marker was detected.",
644
680
  "cli.scan.recommendation.framework-dirs": "L1: Review {framework} directories for future scoped Fabric rule files.",
645
- "cli.serve.description": "Start the local Fabric MCP HTTP service.\n\nExamples:\n fab serve bind 127.0.0.1:7373 (default)\n fab serve --port 8787 use a custom port\n FABRIC_AUTH_TOKEN=<token> fab serve --host 0.0.0.0 bind non-loopback with Bearer auth",
681
+ "cli.serve.description": "Start the local Fabric MCP HTTP service.\n\nExamples:\n fabric serve bind 127.0.0.1:7373 (default)\n fabric serve --port 8787 use a custom port\n FABRIC_AUTH_TOKEN=<token> fabric serve --host 0.0.0.0 bind non-loopback with Bearer auth",
646
682
  "cli.serve.args.port.description": "Listen port, default 7373.",
647
683
  "cli.serve.args.host.description": "Listen host, default 127.0.0.1. Non-loopback hosts (e.g. 0.0.0.0) require FABRIC_AUTH_TOKEN to enable Bearer auth, otherwise serve falls back to 127.0.0.1.",
648
684
  "cli.serve.args.target.description": "Target project path. Defaults to --target, then EXTERNAL_FIXTURE_PATH, then cwd.",
649
685
  "cli.serve.args.debug.description": "Print target resolution details to stderr.",
650
686
  "cli.serve.args.allow-loopback-no-auth.description": "Opt in to running the loopback HTTP server without Bearer auth (default-deny). Use only on a trusted single-user machine; any local process can then read your knowledge ledger.",
651
687
  "cli.serve.ready.title": "Fabric Dashboard",
652
- "cli.serve.lock-held.action-hint": "A `fab serve` instance (PID {pid}) is holding the workspace lock. Stop it (Ctrl-C in that terminal or `kill {pid}`) before running this command.",
653
- "cli.serve.warning.host-fallback": "--host {host} requires FABRIC_AUTH_TOKEN for non-loopback exposure; falling back to 127.0.0.1. To bind {host}, run: FABRIC_AUTH_TOKEN=<token> fab serve --host {host}",
688
+ "cli.serve.lock-held.action-hint": "A `fabric serve` instance (PID {pid}) is holding the workspace lock. Stop it (Ctrl-C in that terminal or `kill {pid}`) before running this command.",
689
+ "cli.serve.warning.host-fallback": "--host {host} requires FABRIC_AUTH_TOKEN for non-loopback exposure; falling back to 127.0.0.1. To bind {host}, run: FABRIC_AUTH_TOKEN=<token> fabric serve --host {host}",
654
690
  "cli.serve.warning.loopback-deny-default": "FABRIC_AUTH_TOKEN is not set: /api /events /mcp will return 401 by default (any local process could otherwise read .fabric/agents.meta.json + forensic.json + events.jsonl). Set FABRIC_AUTH_TOKEN=<secret> or pass --allow-loopback-no-auth to opt in.",
655
691
  "cli.serve.error.port-in-use": "Port {port} in use - try --port {nextPort}",
656
692
  // v2.0.0-rc.29 TASK-008 (BUG-L2): onboard-coverage i18n keys.
@@ -664,7 +700,7 @@ var enMessages = {
664
700
  "cli.sync-meta.description": "Sync Fabric metadata from internal rule files.",
665
701
  "cli.sync-meta.args.target.description": "Target project path, default is the current working directory.",
666
702
  "cli.sync-meta.args.check-only.description": "Exit with code 1 when .fabric/agents.meta.json is out of date.",
667
- "cli.sync-meta.drift-detected": "Fabric metadata drift detected. Run fab sync-meta to update.",
703
+ "cli.sync-meta.drift-detected": "Fabric metadata drift detected. Run fabric sync-meta to update.",
668
704
  "cli.sync-meta.updated": "{label} {path}",
669
705
  "dashboard.app.nav.aria-label": "Dashboard views",
670
706
  "dashboard.app.nav.readiness.label": "Readiness",
@@ -871,7 +907,7 @@ var enMessages = {
871
907
 
872
908
  // src/i18n/locales/zh-CN.ts
873
909
  var zhCNMessages = {
874
- "cli.main.description": "Fabric CLI - AI \u667A\u80FD\u4F53\u534F\u4F5C\u6846\u67B6\u3002\n\n\u4E09\u6B65\u5FC3\u667A\u6A21\u578B\uFF1A\n \u88C5 (install) - fab install \u4E00\u952E\u5B8C\u6210\u9879\u76EE\u521D\u59CB\u5316\n \u914D (config) - fab config \u6253\u5F00\u4EA4\u4E92\u5F0F\u914D\u7F6E\u9762\u677F\n \u8DD1 (run) - fab serve \u542F\u52A8\u672C\u5730 MCP HTTP \u670D\u52A1\n fab doctor \u8FD0\u884C\u76EE\u6807\u6001\u8BCA\u65AD\n\n\u793A\u4F8B\uFF1A\n fab install \u5728\u5F53\u524D\u9879\u76EE\u4E2D\u5B89\u88C5 Fabric\n fab config \u6253\u5F00\u4EA4\u4E92\u5F0F\u914D\u7F6E\u9762\u677F\n fab serve --port 7373 \u542F\u52A8 MCP HTTP \u670D\u52A1\n fab doctor --fix \u4FEE\u590D Fabric \u6D3E\u751F\u72B6\u6001\n fab uninstall --dry-run \u9884\u89C8\u5378\u8F7D\uFF0C\u4E0D\u5220\u9664\u6587\u4EF6",
910
+ "cli.main.description": "Fabric CLI - AI \u667A\u80FD\u4F53\u534F\u4F5C\u6846\u67B6\u3002\n\n\u4E09\u6B65\u5FC3\u667A\u6A21\u578B\uFF1A\n \u88C5 (install) - fabric install \u4E00\u952E\u5B8C\u6210\u9879\u76EE\u521D\u59CB\u5316\n \u914D (config) - fabric config \u6253\u5F00\u4EA4\u4E92\u5F0F\u914D\u7F6E\u9762\u677F\n \u8DD1 (run) - fabric serve \u542F\u52A8\u672C\u5730 MCP HTTP \u670D\u52A1\n fabric doctor \u8FD0\u884C\u76EE\u6807\u6001\u8BCA\u65AD\n\n\u793A\u4F8B\uFF1A\n fabric install \u5728\u5F53\u524D\u9879\u76EE\u4E2D\u5B89\u88C5 Fabric\n fabric config \u6253\u5F00\u4EA4\u4E92\u5F0F\u914D\u7F6E\u9762\u677F\n fabric serve --port 7373 \u542F\u52A8 MCP HTTP \u670D\u52A1\n fabric doctor --fix \u4FEE\u590D Fabric \u6D3E\u751F\u72B6\u6001\n fabric uninstall --dry-run \u9884\u89C8\u5378\u8F7D\uFF0C\u4E0D\u5220\u9664\u6587\u4EF6",
875
911
  "cli.shared.created": "\u5DF2\u521B\u5EFA",
876
912
  "cli.shared.skipped": "\u5DF2\u8DF3\u8FC7",
877
913
  "cli.shared.next": "\u4E0B\u4E00\u6B65",
@@ -909,7 +945,7 @@ var zhCNMessages = {
909
945
  "cli.bootstrap.install.skipped-header": "\u5DF2\u8DF3\u8FC7 {path}\uFF1AFabric Bootstrap \u5934\u90E8\u5DF2\u5B58\u5728\u3002",
910
946
  "cli.bootstrap.install.prepended": "\u5DF2\u524D\u7F6E\u5199\u5165 {path}",
911
947
  "cli.bootstrap.errors.unknown-client": "\u672A\u77E5\u5BA2\u6237\u7AEF\u201C{client}\u201D\u3002\u8BF7\u4F7F\u7528\u9017\u53F7\u5206\u9694\u5217\u8868\uFF0C\u4F8B\u5982 claude,cursor,codex\u3002",
912
- "cli.config.description": "\u6253\u5F00 Fabric \u4EA4\u4E92\u5F0F\u914D\u7F6E\u9762\u677F\uFF08\u8BED\u8A00\u3001\u77E5\u8BC6\u5C42\u3001\u5BA1\u8BA1\u6A21\u5F0F\u3001\u63D0\u793A\u7A97\u53E3\u3001MCP \u5BA2\u6237\u7AEF\u914D\u7F6E\u7B49\uFF09\u3002\n\n\u793A\u4F8B\uFF1A\n fab config \u6253\u5F00\u4EA4\u4E92\u5F0F\u9762\u677F\n fab config --target /path \u7F16\u8F91\u6307\u5B9A\u9879\u76EE\u7684\u914D\u7F6E",
948
+ "cli.config.description": "\u6253\u5F00 Fabric \u4EA4\u4E92\u5F0F\u914D\u7F6E\u9762\u677F\uFF08\u8BED\u8A00\u3001\u77E5\u8BC6\u5C42\u3001\u5BA1\u8BA1\u6A21\u5F0F\u3001\u63D0\u793A\u7A97\u53E3\u3001MCP \u5BA2\u6237\u7AEF\u914D\u7F6E\u7B49\uFF09\u3002\n\n\u793A\u4F8B\uFF1A\n fabric config \u6253\u5F00\u4EA4\u4E92\u5F0F\u9762\u677F\n fabric config --target /path \u7F16\u8F91\u6307\u5B9A\u9879\u76EE\u7684\u914D\u7F6E",
913
949
  "cli.config.args.target.description": "\u76EE\u6807\u9879\u76EE\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF09\u3002",
914
950
  "cli.config.clients.claude": "Claude Code CLI",
915
951
  "cli.config.install.description": "\u5C06 Fabric MCP \u670D\u52A1\u7AEF\u6761\u76EE\u5B89\u88C5\u5230\u68C0\u6D4B\u5230\u7684\u5BA2\u6237\u7AEF\u914D\u7F6E\u4E2D\u3002",
@@ -921,14 +957,14 @@ var zhCNMessages = {
921
957
  "cli.config.install.no-config-path": "\u8DF3\u8FC7 {client}\uFF1A\u672A\u68C0\u6D4B\u5230\u914D\u7F6E\u8DEF\u5F84\u3002",
922
958
  "cli.config.install.dry-run": "[dry-run] {client}\uFF1A\u5C06\u5199\u5165 {path}",
923
959
  "cli.config.install.wrote": "{client}\uFF1A\u5DF2\u5199\u5165 {path}",
924
- // rc.16 TASK-006 (F1-panel): clack 驱动的 `fab config` 交互式面板。
960
+ // rc.16 TASK-006 (F1-panel): clack 驱动的 `fabric config` 交互式面板。
925
961
  // 由 packages/cli/src/commands/config.ts(菜单循环 + 字段编辑)以及
926
962
  // getPanelFields() 的 label_i18n_key 引用消费。
927
963
  "cli.config.intro": "Fabric \u914D\u7F6E",
928
964
  "cli.config.outro": "\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002",
929
965
  "cli.config.outro-no-changes": "\u672A\u505A\u4EFB\u4F55\u4FEE\u6539\u3002",
930
966
  "cli.config.cancel": "\u5DF2\u53D6\u6D88\u3002",
931
- "cli.config.non-tty-notice": "fab config \u9700\u8981\u5728\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\u4E2D\u8FD0\u884C\u3002\u8BF7\u5728 TTY \u4E2D\u6267\u884C\u4EE5\u7F16\u8F91\u914D\u7F6E\u5B57\u6BB5\u3002",
967
+ "cli.config.non-tty-notice": "fabric config \u9700\u8981\u5728\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\u4E2D\u8FD0\u884C\u3002\u8BF7\u5728 TTY \u4E2D\u6267\u884C\u4EE5\u7F16\u8F91\u914D\u7F6E\u5B57\u6BB5\u3002",
932
968
  "cli.config.menu.field-select": "\u9009\u62E9\u8981\u7F16\u8F91\u7684\u5B57\u6BB5\uFF1A",
933
969
  "cli.config.menu.exit": "\u9000\u51FA",
934
970
  "cli.config.value.current": "\u5F53\u524D\uFF1A{value}",
@@ -937,7 +973,7 @@ var zhCNMessages = {
937
973
  "cli.config.prompt.text": "\u4E3A {key} \u8F93\u5165\u65B0\u503C\uFF08\u5F53\u524D\uFF1A{current}\uFF09\uFF1A",
938
974
  "cli.config.write.success": "\u5DF2\u4FDD\u5B58 {key} = {value}",
939
975
  "cli.config.write.failure": "\u5199\u5165 fabric-config.json \u5931\u8D25\uFF1A{message}",
940
- "cli.config.errors.uninit-workspace.message": "\u5DE5\u4F5C\u533A\u5C1A\u672A\u521D\u59CB\u5316\u3002\u8BF7\u5148\u8FD0\u884C `fab install`\u3002",
976
+ "cli.config.errors.uninit-workspace.message": "\u5DE5\u4F5C\u533A\u5C1A\u672A\u521D\u59CB\u5316\u3002\u8BF7\u5148\u8FD0\u884C `fabric install`\u3002",
941
977
  "cli.config.errors.invalid-int": "\u5FC5\u987B\u662F\u6B63\u6574\u6570\u3002",
942
978
  "cli.config.errors.unknown-field": "\u672A\u77E5\u5B57\u6BB5\u9009\u62E9 \u2014 \u5DF2\u8DF3\u8FC7\u3002",
943
979
  "cli.config.errors.no-enum-options": "\u8BE5\u5B57\u6BB5\u6CA1\u6709\u53EF\u9009\u679A\u4E3E\u503C \u2014 \u5DF2\u8DF3\u8FC7\u3002",
@@ -964,13 +1000,13 @@ var zhCNMessages = {
964
1000
  "cli.config.fields.maintenance_hint_cooldown_days.description": "\u7EF4\u62A4\u63D0\u793A\u518D\u6B21\u89E6\u53D1\u524D\u7684\u51B7\u5374\u65F6\u95F4\uFF08\u5929\uFF09\u3002",
965
1001
  "cli.config.fields.audit_mode.label": "\u5BA1\u8BA1\u6A21\u5F0F",
966
1002
  "cli.config.fields.audit_mode.description": "human-lock \u4E0E\u6F02\u79FB\u68C0\u6D4B\u7684\u5BA1\u8BA1\u7C92\u5EA6\uFF08strict / warn / off\uFF09\u3002",
967
- "cli.doctor.description": "\u8FD0\u884C Fabric \u76EE\u6807\u6001\u8BCA\u65AD\uFF08meta \u540C\u6B65\u3001\u77E5\u8BC6\u7D22\u5F15\u3001bootstrap\u3001events ledger\u3001human-lock \u6F02\u79FB\uFF09\u3002\n\n\u793A\u4F8B\uFF1A\n fab doctor \u53EA\u8BFB\u8BCA\u65AD\u62A5\u544A\n fab doctor --fix \u4FEE\u590D\u6D3E\u751F\u72B6\u6001\uFF08meta + \u7D22\u5F15\uFF09\n fab doctor --fix-knowledge \u5E94\u7528\u77E5\u8BC6\u5E93 lint \u53D8\u66F4\uFF08\u964D\u7EA7 / \u5F52\u6863\uFF09\n fab doctor --json --strict \u673A\u5668\u53EF\u8BFB\u8F93\u51FA\uFF0Cwarning \u89C6\u4E3A\u5931\u8D25",
1003
+ "cli.doctor.description": "\u8FD0\u884C Fabric \u76EE\u6807\u6001\u8BCA\u65AD\uFF08meta \u540C\u6B65\u3001\u77E5\u8BC6\u7D22\u5F15\u3001bootstrap\u3001events ledger\u3001human-lock \u6F02\u79FB\uFF09\u3002\n\n\u793A\u4F8B\uFF1A\n fabric doctor \u53EA\u8BFB\u8BCA\u65AD\u62A5\u544A\n fabric doctor --fix \u4FEE\u590D\u6D3E\u751F\u72B6\u6001\uFF08meta + \u7D22\u5F15\uFF09\n fabric doctor --fix-knowledge \u5E94\u7528\u77E5\u8BC6\u5E93 lint \u53D8\u66F4\uFF08\u964D\u7EA7 / \u5F52\u6863\uFF09\n fabric doctor --json --strict \u673A\u5668\u53EF\u8BFB\u8F93\u51FA\uFF0Cwarning \u89C6\u4E3A\u5931\u8D25",
968
1004
  "doctor.section.fixable": "\u53EF\u4FEE\u590D\u9519\u8BEF\uFF1A",
969
1005
  "doctor.section.manual": "\u9700\u624B\u52A8\u4FEE\u590D\uFF1A",
970
1006
  "doctor.section.warnings": "\u8B66\u544A\uFF1A",
971
1007
  "doctor.section.fix-knowledge-mutations": "Fix-knowledge \u53D8\u66F4\uFF1A",
972
1008
  // v2.0.0-rc.29 REVIEW (codex LOW-2): F2 的 payload 阈值之前只出现在 JSON envelope,
973
- // 人类输出看不到,导致改了 mcpPayloadLimits 之后没法用 `fab doctor` 快速确认是否生效。
1009
+ // 人类输出看不到,导致改了 mcpPayloadLimits 之后没法用 `fabric doctor` 快速确认是否生效。
974
1010
  "doctor.section.payload-limits": "MCP payload \u9608\u503C\uFF1A",
975
1011
  "doctor.payload-limits.line": "warn={warnKb} KB, hard={hardKb} KB (\u6765\u6E90: {source})",
976
1012
  // rc.20 TASK-07: cite-coverage 人类可读格式化键。
@@ -1006,7 +1042,7 @@ var zhCNMessages = {
1006
1042
  "cite-coverage.contract.cite_id_unresolved": "\u5F15\u7528 ID \u4E0D\u5B58\u5728",
1007
1043
  "cite-coverage.contract.skip_count": "skip \u6876",
1008
1044
  "cite-coverage.contract.status.ok": "\u6B63\u5E38",
1009
- "cite-coverage.contract.status.skipped_bootstrap_drift": "\u5DF2\u8DF3\u8FC7\uFF08bootstrap drift \u2014 \u8BF7\u8FD0\u884C fab install\uFF09",
1045
+ "cite-coverage.contract.status.skipped_bootstrap_drift": "\u5DF2\u8DF3\u8FC7\uFF08bootstrap drift \u2014 \u8BF7\u8FD0\u884C fabric install\uFF09",
1010
1046
  "cite-coverage.contract.status.awaiting_marker": "\u7B49\u5F85\u9996\u6B21 marker emit",
1011
1047
  // 复数知识类型(rc.29 BUG-C1: 与统一后的 KnowledgeTypeSchema 枚举字面量逐字对齐)+ 第六桶 unresolved。
1012
1048
  "cite-coverage.contract.type.decisions": "decisions",
@@ -1033,6 +1069,9 @@ var zhCNMessages = {
1033
1069
  "cli.doctor.args.strict.description": "\u5C06 warning \u4E5F\u89C6\u4E3A\u5931\u8D25\u3002",
1034
1070
  "cli.doctor.args.fix-knowledge.description": "\u5E94\u7528\u77E5\u8BC6\u5E93 lint \u53D8\u66F4\uFF1A\u964D\u7EA7\u5B64\u7ACB\u7684\u89C4\u8303\u6761\u76EE\u3001\u5F52\u6863\u9648\u65E7 draft\u3001\u4FEE\u6B63\u6F02\u79FB\u7684\u7D22\u5F15\u8BA1\u6570\u5668\u3002\u9ED8\u8BA4 doctor \u8FD0\u884C\u4ECD\u7136\u53EA\u8BFB\u3002",
1035
1071
  "cli.doctor.args.yes.description": "\u8DF3\u8FC7 --fix-knowledge \u7684\u5B89\u5168\u786E\u8BA4\uFF1B\u975E tty \u8C03\u7528\u5FC5\u987B\u663E\u5F0F\u8BBE\u7F6E\u8BE5\u6807\u8BB0\uFF0C\u6216\u5728\u73AF\u5883\u53D8\u91CF\u4E2D\u8BBE\u7F6E FABRIC_NONINTERACTIVE=1\u3002",
1072
+ // rc.35 TASK-12 (P0-11): --verbose 展开 maintainer 受众的 remediation。
1073
+ "cli.doctor.args.verbose.description": "\u5C55\u5F00\u5168\u90E8 action hint,\u5305\u62EC maintainer \u53D7\u4F17\u7684(Fabric \u8D21\u732E\u8005\u4FEE\u6E90\u7801\u7528)\u3002\u9ED8\u8BA4 npm \u7EC8\u7AEF\u7528\u6237\u89C6\u56FE\u4F1A\u628A\u8FD9\u4E9B\u6298\u53E0\u3002",
1074
+ "doctor.maintainer-hint-folded": "(maintainer-only remediation \u2014 \u52A0 `fabric doctor --verbose` \u67E5\u770B)",
1036
1075
  "cli.doctor.errors.fix-knowledge-fix-mutually-exclusive": "--fix-knowledge \u4E0E --fix \u4E0D\u53EF\u540C\u65F6\u4F7F\u7528\u3002--fix-knowledge \u4FEE\u6539\u7528\u6237\u77E5\u8BC6\u72B6\u6001\uFF08\u964D\u7EA7/\u5F52\u6863\uFF09\uFF1B--fix \u4FEE\u590D\u6D3E\u751F\u72B6\u6001\uFF08meta/\u7D22\u5F15\uFF09\u3002\u8BF7\u5206\u522B\u8FD0\u884C\u3002",
1037
1076
  // rc.20 TASK-05: --cite-coverage 报告参数;只读,与 --fix/--fix-knowledge 互斥。
1038
1077
  "cli.doctor.args.cite-coverage.description": "Cite \u653F\u7B56\u5408\u89C4\u62A5\u544A(\u53EA\u8BFB;\u8DF3\u8FC7\u6807\u51C6\u68C0\u67E5)",
@@ -1049,7 +1088,7 @@ var zhCNMessages = {
1049
1088
  "cli.doctor.args.auto.description": "\u4E0E --enrich-descriptions \u642D\u914D\uFF1A\u4E3A\u7F3A\u5931\u5B57\u6BB5\u5199\u5165\u786E\u5B9A\u6027 stub \u503C\u3002\u4E0D\u52A0 --auto \u4EC5\u505A\u53EA\u8BFB\u626B\u63CF\u3002",
1050
1089
  "cli.doctor.args.dry-run.description": "\u4E0E --enrich-descriptions --auto \u6216 --fix \u642D\u914D:\u4EC5\u9884\u89C8\u6539\u52A8\u8BA1\u5212,\u4E0D\u5199\u5165\u78C1\u76D8\u3002fix-dry-run \u8F93\u51FA\u4E0E --fix \u76F8\u540C\u7684 fixable_errors \u5217\u8868,\u4F46\u4E0D\u6267\u884C\u4EFB\u4F55 mutation\u3002",
1051
1090
  // v2.0.0-rc.33 W4-B1 (T6 P2): --fix --dry-run banner — 出现在 report 之前, 让用户明确没有发生 mutation。
1052
- "cli.doctor.fix-dry-run-banner": "[dry-run] \u672A\u5E94\u7528\u4EFB\u4F55 mutation\u3002\u4E0B\u65B9 fixable_errors \u5217\u8868\u5C31\u662F `fab doctor --fix` \u4F1A\u5904\u7406\u7684\u9879;\u53BB\u6389 --dry-run \u518D\u8DD1\u53EF\u5B9E\u9645\u4FEE\u590D\u3002",
1091
+ "cli.doctor.fix-dry-run-banner": "[dry-run] \u672A\u5E94\u7528\u4EFB\u4F55 mutation\u3002\u4E0B\u65B9 fixable_errors \u5217\u8868\u5C31\u662F `fabric doctor --fix` \u4F1A\u5904\u7406\u7684\u9879;\u53BB\u6389 --dry-run \u518D\u8DD1\u53EF\u5B9E\u9645\u4FEE\u590D\u3002",
1053
1092
  "cli.doctor.errors.enrich-descriptions-mutex": "--enrich-descriptions \u4E0D\u80FD\u4E0E --fix / --fix-knowledge / --cite-coverage \u540C\u65F6\u4F7F\u7528,\u8BF7\u5206\u522B\u8FD0\u884C\u3002",
1054
1093
  "doctor.enrich.allComplete": "\u6240\u6709\u6B63\u5F0F\u77E5\u8BC6\u6761\u76EE\u5747\u5DF2\u5305\u542B intent_clues / tech_stack / impact / must_read_if\u3002",
1055
1094
  // rc.26 TASK-02a: doctor foundation-batch check messages.
@@ -1057,21 +1096,21 @@ var zhCNMessages = {
1057
1096
  "doctor.check.bootstrap_marker_migration.ok": "bootstrap \u76EE\u6807\u6587\u4EF6\u4E2D\u672A\u68C0\u6D4B\u5230\u65E7 fabric:knowledge-base marker\u3002",
1058
1097
  "doctor.check.bootstrap_marker_migration.message.singular": "{count} \u4E2A\u6587\u4EF6\u4ECD\u5E26\u6709\u65E7 fabric:knowledge-base bootstrap marker\uFF1A{list}\u3002",
1059
1098
  "doctor.check.bootstrap_marker_migration.message.plural": "{count} \u4E2A\u6587\u4EF6\u4ECD\u5E26\u6709\u65E7 fabric:knowledge-base bootstrap marker\uFF1A{list}\u3002",
1060
- "doctor.check.bootstrap_marker_migration.remediation": "\u8FD0\u884C `fab doctor --fix` \u8FC1\u79FB\u5230 fabric:bootstrap marker",
1099
+ "doctor.check.bootstrap_marker_migration.remediation": "\u8FD0\u884C `fabric doctor --fix` \u8FC1\u79FB\u5230 fabric:bootstrap marker",
1061
1100
  "doctor.check.bootstrap_snapshot_drift.name": "Bootstrap snapshot drift",
1062
1101
  "doctor.check.bootstrap_snapshot_drift.message.drift": ".fabric/AGENTS.md \u5185\u5BB9\u4E0E BOOTSTRAP_CANONICAL \u9010\u5B57\u8282\u4E0D\u4E00\u81F4\u3002",
1063
- "doctor.check.bootstrap_snapshot_drift.remediation.drift": "\u8FD0\u884C `fab doctor --fix` \u6062\u590D canonical bootstrap snapshot",
1102
+ "doctor.check.bootstrap_snapshot_drift.remediation.drift": "\u8FD0\u884C `fabric doctor --fix` \u6062\u590D canonical bootstrap snapshot",
1064
1103
  "doctor.check.bootstrap_snapshot_drift.ok.ok": ".fabric/AGENTS.md \u4E0E BOOTSTRAP_CANONICAL \u9010\u5B57\u8282\u4E00\u81F4\u3002",
1065
1104
  "doctor.check.bootstrap_snapshot_drift.ok.missing_delegated": ".fabric/AGENTS.md \u4E0D\u5B58\u5728\uFF0C\u5DF2\u4EA4\u7531 bootstrap_anchor_missing \u62A5\u544A\u3002",
1066
1105
  "doctor.check.managed_block_drift.name": "Managed block drift",
1067
1106
  "doctor.check.managed_block_drift.message.singular": "{count} \u4E2A three-end managed block \u4E0E\u671F\u671B\u5185\u5BB9\uFF08snapshot + \u53EF\u9009 project-rules concat\uFF09\u4E0D\u4E00\u81F4\uFF1A{list}\u3002",
1068
1107
  "doctor.check.managed_block_drift.message.plural": "{count} \u4E2A three-end managed block \u4E0E\u671F\u671B\u5185\u5BB9\uFF08snapshot + \u53EF\u9009 project-rules concat\uFF09\u4E0D\u4E00\u81F4\uFF1A{list}\u3002",
1069
- "doctor.check.managed_block_drift.remediation": "\u8FD0\u884C `fab doctor --fix` \u4ECE canonical \u6062\u590D three-end managed blocks",
1108
+ "doctor.check.managed_block_drift.remediation": "\u8FD0\u884C `fabric doctor --fix` \u4ECE canonical \u6062\u590D three-end managed blocks",
1070
1109
  "doctor.check.managed_block_drift.ok.ok": "Three-end managed blocks \u4E0E expectedBody \u9010\u5B57\u8282\u4E00\u81F4\u3002",
1071
1110
  "doctor.check.managed_block_drift.ok.no_managed_block": "\u672A\u68C0\u6D4B\u5230 three-end managed blocks\uFF1B\u53EF\u80FD\u5C1A\u672A\u4F20\u64AD\uFF0C\u6216\u4ECD\u5904\u4E8E legacy-marker \u72B6\u6001\u3002",
1072
1111
  "doctor.check.bootstrap_anchor.name": "Bootstrap anchor",
1073
1112
  "doctor.check.bootstrap_anchor.message.missing": "repo root \u4E0B AGENTS.md \u4E0E CLAUDE.md \u90FD\u4E0D\u5B58\u5728\u3002Fabric \u9700\u8981\u5728\u9879\u76EE\u6839\u76EE\u5F55\u5B58\u5728 bootstrap anchor \u6587\u4EF6\u3002",
1074
- "doctor.check.bootstrap_anchor.remediation.missing": "\u8FD0\u884C `fab install` \u5728 repo root \u751F\u6210 AGENTS.md / CLAUDE.md bootstrap anchor\u3002",
1113
+ "doctor.check.bootstrap_anchor.remediation.missing": "\u8FD0\u884C `fabric install` \u5728 repo root \u751F\u6210 AGENTS.md / CLAUDE.md bootstrap anchor\u3002",
1075
1114
  "doctor.check.bootstrap_anchor.ok": "repo root \u4E0B\u5DF2\u5B58\u5728 Bootstrap anchor\uFF1A{present}\u3002",
1076
1115
  "doctor.check.baseline_filename_format.name": "Baseline \u6587\u4EF6\u540D\u683C\u5F0F",
1077
1116
  "doctor.check.baseline_filename_format.ok": "\u6240\u6709 baseline knowledge \u6587\u4EF6\u90FD\u4F7F\u7528 canonical `${id}--${slug}.md` \u6587\u4EF6\u540D\u683C\u5F0F\u3002",
@@ -1082,60 +1121,64 @@ var zhCNMessages = {
1082
1121
  "doctor.check.knowledge_dir_missing.name": "Knowledge layout",
1083
1122
  "doctor.check.knowledge_dir_missing.message.singular": "{count} \u4E2A\u5FC5\u9700 knowledge subdir \u7F3A\u5931\uFF1A{list}\u3002",
1084
1123
  "doctor.check.knowledge_dir_missing.message.plural": "{count} \u4E2A\u5FC5\u9700 knowledge subdir \u7F3A\u5931\uFF1A{list}\u3002",
1085
- "doctor.check.knowledge_dir_missing.remediation": "\u8FD0\u884C `fab doctor --fix` \u521B\u5EFA\u7F3A\u5931\u7684 .fabric/knowledge/* subdirectories\u3002",
1124
+ "doctor.check.knowledge_dir_missing.remediation": "\u8FD0\u884C `fabric doctor --fix` \u521B\u5EFA\u7F3A\u5931\u7684 .fabric/knowledge/* subdirectories\u3002",
1086
1125
  "doctor.check.knowledge_dir_missing.ok": "\u5168\u90E8 {count} \u4E2A\u5FC5\u9700 .fabric/knowledge/* subdirectories \u5747\u5DF2\u5B58\u5728\u3002",
1087
1126
  "doctor.check.forensic.name": "Scan evidence",
1088
1127
  "doctor.check.forensic.message.missing.singular": "{error} \u5B9E\u65F6\u626B\u63CF\u68C0\u6D4B\u5230 {frameworkKind}\uFF0C\u5171\u6709 {count} \u4E2A\u5165\u53E3\u70B9\u3002",
1089
1128
  "doctor.check.forensic.message.missing.plural": "{error} \u5B9E\u65F6\u626B\u63CF\u68C0\u6D4B\u5230 {frameworkKind}\uFF0C\u5171\u6709 {count} \u4E2A\u5165\u53E3\u70B9\u3002",
1090
1129
  "doctor.check.forensic.message.missing-default": ".fabric/forensic.json \u7F3A\u5931\u3002",
1091
1130
  "doctor.check.forensic.message.invalid-default": ".fabric/forensic.json \u65E0\u6548\u3002",
1092
- "doctor.check.forensic.remediation": "\u8FD0\u884C `fab install` \u91CD\u65B0\u751F\u6210 .fabric/forensic.json\u3002",
1131
+ "doctor.check.forensic.remediation": "\u8FD0\u884C `fabric install` \u91CD\u65B0\u751F\u6210 .fabric/forensic.json\u3002",
1093
1132
  "doctor.check.forensic.ok": ".fabric/forensic.json \u5BF9 {frameworkKind} \u6709\u6548\u3002",
1094
1133
  "doctor.check.agents_meta.name": "Agents metadata",
1095
1134
  "doctor.check.agents_meta.message.missing": ".fabric/agents.meta.json \u7F3A\u5931\u3002",
1096
- "doctor.check.agents_meta.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u4ECE .fabric/knowledge/ \u91CD\u5EFA agents.meta.json\u3002",
1135
+ "doctor.check.agents_meta.remediation.missing": "\u8FD0\u884C `fabric doctor --fix` \u4ECE .fabric/knowledge/ \u91CD\u5EFA agents.meta.json\u3002",
1097
1136
  "doctor.check.agents_meta.message.invalid-default": ".fabric/agents.meta.json \u65E0\u6548\u3002",
1098
- "doctor.check.agents_meta.remediation.invalid": "\u8FD0\u884C `fab doctor --fix` \u8BA9 reconcile \u4ECE .fabric/knowledge/ \u78C1\u76D8 ground-truth \u91CD\u5EFA agents.meta.json\uFF08rc.31 \u8D77\u517C\u5BB9\u5386\u53F2 schema \u7684 singular knowledge_type \u81EA\u52A8\u8FC1\u79FB\u5230 plural\uFF1B\u4E0D\u8981\u624B\u52A8\u5220\u9664 agents.meta.json\uFF0C\u4F1A\u4E22 counters envelope \u4E0E promote ledger \u5173\u8054\uFF09\u3002",
1137
+ // rc.35 TASK-09 (P0-14): 人话化的 schema 解析失败消息。
1138
+ "doctor.check.agents_meta.message.invalid-zod": ".fabric/agents.meta.json schema \u6821\u9A8C\u5931\u8D25 \u2014 {issues}\u3002\u8BE5\u6587\u4EF6\u5F88\u53EF\u80FD\u7531\u4E0D\u517C\u5BB9\u7248\u672C\u7684 fabric CLI \u5199\u5165,\u6216\u88AB\u624B\u5DE5\u7F16\u8F91\u3002",
1139
+ "doctor.check.agents_meta.message.invalid-from-old-cli": ".fabric/agents.meta.json schema \u6821\u9A8C\u5931\u8D25,\u56E0\u4E3A PATH \u4E0A\u7684\u5168\u5C40 `fabric` CLI ({version}) \u4F4E\u4E8E\u6700\u4F4E\u652F\u6301\u7248\u672C {minVersion}\u3002rc.31 \u5F15\u5165\u4E86\u5411\u540E\u517C\u5BB9\u7684 singular\u2192plural \u5F52\u4E00\u5316,\u65E7\u7248 CLI \u5199\u51FA\u7684\u6587\u4EF6\u81EA\u5DF1\u4E5F\u65E0\u6CD5\u89E3\u6790\u3002",
1140
+ "doctor.check.agents_meta.remediation.invalid": "\u8FD0\u884C `fabric doctor --fix` \u8BA9 reconcile \u4ECE .fabric/knowledge/ \u78C1\u76D8 ground-truth \u91CD\u5EFA agents.meta.json\uFF08rc.31 \u8D77\u517C\u5BB9\u5386\u53F2 schema \u7684 singular knowledge_type \u81EA\u52A8\u8FC1\u79FB\u5230 plural\uFF1B\u4E0D\u8981\u624B\u52A8\u5220\u9664 agents.meta.json\uFF0C\u4F1A\u4E22 counters envelope \u4E0E promote ledger \u5173\u8054\uFF09\u3002",
1099
1141
  "doctor.check.agents_meta.message.stale": ".fabric/agents.meta.json revision {revision} \u4E0E .fabric/knowledge \u6D3E\u751F revision {computedRevision} \u4E0D\u4E00\u81F4\u3002",
1100
- "doctor.check.agents_meta.remediation.stale": "\u53EF\u5FFD\u7565\uFF1Bengine \u4F1A\u5728\u4E0B\u4E00\u6B21 plan-context/get-sections \u8C03\u7528\u65F6\u81EA\u52A8\u4FEE\u590D\u3002\u9700\u8981\u663E\u5F0F reconcile \u65F6\u8FD0\u884C `fab doctor --fix`\u3002",
1142
+ "doctor.check.agents_meta.message.stale_hash_equal": ".fabric/agents.meta.json \u5DF2\u4E0E .fabric/knowledge \u5185\u5BB9\u4E00\u81F4\uFF08revision {revision}\uFF09\uFF0C\u4F46 mtime/counters \u6D3E\u751F\u72B6\u6001\u8FC7\u671F\u3002\u53EF\u5FFD\u7565\u3002",
1143
+ "doctor.check.agents_meta.remediation.stale": "\u53EF\u5FFD\u7565\uFF1Bengine \u4F1A\u5728\u4E0B\u4E00\u6B21 plan-context/get-sections \u8C03\u7528\u65F6\u81EA\u52A8\u4FEE\u590D\u3002\u9700\u8981\u663E\u5F0F reconcile \u65F6\u8FD0\u884C `fabric doctor --fix`\u3002",
1101
1144
  "doctor.check.agents_meta.ok": ".fabric/agents.meta.json revision {revision} \u5DF2\u4E0E .fabric/knowledge \u5BF9\u9F50\u3002",
1102
1145
  "doctor.check.rule_content_refs.name": "Rule content refs",
1103
1146
  "doctor.check.rule_content_refs.message.unavailable": "agents.meta.json \u6709\u6548\u524D\uFF0C\u65E0\u6CD5\u68C0\u67E5 content_ref entries\u3002",
1104
- "doctor.check.rule_content_refs.remediation.unavailable": "\u5148\u4FEE\u590D agents.meta.json\uFF1A\u8FD0\u884C `fab doctor --fix`\u3002",
1147
+ "doctor.check.rule_content_refs.remediation.unavailable": "\u5148\u4FEE\u590D agents.meta.json\uFF1A\u8FD0\u884C `fabric doctor --fix`\u3002",
1105
1148
  "doctor.check.rule_content_refs.message.outside.singular": "{count} \u4E2A content_ref entry \u4F4D\u4E8E .fabric/knowledge \u5916\u90E8\u3002",
1106
1149
  "doctor.check.rule_content_refs.message.outside.plural": "{count} \u4E2A content_ref entries \u4F4D\u4E8E .fabric/knowledge \u5916\u90E8\u3002",
1107
1150
  // v2.0.0-rc.33 W3-2 (T6 #12): 项目规则禁止手动编辑 agents.meta.json (见 .fabric/AGENTS.md); 改引导用户跑 doctor --fix 走 reconcile 路径 (rc.31+ 兼容自动剔除外部 refs)。
1108
- "doctor.check.rule_content_refs.remediation.outside": "\u8FD0\u884C `fab doctor --fix` \u8BA9 reconcile \u81EA\u52A8\u5254\u9664\u5916\u90E8 content_ref (rc.31+ \u517C\u5BB9)\u3002\u4E25\u7981\u624B\u52A8\u7F16\u8F91 agents.meta.json \u2014 engine \u4F1A\u81EA\u52A8 reconcile\u3002",
1109
- "doctor.check.rule_content_refs.message.missing.singular": "{count} \u4E2A content_ref target \u7F3A\u5931\u3002\u8FD0\u884C `fab doctor --fix` \u6267\u884C reconcile\u3002",
1110
- "doctor.check.rule_content_refs.message.missing.plural": "{count} \u4E2A content_ref targets \u7F3A\u5931\u3002\u8FD0\u884C `fab doctor --fix` \u6267\u884C reconcile\u3002",
1111
- "doctor.check.rule_content_refs.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u8BA9 agents.meta.json \u4E0E .fabric/knowledge/ \u4E2D\u7684\u73B0\u6709\u6587\u4EF6 reconcile\u3002",
1151
+ "doctor.check.rule_content_refs.remediation.outside": "\u8FD0\u884C `fabric doctor --fix` \u8BA9 reconcile \u81EA\u52A8\u5254\u9664\u5916\u90E8 content_ref (rc.31+ \u517C\u5BB9)\u3002\u4E25\u7981\u624B\u52A8\u7F16\u8F91 agents.meta.json \u2014 engine \u4F1A\u81EA\u52A8 reconcile\u3002",
1152
+ "doctor.check.rule_content_refs.message.missing.singular": "{count} \u4E2A content_ref target \u7F3A\u5931\u3002\u8FD0\u884C `fabric doctor --fix` \u6267\u884C reconcile\u3002",
1153
+ "doctor.check.rule_content_refs.message.missing.plural": "{count} \u4E2A content_ref targets \u7F3A\u5931\u3002\u8FD0\u884C `fabric doctor --fix` \u6267\u884C reconcile\u3002",
1154
+ "doctor.check.rule_content_refs.remediation.missing": "\u8FD0\u884C `fabric doctor --fix` \u8BA9 agents.meta.json \u4E0E .fabric/knowledge/ \u4E2D\u7684\u73B0\u6709\u6587\u4EF6 reconcile\u3002",
1112
1155
  "doctor.check.rule_content_refs.ok": "\u6240\u6709 content_ref entries \u90FD\u80FD\u89E3\u6790\u5230 .fabric/knowledge files\u3002",
1113
1156
  "doctor.check.knowledge_test_index.name": "Knowledge-test index",
1114
- "doctor.check.knowledge_test_index.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u91CD\u5EFA .fabric/.cache/knowledge-test.index.json\u3002",
1115
- "doctor.check.knowledge_test_index.remediation.invalid": "\u5220\u9664 .fabric/.cache/knowledge-test.index.json \u5E76\u8FD0\u884C `fab doctor --fix` \u91CD\u65B0\u751F\u6210\u3002",
1157
+ "doctor.check.knowledge_test_index.remediation.missing": "\u8FD0\u884C `fabric doctor --fix` \u91CD\u5EFA .fabric/.cache/knowledge-test.index.json\u3002",
1158
+ "doctor.check.knowledge_test_index.remediation.invalid": "\u5220\u9664 .fabric/.cache/knowledge-test.index.json \u5E76\u8FD0\u884C `fabric doctor --fix` \u91CD\u65B0\u751F\u6210\u3002",
1116
1159
  "doctor.check.knowledge_test_index.message.stale": ".fabric/.cache/knowledge-test.index.json \u5DF2\u8FC7\u671F\u3002",
1117
- "doctor.check.knowledge_test_index.remediation.stale": "\u8FD0\u884C `fab doctor --fix` \u91CD\u5EFA knowledge-test index\u3002",
1160
+ "doctor.check.knowledge_test_index.remediation.stale": "\u8FD0\u884C `fabric doctor --fix` \u91CD\u5EFA knowledge-test index\u3002",
1118
1161
  "doctor.check.knowledge_test_index.ok.link_singular.orphan_singular": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1119
1162
  "doctor.check.knowledge_test_index.ok.link_singular.orphan_plural": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1120
1163
  "doctor.check.knowledge_test_index.ok.link_plural.orphan_singular": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1121
1164
  "doctor.check.knowledge_test_index.ok.link_plural.orphan_plural": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1122
1165
  "doctor.check.event_ledger.name": "Event ledger",
1123
1166
  "doctor.check.event_ledger.message.missing": ".fabric/events.jsonl \u7F3A\u5931\u3002",
1124
- "doctor.check.event_ledger.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u521B\u5EFA .fabric/events.jsonl\u3002",
1167
+ "doctor.check.event_ledger.remediation.missing": "\u8FD0\u884C `fabric doctor --fix` \u521B\u5EFA .fabric/events.jsonl\u3002",
1125
1168
  "doctor.check.event_ledger.message.not_writable-default": ".fabric/events.jsonl \u4E0D\u53EF\u5199\u3002",
1126
1169
  "doctor.check.event_ledger.remediation.not_writable": "\u68C0\u67E5 .fabric/events.jsonl \u7684\u6587\u4EF6\u6743\u9650\uFF0C\u5E76\u786E\u8BA4\u6CA1\u6709\u5176\u4ED6\u8FDB\u7A0B\u6301\u6709\u5199\u9501\u3002",
1127
1170
  "doctor.check.event_ledger.message.invalid-default": ".fabric/events.jsonl \u65E0\u6548\u3002",
1128
1171
  // v2.0.0-rc.33 W3-1 (P0-6): archive-history 模式 — 引导用户先 mv 备份到 events.archive/ 保留历史, 再跑 --fix 重建空 ledger。与 rotateEventLedgerIfNeeded 的命名约定一致 (events-rotated-YYYY-MM-DD.jsonl 是滑窗 rotation; events-corrupted-YYYY-MM-DD.jsonl 是 invalid-fix 归档)。
1129
- "doctor.check.event_ledger.remediation.invalid": "\u5148\u5F52\u6863\u5386\u53F2 (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-corrupted-$(date +%Y-%m-%d).jsonl`), \u518D\u8FD0\u884C `fab doctor --fix` \u521B\u5EFA\u65B0\u7A7A ledger\u3002\u5386\u53F2\u4E8B\u4EF6\u4FDD\u7559\u5728 events.archive/ \u4E0D\u4E22\u3002",
1172
+ "doctor.check.event_ledger.remediation.invalid": "\u5148\u5F52\u6863\u5386\u53F2 (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-corrupted-$(date +%Y-%m-%d).jsonl`), \u518D\u8FD0\u884C `fabric doctor --fix` \u521B\u5EFA\u65B0\u7A7A ledger\u3002\u5386\u53F2\u4E8B\u4EF6\u4FDD\u7559\u5728 events.archive/ \u4E0D\u4E22\u3002",
1130
1173
  "doctor.check.event_ledger.ok": ".fabric/events.jsonl \u5DF2\u5B58\u5728\uFF0C\u53EF\u5199\uFF0C\u4E14\u53EF\u89E3\u6790\u3002",
1131
1174
  "doctor.check.mcp_config_in_wrong_file.name": "Claude MCP config \u4F4D\u7F6E",
1132
- "doctor.check.mcp_config_in_wrong_file.message": ".claude/settings.json \u5305\u542B mcpServers.fabric\uFF1B\u6B64\u6587\u4EF6\u4EC5\u7528\u4E8E hooks/permissions\u3002\u8FD0\u884C --fix \u79FB\u9664\u5B83\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C fab install \u5199\u5165 .mcp.json\u3002",
1133
- "doctor.check.mcp_config_in_wrong_file.remediation": "\u8FD0\u884C `fab doctor --fix` \u4ECE .claude/settings.json \u4E2D\u79FB\u9664 mcpServers.fabric\uFF0C\u7136\u540E\u8FD0\u884C `fab install` \u5199\u5165 .mcp.json\u3002",
1175
+ "doctor.check.mcp_config_in_wrong_file.message": ".claude/settings.json \u5305\u542B mcpServers.fabric\uFF1B\u6B64\u6587\u4EF6\u4EC5\u7528\u4E8E hooks/permissions\u3002\u8FD0\u884C --fix \u79FB\u9664\u5B83\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C fabric install \u5199\u5165 .mcp.json\u3002",
1176
+ "doctor.check.mcp_config_in_wrong_file.remediation": "\u8FD0\u884C `fabric doctor --fix` \u4ECE .claude/settings.json \u4E2D\u79FB\u9664 mcpServers.fabric\uFF0C\u7136\u540E\u8FD0\u884C `fabric install` \u5199\u5165 .mcp.json\u3002",
1134
1177
  "doctor.check.mcp_config_in_wrong_file.ok": "mcpServers.fabric \u4E0D\u5728 .claude/settings.json \u4E2D\u3002",
1135
1178
  "doctor.check.event_ledger_partial_write.name": "Event ledger partial write",
1136
1179
  "doctor.check.event_ledger_partial_write.ok.skipped": "\u65E0\u9700\u6267\u884C partial-write \u68C0\u67E5\uFF08ledger \u7F3A\u5931\u6216\u4E0D\u53EF\u5199\uFF09\u3002",
1137
1180
  "doctor.check.event_ledger_partial_write.message": "events.jsonl \u5728 byte offset {byteOffset} \u5904\u5B58\u5728 partial write\uFF08{byteLength} \u4E2A corrupted bytes\uFF09\u3002\u8FD0\u884C --fix \u622A\u65AD\u5E76\u4FDD\u7559 corrupted bytes\u3002",
1138
- "doctor.check.event_ledger_partial_write.remediation": "\u8FD0\u884C `fab doctor --fix` \u622A\u65AD partial write \u5E76\u5C06 events.jsonl \u6062\u590D\u5230\u6709\u6548\u72B6\u6001\u3002",
1181
+ "doctor.check.event_ledger_partial_write.remediation": "\u8FD0\u884C `fabric doctor --fix` \u622A\u65AD partial write \u5E76\u5C06 events.jsonl \u6062\u590D\u5230\u6709\u6548\u72B6\u6001\u3002",
1139
1182
  "doctor.check.event_ledger_partial_write.ok.clean": "events.jsonl \u6CA1\u6709 partial trailing write\u3002",
1140
1183
  // v2.0.0-rc.27 TASK-010 (audit §2.24): schema-compat 向前兼容警告类别。
1141
1184
  "doctor.check.event_ledger_schema_compat.name": "Event ledger schema \u517C\u5BB9\u6027",
@@ -1144,48 +1187,58 @@ var zhCNMessages = {
1144
1187
  "doctor.check.event_ledger_schema_compat.message.schema_version": "events.jsonl \u542B {count} \u884C `schema_version` \u4E0D\u88AB\u5F53\u524D CLI \u8BC6\u522B\uFF08\u6837\u672C: {samples}\uFF09\u3002",
1145
1188
  "doctor.check.event_ledger_schema_compat.message.event_type": "events.jsonl \u542B {count} \u884C `event_type` \u4E0D\u5728\u5F53\u524D schema \u4E2D\uFF08\u6837\u672C: {samples}\uFF09\u3002",
1146
1189
  // v2.0.0-rc.33 W3-1 (P0-6): archive-history 模式 — 同 event_ledger.invalid, 文案显式说"归档备份"而非"备份后重建",避免用户误以为旧 ledger 被丢弃。
1147
- "doctor.check.event_ledger_schema_compat.remediation": "\u5347\u7EA7 fab CLI \u5230\u4E0E server \u517C\u5BB9\u7684\u7248\u672C (\u9996\u9009);\u6216\u5148\u5F52\u6863\u5386\u53F2 (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-schema-mismatch-$(date +%Y-%m-%d).jsonl`),\u518D\u8DD1 `fab doctor --fix` \u521B\u5EFA\u65B0\u7A7A ledger\u3002\u5386\u53F2\u4E8B\u4EF6\u4FDD\u7559\u5728 events.archive/ \u4E0D\u4E22,\u53EF\u540E\u7EED\u624B\u52A8\u8FC1\u79FB\u3002",
1190
+ "doctor.check.event_ledger_schema_compat.remediation": "\u5347\u7EA7 fabric CLI \u5230\u4E0E server \u517C\u5BB9\u7684\u7248\u672C (\u9996\u9009);\u6216\u5148\u5F52\u6863\u5386\u53F2 (`mkdir -p .fabric/events.archive && mv .fabric/events.jsonl .fabric/events.archive/events-schema-mismatch-$(date +%Y-%m-%d).jsonl`),\u518D\u8DD1 `fabric doctor --fix` \u521B\u5EFA\u65B0\u7A7A ledger\u3002\u5386\u53F2\u4E8B\u4EF6\u4FDD\u7559\u5728 events.archive/ \u4E0D\u4E22,\u53EF\u540E\u7EED\u624B\u52A8\u8FC1\u79FB\u3002",
1148
1191
  // v2.0.0-rc.28 TASK-04 (audit §3.1): SKILL ref/ 镜像一致性检查。
1149
1192
  "doctor.check.skill_ref_mirror.name": "Skill ref \u955C\u50CF\u4E00\u81F4\u6027",
1150
1193
  "doctor.check.skill_ref_mirror.ok": "`.claude/skills/<slug>/ref/` \u4E0E `.codex/skills/<slug>/ref/` \u5B57\u8282\u4E00\u81F4\u3002",
1151
1194
  "doctor.check.skill_ref_mirror.message": "\u6709 {count} \u4E2A ref \u6587\u4EF6\u5728 `.claude/skills/` \u4E0E `.codex/skills/` \u4E4B\u95F4\u4E0D\u4E00\u81F4\uFF08\u8DEF\u5F84: {list}\uFF09\u3002\u53EF\u80FD\u67D0\u7AEF\u88AB\u624B\u52A8\u7F16\u8F91\u6216 install \u5199\u5165\u5931\u8D25\u3002",
1152
- "doctor.check.skill_ref_mirror.remediation": "\u8DD1 `fab install` \u4ECE canonical templates \u91CD\u5199\u4E24\u7AEF ref \u5B50\u6811\u4EE5\u6062\u590D\u4E00\u81F4\u3002",
1195
+ "doctor.check.skill_ref_mirror.remediation": "\u8DD1 `fabric install` \u4ECE canonical templates \u91CD\u5199\u4E24\u7AEF ref \u5B50\u6811\u4EE5\u6062\u590D\u4E00\u81F4\u3002",
1153
1196
  // v2.0.0-rc.33 W3-6 (P1-13): SKILL.md token budget lint。warn > 5K / error > 10K token (chars/3 估算)。基于 Anthropic 推荐 SKILL.md 热路径 ~3K, 超过 5K 已影响 progressive disclosure;超过 10K 是阻断级 (model context 浪费 + 加载延迟)。
1154
1197
  "doctor.check.skill_token_budget.name": "Skill token budget",
1155
1198
  "doctor.check.skill_token_budget.ok": "\u6240\u6709 .claude/skills/<slug>/SKILL.md \u5728 token budget \u5185 (warn 5K / error 10K)\u3002",
1156
1199
  "doctor.check.skill_token_budget.message.singular": "{count} \u4E2A SKILL.md \u8D85\u51FA token budget: {list}\u3002\u5EFA\u8BAE\u628A\u8BE6\u7EC6\u5185\u5BB9\u4E0B\u6C89\u5230 ref/ progressive disclosure\u3002",
1157
1200
  "doctor.check.skill_token_budget.message.plural": "{count} \u4E2A SKILL.md \u8D85\u51FA token budget: {list}\u3002\u5EFA\u8BAE\u628A\u8BE6\u7EC6\u5185\u5BB9\u4E0B\u6C89\u5230 ref/ progressive disclosure\u3002",
1158
- "doctor.check.skill_token_budget.remediation": "\u5C06\u8D85\u6807 SKILL.md \u4E2D\u7684\u8BE6\u7EC6 phase / worked-examples / decision \u8868\u79FB\u5230 `templates/skills/<slug>/ref/*.md`,SKILL.md \u70ED\u8DEF\u5F84\u53EA\u7559 trigger gate + \u5173\u952E phase \u6982\u8981;\u53C2\u8003 W1 progressive disclosure \u62C6\u5206\u6A21\u5F0F\u3002\u91CD\u65B0\u8DD1 `fab install` \u540C\u6B65\u4E24\u7AEF\u3002",
1201
+ "doctor.check.skill_token_budget.remediation": "\u5C06\u8D85\u6807 SKILL.md \u4E2D\u7684\u8BE6\u7EC6 phase / worked-examples / decision \u8868\u79FB\u5230 `templates/skills/<slug>/ref/*.md`,SKILL.md \u70ED\u8DEF\u5F84\u53EA\u7559 trigger gate + \u5173\u952E phase \u6982\u8981;\u53C2\u8003 W1 progressive disclosure \u62C6\u5206\u6A21\u5F0F\u3002\u91CD\u65B0\u8DD1 `fabric install` \u540C\u6B65\u4E24\u7AEF\u3002",
1159
1202
  // v2.0.0-rc.33 W3-7 (P1-14): SKILL.md description 结构 lint。代理 trigger-recall (真 LLM 测要 live model, W1 已用 gemini 跑过);本 lint 抓回归: description 缺失 / 超 60 token / 缺中文 trigger / 缺英文 trigger。
1160
1203
  "doctor.check.skill_description.name": "Skill description quality",
1161
1204
  "doctor.check.skill_description.ok": "\u6240\u6709 SKILL.md description \u5B57\u6BB5\u7ED3\u6784\u826F\u597D (\u975E\u7A7A / <60 token / \u4E2D\u82F1\u53CC\u8BED trigger)\u3002",
1162
1205
  "doctor.check.skill_description.message.singular": "{count} \u4E2A SKILL.md description \u7ED3\u6784\u95EE\u9898: {list}\u3002description \u662F host \u7AEF auto-invoke \u7684\u4E3B\u8981\u5339\u914D\u4FE1\u53F7\u3002",
1163
1206
  "doctor.check.skill_description.message.plural": "{count} \u4E2A SKILL.md description \u7ED3\u6784\u95EE\u9898: {list}\u3002description \u662F host \u7AEF auto-invoke \u7684\u4E3B\u8981\u5339\u914D\u4FE1\u53F7\u3002",
1164
- "doctor.check.skill_description.remediation": "\u7F16\u8F91 `packages/cli/templates/skills/<slug>/SKILL.md` frontmatter `description:` \u5B57\u6BB5: (1) \u975E\u7A7A; (2) <60 token (chars/3 \u4F30\u7B97, \u7EA6 180 \u5B57\u7B26); (3) \u81F3\u5C11 1 \u4E2A\u4E2D\u6587 trigger \u77ED\u8BED; (4) \u81F3\u5C11 1 \u4E2A\u82F1\u6587 trigger \u77ED\u8BED\u3002\u53C2\u8003 W1 description rewrite \u98CE\u683C\u3002\u91CD\u65B0\u8DD1 `fab install` \u540C\u6B65\u4E24\u7AEF\u3002\u5982\u9700\u9A8C\u8BC1 recall, \u8DD1 W1 \u7684 gemini delegate (\u89C1 .workflow/.scratchpad/rc33-plan/W1-VERIFY-RESULT.md)\u3002",
1207
+ "doctor.check.skill_description.remediation": "\u7F16\u8F91 `packages/cli/templates/skills/<slug>/SKILL.md` frontmatter `description:` \u5B57\u6BB5: (1) \u975E\u7A7A; (2) <60 token (chars/3 \u4F30\u7B97, \u7EA6 180 \u5B57\u7B26); (3) \u81F3\u5C11 1 \u4E2A\u4E2D\u6587 trigger \u77ED\u8BED; (4) \u81F3\u5C11 1 \u4E2A\u82F1\u6587 trigger \u77ED\u8BED\u3002\u53C2\u8003 W1 description rewrite \u98CE\u683C\u3002\u91CD\u65B0\u8DD1 `fabric install` \u540C\u6B65\u4E24\u7AEF\u3002\u5982\u9700\u9A8C\u8BC1 recall, \u8DD1 W1 \u7684 gemini delegate (\u89C1 .workflow/.scratchpad/rc33-plan/W1-VERIFY-RESULT.md)\u3002",
1165
1208
  // v2.0.0-rc.33 W3-3 (P1-3): cite-policy Goodhart 模式检测。扫 7d 内 assistant_turn_observed 事件, 4 个 anti-pattern (G1 仪式化 / G2 抄底引用 / G3 chained-from 滥用 / G5 placeholder cite)。warning 级 (启发式有 false-positive, 不阻断)。
1166
1209
  "doctor.check.cite_goodhart.name": "Cite-policy Goodhart",
1167
1210
  "doctor.check.cite_goodhart.ok": "\u8FC7\u53BB 7d \u672A\u68C0\u6D4B\u5230 cite-policy Goodhart \u53CD\u6A21\u5F0F\u3002",
1168
1211
  "doctor.check.cite_goodhart.message.singular": "\u68C0\u6D4B\u5230 {count} \u4E2A cite-policy Goodhart \u6A21\u5F0F: {list}\u3002",
1169
1212
  "doctor.check.cite_goodhart.message.plural": "\u68C0\u6D4B\u5230 {count} \u4E2A cite-policy Goodhart \u6A21\u5F0F: {list}\u3002",
1170
- "doctor.check.cite_goodhart.remediation": "\u5BA1\u9605\u89E6\u53D1\u7684 pattern: G1 \u4EEA\u5F0F\u5316 \u2192 \u540C\u4E00 [recalled] cite \u91CD\u590D\u7528,\u8BE5\u628A KB \u771F\u6B63\u843D\u5230 contract; G2 \u6284\u5E95\u5F15\u7528 \u2192 > 60% recalled \u7528 skip: \u662F\u7ED5\u8FC7 contract, review skip reason \u771F\u5B9E\u6027; G3 chained-from \u6EE5\u7528 \u2192 chained-from \u6807\u4E86\u4F46\u6CA1 commitment, \u8981\u8865 operators \u6216\u6539\u7528\u5176\u4ED6 tag; G5 placeholder cite \u2192 'KB: none' / [unspecified] \u592A\u591A, \u8BE5\u7528\u5177\u4F53 sentinel \u5982 [no-relevant] / [not-applicable]\u3002\u8BE6\u7EC6\u6570\u636E\u8DD1 `fab doctor --cite-coverage --since=7d`\u3002",
1213
+ "doctor.check.cite_goodhart.remediation": "\u5BA1\u9605\u89E6\u53D1\u7684 pattern: G1 \u4EEA\u5F0F\u5316 \u2192 \u540C\u4E00 [recalled] cite \u91CD\u590D\u7528,\u8BE5\u628A KB \u771F\u6B63\u843D\u5230 contract; G2 \u6284\u5E95\u5F15\u7528 \u2192 > 60% recalled \u7528 skip: \u662F\u7ED5\u8FC7 contract, review skip reason \u771F\u5B9E\u6027; G3 chained-from \u6EE5\u7528 \u2192 chained-from \u6807\u4E86\u4F46\u6CA1 commitment, \u8981\u8865 operators \u6216\u6539\u7528\u5176\u4ED6 tag; G5 placeholder cite \u2192 'KB: none' / [unspecified] \u592A\u591A, \u8BE5\u7528\u5177\u4F53 sentinel \u5982 [no-relevant] / [not-applicable]\u3002\u8BE6\u7EC6\u6570\u636E\u8DD1 `fabric doctor --cite-coverage --since=7d`\u3002",
1171
1214
  // v2.0.0-rc.33 W4-A4 (T5 P2): draft-backlog lint。rc.32 baseline 92% entry 卡在 draft, 揭示 promote 断流。> 50% draft 触发 warning (workspace 必须 >= 10 entries 才计算比率, 避免小语料噪音)。
1172
1215
  "doctor.check.draft_backlog.name": "Knowledge draft backlog",
1173
1216
  "doctor.check.draft_backlog.ok": "canonical knowledge entries \u4E2D draft \u5360\u6BD4\u6B63\u5E38 (< 50%, \u6216 workspace \u592A\u5C0F\u4E0D\u8BC4)\u3002",
1174
1217
  "doctor.check.draft_backlog.message": "{draftCount}/{totalCount} ({pct}%) canonical knowledge entries \u5361\u5728 draft maturity \u2014 promote \u65AD\u6D41 (rc.32 baseline 92%)\u3002",
1175
1218
  "doctor.check.draft_backlog.remediation": "\u8C03 `/fabric-review` \u6279\u91CF\u5BA1 draft entries: approve \u5347 verified/proven, reject \u4E22, modify \u4FEE\u3002draft \u957F\u671F\u5806\u79EF\u901A\u5E38\u610F\u5473\u7740 archive skill \u4EA7 draft \u592A\u5FEB\u6216 review skill \u6CA1\u8DDF\u4E0A\u3002",
1219
+ // rc.36 TASK-05 (P0-8): empty-tags ratio warn.
1220
+ "doctor.check.knowledge_tags_empty.name": "Knowledge tags coverage",
1221
+ "doctor.check.knowledge_tags_empty.ok": "canonical knowledge entries \u4E2D empty tags \u5360\u6BD4\u6B63\u5E38 (\u2264 50%, \u6216 workspace \u592A\u5C0F\u4E0D\u8BC4)\u3002",
1222
+ "doctor.check.knowledge_tags_empty.message": "{emptyCount}/{totalCount} ({pct}%) canonical knowledge entries \u7684 `tags:` \u4E3A\u7A7A \u2014 \u4E3B\u9898\u805A\u7C7B\u4E0E\u8DE8\u6761\u76EE\u68C0\u7D22\u9000\u5316\u3002fabric-archive / fabric-import skill \u5E94\u6BCF\u4E2A entry \u4EA7 2-4 \u4E2A tag\u3002",
1223
+ "doctor.check.knowledge_tags_empty.remediation": "\u4E0B\u4E00\u8F6E archive/import \u65F6,\u5728 frontmatter `tags:` \u5199 2-4 \u4E2A kebab-case \u4E3B\u9898\u8BCD;\u6279\u91CF\u8865\u65E7 entry tag \u7528 `/fabric-review` modify \u6D41\u3002",
1224
+ // rc.36 TASK-09 (P1-NEW1): drift_detected 未消化告警。
1225
+ "doctor.check.drift_unconsumed.name": "Knowledge drift unconsumed",
1226
+ "doctor.check.drift_unconsumed.ok": "\u8FD1 30 \u5929\u5185 knowledge_drift_detected \u4E8B\u4EF6\u5DF2\u88AB\u5BF9\u5E94 knowledge_demoted \u6D88\u5316,\u6216\u4E8B\u4EF6\u6570\u592A\u5C11\u4E0D\u8BC4\u3002",
1227
+ "doctor.check.drift_unconsumed.message": "\u8FD1 30 \u5929\u5185 knowledge_drift_detected \u4E8B\u4EF6 {driftCount} \u6B21,knowledge_demoted \u4E8B\u4EF6 {demoteCount} \u6B21\u3002drift > demote \u81F3\u5C11 5 \u2192 \u90E8\u5206 drift \u6CA1\u88AB\u6D88\u5316,KB \u4F1A\u7F13\u6162\u5931\u6D3B\u3002",
1228
+ "doctor.check.drift_unconsumed.remediation": "rc.36 \u6CA1\u6709 auto-demote pipeline,\u9700\u624B\u52A8\u5904\u7406:\u8FD0\u884C `fabric doctor --fix` \u89E6\u53D1 orphan-demote / stale-archive \u81EA\u6108\u6D41,\u6216\u8C03 `/fabric-review` \u4E3B\u52A8\u5BA1 drift \u6807\u8BB0\u7684\u6761\u76EE\u3002rc.37 \u8BA1\u5212\u4E0A\u7EBF\u81EA\u52A8 14-day demote\u3002",
1176
1229
  "doctor.check.meta_manually_diverged.name": "Meta manual divergence",
1177
1230
  "doctor.check.meta_manually_diverged.ok.unreadable": "agents.meta.json \u4E0D\u53EF\u8BFB\uFF0C\u8DF3\u8FC7 divergence \u68C0\u67E5\u3002",
1178
1231
  "doctor.check.meta_manually_diverged.message.extra.singular": "agents.meta.json \u4E2D\u6709 {count} \u4E2A entry \u5728\u78C1\u76D8\u4E0A\u6CA1\u6709\u5BF9\u5E94\u6587\u4EF6\u3002\u8FD0\u884C --fix \u6267\u884C reconcile\u3002",
1179
1232
  "doctor.check.meta_manually_diverged.message.extra.plural": "agents.meta.json \u4E2D\u6709 {count} \u4E2A entries \u5728\u78C1\u76D8\u4E0A\u6CA1\u6709\u5BF9\u5E94\u6587\u4EF6\u3002\u8FD0\u884C --fix \u6267\u884C reconcile\u3002",
1180
- "doctor.check.meta_manually_diverged.remediation.extra": "\u8FD0\u884C `fab doctor --fix` \u8BA9 agents.meta.json \u4E0E\u78C1\u76D8\u4E0A\u5F53\u524D\u7684 rule files reconcile\u3002",
1233
+ "doctor.check.meta_manually_diverged.remediation.extra": "\u8FD0\u884C `fabric doctor --fix` \u8BA9 agents.meta.json \u4E0E\u78C1\u76D8\u4E0A\u5F53\u524D\u7684 rule files reconcile\u3002",
1181
1234
  "doctor.check.meta_manually_diverged.message.hash.singular": "agents.meta.json \u4E2D\u6709 {count} \u4E2A entry \u7684 hash \u4E0E\u78C1\u76D8\u6587\u4EF6\u4E0D\u5339\u914D\u3002\u8FD0\u884C --fix \u6267\u884C reconcile\u3002",
1182
1235
  "doctor.check.meta_manually_diverged.message.hash.plural": "agents.meta.json \u4E2D\u6709 {count} \u4E2A entries \u7684 hash \u4E0E\u78C1\u76D8\u6587\u4EF6\u4E0D\u5339\u914D\u3002\u8FD0\u884C --fix \u6267\u884C reconcile\u3002",
1183
- "doctor.check.meta_manually_diverged.remediation.hash": "\u8FD0\u884C `fab doctor --fix` \u8BA9 agents.meta.json \u4E0E\u5F53\u524D rule file \u5185\u5BB9 reconcile\u3002",
1236
+ "doctor.check.meta_manually_diverged.remediation.hash": "\u8FD0\u884C `fabric doctor --fix` \u8BA9 agents.meta.json \u4E0E\u5F53\u524D rule file \u5185\u5BB9 reconcile\u3002",
1184
1237
  "doctor.check.meta_manually_diverged.ok.consistent": "agents.meta.json \u4E0E\u78C1\u76D8\u4E0A\u7684 rule files \u4E00\u81F4\u3002",
1185
1238
  "doctor.check.knowledge_dir_unindexed.name": "Knowledge dir unindexed",
1186
- "doctor.check.knowledge_dir_unindexed.message.singular": ".fabric/knowledge/ \u4E2D\u6709 {count} \u4E2A .md file \u672A\u7D22\u5F15\u5230 agents.meta.json\u3002\u8FD0\u884C `fab doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1187
- "doctor.check.knowledge_dir_unindexed.message.plural": ".fabric/knowledge/ \u4E2D\u6709 {count} \u4E2A .md files \u672A\u7D22\u5F15\u5230 agents.meta.json\u3002\u8FD0\u884C `fab doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1188
- "doctor.check.knowledge_dir_unindexed.remediation": "\u8FD0\u884C `fab doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1239
+ "doctor.check.knowledge_dir_unindexed.message.singular": ".fabric/knowledge/ \u4E2D\u6709 {count} \u4E2A .md file \u672A\u7D22\u5F15\u5230 agents.meta.json\u3002\u8FD0\u884C `fabric doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1240
+ "doctor.check.knowledge_dir_unindexed.message.plural": ".fabric/knowledge/ \u4E2D\u6709 {count} \u4E2A .md files \u672A\u7D22\u5F15\u5230 agents.meta.json\u3002\u8FD0\u884C `fabric doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1241
+ "doctor.check.knowledge_dir_unindexed.remediation": "\u8FD0\u884C `fabric doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1189
1242
  "doctor.check.knowledge_dir_unindexed.ok": "\u6240\u6709 .fabric/knowledge/ .md files \u90FD\u5DF2\u7D22\u5F15\u5230 agents.meta.json\u3002",
1190
1243
  "doctor.check.stable_id_collision.name": "Stable ID collision",
1191
1244
  "doctor.check.stable_id_collision.message.singular": 'stable_id "{stableId}" \u88AB\u58F0\u660E\u5728 {fileCount} \u4E2A\u6587\u4EF6\u4E2D\uFF1A{files}\u3002\u8BF7\u7F16\u8F91\u5176\u4E2D\u4E00\u4E2A knowledge file\uFF0C\u6539\u7528\u552F\u4E00 stable_id\u3002',
@@ -1194,9 +1247,9 @@ var zhCNMessages = {
1194
1247
  "doctor.check.stable_id_collision.remediation": "\u8C03 `/fabric-review modify <message \u4E2D\u5217\u51FA\u7684 colliding id \u4E4B\u4E00>`, \u8BA9 canonical id allocator \u81EA\u52A8\u91CD\u5206\u914D id (\u4F1A\u540C\u6B65\u66F4\u65B0 frontmatter + counters + \u5386\u53F2 cross-ref)\u3002\u4E25\u7981\u624B\u5DE5\u7F16\u8F91 id frontmatter \u2014 \u4F1A\u649E counter\u3002",
1195
1248
  "doctor.check.stable_id_collision.ok": ".fabric/knowledge/ \u4E2D\u672A\u53D1\u73B0\u5DF2\u58F0\u660E\u7684 stable_id collisions\u3002",
1196
1249
  "doctor.check.counter_desync.name": "Knowledge counter desync",
1197
- "doctor.check.counter_desync.message.singular": "{count} \u4E2A knowledge counter \u4E0E\u89C2\u6D4B\u5230\u7684 stable_ids \u4E0D\u540C\u6B65\u3002{counterPath} = {current}\uFF0C\u4F46\u68C0\u6D4B\u5230 {observedId}\u3002\u8FD0\u884C `fab doctor --fix` bump counters\u3002",
1198
- "doctor.check.counter_desync.message.plural": "{count} \u4E2A knowledge counters \u4E0E\u89C2\u6D4B\u5230\u7684 stable_ids \u4E0D\u540C\u6B65\u3002{counterPath} = {current}\uFF0C\u4F46\u68C0\u6D4B\u5230 {observedId}\u3002\u8FD0\u884C `fab doctor --fix` bump counters\u3002",
1199
- "doctor.check.counter_desync.remediation": "\u8FD0\u884C `fab doctor --fix` \u5C06 agents.meta.json counters \u63D0\u5347\u5230\u89C2\u6D4B\u5230\u7684\u6700\u5927 counter \u503C\u3002",
1250
+ "doctor.check.counter_desync.message.singular": "{count} \u4E2A knowledge counter \u4E0E\u89C2\u6D4B\u5230\u7684 stable_ids \u4E0D\u540C\u6B65\u3002{counterPath} = {current}\uFF0C\u4F46\u68C0\u6D4B\u5230 {observedId}\u3002\u8FD0\u884C `fabric doctor --fix` bump counters\u3002",
1251
+ "doctor.check.counter_desync.message.plural": "{count} \u4E2A knowledge counters \u4E0E\u89C2\u6D4B\u5230\u7684 stable_ids \u4E0D\u540C\u6B65\u3002{counterPath} = {current}\uFF0C\u4F46\u68C0\u6D4B\u5230 {observedId}\u3002\u8FD0\u884C `fabric doctor --fix` bump counters\u3002",
1252
+ "doctor.check.counter_desync.remediation": "\u8FD0\u884C `fabric doctor --fix` \u5C06 agents.meta.json counters \u63D0\u5347\u5230\u89C2\u6D4B\u5230\u7684\u6700\u5927 counter \u503C\u3002",
1200
1253
  "doctor.check.counter_desync.ok": "agents.meta.json counters envelope \u4E0E\u89C2\u6D4B\u5230\u7684 stable_ids \u4E00\u81F4\u3002",
1201
1254
  "doctor.check.preexisting_root_files.name": "Preexisting root markdown",
1202
1255
  "doctor.check.preexisting_root_files.ok": "project root \u672A\u68C0\u6D4B\u5230 CLAUDE.md \u6216 AGENTS.md\u3002",
@@ -1211,12 +1264,12 @@ var zhCNMessages = {
1211
1264
  "doctor.check.orphan_demote.ok": "\u6CA1\u6709 canonical knowledge entries \u8D85\u8FC7\u6309 maturity \u8BBE\u5B9A\u7684 inactivity threshold\u3002",
1212
1265
  "doctor.check.orphan_demote.message.singular": "{count} \u4E2A canonical knowledge entry \u8D85\u8FC7\u6309 maturity \u8BBE\u5B9A\u7684 inactivity threshold\uFF08stable={stableDays}d / endorsed={endorsedDays}d / draft={draftDays}d\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1213
1266
  "doctor.check.orphan_demote.message.plural": "{count} \u4E2A canonical knowledge entries \u8D85\u8FC7\u6309 maturity \u8BBE\u5B9A\u7684 inactivity threshold\uFF08stable={stableDays}d / endorsed={endorsedDays}d / draft={draftDays}d\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1214
- "doctor.check.orphan_demote.remediation": "\u8FD0\u884C `fab doctor --fix-knowledge`\u5C06 orphan entries \u964D\u7EA7\u4E00\u4E2A maturity tier\u3002",
1267
+ "doctor.check.orphan_demote.remediation": "\u8FD0\u884C `fabric doctor --fix-knowledge`\u5C06 orphan entries \u964D\u7EA7\u4E00\u4E2A maturity tier\u3002",
1215
1268
  "doctor.check.stale_archive.name": "Knowledge stale archive",
1216
1269
  "doctor.check.stale_archive.ok": "\u6CA1\u6709 draft knowledge entries \u8D85\u8FC7\u989D\u5916\u7684 stale-archive quiet window\u3002",
1217
1270
  "doctor.check.stale_archive.message.singular": "{count} \u4E2A draft knowledge entry \u5DF2\u8D85\u8FC7 demote+{additionalDays}d \u989D\u5916 quiet window\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1218
1271
  "doctor.check.stale_archive.message.plural": "{count} \u4E2A draft knowledge entries \u5DF2\u8D85\u8FC7 demote+{additionalDays}d \u989D\u5916 quiet window\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1219
- "doctor.check.stale_archive.remediation": "\u8FD0\u884C `fab doctor --fix-knowledge`\u5C06 stale entries \u79FB\u52A8\u5230 `.fabric/.archive/<type>/`\u3002",
1272
+ "doctor.check.stale_archive.remediation": "\u8FD0\u884C `fabric doctor --fix-knowledge`\u5C06 stale entries \u79FB\u52A8\u5230 `.fabric/.archive/<type>/`\u3002",
1220
1273
  "doctor.check.pending_overdue.name": "Knowledge pending overdue",
1221
1274
  "doctor.check.pending_overdue.ok": "\u6CA1\u6709 pending knowledge entries \u8D85\u8FC7 14-day review threshold\u3002",
1222
1275
  "doctor.check.pending_overdue.message.singular": "{count} \u4E2A pending knowledge entry \u5DF2\u7B49\u5F85 review \u8D85\u8FC7 {thresholdDays} \u5929\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
@@ -1238,7 +1291,7 @@ var zhCNMessages = {
1238
1291
  "doctor.check.index_drift.ok": "agents.meta.json counters envelope \u5BF9\u6BCF\u4E2A (layer, type) pair \u90FD\u5927\u4E8E\u6216\u7B49\u4E8E\u73B0\u6709 canonical counter \u6700\u5927\u503C\u3002",
1239
1292
  "doctor.check.index_drift.message.singular": "{count} \u4E2A (layer, type) counter slot \u5DF2\u4F4E\u4E8E\u89C2\u6D4B\u5230\u7684 canonical maximum\uFF08next allocate would collide\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1240
1293
  "doctor.check.index_drift.message.plural": "{count} \u4E2A (layer, type) counter slots \u5DF2\u4F4E\u4E8E\u89C2\u6D4B\u5230\u7684 canonical maximum\uFF08next allocate would collide\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1241
- "doctor.check.index_drift.remediation": "\u8FD0\u884C `fab doctor --fix-knowledge`\u5C06 agents.meta.json counters \u63D0\u5347\u5230 max_observed + 1\u3002",
1294
+ "doctor.check.index_drift.remediation": "\u8FD0\u884C `fabric doctor --fix-knowledge`\u5C06 agents.meta.json counters \u63D0\u5347\u5230 max_observed + 1\u3002",
1242
1295
  "doctor.check.underseeded.name": "Knowledge underseeded",
1243
1296
  "doctor.check.underseeded.ok": "\u77E5\u8BC6\u5E93\u5DF2\u6709 {count} \u4E2A canonical entries\uFF08>= {threshold}\uFF09\u3002",
1244
1297
  "doctor.check.underseeded.message.singular": "\u77E5\u8BC6\u5E93\u4EC5\u6709 {count} \u4E2A canonical entry\uFF08< {threshold} threshold\uFF09\u3002plan_context \u68C0\u7D22\u9762\u4F4E\u4E8E\u53EF\u7528\u4E0B\u9650\u3002",
@@ -1272,7 +1325,7 @@ var zhCNMessages = {
1272
1325
  "doctor.check.session_hints_stale.ok": ".fabric/.cache/ \u4E0B\u6CA1\u6709\u8D85\u8FC7 {days} \u5929\u7684 session-hints cache files\u3002",
1273
1326
  "doctor.check.session_hints_stale.message.singular": ".fabric/.cache/ \u4E0B\u6709 {count} \u4E2A session-hints cache file \u8D85\u8FC7 {days} \u5929\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1274
1327
  "doctor.check.session_hints_stale.message.plural": ".fabric/.cache/ \u4E0B\u6709 {count} \u4E2A session-hints cache files \u8D85\u8FC7 {days} \u5929\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1275
- "doctor.check.session_hints_stale.remediation": "\u8FD0\u884C `fab doctor --fix-knowledge` \u5220\u9664\u8FC7\u671F\u7684 session-hints cache files\u3002",
1328
+ "doctor.check.session_hints_stale.remediation": "\u8FD0\u884C `fabric doctor --fix-knowledge` \u5220\u9664\u8FC7\u671F\u7684 session-hints cache files\u3002",
1276
1329
  "doctor.check.stale_serve_lock.name": "Serve lock",
1277
1330
  "doctor.check.stale_serve_lock.ok.no_lock": "\u672A\u53D1\u73B0 .fabric/.serve.lock\u3002",
1278
1331
  "doctor.check.stale_serve_lock.ok.live_pid": ".fabric/.serve.lock \u7531 live PID {pid} \u6301\u6709\u3002",
@@ -1280,26 +1333,39 @@ var zhCNMessages = {
1280
1333
  "doctor.check.stale_serve_lock.age.day.plural": "{count} \u5929\u524D",
1281
1334
  "doctor.check.stale_serve_lock.age.hour.singular": "{count} \u5C0F\u65F6\u524D",
1282
1335
  "doctor.check.stale_serve_lock.age.hour.plural": "{count} \u5C0F\u65F6\u524D",
1283
- "doctor.check.stale_serve_lock.message.dead_pid": "[advisory] .fabric/.serve.lock \u6301\u6709 dead PID {pid}\uFF08acquired {acquiredAgo}\uFF09\u3002\u8FD0\u884C `fab doctor --fix` \u79FB\u9664\u3002",
1284
- "doctor.check.stale_serve_lock.remediation.dead_pid": "\u8FD0\u884C `fab doctor --fix` \u79FB\u9664\u8FC7\u671F\u7684 .fabric/.serve.lock\u3002",
1336
+ "doctor.check.stale_serve_lock.message.dead_pid": "[advisory] .fabric/.serve.lock \u6301\u6709 dead PID {pid}\uFF08acquired {acquiredAgo}\uFF09\u3002\u8FD0\u884C `fabric doctor --fix` \u79FB\u9664\u3002",
1337
+ "doctor.check.stale_serve_lock.remediation.dead_pid": "\u8FD0\u884C `fabric doctor --fix` \u79FB\u9664\u8FC7\u671F\u7684 .fabric/.serve.lock\u3002",
1285
1338
  "doctor.check.relevance_fields_missing.name": "Knowledge relevance fields missing",
1286
1339
  "doctor.check.relevance_fields_missing.ok": "\u6240\u6709 pending entries \u90FD\u58F0\u660E\u4E86 relevance_scope \u548C relevance_paths\u3002",
1287
1340
  "doctor.check.relevance_fields_missing.message.singular": "{count} \u4E2A pending entry \u7684 frontmatter \u7F3A\u5C11 relevance_scope \u548C/\u6216 relevance_paths\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1288
1341
  "doctor.check.relevance_fields_missing.message.plural": "{count} \u4E2A pending entries \u7684 frontmatter \u7F3A\u5C11 relevance_scope \u548C/\u6216 relevance_paths\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1289
- "doctor.check.relevance_fields_missing.remediation": "\u8FD0\u884C `fab doctor --fix-knowledge` \u56DE\u586B schema defaults\uFF08relevance_scope: broad\uFF0Crelevance_paths: []\uFF09\u3002",
1342
+ "doctor.check.relevance_fields_missing.remediation": "\u8FD0\u884C `fabric doctor --fix-knowledge` \u56DE\u586B schema defaults\uFF08relevance_scope: broad\uFF0Crelevance_paths: []\uFF09\u3002",
1290
1343
  // rc.31 BUG-M3/NEW-4: hooks_wired observability.
1291
1344
  "doctor.check.hooks_wired.name": "Claude Code hooks wired",
1292
1345
  "doctor.check.hooks_wired.ok.skipped": "\u9879\u76EE\u672A\u542F\u7528 Claude Code\uFF08\u65E0 .claude/ \u76EE\u5F55\uFF09\uFF1B\u8DF3\u8FC7 hooks_wired \u68C0\u67E5\u3002",
1293
1346
  "doctor.check.hooks_wired.ok.wired": ".claude/settings.json \u5DF2\u6CE8\u5165 Stop:fabric-hint / SessionStart:knowledge-hint-broad / PreToolUse:knowledge-hint-narrow \u4E09\u4E2A fabric hook\u3002",
1294
- "doctor.check.hooks_wired.message.missing_settings": ".claude/ \u76EE\u5F55\u5B58\u5728\u4F46 .claude/settings.json \u7F3A\u5931\u6216\u65E0\u6CD5\u89E3\u6790\uFF1Bfab install \u53EF\u80FD\u4ECE\u672A\u8DD1\u6210\u529F\uFF0C\u6216\u6587\u4EF6\u88AB\u5916\u90E8\u6E05\u7A7A\u3002",
1295
- "doctor.check.hooks_wired.message.incomplete": ".claude/settings.json \u7F3A\u5C11 fabric hook \u6CE8\u5165\uFF1A{missing}\u3002fab install \u7684 dry-run \u62A5\u544A\u4E0E\u5B9E\u9645\u72B6\u6001\u4E0D\u4E00\u81F4\uFF08rc.30 audit BUG-M3 / NEW-4\uFF09\u3002",
1296
- "doctor.check.hooks_wired.remediation": "\u8FD0\u884C `fab install` \u91CD\u65B0\u6CE8\u5165 hooks\uFF08\u5E42\u7B49\uFF1B\u53EA\u8865\u7F3A\u5931\u9879\uFF09\u3002\u82E5\u610F\u5916\u8986\u76D6\u4E86 hooks \u914D\u7F6E\uFF0C\u5148\u5907\u4EFD .claude/settings.json \u518D\u8DD1\u3002",
1347
+ "doctor.check.hooks_wired.message.missing_settings": ".claude/ \u76EE\u5F55\u5B58\u5728\u4F46 .claude/settings.json \u7F3A\u5931\u6216\u65E0\u6CD5\u89E3\u6790\uFF1Bfabric install \u53EF\u80FD\u4ECE\u672A\u8DD1\u6210\u529F\uFF0C\u6216\u6587\u4EF6\u88AB\u5916\u90E8\u6E05\u7A7A\u3002",
1348
+ "doctor.check.hooks_wired.message.incomplete": ".claude/settings.json \u7F3A\u5C11 fabric hook \u6CE8\u5165\uFF1A{missing}\u3002fabric install \u7684 dry-run \u62A5\u544A\u4E0E\u5B9E\u9645\u72B6\u6001\u4E0D\u4E00\u81F4\uFF08rc.30 audit BUG-M3 / NEW-4\uFF09\u3002",
1349
+ "doctor.check.hooks_wired.remediation": "\u8FD0\u884C `fabric install` \u91CD\u65B0\u6CE8\u5165 hooks\uFF08\u5E42\u7B49\uFF1B\u53EA\u8865\u7F3A\u5931\u9879\uFF09\u3002\u82E5\u610F\u5916\u8986\u76D6\u4E86 hooks \u914D\u7F6E\uFF0C\u5148\u5907\u4EFD .claude/settings.json \u518D\u8DD1\u3002",
1297
1350
  // rc.31 BUG-G2/G5: promote-ledger invariant check.
1298
1351
  "doctor.check.promote_ledger_invariant.name": "Promote ledger invariant",
1299
1352
  "doctor.check.promote_ledger_invariant.ok": "knowledge_proposed={proposed} \u2265 knowledge_promote_started={started} \u2265 knowledge_promoted={promoted}\uFF0Cledger \u4E0D\u53D8\u91CF\u6301\u6709\u3002",
1300
1353
  "doctor.check.promote_ledger_invariant.message.proposed-lt-started": "knowledge_proposed={proposed} \u5C0F\u4E8E knowledge_promote_started={started}\uFF08ledger \u4E0D\u53D8\u91CF\u88AB\u7834\u574F\uFF1B\u90E8\u5206 pending \u5728 approve \u65F6\u672A\u7ECF\u8FC7 fab_extract_knowledge \u2192 \u7F3A\u5C11 propose \u4E8B\u4EF6\uFF09\u3002",
1301
1354
  "doctor.check.promote_ledger_invariant.message.started-lt-promoted": "knowledge_promote_started={started} \u5C0F\u4E8E knowledge_promoted={promoted}\uFF08ledger \u4E0D\u53D8\u91CF\u88AB\u7834\u574F\uFF1B\u5B58\u5728\u672A\u914D\u5BF9\u7684 promoted \u4E8B\u4EF6\uFF0C\u53EF\u80FD\u6765\u81EA doctor filesystem-edit fallback \u6216\u5916\u90E8\u5199\u5165\uFF09\u3002",
1302
- "doctor.check.promote_ledger_invariant.remediation": "rc.31 \u8D77 review.approve \u4F1A\u8865\u53D1 knowledge_proposed \u4E8B\u4EF6\u4EE5\u7EF4\u62A4\u4E0D\u53D8\u91CF\uFF1B\u65B0 approve \u540E\u518D\u8DD1\u4E00\u6B21 fab doctor \u5373\u53EF\u6062\u590D\u3002\u5386\u53F2\u5931\u8861\u4EC5\u662F\u53EF\u89C2\u6D4B\u6027\u6307\u793A\uFF0C\u4E0D\u5F71\u54CD KB \u529F\u80FD\u3002",
1355
+ "doctor.check.promote_ledger_invariant.remediation": "rc.31 \u8D77 review.approve \u4F1A\u8865\u53D1 knowledge_proposed \u4E8B\u4EF6\u4EE5\u7EF4\u62A4\u4E0D\u53D8\u91CF\uFF1B\u65B0 approve \u540E\u518D\u8DD1\u4E00\u6B21 fabric doctor \u5373\u53EF\u6062\u590D\u3002\u5386\u53F2\u5931\u8861\u4EC5\u662F\u53EF\u89C2\u6D4B\u6027\u6307\u793A\uFF0C\u4E0D\u5F71\u54CD KB \u529F\u80FD\u3002",
1356
+ // rc.35 TASK-04 (P0-9.b): global_cli_outdated.
1357
+ "doctor.check.global_cli_outdated.name": "\u5168\u5C40 fabric CLI \u7248\u672C",
1358
+ "doctor.check.global_cli_outdated.ok": "PATH \u4E0A\u7684 `fabric` \u662F {version}\uFF0C\u4E0E rc.31+ \u9879\u76EE schema \u517C\u5BB9\u3002",
1359
+ "doctor.check.global_cli_outdated.message.outdated": "PATH \u4E0A\u7684 `fabric` \u662F {version}\uFF0C\u4F4E\u4E8E\u6700\u4F4E\u652F\u6301\u7248\u672C {minVersion}\u3002rc.31 \u4FEE\u590D\u4E86 agents.meta.json schema\uFF0C\u65E7\u7248 CLI \u5B89\u88C5\u7684 hook \u4F1A\u9759\u9ED8\u5931\u6548\uFF0C\u5FC5\u987B\u5347\u7EA7\u3002",
1360
+ "doctor.check.global_cli_outdated.message.not_found": "PATH \u4E0A\u627E\u4E0D\u5230 `fabric` \u4E8C\u8FDB\u5236\u3002`fabric install` / `fabric doctor` \u90FD\u4F9D\u8D56\u5B83\uFF0C\u8BF7\u5148\u5168\u5C40\u5B89\u88C5\u3002",
1361
+ "doctor.check.global_cli_outdated.message.unparseable": "\u65E0\u6CD5\u89E3\u6790 `fabric -v` \u8F93\u51FA\uFF08{detail}\uFF09\uFF0C\u8DF3\u8FC7\u7248\u672C\u68C0\u67E5\u3002",
1362
+ "doctor.check.global_cli_outdated.remediation": "\u8FD0\u884C `npm install -g @fenglimg/fabric-cli@latest`\uFF0C\u7136\u540E\u5230\u6BCF\u4E2A fabric-managed \u9879\u76EE\u4E0B\u91CD\u8DD1 `fabric install` \u540C\u6B65 hook + SKILL.md\u3002",
1363
+ // rc.35 TASK-05 (P0-10.a): knowledge_summary_opaque.
1364
+ "doctor.check.knowledge_summary_opaque.name": "\u77E5\u8BC6 summary \u900F\u660E\u5EA6",
1365
+ "doctor.check.knowledge_summary_opaque.ok.skipped": "agents.meta.json \u7F3A\u5931\u6216\u65E0\u6548\uFF0C\u8DF3\u8FC7 summary \u900F\u660E\u5EA6\u68C0\u67E5\u3002",
1366
+ "doctor.check.knowledge_summary_opaque.ok": "{opaque}/{total} \u4E2A entry \u7684 summary == stable_id\uFF0C\u6BD4\u4F8B\u5728\u5065\u5EB7\u8303\u56F4\u5185\u3002",
1367
+ "doctor.check.knowledge_summary_opaque.message.warn": "{opaque}/{total} \u4E2A entry ({pct}%) \u7684 description.summary \u7B49\u4E8E stable_id\uFF0C\u8D85\u8FC7 {threshold}% \u9608\u503C\u3002narrow hint \u8F93\u51FA\u4F1A\u53D8\u6210 `<id> \xB7 <id>` \u800C\u975E\u771F\u5B9E\u6982\u8981\uFF0CAI \u770B\u4E0D\u5230\u4FE1\u606F\u4F1A\u4E3B\u52A8\u8DF3\u8FC7 fetch\u3002\u9996\u6279\u4E0D\u900F\u660E: {sample}\u3002",
1368
+ "doctor.check.knowledge_summary_opaque.remediation": "\u8C03 fabric-review skill \u91CD\u5199\u4E0D\u900F\u660E summary \u4E3A\u4E00\u53E5\u4EBA\u7C7B\u53EF\u8BFB\u7684\u6982\u8981\u3002rc.35 hint renderer fallback (TASK-06) \u4E5F\u4F1A\u4ECE entry \u7684 `## Summary` \u6BB5\u81EA\u52A8\u5408\u6210\u4E34\u65F6 summary\u3002",
1303
1369
  "doctor.check.skill_md_yaml_invalid.name": "Skill markdown YAML",
1304
1370
  "doctor.check.skill_md_yaml_invalid.ok": "\u6240\u6709 .claude/.codex SKILL.md frontmatter values \u90FD\u80FD\u6309 strict YAML \u89E3\u6790\u3002",
1305
1371
  "doctor.check.skill_md_yaml_invalid.message.singular": "{count} \u4E2A SKILL.md frontmatter value \u5305\u542B\u672A\u52A0\u5F15\u53F7\u7684 ': '\uFF0Cstrict YAML parsers \u4F1A\u62D2\u7EDD\uFF08Claude Code tolerates it\uFF1BCodex CLI drops the skill at load\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
@@ -1334,11 +1400,17 @@ var zhCNMessages = {
1334
1400
  "cli.human-lint.table.location": "\u4F4D\u7F6E",
1335
1401
  "cli.human-lint.table.expected": "\u9884\u671F",
1336
1402
  "cli.human-lint.table.got": "\u5B9E\u9645",
1337
- "cli.install.description": "\u5728\u76EE\u6807\u9879\u76EE\u4E2D\u5B89\u88C5 Fabric\uFF08\u811A\u624B\u67B6 .fabric/\u3001bootstrap \u6A21\u677F\u3001MCP \u5BA2\u6237\u7AEF\u914D\u7F6E\u3001git hooks\uFF09\u3002\n\n\u793A\u4F8B\uFF1A\n fab install \u5728\u5F53\u524D\u9879\u76EE\u4E2D\u4EE5\u4EA4\u4E92\u6A21\u5F0F\u5B89\u88C5\n fab install --yes \u63A5\u53D7\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7 TTY \u5411\u5BFC\n fab install --dry-run \u4EC5\u9884\u89C8\u5B89\u88C5\u8BA1\u5212\uFF0C\u4E0D\u5199\u5165\u6587\u4EF6",
1403
+ "cli.install.description": "\u5728\u76EE\u6807\u9879\u76EE\u4E2D\u5B89\u88C5 Fabric\uFF08\u811A\u624B\u67B6 .fabric/\u3001bootstrap \u6A21\u677F\u3001MCP \u5BA2\u6237\u7AEF\u914D\u7F6E\u3001git hooks\uFF09\u3002\n\n\u793A\u4F8B\uFF1A\n fabric install \u5728\u5F53\u524D\u9879\u76EE\u4E2D\u4EE5\u4EA4\u4E92\u6A21\u5F0F\u5B89\u88C5\n fabric install --yes \u63A5\u53D7\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7 TTY \u5411\u5BFC\n fabric install --dry-run \u4EC5\u9884\u89C8\u5B89\u88C5\u8BA1\u5212\uFF0C\u4E0D\u5199\u5165\u6587\u4EF6",
1338
1404
  "cli.install.args.target.description": "\u76EE\u6807\u9879\u76EE\u8DEF\u5F84\u3002\u9ED8\u8BA4\u4F9D\u6B21\u4F7F\u7528 --target\u3001EXTERNAL_FIXTURE_PATH\u3001\u5F53\u524D\u76EE\u5F55\u3002",
1339
1405
  "cli.install.args.debug.description": "\u5C06\u76EE\u6807\u89E3\u6790\u7EC6\u8282\u8F93\u51FA\u5230 stderr\u3002",
1340
1406
  "cli.install.args.yes.description": "\u63A5\u53D7\u5F53\u524D\u5B89\u88C5\u8BA1\u5212\u5E76\u8DF3\u8FC7 TTY \u5411\u5BFC\u76F4\u63A5\u6267\u884C",
1341
1407
  "cli.install.args.dry-run.description": "\u4EC5\u8F93\u51FA\u5B89\u88C5\u8BA1\u5212\uFF0C\u4E0D\u5199\u6587\u4EF6\u4E5F\u4E0D\u6267\u884C\u540E\u7EED\u9636\u6BB5",
1408
+ // rc.35 TASK-08 (P0-5/6): --force-skills-only。
1409
+ "cli.install.args.force-skills-only.description": "\u8DF3\u8FC7 bootstrap / MCP / hooks / settings,\u53EA\u91CD\u65B0\u5237\u65B0 fabric Skill \u6A21\u677F (.claude/.codex/.cursor/skills/*)\u3002",
1410
+ "cli.install.force-skills-only.banner": "\u53EA\u5237\u65B0 fabric Skill \u6A21\u677F",
1411
+ "cli.install.force-skills-only.uninitialised.message": "fabric install --force-skills-only: \u9879\u76EE\u672A\u521D\u59CB\u5316(\u627E\u4E0D\u5230 .fabric/agents.meta.json)\u3002",
1412
+ "cli.install.force-skills-only.uninitialised.hint": "\u8BF7\u5148\u8FD0\u884C `fabric install`(\u4E0D\u5E26 --force-skills-only)\u94FA\u8BBE\u57FA\u7840 scaffold;\u4E4B\u540E\u518D\u7528 --force-skills-only \u505A\u540E\u7EED Skill \u5237\u65B0\u3002",
1413
+ "cli.install.force-skills-only.summary": "Skill \u5237\u65B0\u5B8C\u6210 \u2014 \u5199\u5165: {written}, \u8DF3\u8FC7: {skipped}, \u9519\u8BEF: {errors}",
1342
1414
  "cli.install.mcp.install.global": "\u4F7F\u7528\u5168\u5C40\u5B89\u88C5\u7684 @fenglimg/fabric-server",
1343
1415
  "cli.install.mcp.install.local": "\u5C06 @fenglimg/fabric-server \u5B89\u88C5\u5230\u9879\u76EE devDependencies",
1344
1416
  "cli.install.mcp.local.installing": "\u6B63\u5728\u8FD0\u884C {manager} add -D @fenglimg/fabric-server...",
@@ -1413,7 +1485,7 @@ var zhCNMessages = {
1413
1485
  "cli.install.capabilities.follow-up.ready": "\u53EF\u5728\u5BA2\u6237\u7AEF\u7EE7\u7EED",
1414
1486
  "cli.install.capabilities.follow-up.install": "\u5B89\u88C5\u5BA2\u6237\u7AEF\u8D44\u4EA7",
1415
1487
  "cli.install.capabilities.follow-up.manual": "\u9700\u8981\u624B\u52A8\u540E\u7EED\u5904\u7406",
1416
- "cli.install.next-step.message": "\u8FD0\u884C fab hooks install \u4EE5\u6DFB\u52A0\u7B2C 4 \u5929\u7684 pre-commit \u6D41\u6C34\u7EBF\u3002",
1488
+ "cli.install.next-step.message": "\u8FD0\u884C fabric hooks install \u4EE5\u6DFB\u52A0\u7B2C 4 \u5929\u7684 pre-commit \u6D41\u6C34\u7EBF\u3002",
1417
1489
  "cli.install.reason-message.installable-body": ".fabric/forensic.json \u5DF2\u5C31\u7EEA\uFF1B\u90E8\u5206\u5DF2\u68C0\u6D4B\u5230\u7684\u5BA2\u6237\u7AEF\u5DF2\u652F\u6301 Fabric \u540E\u7EED\u63A5\u529B\uFF0C\u4F46\u4ECD\u9700\u5B89\u88C5\u5BA2\u6237\u7AEF\u8D44\u4EA7\u3002",
1418
1490
  "cli.install.reason-message.manual-body": ".fabric/forensic.json \u5DF2\u5C31\u7EEA\uFF1B\u90E8\u5206\u5DF2\u68C0\u6D4B\u5230\u7684\u5BA2\u6237\u7AEF\u5C1A\u672A\u5B89\u88C5 Fabric skill\uFF0C\u9700\u8981\u624B\u52A8\u5B8C\u6210\u540E\u7EED\u5B89\u88C5\u3002",
1419
1491
  "cli.install.codex-hooks.created": "{label} {path}\uFF0C\u5E76\u5199\u5165 Codex hooks \u914D\u7F6E\uFF08\u9700\u542F\u7528 features.codex_hooks = true\uFF09\u3002",
@@ -1427,15 +1499,15 @@ var zhCNMessages = {
1427
1499
  "cli.install.claude-settings.invalid-json": "{label} {path}\uFF1AJSON \u65E0\u6548\uFF08{reason}\uFF09\u3002",
1428
1500
  "cli.install.claude-settings.invalid-hooks": '{label} {path}\uFF1A"hooks" \u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002',
1429
1501
  "cli.install.claude-settings.invalid-stop-array": '{label} {path}\uFF1A"hooks.Stop" \u5FC5\u987B\u662F\u6570\u7EC4\u3002',
1430
- "cli.install.errors.abort-existing": "\u4E2D\u6B62\uFF1A{path} \u5DF2\u5B58\u5728\u3002fab install \u662F\u975E\u7834\u574F\u6027\u7684\u3002",
1502
+ "cli.install.errors.abort-existing": "\u4E2D\u6B62\uFF1A{path} \u5DF2\u5B58\u5728\u3002fabric install \u662F\u975E\u7834\u574F\u6027\u7684\u3002",
1431
1503
  "cli.install.diff.canonical": "\u5DE5\u4F5C\u533A\u5DF2\u662F\u89C4\u8303\u72B6\u6001\uFF08\u5DF2\u6821\u9A8C {count} \u4E2A\u6587\u4EF6\uFF09\u3002",
1432
1504
  "cli.install.diff.applying-missing": "\u6B63\u5728\u8865\u9F50 {count} \u4E2A\u7F3A\u5931\u9879\uFF1A{files}",
1433
- "cli.install.diff.drift-abort": "\u68C0\u6D4B\u5230 {path} \u5DF2\u88AB\u4FEE\u6539\u3002\u8FD0\u884C `fab doctor` \u8FDB\u884C\u68C0\u67E5\uFF0C\u6216 `fab uninstall && fab install` \u8FDB\u884C\u91CD\u7F6E\u3002",
1505
+ "cli.install.diff.drift-abort": "\u68C0\u6D4B\u5230 {path} \u5DF2\u88AB\u4FEE\u6539\u3002\u8FD0\u884C `fabric doctor` \u8FDB\u884C\u68C0\u67E5\uFF0C\u6216 `fabric uninstall && fabric install` \u8FDB\u884C\u91CD\u7F6E\u3002",
1434
1506
  "cli.install.diff.state.missing": "\u7F3A\u5931",
1435
1507
  "cli.install.diff.state.present-canonical": "\u89C4\u8303",
1436
1508
  "cli.install.diff.state.drifted": "\u6F02\u79FB",
1437
1509
  "cli.install.diff.state.user-modified": "\u7528\u6237\u4FEE\u6539",
1438
- "cli.uninstall.description": "\u4ECE\u76EE\u6807\u9879\u76EE\u4E2D\u5378\u8F7D Fabric\u3002.fabric/knowledge/ \u59CB\u7EC8\u4FDD\u7559\uFF1B~/.fabric/knowledge/ \u6C38\u4E0D\u53D7\u5F71\u54CD\u3002\n\n\u793A\u4F8B\uFF1A\n fab uninstall \u5728\u5F53\u524D\u9879\u76EE\u4E2D\u4EE5\u4EA4\u4E92\u6A21\u5F0F\u5378\u8F7D\n fab uninstall --yes \u63A5\u53D7\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7 TTY \u5411\u5BFC\n fab uninstall --dry-run \u4EC5\u9884\u89C8\u5378\u8F7D\u8BA1\u5212\uFF0C\u4E0D\u5220\u9664\u6587\u4EF6",
1510
+ "cli.uninstall.description": "\u4ECE\u76EE\u6807\u9879\u76EE\u4E2D\u5378\u8F7D Fabric\u3002.fabric/knowledge/ \u59CB\u7EC8\u4FDD\u7559\uFF1B~/.fabric/knowledge/ \u6C38\u4E0D\u53D7\u5F71\u54CD\u3002\n\n\u793A\u4F8B\uFF1A\n fabric uninstall \u5728\u5F53\u524D\u9879\u76EE\u4E2D\u4EE5\u4EA4\u4E92\u6A21\u5F0F\u5378\u8F7D\n fabric uninstall --yes \u63A5\u53D7\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7 TTY \u5411\u5BFC\n fabric uninstall --dry-run \u4EC5\u9884\u89C8\u5378\u8F7D\u8BA1\u5212\uFF0C\u4E0D\u5220\u9664\u6587\u4EF6",
1439
1511
  "cli.uninstall.args.target.description": "\u76EE\u6807\u9879\u76EE\u8DEF\u5F84\u3002\u9ED8\u8BA4\u4F9D\u6B21\u4F7F\u7528 --target\u3001EXTERNAL_FIXTURE_PATH\u3001\u5F53\u524D\u76EE\u5F55\u3002",
1440
1512
  "cli.uninstall.args.debug.description": "\u5C06\u76EE\u6807\u89E3\u6790\u7EC6\u8282\u8F93\u51FA\u5230 stderr\u3002",
1441
1513
  "cli.uninstall.args.yes.description": "\u63A5\u53D7\u5F53\u524D\u5378\u8F7D\u8BA1\u5212\u5E76\u8DF3\u8FC7 TTY \u5411\u5BFC\u76F4\u63A5\u6267\u884C\u3002",
@@ -1486,7 +1558,7 @@ var zhCNMessages = {
1486
1558
  "cli.scan.args.target.description": "\u76EE\u6807\u7EDD\u5BF9\u8DEF\u5F84\u3002\u9ED8\u8BA4\u4F9D\u6B21\u4F7F\u7528 --target\u3001EXTERNAL_FIXTURE_PATH\u3001\u5F53\u524D\u76EE\u5F55\u3002",
1487
1559
  "cli.scan.args.debug.description": "\u4EE5\u683C\u5F0F\u5316\u8F93\u51FA\u6253\u5370\u68C0\u6D4B\u8BC1\u636E\u3002",
1488
1560
  "cli.scan.args.json.description": "\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA\u8BCA\u65AD\u62A5\u544A\u3002",
1489
- "cli.scan.error.missing-forensic": "\u672A\u627E\u5230 forensic.json\uFF08\u8DEF\u5F84 {path}\uFF09\uFF1B\u8BF7\u5148\u8FD0\u884C `fab install` \u751F\u6210\u9879\u76EE\u5FEB\u7167\u3002",
1561
+ "cli.scan.error.missing-forensic": "\u672A\u627E\u5230 forensic.json\uFF08\u8DEF\u5F84 {path}\uFF09\uFF1B\u8BF7\u5148\u8FD0\u884C `fabric install` \u751F\u6210\u9879\u76EE\u5FEB\u7167\u3002",
1490
1562
  "cli.scan.summary.created": "\u5DF2\u5199\u5165 {count} \u6761\u77E5\u8BC6\u6761\u76EE\u81F3 .fabric/knowledge/\u3002",
1491
1563
  "cli.scan.summary.skipped": "\u65E0\u5DEE\u5F02\uFF1B{count} \u6761\u5DF2\u5B58\u5728\u7684\u6761\u76EE\u4FDD\u6301\u4E0D\u53D8\u3002",
1492
1564
  "cli.scan.report.title": "Fabric \u626B\u63CF\u62A5\u544A",
@@ -1501,20 +1573,20 @@ var zhCNMessages = {
1501
1573
  "cli.scan.report.recommendations": "\u5EFA\u8BAE\uFF1A",
1502
1574
  "cli.scan.readme-quality.ok": "\u826F\u597D",
1503
1575
  "cli.scan.readme-quality.stub": "\u8349\u7A3F",
1504
- "cli.scan.recommendation.init": "L0\uFF1A\u8FD0\u884C fab install\uFF0C\u5728 .fabric/AGENTS.md \u751F\u6210 Fabric \u5F15\u5BFC\u89C4\u8303\u5185\u5BB9\u3002",
1576
+ "cli.scan.recommendation.init": "L0\uFF1A\u8FD0\u884C fabric install\uFF0C\u5728 .fabric/AGENTS.md \u751F\u6210 Fabric \u5F15\u5BFC\u89C4\u8303\u5185\u5BB9\u3002",
1505
1577
  "cli.scan.recommendation.readme": "L0\uFF1A\u5148\u8865\u5145 README.md\uFF0C\u518D\u628A\u9879\u76EE\u4E8B\u5B9E\u6574\u7406\u5230 Fabric \u53C2\u8003\u6587\u4EF6\u4E2D\u3002",
1506
1578
  "cli.scan.recommendation.contributing": "L0\uFF1A\u6DFB\u52A0 CONTRIBUTING.md\uFF0C\u6216\u5728 bootstrap \u4E2D\u7559\u4E0B\u8D21\u732E\u6D41\u7A0B\u7684 TODO \u8BF4\u660E\u3002",
1507
1579
  "cli.scan.recommendation.unknown-framework": "L1\uFF1A\u5F53\u524D\u672A\u68C0\u6D4B\u5230\u6846\u67B6\u6807\u8BB0\uFF0C\u9700\u8981\u624B\u52A8\u8865\u5145\u6280\u672F\u6808\u8BF4\u660E\u3002",
1508
1580
  "cli.scan.recommendation.framework-dirs": "L1\uFF1A\u68C0\u67E5 {framework} \u76EE\u5F55\uFF0C\u540E\u7EED\u4E3A\u5176\u8865\u5145\u5BF9\u5E94\u4F5C\u7528\u57DF\u7684 Fabric \u89C4\u5219\u6587\u4EF6\u3002",
1509
- "cli.serve.description": "\u542F\u52A8\u672C\u5730 Fabric MCP HTTP \u670D\u52A1\u3002\n\n\u793A\u4F8B\uFF1A\n fab serve \u7ED1\u5B9A 127.0.0.1:7373\uFF08\u9ED8\u8BA4\uFF09\n fab serve --port 8787 \u4F7F\u7528\u81EA\u5B9A\u4E49\u7AEF\u53E3\n FABRIC_AUTH_TOKEN=<token> fab serve --host 0.0.0.0 \u7ED1\u5B9A\u975E loopback \u5E76\u542F\u7528 Bearer \u9274\u6743",
1581
+ "cli.serve.description": "\u542F\u52A8\u672C\u5730 Fabric MCP HTTP \u670D\u52A1\u3002\n\n\u793A\u4F8B\uFF1A\n fabric serve \u7ED1\u5B9A 127.0.0.1:7373\uFF08\u9ED8\u8BA4\uFF09\n fabric serve --port 8787 \u4F7F\u7528\u81EA\u5B9A\u4E49\u7AEF\u53E3\n FABRIC_AUTH_TOKEN=<token> fabric serve --host 0.0.0.0 \u7ED1\u5B9A\u975E loopback \u5E76\u542F\u7528 Bearer \u9274\u6743",
1510
1582
  "cli.serve.args.port.description": "\u76D1\u542C\u7AEF\u53E3\uFF0C\u9ED8\u8BA4 7373\u3002",
1511
1583
  "cli.serve.args.host.description": "\u76D1\u542C\u4E3B\u673A\uFF0C\u9ED8\u8BA4 127.0.0.1\u3002\u7ED1\u5B9A\u975E loopback \u4E3B\u673A\uFF08\u5982 0.0.0.0\uFF09\u5FC5\u987B\u8BBE\u7F6E FABRIC_AUTH_TOKEN \u542F\u7528 Bearer \u9274\u6743\uFF0C\u5426\u5219\u5C06\u81EA\u52A8\u56DE\u9000\u5230 127.0.0.1\u3002",
1512
1584
  "cli.serve.args.target.description": "\u76EE\u6807\u9879\u76EE\u8DEF\u5F84\u3002\u9ED8\u8BA4\u4F9D\u6B21\u4F7F\u7528 --target\u3001EXTERNAL_FIXTURE_PATH\u3001\u5F53\u524D\u76EE\u5F55\u3002",
1513
1585
  "cli.serve.args.debug.description": "\u5C06\u76EE\u6807\u89E3\u6790\u7EC6\u8282\u8F93\u51FA\u5230 stderr\u3002",
1514
1586
  "cli.serve.args.allow-loopback-no-auth.description": "\u663E\u5F0F\u5141\u8BB8\u5728 loopback \u4E0A\u4EE5\u65E0\u9274\u6743\u65B9\u5F0F\u8FD0\u884C\uFF08\u9ED8\u8BA4 default-deny\uFF09\u3002\u4EC5\u5728\u53EF\u4FE1\u5355\u7528\u6237\u673A\u5668\u4E0A\u4F7F\u7528\u2014\u2014\u5426\u5219\u4EFB\u4F55\u672C\u673A\u8FDB\u7A0B\u90FD\u80FD\u8BFB\u53D6\u4F60\u7684\u77E5\u8BC6\u5E93\u8D26\u672C\u3002",
1515
1587
  "cli.serve.ready.title": "Fabric \u4EEA\u8868\u76D8",
1516
- "cli.serve.lock-held.action-hint": "\u53E6\u4E00\u4E2A `fab serve` \u8FDB\u7A0B (PID {pid}) \u6B63\u5360\u7528\u5DE5\u4F5C\u533A\u9501\u3002\u8BF7\u5148\u505C\u6B62\u5B83 (\u5728\u8BE5\u7EC8\u7AEF\u6309 Ctrl-C \u6216\u8FD0\u884C `kill {pid}`) \u518D\u6267\u884C\u6B64\u547D\u4EE4\u3002",
1517
- "cli.serve.warning.host-fallback": "--host {host} \u9700\u8981\u8BBE\u7F6E FABRIC_AUTH_TOKEN \u624D\u80FD\u5BF9\u5916\u66B4\u9732\uFF1B\u5DF2\u56DE\u9000\u5230 127.0.0.1\u3002\u5982\u9700\u7ED1\u5B9A {host}\uFF0C\u8BF7\u8FD0\u884C\uFF1AFABRIC_AUTH_TOKEN=<token> fab serve --host {host}",
1588
+ "cli.serve.lock-held.action-hint": "\u53E6\u4E00\u4E2A `fabric serve` \u8FDB\u7A0B (PID {pid}) \u6B63\u5360\u7528\u5DE5\u4F5C\u533A\u9501\u3002\u8BF7\u5148\u505C\u6B62\u5B83 (\u5728\u8BE5\u7EC8\u7AEF\u6309 Ctrl-C \u6216\u8FD0\u884C `kill {pid}`) \u518D\u6267\u884C\u6B64\u547D\u4EE4\u3002",
1589
+ "cli.serve.warning.host-fallback": "--host {host} \u9700\u8981\u8BBE\u7F6E FABRIC_AUTH_TOKEN \u624D\u80FD\u5BF9\u5916\u66B4\u9732\uFF1B\u5DF2\u56DE\u9000\u5230 127.0.0.1\u3002\u5982\u9700\u7ED1\u5B9A {host}\uFF0C\u8BF7\u8FD0\u884C\uFF1AFABRIC_AUTH_TOKEN=<token> fabric serve --host {host}",
1518
1590
  "cli.serve.warning.loopback-deny-default": "\u672A\u8BBE\u7F6E FABRIC_AUTH_TOKEN\uFF1A/api /events /mcp \u9ED8\u8BA4\u8FD4\u56DE 401\uFF08\u5426\u5219\u4EFB\u4F55\u672C\u673A\u8FDB\u7A0B\u90FD\u80FD\u8BFB\u53D6 .fabric/agents.meta.json + forensic.json + events.jsonl\uFF09\u3002\u8BF7\u8BBE\u7F6E FABRIC_AUTH_TOKEN=<secret>\uFF0C\u6216\u4F20\u5165 --allow-loopback-no-auth \u663E\u5F0F\u653E\u884C\u3002",
1519
1591
  "cli.serve.error.port-in-use": "\u7AEF\u53E3 {port} \u5DF2\u88AB\u5360\u7528\uFF0C\u53EF\u5C1D\u8BD5 --port {nextPort}",
1520
1592
  // v2.0.0-rc.29 TASK-008 (BUG-L2): onboard-coverage 国际化键。
@@ -1528,7 +1600,7 @@ var zhCNMessages = {
1528
1600
  "cli.sync-meta.description": "\u4ECE\u5185\u90E8\u89C4\u5219\u6587\u4EF6\u540C\u6B65 Fabric \u5143\u6570\u636E\u3002",
1529
1601
  "cli.sync-meta.args.target.description": "\u76EE\u6807\u9879\u76EE\u8DEF\u5F84\uFF0C\u9ED8\u8BA4\u4E3A\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002",
1530
1602
  "cli.sync-meta.args.check-only.description": "\u5982\u679C .fabric/agents.meta.json \u5DF2\u8FC7\u671F\uFF0C\u5219\u4EE5\u4EE3\u7801 1 \u9000\u51FA\u3002",
1531
- "cli.sync-meta.drift-detected": "\u68C0\u6D4B\u5230 Fabric \u5143\u6570\u636E\u6F02\u79FB\u3002\u8BF7\u8FD0\u884C fab sync-meta \u8FDB\u884C\u66F4\u65B0\u3002",
1603
+ "cli.sync-meta.drift-detected": "\u68C0\u6D4B\u5230 Fabric \u5143\u6570\u636E\u6F02\u79FB\u3002\u8BF7\u8FD0\u884C fabric sync-meta \u8FDB\u884C\u66F4\u65B0\u3002",
1532
1604
  "cli.sync-meta.updated": "{label} {path}",
1533
1605
  "dashboard.app.nav.aria-label": "\u4EEA\u8868\u76D8\u89C6\u56FE\u5BFC\u822A",
1534
1606
  "dashboard.app.nav.readiness.label": "\u51C6\u5907\u60C5\u51B5",
@@ -1806,7 +1878,7 @@ function resolveFabricLocale(projectRoot) {
1806
1878
  }
1807
1879
  if (fabricLanguage === "match-existing" || fabricLanguage === "zh-CN-hybrid") {
1808
1880
  console.warn(
1809
- `[fabric] fabric_language="${fabricLanguage}" is a pre-init placeholder that should have been resolved during 'fab init' (KT-DEC-9004). Falling back to FAB_LANG / LANG environment detection.`
1881
+ `[fabric] fabric_language="${fabricLanguage}" is a pre-init placeholder that should have been resolved during 'fabric init' (KT-DEC-9004). Falling back to FAB_LANG / LANG environment detection.`
1810
1882
  );
1811
1883
  return detectNodeLocale();
1812
1884
  }