@fenglimg/fabric-shared 2.2.0-rc.1 → 2.2.0-rc.3

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.
@@ -134,7 +134,13 @@ var planContextOutputSchema = z2.object({
134
134
  // the new id before issuing fab_get_knowledge_sections / fab_recall. Empty
135
135
  // (field omitted) when no actionable redirects exist for the surfaced
136
136
  // candidate set. See packages/server/src/services/id-redirect.ts.
137
- redirects: z2.record(z2.string()).optional()
137
+ redirects: z2.record(z2.string()).optional(),
138
+ // lifecycle-refactor W3-T2 (§7 图谱消费): related-expansion provenance map
139
+ // (appended id → surfaced source id). Present only when `include_related` was
140
+ // requested AND at least one in-corpus one-hop neighbour was appended. Omitted
141
+ // on the graph-empty / steady-state path. Additive — declare it here or zod
142
+ // strips it on output validation.
143
+ related_appended: z2.record(z2.string()).optional()
138
144
  });
139
145
  var planContextAnnotations = {
140
146
  readOnlyHint: true,
@@ -161,7 +167,9 @@ var knowledgeSectionsInputSchema = z2.object({
161
167
  ai_selected_stable_ids: z2.array(z2.string()).describe(
162
168
  "Stable ids picked from fab_plan_context candidates[].stable_id; choose 1..N to fetch bodies for"
163
169
  ),
164
- ai_selection_reasons: z2.record(z2.string().min(1)).describe("Reason for each AI-selected L1 stable_id"),
170
+ ai_selection_reasons: z2.record(z2.string().min(1)).optional().default({}).describe(
171
+ "Optional reason for each AI-selected L1 stable_id (audit telemetry). Omit to fetch bodies without annotating \u2014 server defaults to {} rather than rejecting the documented two-step call."
172
+ ),
165
173
  correlation_id: z2.string().optional().describe("Optional caller-provided correlation id for Event Ledger records"),
166
174
  session_id: z2.string().optional().describe("Optional caller-provided session id for Event Ledger records"),
167
175
  // v2.0 rc.5 TASK-014 (C5): optional client identity hash propagated into
@@ -196,7 +204,7 @@ var knowledgeSectionsOutputSchema = z2.object({
196
204
  // for un-migrated v1.x entries (no knowledge_type AND no knowledge_layer
197
205
  // in frontmatter). Does NOT block selection.
198
206
  z2.object({
199
- code: z2.literal("missing_knowledge_metadata"),
207
+ code: z2.enum(["missing_knowledge_metadata", "unresolved_selected_id"]),
200
208
  severity: z2.literal("warn"),
201
209
  stable_id: z2.string(),
202
210
  message: z2.string()
@@ -279,13 +287,21 @@ var recallOutputSchema = z2.object({
279
287
  stable_id: z2.string(),
280
288
  level: z2.enum(["L0", "L1", "L2"]),
281
289
  path: z2.string(),
282
- body: z2.string()
290
+ body: z2.string(),
291
+ // lifecycle-refactor W3-T4 (§2 store 轴 / store-qualified 观测 / D7 物理 store
292
+ // 边界对 AI 可见): per-rule store provenance so the caller can trace which
293
+ // store each recalled entry came from. cross-store-recall already prefixes
294
+ // store entries `<alias>:<stable_id>`; this surfaces that as a structured
295
+ // field (`{ alias }`) instead of forcing the caller to parse the id. Omitted
296
+ // for project-local entries (no alias prefix). Additive — declare it or zod
297
+ // strips it on output validation.
298
+ store: z2.object({ alias: z2.string() }).optional()
283
299
  })
284
300
  ),
285
301
  selected_stable_ids: z2.array(z2.string()),
286
302
  diagnostics: z2.array(
287
303
  z2.object({
288
- code: z2.literal("missing_knowledge_metadata"),
304
+ code: z2.enum(["missing_knowledge_metadata", "unresolved_selected_id"]),
289
305
  severity: z2.literal("warn"),
290
306
  stable_id: z2.string(),
291
307
  message: z2.string()
@@ -371,8 +387,12 @@ var PROPOSED_REASON_DESCRIPTIONS = {
371
387
  var _sourceSessionsField = z2.array(z2.string().min(1)).min(1);
372
388
  var _FabExtractKnowledgeInputBaseSchema = z2.object({
373
389
  // v2.0.0-rc.7 T5: array form. rc.23 dropped the legacy single-string alias.
374
- source_sessions: _sourceSessionsField.optional().describe(
375
- "Originating session ids; correlates with Event Ledger records. Array form (T5+, rc.23 made it the sole accepted shape)."
390
+ // v2.2 全砍 F13: REQUIRED in the base schema (was `.optional()`) so the MCP
391
+ // tool's advertised inputSchema (registerTool reads `.shape`) matches the
392
+ // requirement the superRefine enforces. Previously a caller reading the schema
393
+ // saw it optional, omitted it, and got rejected at parse — a contract lie.
394
+ source_sessions: _sourceSessionsField.describe(
395
+ "Originating session ids (REQUIRED, non-empty array); correlates with Event Ledger records. Array form (T5+, rc.23 made it the sole accepted shape)."
376
396
  ),
377
397
  recent_paths: z2.array(z2.string()).describe("Workspace paths recently touched in the source session \u2014 used as scope hints"),
378
398
  user_messages_summary: z2.string().describe("Skill-side summary of the user's intent/messages, kept compact"),
@@ -804,7 +824,71 @@ var citeCoverageReportSchema = z2.object({
804
824
  // expected_but_missed. >0 typically means a stale pre-session_id hook is
805
825
  // installed (run `fabric install`). Surfaced so the denominator gap is
806
826
  // visible rather than a silent 100% confound.
807
- uncorrelatable_edits: z2.number().int().nonnegative().optional()
827
+ uncorrelatable_edits: z2.number().int().nonnegative().optional(),
828
+ // v2.1 ⑤ cite-redesign (P5): recall-based coverage口径. The redesign infers
829
+ // a citation from real behavior — an in-session fab_recall
830
+ // (knowledge_context_planned) whose target_paths overlap a subsequently
831
+ // edited file IS the citation, no hand-written `KB:` line required.
832
+ // recall_backed_edits = correlatable edits preceded (within the recall
833
+ // window) by such an overlapping recall. recall_coverage_rate =
834
+ // recall_backed_edits / edits_touched (null when no edits). Additive — the
835
+ // legacy first-line-`KB:` metrics above are unchanged (back-compat).
836
+ recall_backed_edits: z2.number().int().nonnegative().optional(),
837
+ recall_coverage_rate: z2.number().min(0).max(1).nullable().optional(),
838
+ // v2.2.0-rc.1 W1-T3 (cite 诚实拆分 / lifecycle §3): exposed_and_mutated is a
839
+ // WEAK auxiliary signal — strictly SEPARATE from cite_compliance_rate (which
840
+ // is the true explicit-adherence rate, currently ~2.5%). It MUST NOT be
841
+ // merged into compliance: it estimates "a narrow PreToolUse-surfaced KB id
842
+ // whose contract-specific glob was subsequently edited (mutated) in the same
843
+ // session, and was not [dismissed] that round". It credits NOTHING toward the
844
+ // real `KB:`-line compliance — it is an observational hint that surfaced
845
+ // knowledge influenced an edit, surfaced ONLY as its own field so the renderer
846
+ // can label it "weak signal, NOT counted toward true adherence". Three
847
+ // conditions (all required): (1) id came from a `hook_surface_emitted` with
848
+ // hook_name === "knowledge-hint-narrow"; (2) the id's contract glob is
849
+ // SPECIFIC (excludes `**/*` wildcards and generic guideline-type entries);
850
+ // (3) the id was not [dismissed] in the same session. `count` = number of
851
+ // distinct (session_id, stable_id) pairs satisfying all three; `ids` =
852
+ // sorted distinct stable_ids (capped, diagnostics only). Always >= 0; null/
853
+ // absent on degraded/skipped reports.
854
+ exposed_and_mutated: z2.object({
855
+ count: z2.number().int().nonnegative(),
856
+ ids: z2.array(z2.string()).optional()
857
+ }).optional(),
858
+ // lifecycle-refactor W2-T4 (§5 row7 PostToolUse / §0 下沉 doctor): mutation
859
+ // funnel rebuilt offline from the new `file_mutated` PostToolUse marker —
860
+ // the权威 signal that a mutation actually completed (path + tool_call_id),
861
+ // distinct from the PreToolUse `edit_intent_checked` EDIT-INTENT signal that
862
+ // feeds `edits_touched`. mutations_observed.count = number of distinct
863
+ // `file_mutated` events in window (per-call tool_call_id dedup guards the
864
+ // PostToolUse parallel-fire race). Strictly ADDITIVE — never folded into
865
+ // cite_compliance_rate (honesty 铁律, mirrors exposed_and_mutated). Absent on
866
+ // degraded/skipped reports.
867
+ mutations_observed: z2.object({
868
+ count: z2.number().int().nonnegative()
869
+ }).optional(),
870
+ // lifecycle-refactor W2-T4 (§5 row7 mutation_pool + downgrade): low-confidence
871
+ // mutation attribution pool. A `file_mutated` event is `attributed` ONLY when
872
+ // its `source_event_id` links back to a `hook_surface_emitted` (surfaced/cited
873
+ // knowledge) in window — attribution key = store_id + stable_id +
874
+ // source_event_id (distinct dedup so multi-store never double-counts). Every
875
+ // other mutation (no source_event_id, or a source_event_id that does not
876
+ // resolve to a surfaced event) downgrades to `unattributed_workspace_dirty`.
877
+ // NOTE: this is the events.jsonl-only attribution. The §9 git-diff fallback
878
+ // (升 fallback via session shell event + baseline) is a SPECULATIVE
879
+ // implementation note — deliberately NOT run here (doctor stays read-only,
880
+ // no git diff / no disk write). Additive; absent on degraded/skipped reports.
881
+ mutation_pool: z2.object({
882
+ attributed: z2.number().int().nonnegative(),
883
+ unattributed_workspace_dirty: z2.number().int().nonnegative()
884
+ }).optional(),
885
+ // lifecycle-refactor W2-T4 (§5 row2 SessionEnd funnel 对账下沉 doctor): the
886
+ // SessionEnd hook only O(1)-appends a `session_ended` marker; this counts the
887
+ // distinct sessions that emitted one (funnel "closed" boundary). Purely an
888
+ // observability marker — not joined into any rate. Additive.
889
+ sessions_closed: z2.object({
890
+ count: z2.number().int().nonnegative()
891
+ }).optional()
808
892
  }),
809
893
  per_client: z2.record(
810
894
  z2.string(),
@@ -42,9 +42,9 @@ var BOOTSTRAP_CANONICAL = `# Fabric Bootstrap
42
42
  - **Discovery**:SessionStart hook \u5217 broad-scoped \u6761\u76EE(\u542B personal layer \`KP-*\` \u6761\u76EE,\u5F15\u7528\u65B9\u5F0F\u76F8\u540C);edit \u6587\u4EF6\u65F6 PreToolUse hook \u53EF\u80FD\u89E6\u53D1 narrow hint\u3002
43
43
  - **Usage**:\u5E38\u6001\u8D70\u5355\u6B65 \`fab_recall(paths=[...])\` \u4E00\u6B21\u62FF\u56DE\u76F8\u5173 KB \u6B63\u6587\u3002\u4EC5\u5F53\u5355\u6B65\u6B63\u6587\u8FC7\u591A\u81F4\u4E0A\u4E0B\u6587\u8FC7\u8F7D\u3001\u9700\u7CBE\u786E\u88C1\u526A\u566A\u97F3\u65F6\u624D\u4E24\u6B65:\`fab_plan_context(paths=[...])\` \u8FD4\u56DE \`selection_token\` + \u9876\u5C42 \`candidates[]\`,\u518D \`fab_get_knowledge_sections({ selection_token, ai_selected_stable_ids: [<\u4ECE candidates[].stable_id \u6311>...] })\` \u62C9\u5168\u6587;\`selection_token\` \u5FC5\u987B\u6765\u81EA\u6700\u8FD1\u4E00\u6B21 \`fab_plan_context\`,\u4E0D\u53EF\u51ED\u7A7A\u7F16\u9020\u3002
44
44
  - **session_id**: \u8C03\u7528 \`fab_recall\` / \`fab_plan_context\` \u65F6, \u52A1\u5FC5\u628A\u5F53\u524D client session id \u4F5C\u4E3A \`session_id\` \u53C2\u6570\u4F20\u5165(Claude Code \u7684 session id \u5728 stdin payload \u4E2D, Codex \u7684\u5BF9\u5E94 identifier \u540C\u7406)\u3002\u8FD9\u80FD\u8BA9 \`fabric doctor --archive-history\` \u4E0E archive-hint hook \u51C6\u786E\u8BC6\u522B\u8DE8\u4F1A\u8BDD debt \u72B6\u6001\u3002
45
- - **Write flows**:\`fabric-archive\` / \`fabric-review\` / \`fabric-import\` \u4E09\u4E2A Skills\u3002
45
+ - **Skills (7)**:\u5199\u6D41\u7A0B \`fabric-archive\` / \`fabric-review\` / \`fabric-import\`;store \u6D41\u7A0B \`fabric-store\` / \`fabric-sync\` / \`fabric-connect\`;\u8BCA\u65AD \`fabric-audit\`\u3002
46
46
  - **Language**:\u6E32\u67D3\u6309 \`.fabric/fabric-config.json\` \u7684 \`fabric_language\` \u5B57\u6BB5\u3002
47
- - **Archive cadence nudge** (rc.36): \u6BCF\u5B8C\u6210 5+ \u6B21 Edit / \u663E\u8457 decision \u540E,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 \`fabric-archive\` skill \u2014 archive \u6CA1\u5EFA\u7ACB\u9891\u7387\u4F1A\u8BA9 KB \u6162\u901F\u6B7B\u6389\u3002
47
+ - **Archive cadence nudge** (rc.36): \u6BCF\u5B8C\u6210\u4E00\u6279 Edit(\u9ED8\u8BA4 ~20 \u6B21, \u4E0E Stop hook \u9608\u503C config \`archive_edit_threshold\` \u4E00\u81F4)/ \u663E\u8457 decision \u540E,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 \`fabric-archive\` skill \u2014 archive \u6CA1\u5EFA\u7ACB\u9891\u7387\u4F1A\u8BA9 KB \u6162\u901F\u6B7B\u6389\u3002
48
48
  - **Review backlog nudge** (rc.36): \`.fabric/knowledge/pending/\` \u7D2F\u79EF >10 \u6761\u65F6,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 \`fabric-review\` skill \u6279\u91CF\u5BA1,\u907F\u514D draft \u5361\u6B7B\u3002
49
49
 
50
50
  ## Self-archive policy (v2.0.0-rc.37 NEW-2: \u7B80\u5316 4 \u4FE1\u53F7 \u2192 2 \u5927\u7C7B)
@@ -75,10 +75,11 @@ var BOOTSTRAP_CANONICAL = `# Fabric Bootstrap
75
75
 
76
76
  Backward compat: Phase 1.5 entry-point regex \u540C\u65F6\u8BC6\u522B\u8001 4 \u4E2A\u4FE1\u53F7\u540D (Normative / Wrong-turn-and-revert / Decision confirmation / Explicit dismissal) \u4E0E\u65B0 2 \u5927\u7C7B\u540D, \u65E7 session marker \u4ECD\u80FD\u6B63\u786E\u8DEF\u7531\u3002
77
77
 
78
- ## Cite policy (v2.0.0-rc.37 NEW-1: \u7B80\u5316 4-state \u2192 2-state)
78
+ ## Cite policy (v2.1 \u2464 recall-based: \u81EA\u52A8\u8BB0\u8D26\u4F18\u5148, \u9996\u884C KB: \u53EF\u9009 override)
79
79
 
80
- - **\u89E6\u53D1**: \u505A edit / decide / propose plan \u4E4B\u524D,**\u56DE\u590D\u9996\u884C**\u5FC5\u987B\u5199 \`KB: <id> (<\u22648\u5B57 \u7528\u6CD5>) [applied|dismissed:<reason>]\` \u6216 \`KB: none [<reason>]\`\u3002
81
- - **\`[applied]\` \u9A8C\u8BC1\u4E49\u52A1**: \u5F15\u7528\u4EFB\u4F55 id \u524D\u5FC5\u987B\u5148\u7528 fab_recall (\u6216\u4E24\u6B65 fab_plan_context \u2192 fab_get_knowledge_sections) \u5B9E\u9645\u6293 KB body, \u9632\u6B62\u7F16\u9020 id\u3002\u9A8C\u8BC1\u4E0D\u901A\u8FC7 = \u4E0D\u80FD cite\u3002
80
+ - **\u6838\u5FC3 (recall-first \u81EA\u52A8\u8BB0\u8D26)**: \u6539\u4EFB\u4F55\u6587\u4EF6\u524D\u5148 \`fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>])\`\u3002\u7CFB\u7EDF\u6309"\u672C session \u8FD1\u671F recall \u547D\u4E2D\u7684 path \u4E0E\u7F16\u8F91\u76EE\u6807\u91CD\u53E0"\u81EA\u52A8\u628A\u53EC\u56DE\u7684 KB \u5173\u8054\u4E3A\u8BE5\u6B21 edit \u7684\u5F15\u7528 \u2014\u2014 **\u65E0\u9700\u624B\u5199\u56DE\u590D\u9996\u884C**\u3002PreToolUse hook \u5728\u68C0\u6D4B\u4E0D\u5230\u76F8\u5173 recall \u65F6\u7ED9\u4E00\u6761\u8F6F nudge(nudge \u975E gate,\u5B88 KT-DEC-0007);\u6539\u524D recall \u8FC7(\u6216\u5DF2\u624B\u5199 cite)\u5373\u9759\u9ED8\u3002\u4E3A\u4EC0\u4E48\u4E0D\u518D\u903C\u9996\u884C:\u5148\u60F3\u540E\u8BF4,recall \u624D\u662F\u5F15\u7528\u53D1\u751F\u7684\u771F\u5B9E\u4FE1\u53F7,\u624B\u5199\u9996\u884C\u8FDD\u80CC CoT \u4E14 \`KB: none\` \u9003\u9038\u4F7F\u65E7\u89C4\u5219\u5F62\u540C\u865A\u8BBE\u3002
81
+ - **\u53EF\u9009 override (\u9996\u884C KB:)**: \u4ECD\u53EF\u5728\u56DE\u590D\u9996\u884C\u624B\u5199 \`KB: <id> (<\u22648\u5B57 \u7528\u6CD5>) [applied|dismissed:<reason>]\` \u6216 \`KB: none [<reason>]\` \u6765\u663E\u5F0F\u6807\u6CE8/\u7CBE\u786E\u5316\u5F15\u7528;cite-line \u89E3\u6790\u5668\u4FDD\u7559(\u5411\u540E\u517C\u5BB9),\u65E7\u4E60\u60EF\u4E0D\u7834\u3002
82
+ - **\`[applied]\` \u9A8C\u8BC1\u4E49\u52A1**: \u5F15\u7528\u4EFB\u4F55 id(\u81EA\u52A8\u6216\u624B\u5199)\u7684\u524D\u63D0\u662F\u5148\u7528 fab_recall (\u6216\u4E24\u6B65 fab_plan_context \u2192 fab_get_knowledge_sections) \u5B9E\u9645\u6293 KB body, \u9632\u6B62\u7F16\u9020 id\u3002\u9A8C\u8BC1\u4E0D\u901A\u8FC7 = \u4E0D\u80FD cite\u3002
82
83
  - **store \u524D\u7F00 (v2.1, \u591A store)**: \u5F53 read-set \u542B\u591A\u4E2A store \u4E14\u540C\u4E00 local id \u5728\u591A store \u95F4 shadow \u65F6,cite \u5FC5\u987B store-qualified: \`KB: <store-alias>:<id> ...\`(\u5982 \`KB: team:KT-DEC-0001 (auth) [applied]\`);alias \u7528\u6237\u81EA\u5B9A/canonical,\u5E95\u5C42 UUID\u3002\u5355 store \u6216\u65E0\u6B67\u4E49\u65F6\u88F8 \`KB: <id>\` \u4ECD valid\u3002personal-only \u6761\u76EE cite \u8FDB\u56E2\u961F\u4EA7\u7269=\u5F3A warning(\u63A5 P2 \u5199\u8DEF\u5F84\u9632\u6CC4\u6F0F R5#3)\u3002
83
84
  - **contract \u8BED\u6CD5**: decisions/pitfalls \u7C7B \`[applied]\` cite \u5C3E\u6BB5\u52A0 contract: \`\u2192 <operator> [<operator> ...]\`,operator \u2208 {\`edit:<glob>\` \`!edit:<glob>\` \`require:<symbol>\` \`forbid:<symbol>\` \`skip:<reason>\`}\u3002\u4F8B:\`KB: K-001 (auth) [applied] \u2192 edit:src/auth/**/*.ts !edit:src/legacy/**\`\u3002
84
85
  - **skip reason \u8BCD\u5178**: \`sequencing | conditional | semantic | aesthetic | architectural | other:<text>\`\u3002
@@ -116,6 +116,18 @@ var enMessages = {
116
116
  "doctor.cite.metric.complianceRate": "cite compliance rate (incl. KB:none[reason])",
117
117
  "doctor.cite.metric.complianceNA": "N/A (no cite-expected turns)",
118
118
  "doctor.cite.metric.uncorrelatableEdits": "Uncorrelatable edits (no session_id \u2014 stale hook? run `fabric install`)",
119
+ "doctor.cite.metric.recallCoverage": "recall coverage (edits preceded by a relevant fab_recall)",
120
+ "doctor.cite.metric.recallCoverageNA": "N/A (no correlatable edits)",
121
+ // v2.2.0-rc.1 W1-T3 (cite 诚实拆分): WEAK auxiliary signal, rendered separately
122
+ // from the compliance rate. The parenthetical MUST state it is not counted
123
+ // toward true adherence (honesty 铁律).
124
+ "doctor.cite.metric.exposedAndMutated": "exposed & mutated (weak auxiliary signal \u2014 NOT counted toward true adherence)",
125
+ // lifecycle-refactor W2-T4 (§5 row7/row2): PostToolUse mutation funnel +
126
+ // SessionEnd boundary. Observability markers, NOT folded into adherence.
127
+ "doctor.cite.metric.mutationsObserved": "mutations observed (PostToolUse file_mutated \u2014 authoritative, NOT counted toward adherence)",
128
+ "doctor.cite.metric.mutationPool": "mutation pool (low-confidence attribution via source_event_id)",
129
+ "doctor.cite.metric.sessionsClosed": "sessions closed (SessionEnd markers \u2014 funnel boundary)",
130
+ "doctor.cite.metric.byStore": "qualifying cites by store (diagnostic split \u2014 NOT counted toward adherence; 'local' = project)",
119
131
  "doctor.cite.section.perClient": "Per-client",
120
132
  "doctor.cite.section.dismissedReasons": "Dismissed reasons",
121
133
  "doctor.cite.dismissed.scope-mismatch": "Scope mismatch",
@@ -180,6 +192,16 @@ var enMessages = {
180
192
  // v2.0.0-rc.24 TASK-10: --layer filters cite contract audit by KB layer (team|personal|all).
181
193
  "cli.doctor.args.layer.description": "Filter cite contract audit by KB layer (team|personal|all)",
182
194
  "cli.doctor.errors.cite-coverage-mutex": "--cite-coverage cannot be combined with --fix or --fix-knowledge",
195
+ "cli.doctor.errors.lint-conflicts-mutex": "--lint-conflicts cannot be combined with --fix, --fix-knowledge or --cite-coverage",
196
+ "cli.doctor.args.lint-conflicts.description": "Lint the knowledge base for conflicting/duplicate entry pairs (bm25 candidates)",
197
+ "cli.doctor.args.deep.description": "With --lint-conflicts: run the LLM judge over candidates (cold-eval seam)",
198
+ "doctor.conflict.header": "Knowledge conflict lint",
199
+ "doctor.conflict.none": "No candidate conflicting/duplicate pairs found",
200
+ "doctor.conflict.summary": "{candidates} candidate pair(s), {conflicts} judged conflict(s) (similarity \u2265 {threshold})",
201
+ "doctor.conflict.deep_no_judge": "--deep requested but no LLM judge is wired (run the cold-eval review manually); showing cheap candidates",
202
+ "doctor.conflict.verdict.conflict": "conflict",
203
+ "doctor.conflict.verdict.similar": "similar (possible duplicate)",
204
+ "doctor.conflict.verdict.unknown": "review (possible duplicate or conflict)",
183
205
  "cli.doctor.errors.invalid-since": "Invalid --since value: {input}. Expected duration like 7d, 24h, 30m or epoch ms.",
184
206
  "cli.doctor.errors.invalid-client": "Invalid --client value: {input}. Expected cc, codex, cursor, or all.",
185
207
  "cli.doctor.errors.invalid-layer": "Invalid --layer value: {input}. Expected team, personal, or all.",
@@ -281,7 +303,7 @@ var enMessages = {
281
303
  "doctor.check.events_jsonl_health.message.metric_leak": ".fabric/events.jsonl contains {count} rows with metric-counter event_types ({samples}). Those events should be aggregated in metrics.jsonl, not in the audit ledger.",
282
304
  "doctor.check.events_jsonl_health.message.metrics_stale": ".fabric/metrics.jsonl hasn't been updated for {minutes} minutes; the server-side 60s flush may be stalled.",
283
305
  "doctor.check.events_jsonl_health.message.rotation_overdue": ".fabric/events.jsonl hasn't rotated for {days} days; the 6h rotation tick may not be running.",
284
- "doctor.check.events_jsonl_health.remediation": "Run `fabric doctor --fix` to trigger a rotation; restart the MCP server so startMetricsFlush + startRotationTick reschedule. If metric_leak fires, audit recent code changes for direct appendEventLedgerEvent calls bypassing bumpCounter for one of the 4 metric-managed event_types.",
306
+ "doctor.check.events_jsonl_health.remediation": "Run `fabric doctor --fix` \u2014 it triggers a rotation AND flushes metrics.jsonl (rc.2 F16: clears idle-buffered metric counters without a server restart). If the warning persists, restart the MCP server so startMetricsFlush + startRotationTick reschedule. If metric_leak fires, audit recent code changes for direct appendEventLedgerEvent calls bypassing bumpCounter for one of the 4 metric-managed event_types.",
285
307
  "doctor.check.mcp_config_in_wrong_file.name": "Claude MCP config location",
286
308
  "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.",
287
309
  "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.",
@@ -554,6 +576,8 @@ var enMessages = {
554
576
  "cli.install.args.debug.description": "Print target resolution details to stderr.",
555
577
  "cli.install.args.yes.description": "Accept the current install plan and run without the TTY wizard",
556
578
  "cli.install.args.dry-run.description": "Print the install plan without writing files or running follow-up stages",
579
+ "cli.install.args.enable-embed.description": "Opt in to vector semantic search (sets embed_enabled + embed_model; prints fastembed install steps)",
580
+ "cli.install.args.embed-model.description": "With --enable-embed: override the pinned embed model (default fast-bge-small-zh-v1.5)",
557
581
  // rc.35 TASK-08 (P0-5/6): --force-skills-only.
558
582
  "cli.install.args.force-skills-only.description": "Skip bootstrap / MCP / hooks / settings; refresh ONLY the fabric Skill template copies (.claude/.codex/.cursor/skills/*).",
559
583
  "cli.install.force-skills-only.banner": "Refreshing fabric Skill templates only",
@@ -628,6 +652,7 @@ var enMessages = {
628
652
  // sessions won't pick up the new mcp config until they restart.
629
653
  "cli.install.restart-banner": "Restart hint: any already-running Claude Code / Cursor / Codex CLI session must restart to pick up the new MCP server config; new sessions will autoload the Fabric tools.",
630
654
  "cli.install.next-steps": 'Next steps \u2014 get your first value:\n 1. Restart your AI client (Claude Code / Codex). It now auto-surfaces this project\'s knowledge to the assistant.\n 2. Seed knowledge: just work normally \u2014 when you make a decision or hit a pitfall, the fabric-archive skill proposes an entry. Or run the fabric-import skill to backfill from git history.\n 3. Verify it works: ask your AI "what does Fabric know about this repo?", or run `fabric doctor` to check health.',
655
+ "cli.install.store-bind-nudge": "\u{1F4A1} Mounted store(s) not bound to this project: {aliases}. Run `fabric store bind {first}` to read their knowledge here, then `fabric store switch-write {first}` to write team knowledge into it.",
631
656
  "cli.install.capabilities.none": "No supported client was detected for bootstrap or MCP follow-up.",
632
657
  "cli.install.capabilities.header.client": "Client",
633
658
  "cli.install.capabilities.header.bootstrap": "Bootstrap",
@@ -972,6 +997,12 @@ var enMessages = {
972
997
  "cli.store.detached": "detached '{alias}' \u2014 on-disk store tree left intact (detach \u2260 delete)",
973
998
  "cli.store.bound": "bound required store '{id}' ({count} required)",
974
999
  "cli.store.switch-write": "active write store set to '{alias}' for this project",
1000
+ "cli.store.migrate.none": "no project-local knowledge to migrate (dual-root is empty)",
1001
+ "cli.store.migrate.dry-run-header": "migration preview (dry-run, nothing written):",
1002
+ "cli.store.migrate.applied-header": "migrated {count} entries into stores:",
1003
+ "cli.store.migrate.committed": "committed migration changes in the store repo",
1004
+ "cli.store.migrate.remap-note": " \u2191 remapped {oldId} \u2192 {newId} (target store id collision)",
1005
+ "cli.store.migrate.skips-header": "skipped {count} item(s):",
975
1006
  "cli.sync.deferred": "{count} store(s) offline \u2014 push deferred; re-run `fabric sync` when online",
976
1007
  "cli.sync.paused": "sync paused on a conflict \u2014 resolve it, then run `fabric sync --continue` (or `--abort`)",
977
1008
  "cli.metrics.invalid-since": '--since: invalid duration "{raw}" (expected e.g. 24h, 7d, 30m)',
@@ -1113,6 +1144,17 @@ var zhCNMessages = {
1113
1144
  "doctor.cite.metric.complianceRate": "cite \u5408\u89C4\u7387 (\u542B KB:none[reason])",
1114
1145
  "doctor.cite.metric.complianceNA": "N/A (\u65E0\u5E94 cite \u56DE\u5408)",
1115
1146
  "doctor.cite.metric.uncorrelatableEdits": "\u65E0\u6CD5\u5173\u8054\u7684 edit (\u7F3A session_id \u2014 hook \u8FC7\u671F? \u8BF7\u8DD1 `fabric install`)",
1147
+ "doctor.cite.metric.recallCoverage": "recall \u8986\u76D6\u7387 (\u6539\u524D\u6709\u76F8\u5173 fab_recall \u7684 edit \u5360\u6BD4)",
1148
+ "doctor.cite.metric.recallCoverageNA": "N/A (\u65E0\u53EF\u5173\u8054 edit)",
1149
+ // v2.2.0-rc.1 W1-T3 (cite 诚实拆分): 弱辅助信号, 与真遵循率分列展示。括注必须
1150
+ // 明确「不计入真遵循度」(诚实铁律)。
1151
+ "doctor.cite.metric.exposedAndMutated": "\u66DD\u5149\u4E14\u8DEF\u5F84\u53D8\u66F4 (\u5F31\u8F85\u52A9\u4FE1\u53F7 \u2014 \u4E0D\u8BA1\u5165\u771F\u9075\u5FAA\u5EA6)",
1152
+ // lifecycle-refactor W2-T4 (§5 row7/row2): PostToolUse mutation funnel +
1153
+ // SessionEnd 边界。均为可观测性 marker, 不计入真遵循度。
1154
+ "doctor.cite.metric.mutationsObserved": "mutation \u89C2\u6D4B\u6570 (PostToolUse file_mutated \u2014 \u6743\u5A01\u4FE1\u53F7, \u4E0D\u8BA1\u5165\u771F\u9075\u5FAA\u5EA6)",
1155
+ "doctor.cite.metric.mutationPool": "mutation \u5F52\u56E0\u6C60 (\u7ECF source_event_id \u7684 low-confidence \u5F52\u56E0)",
1156
+ "doctor.cite.metric.sessionsClosed": "\u5DF2\u95ED\u5408 session \u6570 (SessionEnd marker \u2014 funnel \u8FB9\u754C)",
1157
+ "doctor.cite.metric.byStore": "\u6309 store \u62C6\u5206\u7684\u5408\u89C4 cite \u6570 (\u8BCA\u65AD\u62C6\u5206 \u2014 \u4E0D\u8BA1\u5165\u771F\u9075\u5FAA\u5EA6; 'local' = \u672C\u9879\u76EE)",
1116
1158
  "doctor.cite.section.perClient": "\u6309\u5BA2\u6237\u7AEF\u62C6\u5206",
1117
1159
  "doctor.cite.section.dismissedReasons": "\u9A73\u56DE\u539F\u56E0\u5206\u5E03",
1118
1160
  "doctor.cite.dismissed.scope-mismatch": "\u8303\u56F4\u4E0D\u7B26",
@@ -1175,6 +1217,16 @@ var zhCNMessages = {
1175
1217
  // v2.0.0-rc.24 TASK-10: --layer 过滤 cite 合约审计的知识层 (team|personal|all)。
1176
1218
  "cli.doctor.args.layer.description": "\u6309\u77E5\u8BC6\u5C42\u8FC7\u6EE4 cite \u5408\u7EA6\u5BA1\u8BA1 (team|personal|all)",
1177
1219
  "cli.doctor.errors.cite-coverage-mutex": "--cite-coverage \u4E0D\u80FD\u4E0E --fix \u6216 --fix-knowledge \u540C\u65F6\u4F7F\u7528",
1220
+ "cli.doctor.errors.lint-conflicts-mutex": "--lint-conflicts \u4E0D\u80FD\u4E0E --fix / --fix-knowledge / --cite-coverage \u540C\u65F6\u4F7F\u7528",
1221
+ "cli.doctor.args.lint-conflicts.description": "\u4F53\u68C0\u77E5\u8BC6\u5E93\u4E2D\u4E92\u76F8\u77DB\u76FE/\u91CD\u590D\u7684\u6761\u76EE\u5BF9 (bm25 \u5019\u9009)",
1222
+ "cli.doctor.args.deep.description": "\u914D\u5408 --lint-conflicts: \u5BF9\u5019\u9009\u5BF9\u8DD1 LLM \u5224\u5B9A (\u51B7\u8BC4 seam)",
1223
+ "doctor.conflict.header": "\u77E5\u8BC6\u51B2\u7A81\u4F53\u68C0",
1224
+ "doctor.conflict.none": "\u672A\u53D1\u73B0\u53EF\u7591\u7684\u77DB\u76FE/\u91CD\u590D\u6761\u76EE\u5BF9",
1225
+ "doctor.conflict.summary": "{candidates} \u4E2A\u5019\u9009\u5BF9, {conflicts} \u4E2A\u5224\u5B9A\u4E3A\u77DB\u76FE (\u76F8\u4F3C\u5EA6 \u2265 {threshold})",
1226
+ "doctor.conflict.deep_no_judge": "\u5DF2\u8BF7\u6C42 --deep \u4F46\u672A\u63A5\u5165 LLM judge (\u8BF7\u624B\u52A8\u8DD1\u51B7\u8BC4 review);\u5148\u5C55\u793A\u4FBF\u5B9C\u5019\u9009",
1227
+ "doctor.conflict.verdict.conflict": "\u77DB\u76FE",
1228
+ "doctor.conflict.verdict.similar": "\u76F8\u4F3C (\u53EF\u80FD\u91CD\u590D)",
1229
+ "doctor.conflict.verdict.unknown": "\u5F85\u5BA1 (\u53EF\u80FD\u91CD\u590D\u6216\u77DB\u76FE)",
1178
1230
  "cli.doctor.errors.invalid-since": "--since \u53D6\u503C\u65E0\u6548: {input}\u3002\u9884\u671F\u683C\u5F0F 7d / 24h / 30m \u6216 epoch ms\u3002",
1179
1231
  "cli.doctor.errors.invalid-client": "--client \u53D6\u503C\u65E0\u6548: {input}\u3002\u9884\u671F cc / codex / cursor / all\u3002",
1180
1232
  "cli.doctor.errors.invalid-layer": "--layer \u53D6\u503C\u65E0\u6548: {input}\u3002\u9884\u671F team / personal / all\u3002",
@@ -1274,7 +1326,7 @@ var zhCNMessages = {
1274
1326
  "doctor.check.events_jsonl_health.message.metric_leak": ".fabric/events.jsonl \u542B {count} \u884C metric-counter \u7C7B event_type ({samples})\u3002\u8FD9\u4E9B event \u5E94\u7531 metrics.jsonl \u8BA1\u6570, \u4E0D\u518D\u8FDB\u5165 audit ledger\u3002",
1275
1327
  "doctor.check.events_jsonl_health.message.metrics_stale": ".fabric/metrics.jsonl \u5DF2 {minutes} \u5206\u949F\u672A\u66F4\u65B0\uFF1Bserver-side 60s flush \u53EF\u80FD stalled\u3002",
1276
1328
  "doctor.check.events_jsonl_health.message.rotation_overdue": ".fabric/events.jsonl \u5DF2 {days} \u5929\u672A rotate\uFF1B6h rotation tick \u53EF\u80FD\u672A\u8FD0\u884C\u3002",
1277
- "doctor.check.events_jsonl_health.remediation": "\u8FD0\u884C `fabric doctor --fix` \u89E6\u53D1 rotation; \u91CD\u542F MCP server \u8BA9 startMetricsFlush + startRotationTick \u91CD\u65B0\u8C03\u5EA6\u3002\u82E5 metric_leak \u547D\u4E2D, \u68C0\u67E5\u6700\u8FD1\u4EE3\u7801\u6539\u52A8\u662F\u5426\u7ED5\u8FC7 bumpCounter API \u76F4\u63A5 appendEventLedgerEvent \u5199\u4E86 4 \u4E2A metric-managed event_type \u4E4B\u4E00\u3002",
1329
+ "doctor.check.events_jsonl_health.remediation": "\u8FD0\u884C `fabric doctor --fix` \u2014\u2014 \u5B83\u4F1A\u89E6\u53D1 rotation \u5E76 flush metrics.jsonl(rc.2 F16: \u65E0\u9700\u91CD\u542F server \u5373\u53EF\u6E05\u51FA idle \u671F\u672A\u5237\u7684 metric counter)\u3002\u82E5\u544A\u8B66\u4ECD\u6301\u7EED, \u518D\u91CD\u542F MCP server \u8BA9 startMetricsFlush + startRotationTick \u91CD\u65B0\u8C03\u5EA6\u3002\u82E5 metric_leak \u547D\u4E2D, \u68C0\u67E5\u6700\u8FD1\u4EE3\u7801\u6539\u52A8\u662F\u5426\u7ED5\u8FC7 bumpCounter API \u76F4\u63A5 appendEventLedgerEvent \u5199\u4E86 4 \u4E2A metric-managed event_type \u4E4B\u4E00\u3002",
1278
1330
  "doctor.check.mcp_config_in_wrong_file.name": "Claude MCP config \u4F4D\u7F6E",
1279
1331
  "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",
1280
1332
  "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",
@@ -1545,6 +1597,8 @@ var zhCNMessages = {
1545
1597
  "cli.install.args.debug.description": "\u5C06\u76EE\u6807\u89E3\u6790\u7EC6\u8282\u8F93\u51FA\u5230 stderr\u3002",
1546
1598
  "cli.install.args.yes.description": "\u63A5\u53D7\u5F53\u524D\u5B89\u88C5\u8BA1\u5212\u5E76\u8DF3\u8FC7 TTY \u5411\u5BFC\u76F4\u63A5\u6267\u884C",
1547
1599
  "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",
1600
+ "cli.install.args.enable-embed.description": "\u542F\u7528\u5411\u91CF\u8BED\u4E49\u641C\u7D22 (\u8BBE embed_enabled + embed_model;\u6253\u5370 fastembed \u5B89\u88C5\u6B65\u9AA4)",
1601
+ "cli.install.args.embed-model.description": "\u914D\u5408 --enable-embed:\u8986\u76D6\u56FA\u5B9A\u7684 embed \u6A21\u578B (\u9ED8\u8BA4 fast-bge-small-zh-v1.5)",
1548
1602
  // rc.35 TASK-08 (P0-5/6): --force-skills-only。
1549
1603
  "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",
1550
1604
  "cli.install.force-skills-only.banner": "\u53EA\u5237\u65B0 fabric Skill \u6A21\u677F",
@@ -1619,6 +1673,7 @@ var zhCNMessages = {
1619
1673
  // 新 mcp config — 必须重启才能拿到 Fabric tools。
1620
1674
  "cli.install.restart-banner": "\u91CD\u542F\u63D0\u793A: \u5DF2\u8FD0\u884C\u7684 Claude Code / Cursor / Codex CLI session \u9700\u91CD\u542F\u624D\u80FD\u52A0\u8F7D\u65B0 MCP server \u914D\u7F6E;\u65B0\u4F1A\u8BDD\u4F1A\u81EA\u52A8\u4F7F\u7528 Fabric tools\u3002",
1621
1675
  "cli.install.next-steps": "\u4E0B\u4E00\u6B65 \u2014\u2014 \u62FF\u5230\u7B2C\u4E00\u4EFD\u4EF7\u503C:\n 1. \u91CD\u542F\u4F60\u7684 AI \u5BA2\u6237\u7AEF (Claude Code / Codex)\u3002\u5B83\u73B0\u5728\u4F1A\u81EA\u52A8\u628A\u672C\u9879\u76EE\u7684\u77E5\u8BC6 surface \u7ED9\u52A9\u624B\u3002\n 2. \u6C89\u6DC0\u77E5\u8BC6: \u6B63\u5E38\u5E72\u6D3B\u5373\u53EF \u2014\u2014 \u5F53\u4F60\u505A\u51B3\u7B56\u6216\u8E29\u5751\u65F6, fabric-archive skill \u4F1A\u63D0\u8BAE\u5165\u5E93; \u6216\u8DD1 fabric-import skill \u4ECE git \u5386\u53F2\u56DE\u704C\u3002\n 3. \u9A8C\u8BC1\u751F\u6548: \u95EE\u4F60\u7684 AI\u300CFabric \u5BF9\u8FD9\u4E2A repo \u77E5\u9053\u4E9B\u4EC0\u4E48?\u300D, \u6216\u8DD1 `fabric doctor` \u67E5\u5065\u5EB7\u3002",
1676
+ "cli.install.store-bind-nudge": "\u{1F4A1} \u68C0\u6D4B\u5230\u5DF2\u6302\u8F7D\u4F46\u672A\u7ED1\u5B9A\u672C\u9879\u76EE\u7684\u77E5\u8BC6 store: {aliases}\u3002\u8FD0\u884C `fabric store bind {first}` \u628A\u5B83\u7684\u77E5\u8BC6\u63A5\u5165\u672C\u9879\u76EE, \u518D `fabric store switch-write {first}` \u8BBE\u4E3A\u56E2\u961F\u77E5\u8BC6\u7684\u5199\u5165\u76EE\u6807\u3002",
1622
1677
  "cli.install.capabilities.none": "\u6CA1\u6709\u68C0\u6D4B\u5230\u53EF\u7528\u4E8E bootstrap \u6216 MCP \u540E\u7EED\u63A5\u529B\u7684\u53D7\u652F\u6301\u5BA2\u6237\u7AEF\u3002",
1623
1678
  "cli.install.capabilities.header.client": "\u5BA2\u6237\u7AEF",
1624
1679
  "cli.install.capabilities.header.bootstrap": "Bootstrap",
@@ -1962,6 +2017,12 @@ var zhCNMessages = {
1962
2017
  "cli.store.detached": "\u5DF2\u5206\u79BB '{alias}' \u2014\u2014 \u78C1\u76D8\u4E0A\u7684 store \u76EE\u5F55\u4FDD\u7559 (\u5206\u79BB \u2260 \u5220\u9664)",
1963
2018
  "cli.store.bound": "\u5DF2\u7ED1\u5B9A\u5FC5\u9700 store '{id}' (\u5171 {count} \u4E2A\u5FC5\u9700)",
1964
2019
  "cli.store.switch-write": "\u5DF2\u5C06\u672C\u9879\u76EE\u7684\u6D3B\u52A8\u5199\u5165 store \u8BBE\u4E3A '{alias}'",
2020
+ "cli.store.migrate.none": "\u6CA1\u6709\u9700\u8981\u8FC1\u79FB\u7684\u9879\u76EE\u672C\u5730\u77E5\u8BC6 (dual-root \u5DF2\u7A7A)",
2021
+ "cli.store.migrate.dry-run-header": "\u8FC1\u79FB\u9884\u89C8 (dry-run, \u4E0D\u5199\u5165\u78C1\u76D8):",
2022
+ "cli.store.migrate.applied-header": "\u5DF2\u8FC1\u79FB {count} \u6761\u8FDB store:",
2023
+ "cli.store.migrate.committed": "\u5DF2\u5728 store \u4ED3\u5E93\u63D0\u4EA4\u8FC1\u79FB\u53D8\u66F4",
2024
+ "cli.store.migrate.remap-note": " \u2191 \u56E0\u76EE\u6807 store id \u51B2\u7A81, {oldId} \u91CD\u6620\u5C04\u4E3A {newId}",
2025
+ "cli.store.migrate.skips-header": "\u8DF3\u8FC7 {count} \u9879:",
1965
2026
  "cli.sync.deferred": "{count} \u4E2A store \u79BB\u7EBF \u2014\u2014 push \u5DF2\u5EF6\u540E; \u8054\u7F51\u540E\u91CD\u65B0\u8FD0\u884C `fabric sync`",
1966
2027
  "cli.sync.paused": "sync \u56E0\u51B2\u7A81\u6682\u505C \u2014\u2014 \u89E3\u51B3\u540E\u8FD0\u884C `fabric sync --continue` (\u6216 `--abort`)",
1967
2028
  "cli.metrics.invalid-since": '--since: \u65E0\u6548\u7684\u65F6\u957F "{raw}" (\u793A\u4F8B: 24h\u30017d\u300130m)',
@@ -2057,7 +2118,10 @@ function resolveFabricLocale(projectRoot) {
2057
2118
  if (fabricLanguage === "en" || fabricLanguage === "zh-CN") {
2058
2119
  return fabricLanguage;
2059
2120
  }
2060
- if (fabricLanguage === "match-existing" || fabricLanguage === "zh-CN-hybrid") {
2121
+ if (fabricLanguage === "zh-CN-hybrid") {
2122
+ return "zh-CN";
2123
+ }
2124
+ if (fabricLanguage === "match-existing") {
2061
2125
  console.warn(
2062
2126
  `[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.`
2063
2127
  );
@@ -36,6 +36,9 @@ var ConfigPathInvalidError = class extends ConfigError {
36
36
  var GenericConfigError = class extends ConfigError {
37
37
  code = "config_error";
38
38
  };
39
+ var StoreWriteTargetUnresolvedError = class extends ConfigError {
40
+ code = "store_write_target_unresolved";
41
+ };
39
42
 
40
43
  // src/errors/rule-error.ts
41
44
  var RuleError = class extends FabricError {
@@ -78,6 +81,7 @@ export {
78
81
  ConfigError,
79
82
  ConfigPathInvalidError,
80
83
  GenericConfigError,
84
+ StoreWriteTargetUnresolvedError,
81
85
  RuleError,
82
86
  RuleValidationError,
83
87
  IOFabricError,
@@ -28,6 +28,9 @@ declare class ConfigPathInvalidError extends ConfigError {
28
28
  declare class GenericConfigError extends ConfigError {
29
29
  readonly code = "config_error";
30
30
  }
31
+ declare class StoreWriteTargetUnresolvedError extends ConfigError {
32
+ readonly code = "store_write_target_unresolved";
33
+ }
31
34
 
32
35
  declare abstract class RuleError extends FabricError {
33
36
  readonly httpStatus: number;
@@ -62,4 +65,4 @@ declare class InitFrameworkUnknownError extends InitError {
62
65
  readonly code = "init_framework_unknown";
63
66
  }
64
67
 
65
- export { ConfigError, ConfigPathInvalidError, FabricError, GenericConfigError, GenericIOError, IOFabricError, InitError, InitFrameworkUnknownError, MCPError, McpToolError, PathEscapeError, RuleError, RuleValidationError };
68
+ export { ConfigError, ConfigPathInvalidError, FabricError, GenericConfigError, GenericIOError, IOFabricError, InitError, InitFrameworkUnknownError, MCPError, McpToolError, PathEscapeError, RuleError, RuleValidationError, StoreWriteTargetUnresolvedError };
@@ -11,8 +11,9 @@ import {
11
11
  McpToolError,
12
12
  PathEscapeError,
13
13
  RuleError,
14
- RuleValidationError
15
- } from "../chunk-3SZRB42B.js";
14
+ RuleValidationError,
15
+ StoreWriteTargetUnresolvedError
16
+ } from "../chunk-VW5QGPIN.js";
16
17
  export {
17
18
  ConfigError,
18
19
  ConfigPathInvalidError,
@@ -26,5 +27,6 @@ export {
26
27
  McpToolError,
27
28
  PathEscapeError,
28
29
  RuleError,
29
- RuleValidationError
30
+ RuleValidationError,
31
+ StoreWriteTargetUnresolvedError
30
32
  };
@@ -7,7 +7,7 @@ import {
7
7
  normalizeLocale,
8
8
  resolveFabricLocale,
9
9
  zhCNMessages
10
- } from "../chunk-7TZ2PMVH.js";
10
+ } from "../chunk-QSD4PN4W.js";
11
11
  export {
12
12
  PROTECTED_TOKENS,
13
13
  createTranslator,
@@ -184,6 +184,10 @@ declare const fabricConfigSchema: z.ZodObject<{
184
184
  reverse_unarchive_enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
185
185
  reverse_unarchive_dry_run: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
186
186
  cite_evict_interval: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
187
+ cite_recall_nudge: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
188
+ cite_recall_window_minutes: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
189
+ cite_nudge_ignore_globs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
190
+ conflict_lint_similarity_threshold: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
187
191
  fabric_event_retention_days: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<7>, z.ZodLiteral<30>, z.ZodLiteral<90>]>>;
188
192
  onboard_slots_opted_out: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
189
193
  hint_broad_top_k: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
@@ -195,9 +199,11 @@ declare const fabricConfigSchema: z.ZodObject<{
195
199
  hint_narrow_dedup_window_turns: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
196
200
  hint_broad_cooldown_hours: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
197
201
  hint_narrow_cooldown_hours: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
202
+ orphan_demote_proven_days: z.ZodOptional<z.ZodNumber>;
203
+ orphan_demote_verified_days: z.ZodOptional<z.ZodNumber>;
204
+ orphan_demote_draft_days: z.ZodOptional<z.ZodNumber>;
198
205
  orphan_demote_stable_days: z.ZodOptional<z.ZodNumber>;
199
206
  orphan_demote_endorsed_days: z.ZodOptional<z.ZodNumber>;
200
- orphan_demote_draft_days: z.ZodOptional<z.ZodNumber>;
201
207
  hint_summary_max_len: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
202
208
  hint_reminder_to_context: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
203
209
  selection_token_ttl_ms: z.ZodOptional<z.ZodNumber>;
@@ -205,6 +211,7 @@ declare const fabricConfigSchema: z.ZodObject<{
205
211
  retrieval_budget_profile: z.ZodOptional<z.ZodEnum<["conservative", "balanced", "generous"]>>;
206
212
  embed_enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
207
213
  embed_weight: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
214
+ embed_model: z.ZodDefault<z.ZodOptional<z.ZodEnum<["fast-bge-small-zh-v1.5", "fast-multilingual-e5-large", "fast-bge-small-en-v1.5", "fast-bge-small-en", "fast-bge-base-en-v1.5", "fast-bge-base-en", "fast-all-MiniLM-L6-v2"]>>>;
208
215
  }, "strip", z.ZodTypeAny, {
209
216
  fabric_language: "match-existing" | "zh-CN" | "en" | "zh-CN-hybrid";
210
217
  default_layer_filter: "personal" | "team" | "both";
@@ -229,6 +236,9 @@ declare const fabricConfigSchema: z.ZodObject<{
229
236
  reverse_unarchive_enabled: boolean;
230
237
  reverse_unarchive_dry_run: boolean;
231
238
  cite_evict_interval: number;
239
+ cite_recall_nudge: boolean;
240
+ cite_recall_window_minutes: number;
241
+ conflict_lint_similarity_threshold: number;
232
242
  onboard_slots_opted_out: string[];
233
243
  hint_broad_top_k: number;
234
244
  hint_broad_budget_chars: number;
@@ -242,6 +252,7 @@ declare const fabricConfigSchema: z.ZodObject<{
242
252
  hint_reminder_to_context: boolean;
243
253
  embed_enabled: boolean;
244
254
  embed_weight: number;
255
+ embed_model: "fast-bge-small-zh-v1.5" | "fast-multilingual-e5-large" | "fast-bge-small-en-v1.5" | "fast-bge-small-en" | "fast-bge-base-en-v1.5" | "fast-bge-base-en" | "fast-all-MiniLM-L6-v2";
245
256
  clientPaths?: {
246
257
  claudeCodeCLI?: string | undefined;
247
258
  claudeCodeDesktop?: string | undefined;
@@ -260,11 +271,14 @@ declare const fabricConfigSchema: z.ZodObject<{
260
271
  warnBytes?: number | undefined;
261
272
  hardBytes?: number | undefined;
262
273
  } | undefined;
274
+ cite_nudge_ignore_globs?: string[] | undefined;
263
275
  fabric_event_retention_days?: 7 | 30 | 90 | undefined;
264
276
  hint_dismiss_signals?: ("archive" | "review" | "import" | "maintenance")[] | undefined;
277
+ orphan_demote_proven_days?: number | undefined;
278
+ orphan_demote_verified_days?: number | undefined;
279
+ orphan_demote_draft_days?: number | undefined;
265
280
  orphan_demote_stable_days?: number | undefined;
266
281
  orphan_demote_endorsed_days?: number | undefined;
267
- orphan_demote_draft_days?: number | undefined;
268
282
  selection_token_ttl_ms?: number | undefined;
269
283
  plan_context_top_k?: number | undefined;
270
284
  retrieval_budget_profile?: "conservative" | "balanced" | "generous" | undefined;
@@ -310,6 +324,10 @@ declare const fabricConfigSchema: z.ZodObject<{
310
324
  reverse_unarchive_enabled?: boolean | undefined;
311
325
  reverse_unarchive_dry_run?: boolean | undefined;
312
326
  cite_evict_interval?: number | undefined;
327
+ cite_recall_nudge?: boolean | undefined;
328
+ cite_recall_window_minutes?: number | undefined;
329
+ cite_nudge_ignore_globs?: string[] | undefined;
330
+ conflict_lint_similarity_threshold?: number | undefined;
313
331
  fabric_event_retention_days?: 7 | 30 | 90 | undefined;
314
332
  onboard_slots_opted_out?: string[] | undefined;
315
333
  hint_broad_top_k?: number | undefined;
@@ -321,9 +339,11 @@ declare const fabricConfigSchema: z.ZodObject<{
321
339
  hint_narrow_dedup_window_turns?: number | undefined;
322
340
  hint_broad_cooldown_hours?: number | undefined;
323
341
  hint_narrow_cooldown_hours?: number | undefined;
342
+ orphan_demote_proven_days?: number | undefined;
343
+ orphan_demote_verified_days?: number | undefined;
344
+ orphan_demote_draft_days?: number | undefined;
324
345
  orphan_demote_stable_days?: number | undefined;
325
346
  orphan_demote_endorsed_days?: number | undefined;
326
- orphan_demote_draft_days?: number | undefined;
327
347
  hint_summary_max_len?: number | undefined;
328
348
  hint_reminder_to_context?: boolean | undefined;
329
349
  selection_token_ttl_ms?: number | undefined;
@@ -331,6 +351,7 @@ declare const fabricConfigSchema: z.ZodObject<{
331
351
  retrieval_budget_profile?: "conservative" | "balanced" | "generous" | undefined;
332
352
  embed_enabled?: boolean | undefined;
333
353
  embed_weight?: number | undefined;
354
+ embed_model?: "fast-bge-small-zh-v1.5" | "fast-multilingual-e5-large" | "fast-bge-small-en-v1.5" | "fast-bge-small-en" | "fast-bge-base-en-v1.5" | "fast-bge-base-en" | "fast-all-MiniLM-L6-v2" | undefined;
334
355
  }>;
335
356
 
336
357
  interface ClientPaths {