@fenglimg/fabric-shared 2.0.0-rc.25 → 2.0.0-rc.27

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.
@@ -368,7 +368,23 @@ var _fabReviewFiltersSchema = z2.object({
368
368
  // rc.4 TASK-006 fix (c): ISO-8601 lower bound on entry created_at; entries
369
369
  // strictly older than this threshold are excluded from list / search
370
370
  // results. Additive optional field — existing callers unaffected.
371
- created_after: z2.string().datetime().optional()
371
+ created_after: z2.string().datetime().optional(),
372
+ // v2.0.0-rc.27 TASK-001 (§2.2/§2.3): opt-in surfacing of lifecycle-filtered
373
+ // entries. Default (omit both) hides rejected entries and deferred entries
374
+ // whose deferred_until is in the future. Pass true to include them — e.g.
375
+ // for vacuum tooling, audit dashboards, or "show me what I parked" UX.
376
+ include_rejected: z2.boolean().optional(),
377
+ include_deferred: z2.boolean().optional(),
378
+ // v2.0.0-rc.27 TASK-006 (audit §2.23): opt-in body inspection. Default
379
+ // list/search return only frontmatter-derived fields — a malicious
380
+ // pending entry could hide a prompt-injection payload under `## Evidence`
381
+ // body content that frontmatter inspection never surfaces. Setting
382
+ // `include_body: true` attaches the full post-frontmatter content to
383
+ // each item, and (for search) extends the haystack to body text. The
384
+ // default-off design keeps the wire payload small for routine list
385
+ // calls; reviewer workflows pass `true` before approving so the body
386
+ // is rendered into the reviewer's UI for visual scan.
387
+ include_body: z2.boolean().optional()
372
388
  }).optional();
373
389
  var _fabReviewModifyChangesSchema = z2.object({
374
390
  title: z2.string().optional(),
@@ -445,6 +461,14 @@ var FabReviewInputShape = {
445
461
  };
446
462
  var _fabReviewListItemSchema = z2.object({
447
463
  pending_path: z2.string(),
464
+ // v2.0.0-rc.27 TASK-001 (§2.12): for personal-layer entries `pending_path`
465
+ // carries the human-friendly `~/...` form (legacy contract) while
466
+ // `pending_path_absolute` carries the os-expanded absolute path. Programmatic
467
+ // consumers (Read tool, fs.readFile, downstream MCP servers) should prefer
468
+ // the absolute variant — the `~` is a shell-only sigil that breaks every
469
+ // non-shell consumer. Team entries omit this field because their
470
+ // `pending_path` is already project-relative and unambiguous.
471
+ pending_path_absolute: z2.string().optional(),
448
472
  type: z2.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]),
449
473
  layer: z2.enum(["team", "personal"]),
450
474
  maturity: z2.enum(["draft", "verified", "proven"]),
@@ -455,7 +479,19 @@ var _fabReviewListItemSchema = z2.object({
455
479
  // 'personal' = ~/.fabric/knowledge/pending. Distinct from `layer` (frontmatter):
456
480
  // origin reflects where the pending file actually lives on disk; layer reflects
457
481
  // the declared classification that will drive the approve destination.
458
- origin: z2.enum(["team", "personal"]).optional()
482
+ origin: z2.enum(["team", "personal"]).optional(),
483
+ // v2.0.0-rc.27 TASK-001 (§2.2/§2.3): frontmatter status markers. Default
484
+ // "active" (or absent). `rejected` entries are excluded from list/search
485
+ // unless filters.include_rejected=true; `deferred` entries are excluded
486
+ // when deferred_until is in the future. Authored by reject/defer write
487
+ // paths — never by extract or approve.
488
+ status: z2.enum(["active", "rejected", "deferred"]).optional(),
489
+ deferred_until: z2.string().datetime().optional(),
490
+ // v2.0.0-rc.27 TASK-006 (audit §2.23): full body content (everything
491
+ // after the closing `---` of frontmatter). Surfaced only when caller
492
+ // passes `filters.include_body: true`. Default-omitted to keep payload
493
+ // small for routine list calls.
494
+ body: z2.string().optional()
459
495
  });
460
496
  var FabReviewOutputSchema = z2.discriminatedUnion("action", [
461
497
  z2.object({
@@ -178,6 +178,215 @@ var enMessages = {
178
178
  "cli.doctor.args.dry-run.description": "With --enrich-descriptions --auto: preview the would-be changes without writing to disk.",
179
179
  "cli.doctor.errors.enrich-descriptions-mutex": "--enrich-descriptions cannot be combined with --fix, --fix-knowledge, or --cite-coverage. Run them separately.",
180
180
  "doctor.enrich.allComplete": "All canonical knowledge entries already declare intent_clues / tech_stack / impact / must_read_if.",
181
+ // rc.26 TASK-02a: doctor foundation-batch check messages.
182
+ "doctor.check.bootstrap_marker_migration.name": "Bootstrap marker migration",
183
+ "doctor.check.bootstrap_marker_migration.ok": "No legacy fabric:knowledge-base markers detected in bootstrap target files.",
184
+ "doctor.check.bootstrap_marker_migration.message.singular": "{count} file still carry the legacy fabric:knowledge-base bootstrap marker: {list}.",
185
+ "doctor.check.bootstrap_marker_migration.message.plural": "{count} files still carry the legacy fabric:knowledge-base bootstrap marker: {list}.",
186
+ "doctor.check.bootstrap_marker_migration.remediation": "Run `fab doctor --fix` to migrate to fabric:bootstrap marker",
187
+ "doctor.check.bootstrap_snapshot_drift.name": "Bootstrap snapshot drift",
188
+ "doctor.check.bootstrap_snapshot_drift.message.drift": ".fabric/AGENTS.md content diverges byte-for-byte from BOOTSTRAP_CANONICAL.",
189
+ "doctor.check.bootstrap_snapshot_drift.remediation.drift": "Run `fab doctor --fix` to restore canonical bootstrap snapshot",
190
+ "doctor.check.bootstrap_snapshot_drift.ok.ok": ".fabric/AGENTS.md byte-equals BOOTSTRAP_CANONICAL.",
191
+ "doctor.check.bootstrap_snapshot_drift.ok.missing_delegated": ".fabric/AGENTS.md absent \u2014 delegated to bootstrap_anchor_missing.",
192
+ "doctor.check.managed_block_drift.name": "Managed block drift",
193
+ "doctor.check.managed_block_drift.message.singular": "{count} three-end managed block diverge from expected body (snapshot + optional project-rules concat): {list}.",
194
+ "doctor.check.managed_block_drift.message.plural": "{count} three-end managed blocks diverge from expected body (snapshot + optional project-rules concat): {list}.",
195
+ "doctor.check.managed_block_drift.remediation": "Run `fab doctor --fix` to restore three-end managed blocks from canonical",
196
+ "doctor.check.managed_block_drift.ok.ok": "Three-end managed blocks byte-equal expectedBody.",
197
+ "doctor.check.managed_block_drift.ok.no_managed_block": "No three-end managed blocks detected \u2014 propagation pending or legacy-marker state.",
198
+ "doctor.check.bootstrap_anchor.name": "Bootstrap anchor",
199
+ "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.",
200
+ "doctor.check.bootstrap_anchor.remediation.missing": "Run `fabric install` to generate the AGENTS.md / CLAUDE.md bootstrap anchor at the repo root.",
201
+ "doctor.check.bootstrap_anchor.ok": "Bootstrap anchor present at repo root: {present}.",
202
+ "doctor.check.baseline_filename_format.name": "Baseline filename format",
203
+ "doctor.check.baseline_filename_format.ok": "All baseline knowledge files use the canonical `${id}--${slug}.md` filename format.",
204
+ "doctor.check.baseline_filename_format.message.singular": "{count} baseline knowledge file uses the deprecated bare-slug filename format and must be migrated to `${id}--${slug}.md`. First: {detail}.",
205
+ "doctor.check.baseline_filename_format.message.plural": "{count} baseline knowledge files use the deprecated bare-slug filename format and must be migrated to `${id}--${slug}.md`. First: {detail}.",
206
+ "doctor.check.baseline_filename_format.remediation": "Delete the legacy bare-slug baseline file(s) manually \u2014 the baseline pipeline was removed in rc.23 and is no longer an auto-fix path.",
207
+ "doctor.check.knowledge_dir_missing.name": "Knowledge layout",
208
+ "doctor.check.knowledge_dir_missing.message.singular": "{count} required knowledge subdir is missing: {list}.",
209
+ "doctor.check.knowledge_dir_missing.message.plural": "{count} required knowledge subdirs are missing: {list}.",
210
+ "doctor.check.knowledge_dir_missing.remediation": "Run `fab doctor --fix` to create the missing .fabric/knowledge/* subdirectories.",
211
+ "doctor.check.knowledge_dir_missing.ok": "All {count} required .fabric/knowledge/* subdirectories exist.",
212
+ "doctor.check.forensic.name": "Scan evidence",
213
+ "doctor.check.forensic.message.missing.singular": "{error} Live scan detects {frameworkKind} with {count} entry point.",
214
+ "doctor.check.forensic.message.missing.plural": "{error} Live scan detects {frameworkKind} with {count} entry points.",
215
+ "doctor.check.forensic.message.missing-default": ".fabric/forensic.json is missing.",
216
+ "doctor.check.forensic.message.invalid-default": ".fabric/forensic.json is invalid.",
217
+ "doctor.check.forensic.remediation": "Run `fab install` to regenerate .fabric/forensic.json.",
218
+ "doctor.check.forensic.ok": ".fabric/forensic.json is valid for {frameworkKind}.",
219
+ "doctor.check.agents_meta.name": "Agents metadata",
220
+ "doctor.check.agents_meta.message.missing": ".fabric/agents.meta.json is missing.",
221
+ "doctor.check.agents_meta.remediation.missing": "Run `fab doctor --fix` to rebuild agents.meta.json from .fabric/knowledge/.",
222
+ "doctor.check.agents_meta.message.invalid-default": ".fabric/agents.meta.json is invalid.",
223
+ "doctor.check.agents_meta.remediation.invalid": "Delete .fabric/agents.meta.json and run `fab doctor --fix` to regenerate it.",
224
+ "doctor.check.agents_meta.message.stale": ".fabric/agents.meta.json revision {revision} does not match .fabric/knowledge derived revision {computedRevision}.",
225
+ "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.",
226
+ "doctor.check.agents_meta.ok": ".fabric/agents.meta.json revision {revision} is aligned with .fabric/knowledge.",
227
+ "doctor.check.rule_content_refs.name": "Rule content refs",
228
+ "doctor.check.rule_content_refs.message.unavailable": "Cannot inspect content_ref entries until agents.meta.json is valid.",
229
+ "doctor.check.rule_content_refs.remediation.unavailable": "Fix agents.meta.json first: run `fab doctor --fix`.",
230
+ "doctor.check.rule_content_refs.message.outside.singular": "{count} content_ref entry is outside .fabric/knowledge.",
231
+ "doctor.check.rule_content_refs.message.outside.plural": "{count} content_ref entries are outside .fabric/knowledge.",
232
+ "doctor.check.rule_content_refs.remediation.outside": "Edit agents.meta.json to ensure all content_ref values point inside .fabric/knowledge/{type}/ (team) or ~/.fabric/knowledge/{type}/ (personal).",
233
+ "doctor.check.rule_content_refs.message.missing.singular": "{count} content_ref target is missing. Run `fab doctor --fix` to reconcile.",
234
+ "doctor.check.rule_content_refs.message.missing.plural": "{count} content_ref targets are missing. Run `fab doctor --fix` to reconcile.",
235
+ "doctor.check.rule_content_refs.remediation.missing": "Run `fab doctor --fix` to reconcile agents.meta.json with the files present in .fabric/knowledge/.",
236
+ "doctor.check.rule_content_refs.ok": "All content_ref entries resolve to .fabric/knowledge files.",
237
+ "doctor.check.knowledge_test_index.name": "Knowledge-test index",
238
+ "doctor.check.knowledge_test_index.remediation.missing": "Run `fab doctor --fix` to rebuild .fabric/.cache/knowledge-test.index.json.",
239
+ "doctor.check.knowledge_test_index.remediation.invalid": "Delete .fabric/.cache/knowledge-test.index.json and run `fab doctor --fix` to regenerate it.",
240
+ "doctor.check.knowledge_test_index.message.stale": ".fabric/.cache/knowledge-test.index.json is stale.",
241
+ "doctor.check.knowledge_test_index.remediation.stale": "Run `fab doctor --fix` to rebuild the knowledge-test index.",
242
+ "doctor.check.knowledge_test_index.ok.link_singular.orphan_singular": "{linkCount} link and {orphanCount} orphan annotation indexed.",
243
+ "doctor.check.knowledge_test_index.ok.link_singular.orphan_plural": "{linkCount} link and {orphanCount} orphan annotations indexed.",
244
+ "doctor.check.knowledge_test_index.ok.link_plural.orphan_singular": "{linkCount} links and {orphanCount} orphan annotation indexed.",
245
+ "doctor.check.knowledge_test_index.ok.link_plural.orphan_plural": "{linkCount} links and {orphanCount} orphan annotations indexed.",
246
+ "doctor.check.event_ledger.name": "Event ledger",
247
+ "doctor.check.event_ledger.message.missing": ".fabric/events.jsonl is missing.",
248
+ "doctor.check.event_ledger.remediation.missing": "Run `fab doctor --fix` to create .fabric/events.jsonl.",
249
+ "doctor.check.event_ledger.message.not_writable-default": ".fabric/events.jsonl is not writable.",
250
+ "doctor.check.event_ledger.remediation.not_writable": "Check file permissions on .fabric/events.jsonl and ensure no other process holds a write lock.",
251
+ "doctor.check.event_ledger.message.invalid-default": ".fabric/events.jsonl is invalid.",
252
+ "doctor.check.event_ledger.remediation.invalid": "Delete .fabric/events.jsonl and run `fab doctor --fix` to recreate it.",
253
+ "doctor.check.event_ledger.ok": ".fabric/events.jsonl exists, is writable, and is parseable.",
254
+ "doctor.check.mcp_config_in_wrong_file.name": "Claude MCP config location",
255
+ "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.",
256
+ "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.",
257
+ "doctor.check.mcp_config_in_wrong_file.ok": "mcpServers.fabric is not in .claude/settings.json.",
258
+ "doctor.check.event_ledger_partial_write.name": "Event ledger partial write",
259
+ "doctor.check.event_ledger_partial_write.ok.skipped": "No partial-write check needed (ledger missing or not writable).",
260
+ "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.",
261
+ "doctor.check.event_ledger_partial_write.remediation": "Run `fab doctor --fix` to truncate the partial write and restore events.jsonl to a valid state.",
262
+ "doctor.check.event_ledger_partial_write.ok.clean": "events.jsonl has no partial trailing write.",
263
+ // v2.0.0-rc.27 TASK-010 (audit §2.24): schema-compat forward-warn category.
264
+ "doctor.check.event_ledger_schema_compat.name": "Event ledger schema compat",
265
+ "doctor.check.event_ledger_schema_compat.ok.skipped": "No schema-compat check needed (ledger missing or not writable).",
266
+ "doctor.check.event_ledger_schema_compat.ok.clean": "events.jsonl rows all parse against the current schema.",
267
+ "doctor.check.event_ledger_schema_compat.message.schema_version": "events.jsonl has {count} row(s) with unsupported `schema_version` (samples: {samples}).",
268
+ "doctor.check.event_ledger_schema_compat.message.event_type": "events.jsonl has {count} row(s) with unknown `event_type` (samples: {samples}).",
269
+ "doctor.check.event_ledger_schema_compat.remediation": "Either upgrade the fab CLI to a server-compatible version, or archive `.fabric/events.jsonl` and run `fab doctor --fix` to recreate a fresh ledger.",
270
+ "doctor.check.meta_manually_diverged.name": "Meta manual divergence",
271
+ "doctor.check.meta_manually_diverged.ok.unreadable": "agents.meta.json not readable; skipping divergence check.",
272
+ "doctor.check.meta_manually_diverged.message.extra.singular": "agents.meta.json has {count} entry with no backing file on disk. Run --fix to reconcile.",
273
+ "doctor.check.meta_manually_diverged.message.extra.plural": "agents.meta.json has {count} entries with no backing file on disk. Run --fix to reconcile.",
274
+ "doctor.check.meta_manually_diverged.remediation.extra": "Run `fab doctor --fix` to reconcile agents.meta.json with the rule files currently on disk.",
275
+ "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.",
276
+ "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.",
277
+ "doctor.check.meta_manually_diverged.remediation.hash": "Run `fab doctor --fix` to reconcile agents.meta.json with the current rule file contents.",
278
+ "doctor.check.meta_manually_diverged.ok.consistent": "agents.meta.json is consistent with rule files on disk.",
279
+ "doctor.check.knowledge_dir_unindexed.name": "Knowledge dir unindexed",
280
+ "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.",
281
+ "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.",
282
+ "doctor.check.knowledge_dir_unindexed.remediation": "Run `fab doctor --fix` to index the missing knowledge files.",
283
+ "doctor.check.knowledge_dir_unindexed.ok": "All .fabric/knowledge/ .md files are indexed in agents.meta.json.",
284
+ "doctor.check.stable_id_collision.name": "Stable ID collision",
285
+ "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.',
286
+ "doctor.check.stable_id_collision.message.plural": '{count} stable_id collisions detected. First: "{stableId}" in {files}. Edit one of the knowledge files to use a unique stable_id.',
287
+ "doctor.check.stable_id_collision.remediation": "Edit one of the colliding knowledge files to declare a different `id: K[PT]-XXX-NNNN` frontmatter value.",
288
+ "doctor.check.stable_id_collision.ok": "No declared stable_id collisions found in .fabric/knowledge/.",
289
+ "doctor.check.counter_desync.name": "Knowledge counter desync",
290
+ "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.",
291
+ "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.",
292
+ "doctor.check.counter_desync.remediation": "Run `fab doctor --fix` to bump agents.meta.json counters to the maximum observed counter value.",
293
+ "doctor.check.counter_desync.ok": "agents.meta.json counters envelope is consistent with observed stable_ids.",
294
+ "doctor.check.preexisting_root_files.name": "Preexisting root markdown",
295
+ "doctor.check.preexisting_root_files.ok": "No CLAUDE.md or AGENTS.md detected at project root.",
296
+ "doctor.check.preexisting_root_files.message": "{files} detected at project root. These root files are not auto-loaded by Fabric MCP.",
297
+ "doctor.check.preexisting_root_files.remediation": "Move knowledge content to `.fabric/knowledge/{type}/` if you want it available in MCP responses.",
298
+ "doctor.check.filesystem_edit_fallback.name": "Filesystem-edit fallback",
299
+ "doctor.check.filesystem_edit_fallback.ok": "No orphan canonical knowledge entries detected; events.jsonl promotion trail is complete.",
300
+ "doctor.check.filesystem_edit_fallback.message.synthesized.singular": "Synthesized {count} knowledge_promoted event for orphan canonical entries ({sample}{suffix}). Reason='{reason}'.",
301
+ "doctor.check.filesystem_edit_fallback.message.synthesized.plural": "Synthesized {count} knowledge_promoted events for orphan canonical entries ({sample}{suffix}). Reason='{reason}'.",
302
+ "doctor.check.filesystem_edit_fallback.remediation.synthesized": "These entries were moved into .fabric/knowledge/<type>/ outside fab_review.approve. The synthesized events restore audit-trail completeness.",
303
+ "doctor.check.orphan_demote.name": "Knowledge orphan demote",
304
+ "doctor.check.orphan_demote.ok": "No canonical knowledge entries exceed their maturity-keyed inactivity threshold.",
305
+ "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}.",
306
+ "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}.",
307
+ "doctor.check.orphan_demote.remediation": "Run `fab doctor --apply-lint` (rc.4 TASK-003) to demote orphan entries one maturity tier.",
308
+ "doctor.check.stale_archive.name": "Knowledge stale archive",
309
+ "doctor.check.stale_archive.ok": "No draft knowledge entries exceed the additional stale-archive quiet window.",
310
+ "doctor.check.stale_archive.message.singular": "{count} draft knowledge entry is stale beyond the demote+{additionalDays}d additional quiet window. First: {detail}.",
311
+ "doctor.check.stale_archive.message.plural": "{count} draft knowledge entries are stale beyond the demote+{additionalDays}d additional quiet window. First: {detail}.",
312
+ "doctor.check.stale_archive.remediation": "Run `fab doctor --apply-lint` (rc.4 TASK-003) to move stale entries into `.fabric/.archive/<type>/`.",
313
+ "doctor.check.pending_overdue.name": "Knowledge pending overdue",
314
+ "doctor.check.pending_overdue.ok": "No pending knowledge entries exceed the 14-day review threshold.",
315
+ "doctor.check.pending_overdue.message.singular": "{count} pending knowledge entry has been awaiting review for more than {thresholdDays} days. First: {detail}.",
316
+ "doctor.check.pending_overdue.message.plural": "{count} pending knowledge entries have been awaiting review for more than {thresholdDays} days. First: {detail}.",
317
+ "doctor.check.pending_overdue.remediation": "Review pending entries via the fabric-review Skill (`/fabric-review`) and approve, reject, defer, or modify.",
318
+ "doctor.check.stable_id_duplicate.name": "Knowledge stable_id duplicate",
319
+ "doctor.check.stable_id_duplicate.ok": "No canonical knowledge files share a stable_id across team / personal trees.",
320
+ "doctor.check.stable_id_duplicate.message.singular": "{count} stable_id duplicated across canonical knowledge files (path-decoupled identity invariant). First: {detail}.",
321
+ "doctor.check.stable_id_duplicate.message.plural": "{count} stable_ids duplicated across canonical knowledge files (path-decoupled identity invariant). First: {detail}.",
322
+ "doctor.check.stable_id_duplicate.remediation": "Manually rename one of the colliding files to a fresh `<prefix>-<type>-<counter>--<slug>.md` allocated via the canonical id allocator; do not edit by hand.",
323
+ "doctor.check.layer_mismatch.name": "Knowledge layer mismatch",
324
+ "doctor.check.layer_mismatch.ok": "All canonical knowledge files are physically located under the layer their stable_id prefix declares.",
325
+ "doctor.check.layer_mismatch.message.singular": "{count} canonical knowledge file are physically misaligned with their stable_id layer prefix (KT-* must live under team/, KP-* under personal/). First: {detail}.",
326
+ "doctor.check.layer_mismatch.message.plural": "{count} canonical knowledge files are physically misaligned with their stable_id layer prefix (KT-* must live under team/, KP-* under personal/). First: {detail}.",
327
+ "doctor.check.layer_mismatch.remediation": "Move the file to the correct layer root, or use the fabric-review modify flow to flip its layer (which renames the stable_id prefix accordingly).",
328
+ "doctor.check.index_drift.name": "Knowledge index drift",
329
+ "doctor.check.index_drift.ok": "agents.meta.json counters envelope is at or above the highest existing canonical counter for every (layer, type) pair.",
330
+ "doctor.check.index_drift.message.singular": "{count} (layer, type) counter slot have drifted below the observed canonical maximum (next allocate would collide). First: {detail}.",
331
+ "doctor.check.index_drift.message.plural": "{count} (layer, type) counter slots have drifted below the observed canonical maximum (next allocate would collide). First: {detail}.",
332
+ "doctor.check.index_drift.remediation": "Run `fab doctor --apply-lint` (rc.4 TASK-003) to bump agents.meta.json counters to max_observed + 1.",
333
+ "doctor.check.underseeded.name": "Knowledge underseeded",
334
+ "doctor.check.underseeded.ok": "Knowledge corpus has {count} canonical entries (>= {threshold}).",
335
+ "doctor.check.underseeded.message.singular": "Knowledge corpus has only {count} canonical entry (< {threshold} threshold). The plan_context retrieval surface is below its useful floor.",
336
+ "doctor.check.underseeded.message.plural": "Knowledge corpus has only {count} canonical entries (< {threshold} threshold). The plan_context retrieval surface is below its useful floor.",
337
+ "doctor.check.underseeded.remediation": "Run the fabric-import Skill (`/fabric-import`) to backfill knowledge from git history and existing docs.",
338
+ "doctor.check.narrow_no_paths.name": "Knowledge narrow without paths",
339
+ "doctor.check.narrow_no_paths.ok": "No narrow-scope canonical entries have an empty relevance_paths array.",
340
+ "doctor.check.narrow_no_paths.message.singular": "{count} narrow-scope canonical entry has an empty relevance_paths array (silent recall risk \u2014 narrow without anchors can never match a target path). First: {detail}.",
341
+ "doctor.check.narrow_no_paths.message.plural": "{count} narrow-scope canonical entries have an empty relevance_paths array (silent recall risk \u2014 narrow without anchors can never match a target path). First: {detail}.",
342
+ "doctor.check.narrow_no_paths.remediation": "Either add path anchors to relevance_paths or widen the entry's relevance_scope to broad.",
343
+ "doctor.check.relevance_paths_dangling.name": "Knowledge relevance_paths dangling",
344
+ "doctor.check.relevance_paths_dangling.ok": "All relevance_paths globs resolve to at least one file under the workspace root.",
345
+ "doctor.check.relevance_paths_dangling.message.singular": "{count} relevance_paths glob resolves to zero files in the current workspace. First: {detail}.",
346
+ "doctor.check.relevance_paths_dangling.message.plural": "{count} relevance_paths globs resolve to zero files in the current workspace. First: {detail}.",
347
+ "doctor.check.relevance_paths_dangling.remediation": "Update the entry's relevance_paths to remove globs that no longer match any files, or use `fab_review.modify` to rewrite the anchor set.",
348
+ "doctor.check.relevance_paths_drift.name": "Knowledge relevance_paths drift",
349
+ "doctor.check.relevance_paths_drift.ok.skipped": "Skipped (git history unavailable; cannot evaluate {windowDays}d drift window).",
350
+ "doctor.check.relevance_paths_drift.ok.fresh": "All narrow-scope canonical entries have at least one relevance_path touched in the last {windowDays}d.",
351
+ "doctor.check.relevance_paths_drift.message.singular": "{count} narrow-scope canonical entry has relevance_paths whose globs match no file touched in the last {windowDays}d of git history. First: {detail}.",
352
+ "doctor.check.relevance_paths_drift.message.plural": "{count} narrow-scope canonical entries have relevance_paths whose globs match no file touched in the last {windowDays}d of git history. First: {detail}.",
353
+ "doctor.check.relevance_paths_drift.remediation": "Review whether the entry is still relevant \u2014 use `fab_review.modify` to refresh the anchors or `fab_review.reject` to archive.",
354
+ "doctor.check.narrow_too_few.name": "Knowledge narrow too few",
355
+ "doctor.check.narrow_too_few.ok": "Narrow-with-paths ratio {ratioPct}% ({narrowCount}/{totalCount}); {teleNote}.",
356
+ "doctor.check.narrow_too_few.message.telemetry_skipped": "telemetry skipped (no edit-counter fires in window)",
357
+ "doctor.check.narrow_too_few.message.telemetry_window": "silence rate {silencePct}% over {windowDays}d",
358
+ "doctor.check.narrow_too_few.message.structural": "narrow-with-paths share {ratioPct}% ({narrowCount}/{totalCount}) below {thresholdPct}% threshold",
359
+ "doctor.check.narrow_too_few.message.telemetry": "narrow-hook silence rate {silencePct}% ({silenceFires}/{totalFires}) over {windowDays}d above {thresholdPct}% threshold",
360
+ "doctor.check.narrow_too_few.message.summary": "Narrow-scope KB coverage is below the useful floor: {parts}.",
361
+ "doctor.check.narrow_too_few.remediation": "Run the fabric-import Skill (`/fabric-import`) to re-seed narrow anchors against the current codebase.",
362
+ "doctor.check.session_hints_stale.name": "Knowledge session-hints stale",
363
+ "doctor.check.session_hints_stale.ok": "No session-hints cache files older than {days} days under .fabric/.cache/.",
364
+ "doctor.check.session_hints_stale.message.singular": "{count} session-hints cache file under .fabric/.cache/ is older than {days} days. First: {detail}.",
365
+ "doctor.check.session_hints_stale.message.plural": "{count} session-hints cache files under .fabric/.cache/ are older than {days} days. First: {detail}.",
366
+ "doctor.check.session_hints_stale.remediation": "Run `fab doctor --apply-lint` to delete stale session-hints cache files.",
367
+ "doctor.check.stale_serve_lock.name": "Serve lock",
368
+ "doctor.check.stale_serve_lock.ok.no_lock": "No .fabric/.serve.lock present.",
369
+ "doctor.check.stale_serve_lock.ok.live_pid": ".fabric/.serve.lock held by live PID {pid}.",
370
+ "doctor.check.stale_serve_lock.age.day.singular": "{count} day ago",
371
+ "doctor.check.stale_serve_lock.age.day.plural": "{count} days ago",
372
+ "doctor.check.stale_serve_lock.age.hour.singular": "{count} hour ago",
373
+ "doctor.check.stale_serve_lock.age.hour.plural": "{count} hours ago",
374
+ "doctor.check.stale_serve_lock.message.dead_pid": "[advisory] .fabric/.serve.lock holds dead PID {pid} (acquired {acquiredAgo}). Run `fab doctor --fix` to remove.",
375
+ "doctor.check.stale_serve_lock.remediation.dead_pid": "Run `fab doctor --fix` to remove the stale .fabric/.serve.lock.",
376
+ "doctor.check.relevance_fields_missing.name": "Knowledge relevance fields missing",
377
+ "doctor.check.relevance_fields_missing.ok": "All pending entries declare both relevance_scope and relevance_paths.",
378
+ "doctor.check.relevance_fields_missing.message.singular": "{count} pending entry is missing relevance_scope and/or relevance_paths in frontmatter. First: {detail}.",
379
+ "doctor.check.relevance_fields_missing.message.plural": "{count} pending entries are missing relevance_scope and/or relevance_paths in frontmatter. First: {detail}.",
380
+ "doctor.check.relevance_fields_missing.remediation": "Run `fab doctor --apply-lint` to back-fill the schema defaults (relevance_scope: broad, relevance_paths: []).",
381
+ "doctor.check.skill_md_yaml_invalid.name": "Skill markdown YAML",
382
+ "doctor.check.skill_md_yaml_invalid.ok": "All .claude/.codex SKILL.md frontmatter values parse as strict YAML.",
383
+ "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}.",
384
+ "doctor.check.skill_md_yaml_invalid.message.plural": "{count} SKILL.md frontmatter values contain an unquoted ': ' that strict YAML parsers reject (Claude Code tolerates it; Codex CLI drops the skill at load). First: {detail}.",
385
+ "doctor.check.skill_md_yaml_invalid.remediation": 'Quote the value with double quotes (`description: "\u2026"`) or rewrite the inner `key: value` token to `key=value`.',
386
+ "doctor.check.onboard_coverage.name": "Onboard coverage",
387
+ "doctor.check.onboard_coverage.ok.complete": "Onboard coverage: {filledCount}/{total} \u2713 (opted-out: {optedOutCount}).",
388
+ "doctor.check.onboard_coverage.message.incomplete": "Onboard slots not yet covered: [{missingSlots}]. {filledCount}/{total} filled; {optedOutCount} opted-out.",
389
+ "doctor.check.onboard_coverage.remediation.incomplete": "Run /fabric-archive to onboard \u2014 the Skill's first-run phase will tour the project and propose pending entries for each unclaimed slot.",
181
390
  // v2.0.0-rc.25 TASK-10: --archive-history flag set. Read-only audit of
182
391
  // session_archive_attempted events; mutually exclusive with the other
183
392
  // mutation/report surfaces.
@@ -775,6 +984,215 @@ var zhCNMessages = {
775
984
  "cli.doctor.args.dry-run.description": "\u4E0E --enrich-descriptions --auto \u642D\u914D\uFF1A\u4EC5\u9884\u89C8\u6539\u52A8\u8BA1\u5212,\u4E0D\u5199\u5165\u78C1\u76D8\u3002",
776
985
  "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",
777
986
  "doctor.enrich.allComplete": "\u6240\u6709\u6B63\u5F0F\u77E5\u8BC6\u6761\u76EE\u5747\u5DF2\u5305\u542B intent_clues / tech_stack / impact / must_read_if\u3002",
987
+ // rc.26 TASK-02a: doctor foundation-batch check messages.
988
+ "doctor.check.bootstrap_marker_migration.name": "Bootstrap marker \u8FC1\u79FB",
989
+ "doctor.check.bootstrap_marker_migration.ok": "bootstrap \u76EE\u6807\u6587\u4EF6\u4E2D\u672A\u68C0\u6D4B\u5230\u65E7 fabric:knowledge-base marker\u3002",
990
+ "doctor.check.bootstrap_marker_migration.message.singular": "{count} \u4E2A\u6587\u4EF6\u4ECD\u5E26\u6709\u65E7 fabric:knowledge-base bootstrap marker\uFF1A{list}\u3002",
991
+ "doctor.check.bootstrap_marker_migration.message.plural": "{count} \u4E2A\u6587\u4EF6\u4ECD\u5E26\u6709\u65E7 fabric:knowledge-base bootstrap marker\uFF1A{list}\u3002",
992
+ "doctor.check.bootstrap_marker_migration.remediation": "\u8FD0\u884C `fab doctor --fix` \u8FC1\u79FB\u5230 fabric:bootstrap marker",
993
+ "doctor.check.bootstrap_snapshot_drift.name": "Bootstrap snapshot drift",
994
+ "doctor.check.bootstrap_snapshot_drift.message.drift": ".fabric/AGENTS.md \u5185\u5BB9\u4E0E BOOTSTRAP_CANONICAL \u9010\u5B57\u8282\u4E0D\u4E00\u81F4\u3002",
995
+ "doctor.check.bootstrap_snapshot_drift.remediation.drift": "\u8FD0\u884C `fab doctor --fix` \u6062\u590D canonical bootstrap snapshot",
996
+ "doctor.check.bootstrap_snapshot_drift.ok.ok": ".fabric/AGENTS.md \u4E0E BOOTSTRAP_CANONICAL \u9010\u5B57\u8282\u4E00\u81F4\u3002",
997
+ "doctor.check.bootstrap_snapshot_drift.ok.missing_delegated": ".fabric/AGENTS.md \u4E0D\u5B58\u5728\uFF0C\u5DF2\u4EA4\u7531 bootstrap_anchor_missing \u62A5\u544A\u3002",
998
+ "doctor.check.managed_block_drift.name": "Managed block drift",
999
+ "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",
1000
+ "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",
1001
+ "doctor.check.managed_block_drift.remediation": "\u8FD0\u884C `fab doctor --fix` \u4ECE canonical \u6062\u590D three-end managed blocks",
1002
+ "doctor.check.managed_block_drift.ok.ok": "Three-end managed blocks \u4E0E expectedBody \u9010\u5B57\u8282\u4E00\u81F4\u3002",
1003
+ "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",
1004
+ "doctor.check.bootstrap_anchor.name": "Bootstrap anchor",
1005
+ "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",
1006
+ "doctor.check.bootstrap_anchor.remediation.missing": "\u8FD0\u884C `fabric install` \u5728 repo root \u751F\u6210 AGENTS.md / CLAUDE.md bootstrap anchor\u3002",
1007
+ "doctor.check.bootstrap_anchor.ok": "repo root \u4E0B\u5DF2\u5B58\u5728 Bootstrap anchor\uFF1A{present}\u3002",
1008
+ "doctor.check.baseline_filename_format.name": "Baseline \u6587\u4EF6\u540D\u683C\u5F0F",
1009
+ "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",
1010
+ "doctor.check.baseline_filename_format.message.singular": "{count} \u4E2A baseline knowledge \u6587\u4EF6\u4ECD\u4F7F\u7528\u5DF2\u5E9F\u5F03\u7684 bare-slug \u6587\u4EF6\u540D\u683C\u5F0F\uFF0C\u5FC5\u987B\u8FC1\u79FB\u4E3A `${id}--${slug}.md`\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1011
+ "doctor.check.baseline_filename_format.message.plural": "{count} \u4E2A baseline knowledge \u6587\u4EF6\u4ECD\u4F7F\u7528\u5DF2\u5E9F\u5F03\u7684 bare-slug \u6587\u4EF6\u540D\u683C\u5F0F\uFF0C\u5FC5\u987B\u8FC1\u79FB\u4E3A `${id}--${slug}.md`\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1012
+ "doctor.check.baseline_filename_format.remediation": "\u624B\u52A8\u5220\u9664\u65E7 bare-slug baseline file(s)\uFF1Bbaseline pipeline \u5DF2\u5728 rc.23 \u79FB\u9664\uFF0C\u4E0D\u518D\u63D0\u4F9B auto-fix \u8DEF\u5F84\u3002",
1013
+ "doctor.check.knowledge_dir_missing.name": "Knowledge layout",
1014
+ "doctor.check.knowledge_dir_missing.message.singular": "{count} \u4E2A\u5FC5\u9700 knowledge subdir \u7F3A\u5931\uFF1A{list}\u3002",
1015
+ "doctor.check.knowledge_dir_missing.message.plural": "{count} \u4E2A\u5FC5\u9700 knowledge subdir \u7F3A\u5931\uFF1A{list}\u3002",
1016
+ "doctor.check.knowledge_dir_missing.remediation": "\u8FD0\u884C `fab doctor --fix` \u521B\u5EFA\u7F3A\u5931\u7684 .fabric/knowledge/* subdirectories\u3002",
1017
+ "doctor.check.knowledge_dir_missing.ok": "\u5168\u90E8 {count} \u4E2A\u5FC5\u9700 .fabric/knowledge/* subdirectories \u5747\u5DF2\u5B58\u5728\u3002",
1018
+ "doctor.check.forensic.name": "Scan evidence",
1019
+ "doctor.check.forensic.message.missing.singular": "{error} \u5B9E\u65F6\u626B\u63CF\u68C0\u6D4B\u5230 {frameworkKind}\uFF0C\u5171\u6709 {count} \u4E2A\u5165\u53E3\u70B9\u3002",
1020
+ "doctor.check.forensic.message.missing.plural": "{error} \u5B9E\u65F6\u626B\u63CF\u68C0\u6D4B\u5230 {frameworkKind}\uFF0C\u5171\u6709 {count} \u4E2A\u5165\u53E3\u70B9\u3002",
1021
+ "doctor.check.forensic.message.missing-default": ".fabric/forensic.json \u7F3A\u5931\u3002",
1022
+ "doctor.check.forensic.message.invalid-default": ".fabric/forensic.json \u65E0\u6548\u3002",
1023
+ "doctor.check.forensic.remediation": "\u8FD0\u884C `fab install` \u91CD\u65B0\u751F\u6210 .fabric/forensic.json\u3002",
1024
+ "doctor.check.forensic.ok": ".fabric/forensic.json \u5BF9 {frameworkKind} \u6709\u6548\u3002",
1025
+ "doctor.check.agents_meta.name": "Agents metadata",
1026
+ "doctor.check.agents_meta.message.missing": ".fabric/agents.meta.json \u7F3A\u5931\u3002",
1027
+ "doctor.check.agents_meta.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u4ECE .fabric/knowledge/ \u91CD\u5EFA agents.meta.json\u3002",
1028
+ "doctor.check.agents_meta.message.invalid-default": ".fabric/agents.meta.json \u65E0\u6548\u3002",
1029
+ "doctor.check.agents_meta.remediation.invalid": "\u5220\u9664 .fabric/agents.meta.json \u5E76\u8FD0\u884C `fab doctor --fix` \u91CD\u65B0\u751F\u6210\u3002",
1030
+ "doctor.check.agents_meta.message.stale": ".fabric/agents.meta.json revision {revision} \u4E0E .fabric/knowledge \u6D3E\u751F revision {computedRevision} \u4E0D\u4E00\u81F4\u3002",
1031
+ "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",
1032
+ "doctor.check.agents_meta.ok": ".fabric/agents.meta.json revision {revision} \u5DF2\u4E0E .fabric/knowledge \u5BF9\u9F50\u3002",
1033
+ "doctor.check.rule_content_refs.name": "Rule content refs",
1034
+ "doctor.check.rule_content_refs.message.unavailable": "agents.meta.json \u6709\u6548\u524D\uFF0C\u65E0\u6CD5\u68C0\u67E5 content_ref entries\u3002",
1035
+ "doctor.check.rule_content_refs.remediation.unavailable": "\u5148\u4FEE\u590D agents.meta.json\uFF1A\u8FD0\u884C `fab doctor --fix`\u3002",
1036
+ "doctor.check.rule_content_refs.message.outside.singular": "{count} \u4E2A content_ref entry \u4F4D\u4E8E .fabric/knowledge \u5916\u90E8\u3002",
1037
+ "doctor.check.rule_content_refs.message.outside.plural": "{count} \u4E2A content_ref entries \u4F4D\u4E8E .fabric/knowledge \u5916\u90E8\u3002",
1038
+ "doctor.check.rule_content_refs.remediation.outside": "\u7F16\u8F91 agents.meta.json\uFF0C\u786E\u4FDD\u6240\u6709 content_ref \u503C\u90FD\u6307\u5411 .fabric/knowledge/{type}/\uFF08team\uFF09\u6216 ~/.fabric/knowledge/{type}/\uFF08personal\uFF09\u5185\u90E8\u3002",
1039
+ "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",
1040
+ "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",
1041
+ "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",
1042
+ "doctor.check.rule_content_refs.ok": "\u6240\u6709 content_ref entries \u90FD\u80FD\u89E3\u6790\u5230 .fabric/knowledge files\u3002",
1043
+ "doctor.check.knowledge_test_index.name": "Knowledge-test index",
1044
+ "doctor.check.knowledge_test_index.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u91CD\u5EFA .fabric/.cache/knowledge-test.index.json\u3002",
1045
+ "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",
1046
+ "doctor.check.knowledge_test_index.message.stale": ".fabric/.cache/knowledge-test.index.json \u5DF2\u8FC7\u671F\u3002",
1047
+ "doctor.check.knowledge_test_index.remediation.stale": "\u8FD0\u884C `fab doctor --fix` \u91CD\u5EFA knowledge-test index\u3002",
1048
+ "doctor.check.knowledge_test_index.ok.link_singular.orphan_singular": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1049
+ "doctor.check.knowledge_test_index.ok.link_singular.orphan_plural": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1050
+ "doctor.check.knowledge_test_index.ok.link_plural.orphan_singular": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1051
+ "doctor.check.knowledge_test_index.ok.link_plural.orphan_plural": "\u5DF2\u7D22\u5F15 {linkCount} \u4E2A link \u548C {orphanCount} \u4E2A orphan annotation\u3002",
1052
+ "doctor.check.event_ledger.name": "Event ledger",
1053
+ "doctor.check.event_ledger.message.missing": ".fabric/events.jsonl \u7F3A\u5931\u3002",
1054
+ "doctor.check.event_ledger.remediation.missing": "\u8FD0\u884C `fab doctor --fix` \u521B\u5EFA .fabric/events.jsonl\u3002",
1055
+ "doctor.check.event_ledger.message.not_writable-default": ".fabric/events.jsonl \u4E0D\u53EF\u5199\u3002",
1056
+ "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",
1057
+ "doctor.check.event_ledger.message.invalid-default": ".fabric/events.jsonl \u65E0\u6548\u3002",
1058
+ "doctor.check.event_ledger.remediation.invalid": "\u5220\u9664 .fabric/events.jsonl \u5E76\u8FD0\u884C `fab doctor --fix` \u91CD\u65B0\u521B\u5EFA\u3002",
1059
+ "doctor.check.event_ledger.ok": ".fabric/events.jsonl \u5DF2\u5B58\u5728\uFF0C\u53EF\u5199\uFF0C\u4E14\u53EF\u89E3\u6790\u3002",
1060
+ "doctor.check.mcp_config_in_wrong_file.name": "Claude MCP config \u4F4D\u7F6E",
1061
+ "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",
1062
+ "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",
1063
+ "doctor.check.mcp_config_in_wrong_file.ok": "mcpServers.fabric \u4E0D\u5728 .claude/settings.json \u4E2D\u3002",
1064
+ "doctor.check.event_ledger_partial_write.name": "Event ledger partial write",
1065
+ "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",
1066
+ "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",
1067
+ "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",
1068
+ "doctor.check.event_ledger_partial_write.ok.clean": "events.jsonl \u6CA1\u6709 partial trailing write\u3002",
1069
+ // v2.0.0-rc.27 TASK-010 (audit §2.24): schema-compat 向前兼容警告类别。
1070
+ "doctor.check.event_ledger_schema_compat.name": "Event ledger schema \u517C\u5BB9\u6027",
1071
+ "doctor.check.event_ledger_schema_compat.ok.skipped": "\u65E0\u9700\u505A schema \u517C\u5BB9\u6027\u68C0\u67E5\uFF08events.jsonl \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u5199\uFF09\u3002",
1072
+ "doctor.check.event_ledger_schema_compat.ok.clean": "events.jsonl \u6240\u6709\u884C\u90FD\u80FD\u89E3\u6790\u4E3A\u5F53\u524D schema\u3002",
1073
+ "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",
1074
+ "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",
1075
+ "doctor.check.event_ledger_schema_compat.remediation": "\u5347\u7EA7 fab CLI \u5230\u4E0E server \u517C\u5BB9\u7684\u7248\u672C\uFF0C\u6216\u5907\u4EFD `.fabric/events.jsonl` \u540E\u8DD1 `fab doctor --fix` \u91CD\u5EFA\u7A7A ledger\u3002",
1076
+ "doctor.check.meta_manually_diverged.name": "Meta manual divergence",
1077
+ "doctor.check.meta_manually_diverged.ok.unreadable": "agents.meta.json \u4E0D\u53EF\u8BFB\uFF0C\u8DF3\u8FC7 divergence \u68C0\u67E5\u3002",
1078
+ "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",
1079
+ "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",
1080
+ "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",
1081
+ "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",
1082
+ "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",
1083
+ "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",
1084
+ "doctor.check.meta_manually_diverged.ok.consistent": "agents.meta.json \u4E0E\u78C1\u76D8\u4E0A\u7684 rule files \u4E00\u81F4\u3002",
1085
+ "doctor.check.knowledge_dir_unindexed.name": "Knowledge dir unindexed",
1086
+ "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",
1087
+ "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",
1088
+ "doctor.check.knowledge_dir_unindexed.remediation": "\u8FD0\u884C `fab doctor --fix` \u7D22\u5F15\u7F3A\u5931\u7684 knowledge files\u3002",
1089
+ "doctor.check.knowledge_dir_unindexed.ok": "\u6240\u6709 .fabric/knowledge/ .md files \u90FD\u5DF2\u7D22\u5F15\u5230 agents.meta.json\u3002",
1090
+ "doctor.check.stable_id_collision.name": "Stable ID collision",
1091
+ "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',
1092
+ "doctor.check.stable_id_collision.message.plural": '\u68C0\u6D4B\u5230 {count} \u4E2A stable_id collisions\u3002\u9996\u4E2A\uFF1A"{stableId}" \u4F4D\u4E8E {files}\u3002\u8BF7\u7F16\u8F91\u5176\u4E2D\u4E00\u4E2A knowledge file\uFF0C\u6539\u7528\u552F\u4E00 stable_id\u3002',
1093
+ "doctor.check.stable_id_collision.remediation": "\u7F16\u8F91\u5176\u4E2D\u4E00\u4E2A colliding knowledge file\uFF0C\u6539\u7528\u4E0D\u540C\u7684 `id: K[PT]-XXX-NNNN` frontmatter \u503C\u3002",
1094
+ "doctor.check.stable_id_collision.ok": ".fabric/knowledge/ \u4E2D\u672A\u53D1\u73B0\u5DF2\u58F0\u660E\u7684 stable_id collisions\u3002",
1095
+ "doctor.check.counter_desync.name": "Knowledge counter desync",
1096
+ "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",
1097
+ "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",
1098
+ "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",
1099
+ "doctor.check.counter_desync.ok": "agents.meta.json counters envelope \u4E0E\u89C2\u6D4B\u5230\u7684 stable_ids \u4E00\u81F4\u3002",
1100
+ "doctor.check.preexisting_root_files.name": "Preexisting root markdown",
1101
+ "doctor.check.preexisting_root_files.ok": "project root \u672A\u68C0\u6D4B\u5230 CLAUDE.md \u6216 AGENTS.md\u3002",
1102
+ "doctor.check.preexisting_root_files.message": "project root \u68C0\u6D4B\u5230 {files}\u3002\u8FD9\u4E9B root files \u4E0D\u4F1A\u88AB Fabric MCP \u81EA\u52A8\u52A0\u8F7D\u3002",
1103
+ "doctor.check.preexisting_root_files.remediation": "\u5982\u679C\u5E0C\u671B\u8FD9\u4E9B knowledge \u5185\u5BB9\u5728 MCP \u54CD\u5E94\u4E2D\u53EF\u7528\uFF0C\u8BF7\u5C06\u5176\u79FB\u52A8\u5230 `.fabric/knowledge/{type}/`\u3002",
1104
+ "doctor.check.filesystem_edit_fallback.name": "Filesystem-edit fallback",
1105
+ "doctor.check.filesystem_edit_fallback.ok": "No orphan canonical knowledge entries detected\uFF1Bevents.jsonl promotion trail \u5B8C\u6574\u3002",
1106
+ "doctor.check.filesystem_edit_fallback.message.synthesized.singular": "\u5DF2\u4E3A\u5B64\u7ACB canonical entries \u5408\u6210 {count} \u4E2A knowledge_promoted event\uFF08{sample}{suffix}\uFF09\u3002Reason='{reason}'\u3002",
1107
+ "doctor.check.filesystem_edit_fallback.message.synthesized.plural": "\u5DF2\u4E3A\u5B64\u7ACB canonical entries \u5408\u6210 {count} \u4E2A knowledge_promoted events\uFF08{sample}{suffix}\uFF09\u3002Reason='{reason}'\u3002",
1108
+ "doctor.check.filesystem_edit_fallback.remediation.synthesized": "\u8FD9\u4E9B entries \u662F\u5728 fab_review.approve \u4E4B\u5916\u88AB\u79FB\u52A8\u5230 .fabric/knowledge/<type>/ \u7684\u3002\u5408\u6210 events \u4F1A\u6062\u590D audit-trail \u5B8C\u6574\u6027\u3002",
1109
+ "doctor.check.orphan_demote.name": "Knowledge orphan demote",
1110
+ "doctor.check.orphan_demote.ok": "\u6CA1\u6709 canonical knowledge entries \u8D85\u8FC7\u6309 maturity \u8BBE\u5B9A\u7684 inactivity threshold\u3002",
1111
+ "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",
1112
+ "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",
1113
+ "doctor.check.orphan_demote.remediation": "\u8FD0\u884C `fab doctor --apply-lint`\uFF08rc.4 TASK-003\uFF09\u5C06 orphan entries \u964D\u7EA7\u4E00\u4E2A maturity tier\u3002",
1114
+ "doctor.check.stale_archive.name": "Knowledge stale archive",
1115
+ "doctor.check.stale_archive.ok": "\u6CA1\u6709 draft knowledge entries \u8D85\u8FC7\u989D\u5916\u7684 stale-archive quiet window\u3002",
1116
+ "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",
1117
+ "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",
1118
+ "doctor.check.stale_archive.remediation": "\u8FD0\u884C `fab doctor --apply-lint`\uFF08rc.4 TASK-003\uFF09\u5C06 stale entries \u79FB\u52A8\u5230 `.fabric/.archive/<type>/`\u3002",
1119
+ "doctor.check.pending_overdue.name": "Knowledge pending overdue",
1120
+ "doctor.check.pending_overdue.ok": "\u6CA1\u6709 pending knowledge entries \u8D85\u8FC7 14-day review threshold\u3002",
1121
+ "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",
1122
+ "doctor.check.pending_overdue.message.plural": "{count} \u4E2A pending knowledge entries \u5DF2\u7B49\u5F85 review \u8D85\u8FC7 {thresholdDays} \u5929\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1123
+ "doctor.check.pending_overdue.remediation": "\u901A\u8FC7 fabric-review Skill\uFF08`/fabric-review`\uFF09\u5BA1\u9605 pending entries\uFF0C\u5E76\u6267\u884C approve / reject / defer / modify\u3002",
1124
+ "doctor.check.stable_id_duplicate.name": "Knowledge stable_id duplicate",
1125
+ "doctor.check.stable_id_duplicate.ok": "team / personal trees \u4E2D\u6CA1\u6709 canonical knowledge files \u5171\u4EAB stable_id\u3002",
1126
+ "doctor.check.stable_id_duplicate.message.singular": "{count} \u4E2A stable_id \u5728 canonical knowledge files \u4E2D\u91CD\u590D\uFF08path-decoupled identity invariant\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1127
+ "doctor.check.stable_id_duplicate.message.plural": "{count} \u4E2A stable_ids \u5728 canonical knowledge files \u4E2D\u91CD\u590D\uFF08path-decoupled identity invariant\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1128
+ "doctor.check.stable_id_duplicate.remediation": "\u624B\u52A8\u5C06\u5176\u4E2D\u4E00\u4E2A colliding file \u91CD\u547D\u540D\u4E3A\u901A\u8FC7 canonical id allocator \u5206\u914D\u7684\u65B0 `<prefix>-<type>-<counter>--<slug>.md`\uFF1B\u4E0D\u8981\u624B\u5DE5\u7F16\u8F91\u3002",
1129
+ "doctor.check.layer_mismatch.name": "Knowledge layer mismatch",
1130
+ "doctor.check.layer_mismatch.ok": "\u6240\u6709 canonical knowledge files \u90FD\u4F4D\u4E8E stable_id prefix \u58F0\u660E\u7684 layer \u4E0B\u3002",
1131
+ "doctor.check.layer_mismatch.message.singular": "{count} \u4E2A canonical knowledge file \u4E0E\u5176 stable_id layer prefix \u7684\u7269\u7406\u4F4D\u7F6E\u4E0D\u4E00\u81F4\uFF08KT-* must live under team/, KP-* under personal/\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1132
+ "doctor.check.layer_mismatch.message.plural": "{count} \u4E2A canonical knowledge files \u4E0E\u5176 stable_id layer prefix \u7684\u7269\u7406\u4F4D\u7F6E\u4E0D\u4E00\u81F4\uFF08KT-* must live under team/, KP-* under personal/\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1133
+ "doctor.check.layer_mismatch.remediation": "\u5C06\u6587\u4EF6\u79FB\u52A8\u5230\u6B63\u786E\u7684 layer root\uFF0C\u6216\u901A\u8FC7 fabric-review modify \u6D41\u7A0B\u5207\u6362\u5176 layer\uFF08\u4F1A\u76F8\u5E94\u91CD\u547D\u540D stable_id prefix\uFF09\u3002",
1134
+ "doctor.check.index_drift.name": "Knowledge index drift",
1135
+ "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",
1136
+ "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",
1137
+ "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",
1138
+ "doctor.check.index_drift.remediation": "\u8FD0\u884C `fab doctor --apply-lint`\uFF08rc.4 TASK-003\uFF09\u5C06 agents.meta.json counters \u63D0\u5347\u5230 max_observed + 1\u3002",
1139
+ "doctor.check.underseeded.name": "Knowledge underseeded",
1140
+ "doctor.check.underseeded.ok": "\u77E5\u8BC6\u5E93\u5DF2\u6709 {count} \u4E2A canonical entries\uFF08>= {threshold}\uFF09\u3002",
1141
+ "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",
1142
+ "doctor.check.underseeded.message.plural": "\u77E5\u8BC6\u5E93\u4EC5\u6709 {count} \u4E2A canonical entries\uFF08< {threshold} threshold\uFF09\u3002plan_context \u68C0\u7D22\u9762\u4F4E\u4E8E\u53EF\u7528\u4E0B\u9650\u3002",
1143
+ "doctor.check.underseeded.remediation": "\u8FD0\u884C fabric-import Skill\uFF08`/fabric-import`\uFF09\u4ECE git history \u4E0E\u73B0\u6709\u6587\u6863\u56DE\u586B knowledge\u3002",
1144
+ "doctor.check.narrow_no_paths.name": "Knowledge narrow without paths",
1145
+ "doctor.check.narrow_no_paths.ok": "\u6CA1\u6709 narrow-scope canonical entries \u7684 relevance_paths array \u4E3A\u7A7A\u3002",
1146
+ "doctor.check.narrow_no_paths.message.singular": "{count} \u4E2A narrow-scope canonical entry \u7684 relevance_paths array \u4E3A\u7A7A\uFF08silent recall risk \u2014 narrow without anchors can never match a target path\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1147
+ "doctor.check.narrow_no_paths.message.plural": "{count} \u4E2A narrow-scope canonical entries \u7684 relevance_paths array \u4E3A\u7A7A\uFF08silent recall risk \u2014 narrow without anchors can never match a target path\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1148
+ "doctor.check.narrow_no_paths.remediation": "\u4E3A relevance_paths \u6DFB\u52A0 path anchors\uFF0C\u6216\u5C06 entry \u7684 relevance_scope \u653E\u5BBD\u5230 broad\u3002",
1149
+ "doctor.check.relevance_paths_dangling.name": "Knowledge relevance_paths dangling",
1150
+ "doctor.check.relevance_paths_dangling.ok": "\u6240\u6709 relevance_paths globs \u90FD\u80FD\u5728 workspace root \u4E0B\u89E3\u6790\u5230\u81F3\u5C11 1 \u4E2A\u6587\u4EF6\u3002",
1151
+ "doctor.check.relevance_paths_dangling.message.singular": "{count} \u4E2A relevance_paths glob \u5728\u5F53\u524D workspace \u4E2D\u89E3\u6790\u5230 0 \u4E2A\u6587\u4EF6\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1152
+ "doctor.check.relevance_paths_dangling.message.plural": "{count} \u4E2A relevance_paths globs \u5728\u5F53\u524D workspace \u4E2D\u89E3\u6790\u5230 0 \u4E2A\u6587\u4EF6\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1153
+ "doctor.check.relevance_paths_dangling.remediation": "\u66F4\u65B0 entry \u7684 relevance_paths\uFF0C\u79FB\u9664\u4E0D\u518D\u5339\u914D\u4EFB\u4F55\u6587\u4EF6\u7684 globs\uFF0C\u6216\u4F7F\u7528 `fab_review.modify` \u91CD\u5199 anchor set\u3002",
1154
+ "doctor.check.relevance_paths_drift.name": "Knowledge relevance_paths drift",
1155
+ "doctor.check.relevance_paths_drift.ok.skipped": "\u5DF2\u8DF3\u8FC7\uFF08git history unavailable\uFF1B\u65E0\u6CD5\u8BC4\u4F30 {windowDays}d drift window\uFF09\u3002",
1156
+ "doctor.check.relevance_paths_drift.ok.fresh": "\u6240\u6709 narrow-scope canonical entries \u90FD\u81F3\u5C11\u6709 1 \u4E2A relevance_path \u5728\u6700\u8FD1 {windowDays}d \u5185\u88AB\u89E6\u78B0\u3002",
1157
+ "doctor.check.relevance_paths_drift.message.singular": "{count} \u4E2A narrow-scope canonical entry \u7684 relevance_paths globs \u6CA1\u6709\u5339\u914D\u5230\u6700\u8FD1 {windowDays}d git history \u4E2D\u89E6\u78B0\u8FC7\u7684\u6587\u4EF6\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1158
+ "doctor.check.relevance_paths_drift.message.plural": "{count} \u4E2A narrow-scope canonical entries \u7684 relevance_paths globs \u6CA1\u6709\u5339\u914D\u5230\u6700\u8FD1 {windowDays}d git history \u4E2D\u89E6\u78B0\u8FC7\u7684\u6587\u4EF6\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
1159
+ "doctor.check.relevance_paths_drift.remediation": "\u5BA1\u9605\u8BE5 entry \u662F\u5426\u4ECD\u7136\u76F8\u5173 \u2014 \u4F7F\u7528 `fab_review.modify` \u5237\u65B0 anchors\uFF0C\u6216\u4F7F\u7528 `fab_review.reject` \u5F52\u6863\u3002",
1160
+ "doctor.check.narrow_too_few.name": "Knowledge narrow too few",
1161
+ "doctor.check.narrow_too_few.ok": "Narrow-with-paths ratio {ratioPct}%\uFF08{narrowCount}/{totalCount}\uFF09\uFF1B{teleNote}\u3002",
1162
+ "doctor.check.narrow_too_few.message.telemetry_skipped": "telemetry skipped\uFF08no edit-counter fires in window\uFF09",
1163
+ "doctor.check.narrow_too_few.message.telemetry_window": "silence rate {silencePct}% over {windowDays}d",
1164
+ "doctor.check.narrow_too_few.message.structural": "narrow-with-paths share {ratioPct}%\uFF08{narrowCount}/{totalCount}\uFF09below {thresholdPct}% threshold",
1165
+ "doctor.check.narrow_too_few.message.telemetry": "narrow-hook silence rate {silencePct}%\uFF08{silenceFires}/{totalFires}\uFF09over {windowDays}d above {thresholdPct}% threshold",
1166
+ "doctor.check.narrow_too_few.message.summary": "Narrow-scope KB coverage \u4F4E\u4E8E\u53EF\u7528\u4E0B\u9650\uFF1A{parts}\u3002",
1167
+ "doctor.check.narrow_too_few.remediation": "\u8FD0\u884C fabric-import Skill\uFF08`/fabric-import`\uFF09\u9488\u5BF9\u5F53\u524D codebase \u91CD\u65B0\u64AD\u79CD narrow anchors\u3002",
1168
+ "doctor.check.session_hints_stale.name": "Knowledge session-hints stale",
1169
+ "doctor.check.session_hints_stale.ok": ".fabric/.cache/ \u4E0B\u6CA1\u6709\u8D85\u8FC7 {days} \u5929\u7684 session-hints cache files\u3002",
1170
+ "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",
1171
+ "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",
1172
+ "doctor.check.session_hints_stale.remediation": "\u8FD0\u884C `fab doctor --apply-lint` \u5220\u9664\u8FC7\u671F\u7684 session-hints cache files\u3002",
1173
+ "doctor.check.stale_serve_lock.name": "Serve lock",
1174
+ "doctor.check.stale_serve_lock.ok.no_lock": "\u672A\u53D1\u73B0 .fabric/.serve.lock\u3002",
1175
+ "doctor.check.stale_serve_lock.ok.live_pid": ".fabric/.serve.lock \u7531 live PID {pid} \u6301\u6709\u3002",
1176
+ "doctor.check.stale_serve_lock.age.day.singular": "{count} \u5929\u524D",
1177
+ "doctor.check.stale_serve_lock.age.day.plural": "{count} \u5929\u524D",
1178
+ "doctor.check.stale_serve_lock.age.hour.singular": "{count} \u5C0F\u65F6\u524D",
1179
+ "doctor.check.stale_serve_lock.age.hour.plural": "{count} \u5C0F\u65F6\u524D",
1180
+ "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",
1181
+ "doctor.check.stale_serve_lock.remediation.dead_pid": "\u8FD0\u884C `fab doctor --fix` \u79FB\u9664\u8FC7\u671F\u7684 .fabric/.serve.lock\u3002",
1182
+ "doctor.check.relevance_fields_missing.name": "Knowledge relevance fields missing",
1183
+ "doctor.check.relevance_fields_missing.ok": "\u6240\u6709 pending entries \u90FD\u58F0\u660E\u4E86 relevance_scope \u548C relevance_paths\u3002",
1184
+ "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",
1185
+ "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",
1186
+ "doctor.check.relevance_fields_missing.remediation": "\u8FD0\u884C `fab doctor --apply-lint` \u56DE\u586B schema defaults\uFF08relevance_scope: broad\uFF0Crelevance_paths: []\uFF09\u3002",
1187
+ "doctor.check.skill_md_yaml_invalid.name": "Skill markdown YAML",
1188
+ "doctor.check.skill_md_yaml_invalid.ok": "\u6240\u6709 .claude/.codex SKILL.md frontmatter values \u90FD\u80FD\u6309 strict YAML \u89E3\u6790\u3002",
1189
+ "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",
1190
+ "doctor.check.skill_md_yaml_invalid.message.plural": "{count} \u4E2A SKILL.md frontmatter values \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",
1191
+ "doctor.check.skill_md_yaml_invalid.remediation": '\u4F7F\u7528\u53CC\u5F15\u53F7\u5305\u88F9\u8BE5 value\uFF08`description: "\u2026"`\uFF09\uFF0C\u6216\u5C06\u5185\u90E8\u7684 `key: value` token \u6539\u5199\u4E3A `key=value`\u3002',
1192
+ "doctor.check.onboard_coverage.name": "Onboard coverage",
1193
+ "doctor.check.onboard_coverage.ok.complete": "Onboard coverage\uFF1A{filledCount}/{total} \u2713\uFF08opted-out\uFF1A{optedOutCount}\uFF09\u3002",
1194
+ "doctor.check.onboard_coverage.message.incomplete": "\u5C1A\u672A\u8986\u76D6\u7684 onboard slots\uFF1A[{missingSlots}]\u3002{filledCount}/{total} filled\uFF1B{optedOutCount} opted-out\u3002",
1195
+ "doctor.check.onboard_coverage.remediation.incomplete": "\u8FD0\u884C /fabric-archive \u6267\u884C onboard \u2014 Skill's first-run phase \u4F1A\u904D\u5386\u9879\u76EE\uFF0C\u5E76\u4E3A\u6BCF\u4E2A unclaimed slot \u63D0\u8BAE pending entries\u3002",
778
1196
  // v2.0.0-rc.25 TASK-10: --archive-history 子命令——按 session 维度审计归档尝试记录。
779
1197
  "cli.doctor.args.archive-history.description": "\u6309 session \u7EF4\u5EA6\u6E32\u67D3\u5F52\u6863\u5C1D\u8BD5\u5386\u53F2(\u53EA\u8BFB;\u8BFB\u53D6 session_archive_attempted \u4E8B\u4EF6)\u3002",
780
1198
  "cli.doctor.errors.archive-history-mutex": "--archive-history \u4E0D\u80FD\u4E0E --fix / --fix-knowledge / --cite-coverage / --enrich-descriptions \u540C\u65F6\u4F7F\u7528,\u8BF7\u5206\u522B\u8FD0\u884C\u3002",
@@ -1240,6 +1658,39 @@ function detectNodeLocale() {
1240
1658
  return "en";
1241
1659
  }
1242
1660
 
1661
+ // src/i18n/resolve-fabric-locale.ts
1662
+ import fs from "fs";
1663
+ import path from "path";
1664
+ function resolveFabricLocale(projectRoot) {
1665
+ const configPath = path.join(projectRoot, ".fabric", "fabric-config.json");
1666
+ let raw;
1667
+ try {
1668
+ raw = fs.readFileSync(configPath, "utf8");
1669
+ } catch {
1670
+ return detectNodeLocale();
1671
+ }
1672
+ let parsed;
1673
+ try {
1674
+ parsed = JSON.parse(raw);
1675
+ } catch {
1676
+ return detectNodeLocale();
1677
+ }
1678
+ if (typeof parsed !== "object" || parsed === null) {
1679
+ return detectNodeLocale();
1680
+ }
1681
+ const fabricLanguage = parsed.fabric_language;
1682
+ if (fabricLanguage === "en" || fabricLanguage === "zh-CN") {
1683
+ return fabricLanguage;
1684
+ }
1685
+ if (fabricLanguage === "match-existing" || fabricLanguage === "zh-CN-hybrid") {
1686
+ console.warn(
1687
+ `[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.`
1688
+ );
1689
+ return detectNodeLocale();
1690
+ }
1691
+ return detectNodeLocale();
1692
+ }
1693
+
1243
1694
  // src/i18n/protected-tokens.ts
1244
1695
  var PROTECTED_TOKENS = [
1245
1696
  // v2.0 MCP tool names
@@ -1288,5 +1739,6 @@ export {
1288
1739
  createTranslator,
1289
1740
  normalizeLocale,
1290
1741
  detectNodeLocale,
1742
+ resolveFabricLocale,
1291
1743
  PROTECTED_TOKENS
1292
1744
  };
@@ -10,6 +10,26 @@ declare function createTranslator(locale: Locale, messages?: Record<Locale, Mess
10
10
 
11
11
  declare function detectNodeLocale(): Locale;
12
12
 
13
+ /**
14
+ * Resolve the effective runtime locale for a given project root.
15
+ *
16
+ * Resolution order (rc.26 — closes KT-DEC-9004 runtime gap):
17
+ * 1. Read `<projectRoot>/.fabric/fabric-config.json` and inspect
18
+ * `fabric_language`.
19
+ * 2. If the value is `"en"` or `"zh-CN"` (the two concrete Locale members),
20
+ * return it verbatim — this is the eager-resolved value `fab init` is
21
+ * supposed to write back per KT-DEC-9004.
22
+ * 3. If the value is `"match-existing"` or `"zh-CN-hybrid"` (placeholders
23
+ * that should NEVER survive `fab init` per KT-DEC-9004's invariant),
24
+ * emit a `console.warn` and fall through to `detectNodeLocale()`.
25
+ * 4. If the file is missing, unreadable, malformed JSON, or `fabric_language`
26
+ * is absent / has any other shape, silently fall through to
27
+ * `detectNodeLocale()` (env-driven: `FAB_LANG` → `LANG` → `"en"`).
28
+ *
29
+ * Never throws — all failure paths degrade to `detectNodeLocale()`.
30
+ */
31
+ declare function resolveFabricLocale(projectRoot: string): Locale;
32
+
13
33
  declare function normalizeLocale(raw: string | null | undefined): Locale;
14
34
 
15
35
  declare const PROTECTED_TOKENS: readonly ["fab_plan_context", "fab_get_knowledge_sections", "fab_extract_knowledge", "fab_review", "AGENTS.md", ".fabric/agents/", ".fabric/agents/_cross/", ".fabric/agents.meta.json", ".fabric/human-lock.json", ".fabric/events.jsonl", ".fabric/knowledge/", "knowledge_proposed", "relevance_scope", "relevance_paths", "narrow", "broad", "source_sessions", "proposed_reason", "session_context", "layer", "team", "personal", "pending_path", "knowledge_scope_degraded", "@HUMAN", "MUST", "NEVER"];
@@ -19,4 +39,4 @@ declare const enMessages: Messages;
19
39
 
20
40
  declare const zhCNMessages: Messages;
21
41
 
22
- export { type Locale, type Messages, PROTECTED_TOKENS, type ProtectedToken, type TranslationKey, type Translator, createTranslator, defaultMessages, detectNodeLocale, enMessages, normalizeLocale, zhCNMessages };
42
+ export { type Locale, type Messages, PROTECTED_TOKENS, type ProtectedToken, type TranslationKey, type Translator, createTranslator, defaultMessages, detectNodeLocale, enMessages, normalizeLocale, resolveFabricLocale, zhCNMessages };
@@ -5,8 +5,9 @@ import {
5
5
  detectNodeLocale,
6
6
  enMessages,
7
7
  normalizeLocale,
8
+ resolveFabricLocale,
8
9
  zhCNMessages
9
- } from "../chunk-AFUQKKGR.js";
10
+ } from "../chunk-LXQ77R3D.js";
10
11
  export {
11
12
  PROTECTED_TOKENS,
12
13
  createTranslator,
@@ -14,5 +15,6 @@ export {
14
15
  detectNodeLocale,
15
16
  enMessages,
16
17
  normalizeLocale,
18
+ resolveFabricLocale,
17
19
  zhCNMessages
18
20
  };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AgentsMetaNode, AgentsIdentitySource, AgentsLayer, AgentsTopologyType, HumanLockEntry, AgentsMeta, LedgerEntry } from './types/index.js';
2
2
  export { AgentsActivationTier, AgentsMetaCountersEnvelope, AgentsMetaKnowledgeTypeCounters, AgentsMetaNodeActivation, AiLedgerEntry, AuditMode, ClientPaths, DefaultLayerFilter, FabricConfig, FabricLanguage, HumanLedgerEntry, McpPayloadLimits, RuleDescription, RuleDescriptionIndexItem } from './types/index.js';
3
- export { Locale, Messages, PROTECTED_TOKENS, ProtectedToken, TranslationKey, Translator, createTranslator, defaultMessages, detectNodeLocale, enMessages, normalizeLocale, zhCNMessages } from './i18n/index.js';
3
+ export { Locale, Messages, PROTECTED_TOKENS, ProtectedToken, TranslationKey, Translator, createTranslator, defaultMessages, detectNodeLocale, enMessages, normalizeLocale, resolveFabricLocale, zhCNMessages } from './i18n/index.js';
4
4
  import { z } from 'zod';
5
5
  import { Layer, KnowledgeType, StableId } from './schemas/api-contracts.js';
6
6
  export { CiteContractMetrics, CiteCoverageReport, CiteLayerTypeBreakdown, FabExtractKnowledgeInput, FabExtractKnowledgeInputSchema, FabExtractKnowledgeInputShape, FabExtractKnowledgeOutput, FabExtractKnowledgeOutputSchema, FabReviewInput, FabReviewInputSchema, FabReviewInputShape, FabReviewOutput, FabReviewOutputSchema, FabReviewOutputShape, KNOWLEDGE_TYPE_CODES, KnowledgeEntryFrontmatter, KnowledgeEntryFrontmatterSchema, KnowledgeTypeCode, KnowledgeTypeSchema, LayerSchema, Maturity, MaturitySchema, PROPOSED_REASON_DESCRIPTIONS, ProposedReason, ProposedReasonSchema, StableIdSchema, annotateIntentRequestSchema, citeContractMetricsSchema, citeCoverageReportSchema, citeLayerTypeBreakdownSchema, fabExtractKnowledgeAnnotations, fabReviewAnnotations, formatKnowledgeId, historyStateQuerySchema, humanLockApproveRequestSchema, humanLockFileParamsSchema, knowledgeSectionsAnnotations, knowledgeSectionsInputSchema, knowledgeSectionsOutputSchema, ledgerQuerySchema, ledgerSourceSchema, parseKnowledgeId, planContextAnnotations, planContextHintNarrowEntrySchema, planContextHintOutputSchema, planContextInputSchema, planContextOutputSchema, structuredWarningSchema } from './schemas/api-contracts.js';
@@ -5480,7 +5480,7 @@ declare const metaReconciledEventSchema: z.ZodObject<{
5480
5480
  event_type: z.ZodLiteral<"meta_reconciled">;
5481
5481
  reconciled_files: z.ZodArray<z.ZodString, "many">;
5482
5482
  duration_ms: z.ZodNumber;
5483
- trigger: z.ZodEnum<["doctor", "manual", "auto-heal-description"]>;
5483
+ trigger: z.ZodEnum<["doctor", "manual", "auto-heal-description", "post-approve", "post-modify"]>;
5484
5484
  source: z.ZodLiteral<"reconcileKnowledge">;
5485
5485
  force_write_reason: z.ZodOptional<z.ZodEnum<["revision_drift"]>>;
5486
5486
  kind: z.ZodLiteral<"fabric-event">;
@@ -5498,7 +5498,7 @@ declare const metaReconciledEventSchema: z.ZodObject<{
5498
5498
  event_type: "meta_reconciled";
5499
5499
  reconciled_files: string[];
5500
5500
  duration_ms: number;
5501
- trigger: "manual" | "doctor" | "auto-heal-description";
5501
+ trigger: "manual" | "doctor" | "auto-heal-description" | "post-approve" | "post-modify";
5502
5502
  correlation_id?: string | undefined;
5503
5503
  session_id?: string | undefined;
5504
5504
  force_write_reason?: "revision_drift" | undefined;
@@ -5511,7 +5511,7 @@ declare const metaReconciledEventSchema: z.ZodObject<{
5511
5511
  event_type: "meta_reconciled";
5512
5512
  reconciled_files: string[];
5513
5513
  duration_ms: number;
5514
- trigger: "manual" | "doctor" | "auto-heal-description";
5514
+ trigger: "manual" | "doctor" | "auto-heal-description" | "post-approve" | "post-modify";
5515
5515
  correlation_id?: string | undefined;
5516
5516
  session_id?: string | undefined;
5517
5517
  force_write_reason?: "revision_drift" | undefined;
@@ -7038,7 +7038,7 @@ declare const eventLedgerEventSchema: z.ZodDiscriminatedUnion<"event_type", [z.Z
7038
7038
  event_type: z.ZodLiteral<"meta_reconciled">;
7039
7039
  reconciled_files: z.ZodArray<z.ZodString, "many">;
7040
7040
  duration_ms: z.ZodNumber;
7041
- trigger: z.ZodEnum<["doctor", "manual", "auto-heal-description"]>;
7041
+ trigger: z.ZodEnum<["doctor", "manual", "auto-heal-description", "post-approve", "post-modify"]>;
7042
7042
  source: z.ZodLiteral<"reconcileKnowledge">;
7043
7043
  force_write_reason: z.ZodOptional<z.ZodEnum<["revision_drift"]>>;
7044
7044
  kind: z.ZodLiteral<"fabric-event">;
@@ -7056,7 +7056,7 @@ declare const eventLedgerEventSchema: z.ZodDiscriminatedUnion<"event_type", [z.Z
7056
7056
  event_type: "meta_reconciled";
7057
7057
  reconciled_files: string[];
7058
7058
  duration_ms: number;
7059
- trigger: "manual" | "doctor" | "auto-heal-description";
7059
+ trigger: "manual" | "doctor" | "auto-heal-description" | "post-approve" | "post-modify";
7060
7060
  correlation_id?: string | undefined;
7061
7061
  session_id?: string | undefined;
7062
7062
  force_write_reason?: "revision_drift" | undefined;
@@ -7069,7 +7069,7 @@ declare const eventLedgerEventSchema: z.ZodDiscriminatedUnion<"event_type", [z.Z
7069
7069
  event_type: "meta_reconciled";
7070
7070
  reconciled_files: string[];
7071
7071
  duration_ms: number;
7072
- trigger: "manual" | "doctor" | "auto-heal-description";
7072
+ trigger: "manual" | "doctor" | "auto-heal-description" | "post-approve" | "post-modify";
7073
7073
  correlation_id?: string | undefined;
7074
7074
  session_id?: string | undefined;
7075
7075
  force_write_reason?: "revision_drift" | undefined;
@@ -8161,6 +8161,12 @@ interface ParseCiteLineResult {
8161
8161
  *
8162
8162
  * Tolerates whitespace, CR/LF line endings, blank lines, and non-KB
8163
8163
  * interleaved prose. Index contract documented above.
8164
+ *
8165
+ * v2.0.0-rc.27 TASK-003 (audit §2.18): multi-id citations
8166
+ * (`KB: KT-DEC-0001, KT-PIT-0005 ...`) emit each id into cite_ids in
8167
+ * declaration order. The chained-from tag's embedded id (when present)
8168
+ * appends after the primary group. cite_tags still carries one tag per
8169
+ * LINE — multi-id lines don't multiply the tag stream.
8164
8170
  */
8165
8171
  declare function parseCiteLine(raw: string): ParseCiteLineResult;
8166
8172
 
package/dist/index.js CHANGED
@@ -1,12 +1,4 @@
1
- import {
2
- BOOTSTRAP_CANONICAL,
3
- BOOTSTRAP_MARKER_BEGIN,
4
- BOOTSTRAP_MARKER_END,
5
- BOOTSTRAP_REGEX,
6
- LEGACY_KB_MARKER_BEGIN,
7
- LEGACY_KB_MARKER_END,
8
- LEGACY_KB_REGEX
9
- } from "./chunk-4OQXR6JW.js";
1
+ import "./chunk-LXNCAKJZ.js";
10
2
  import {
11
3
  PROTECTED_TOKENS,
12
4
  createTranslator,
@@ -14,8 +6,9 @@ import {
14
6
  detectNodeLocale,
15
7
  enMessages,
16
8
  normalizeLocale,
9
+ resolveFabricLocale,
17
10
  zhCNMessages
18
- } from "./chunk-AFUQKKGR.js";
11
+ } from "./chunk-LXQ77R3D.js";
19
12
  import {
20
13
  FabExtractKnowledgeInputSchema,
21
14
  FabExtractKnowledgeInputShape,
@@ -57,8 +50,16 @@ import {
57
50
  planContextInputSchema,
58
51
  planContextOutputSchema,
59
52
  structuredWarningSchema
60
- } from "./chunk-3RSYWMQU.js";
61
- import "./chunk-LXNCAKJZ.js";
53
+ } from "./chunk-G32HVF7H.js";
54
+ import {
55
+ BOOTSTRAP_CANONICAL,
56
+ BOOTSTRAP_MARKER_BEGIN,
57
+ BOOTSTRAP_MARKER_END,
58
+ BOOTSTRAP_REGEX,
59
+ LEGACY_KB_MARKER_BEGIN,
60
+ LEGACY_KB_MARKER_END,
61
+ LEGACY_KB_REGEX
62
+ } from "./chunk-4OQXR6JW.js";
62
63
 
63
64
  // src/schemas/agents-meta.ts
64
65
  import { z } from "zod";
@@ -914,7 +915,11 @@ var metaReconciledEventSchema = z10.object({
914
915
  // revision-hash gate cannot catch — a missing description doesn't move the
915
916
  // revision). Symmetric to rc.22 D2 read-side auto-heal but covers the
916
917
  // description-undefined case which the revision drift gate misses.
917
- trigger: z10.enum(["doctor", "manual", "auto-heal-description"]),
918
+ // v2.0.0-rc.27 TASK-001 (§2.9): `post-approve` / `post-modify` added so
919
+ // `fab_review` write-actions can flush newly-promoted entries into
920
+ // `agents.meta.json.nodes[id]` synchronously — without this the new entry
921
+ // remains description-less until the next plan_context auto-heal.
922
+ trigger: z10.enum(["doctor", "manual", "auto-heal-description", "post-approve", "post-modify"]),
918
923
  source: z10.literal("reconcileKnowledge"),
919
924
  // v2.0.0-rc.22 TASK-014 (Scope E): set when reconcileKnowledge forced a
920
925
  // writeKnowledgeMeta on revision drift alone (no per-file content drift).
@@ -1233,7 +1238,8 @@ var eventLedgerEventSchema = z10.discriminatedUnion("event_type", [
1233
1238
  // src/cite-line-parser.ts
1234
1239
  var ID_RE = /^K[TP]-[A-Z]+-\d+$/;
1235
1240
  var SENTINEL_RE = /^KB:\s*none\b\s*(?:\[[^\]]*\])?\s*$/i;
1236
- var FULL_RE = /^KB:\s+(K[TP]-[A-Z]+-\d+)(?:\s+\(([^)]*)\))?(?:\s+\[([^\]]+)\])?(?:\s+→\s*(.+))?\s*$/;
1241
+ var FULL_RE = /^KB:\s+(K[TP]-[A-Z]+-\d+(?:\s*,\s*K[TP]-[A-Z]+-\d+)*)(?:\s+\(([^)]*)\))?(?:\s+\[([^\]]+)\])?(?:\s+→\s*(.+))?\s*$/;
1242
+ var CHAINED_FROM_ID_RE = /chained-from\s+(K[TP]-[A-Z]+-\d+)/i;
1237
1243
  var ALLOWED_TAGS = /* @__PURE__ */ new Set([
1238
1244
  "planned",
1239
1245
  "recalled",
@@ -1275,15 +1281,24 @@ function parseLine(line) {
1275
1281
  const trimmed = line.trim();
1276
1282
  if (trimmed.length === 0) return null;
1277
1283
  if (SENTINEL_RE.test(trimmed)) {
1278
- return { id: null, tag: "none", commitment: null };
1284
+ return { ids: [], tag: "none", commitment: null };
1279
1285
  }
1280
1286
  const fullMatch = trimmed.match(FULL_RE);
1281
1287
  if (fullMatch) {
1282
- const id = fullMatch[1];
1283
- if (!ID_RE.test(id)) return null;
1288
+ const primaryIds = fullMatch[1].split(",").map((part) => part.trim()).filter((part) => part.length > 0);
1289
+ if (primaryIds.some((id) => !ID_RE.test(id))) return null;
1290
+ const rawTag = fullMatch[3];
1291
+ const tag = parseTag(rawTag);
1292
+ const chainedIds = [];
1293
+ if (rawTag !== void 0) {
1294
+ const chained = CHAINED_FROM_ID_RE.exec(rawTag);
1295
+ if (chained !== null && ID_RE.test(chained[1])) {
1296
+ chainedIds.push(chained[1]);
1297
+ }
1298
+ }
1284
1299
  return {
1285
- id,
1286
- tag: parseTag(fullMatch[3]),
1300
+ ids: [...primaryIds, ...chainedIds],
1301
+ tag,
1287
1302
  commitment: parseContractTail(fullMatch[4])
1288
1303
  };
1289
1304
  }
@@ -1300,9 +1315,13 @@ function parseCiteLine(raw) {
1300
1315
  const parsed = parseLine(line);
1301
1316
  if (!parsed) continue;
1302
1317
  result.cite_tags.push(parsed.tag);
1303
- if (parsed.id !== null) result.cite_ids.push(parsed.id);
1318
+ for (const id of parsed.ids) {
1319
+ result.cite_ids.push(id);
1320
+ }
1304
1321
  if (parsed.commitment !== null) {
1305
- result.cite_commitments.push(parsed.commitment);
1322
+ for (let i = 0; i < parsed.ids.length; i += 1) {
1323
+ result.cite_commitments.push(parsed.commitment);
1324
+ }
1306
1325
  }
1307
1326
  }
1308
1327
  return result;
@@ -1458,6 +1477,7 @@ export {
1458
1477
  planContextOutputSchema,
1459
1478
  reapplyCompletedEventSchema,
1460
1479
  relevanceMigrationRunEventSchema,
1480
+ resolveFabricLocale,
1461
1481
  ruleDescriptionIndexItemSchema,
1462
1482
  ruleDescriptionSchema,
1463
1483
  serveLockClearedEventSchema,
@@ -1011,18 +1011,27 @@ declare const FabReviewInputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObje
1011
1011
  maturity: z.ZodOptional<z.ZodEnum<["draft", "verified", "proven"]>>;
1012
1012
  tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1013
1013
  created_after: z.ZodOptional<z.ZodString>;
1014
+ include_rejected: z.ZodOptional<z.ZodBoolean>;
1015
+ include_deferred: z.ZodOptional<z.ZodBoolean>;
1016
+ include_body: z.ZodOptional<z.ZodBoolean>;
1014
1017
  }, "strip", z.ZodTypeAny, {
1015
1018
  layer?: "personal" | "team" | "both" | undefined;
1016
1019
  type?: "decisions" | "pitfalls" | "guidelines" | "models" | "processes" | undefined;
1017
1020
  maturity?: "draft" | "verified" | "proven" | undefined;
1018
1021
  tags?: string[] | undefined;
1019
1022
  created_after?: string | undefined;
1023
+ include_rejected?: boolean | undefined;
1024
+ include_deferred?: boolean | undefined;
1025
+ include_body?: boolean | undefined;
1020
1026
  }, {
1021
1027
  layer?: "personal" | "team" | "both" | undefined;
1022
1028
  type?: "decisions" | "pitfalls" | "guidelines" | "models" | "processes" | undefined;
1023
1029
  maturity?: "draft" | "verified" | "proven" | undefined;
1024
1030
  tags?: string[] | undefined;
1025
1031
  created_after?: string | undefined;
1032
+ include_rejected?: boolean | undefined;
1033
+ include_deferred?: boolean | undefined;
1034
+ include_body?: boolean | undefined;
1026
1035
  }>>;
1027
1036
  }, "strip", z.ZodTypeAny, {
1028
1037
  action: "list";
@@ -1032,6 +1041,9 @@ declare const FabReviewInputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObje
1032
1041
  maturity?: "draft" | "verified" | "proven" | undefined;
1033
1042
  tags?: string[] | undefined;
1034
1043
  created_after?: string | undefined;
1044
+ include_rejected?: boolean | undefined;
1045
+ include_deferred?: boolean | undefined;
1046
+ include_body?: boolean | undefined;
1035
1047
  } | undefined;
1036
1048
  }, {
1037
1049
  action: "list";
@@ -1041,6 +1053,9 @@ declare const FabReviewInputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObje
1041
1053
  maturity?: "draft" | "verified" | "proven" | undefined;
1042
1054
  tags?: string[] | undefined;
1043
1055
  created_after?: string | undefined;
1056
+ include_rejected?: boolean | undefined;
1057
+ include_deferred?: boolean | undefined;
1058
+ include_body?: boolean | undefined;
1044
1059
  } | undefined;
1045
1060
  }>, z.ZodObject<{
1046
1061
  action: z.ZodLiteral<"approve">;
@@ -1124,18 +1139,27 @@ declare const FabReviewInputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObje
1124
1139
  maturity: z.ZodOptional<z.ZodEnum<["draft", "verified", "proven"]>>;
1125
1140
  tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1126
1141
  created_after: z.ZodOptional<z.ZodString>;
1142
+ include_rejected: z.ZodOptional<z.ZodBoolean>;
1143
+ include_deferred: z.ZodOptional<z.ZodBoolean>;
1144
+ include_body: z.ZodOptional<z.ZodBoolean>;
1127
1145
  }, "strip", z.ZodTypeAny, {
1128
1146
  layer?: "personal" | "team" | "both" | undefined;
1129
1147
  type?: "decisions" | "pitfalls" | "guidelines" | "models" | "processes" | undefined;
1130
1148
  maturity?: "draft" | "verified" | "proven" | undefined;
1131
1149
  tags?: string[] | undefined;
1132
1150
  created_after?: string | undefined;
1151
+ include_rejected?: boolean | undefined;
1152
+ include_deferred?: boolean | undefined;
1153
+ include_body?: boolean | undefined;
1133
1154
  }, {
1134
1155
  layer?: "personal" | "team" | "both" | undefined;
1135
1156
  type?: "decisions" | "pitfalls" | "guidelines" | "models" | "processes" | undefined;
1136
1157
  maturity?: "draft" | "verified" | "proven" | undefined;
1137
1158
  tags?: string[] | undefined;
1138
1159
  created_after?: string | undefined;
1160
+ include_rejected?: boolean | undefined;
1161
+ include_deferred?: boolean | undefined;
1162
+ include_body?: boolean | undefined;
1139
1163
  }>>;
1140
1164
  }, "strip", z.ZodTypeAny, {
1141
1165
  action: "search";
@@ -1146,6 +1170,9 @@ declare const FabReviewInputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObje
1146
1170
  maturity?: "draft" | "verified" | "proven" | undefined;
1147
1171
  tags?: string[] | undefined;
1148
1172
  created_after?: string | undefined;
1173
+ include_rejected?: boolean | undefined;
1174
+ include_deferred?: boolean | undefined;
1175
+ include_body?: boolean | undefined;
1149
1176
  } | undefined;
1150
1177
  }, {
1151
1178
  action: "search";
@@ -1156,6 +1183,9 @@ declare const FabReviewInputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObje
1156
1183
  maturity?: "draft" | "verified" | "proven" | undefined;
1157
1184
  tags?: string[] | undefined;
1158
1185
  created_after?: string | undefined;
1186
+ include_rejected?: boolean | undefined;
1187
+ include_deferred?: boolean | undefined;
1188
+ include_body?: boolean | undefined;
1159
1189
  } | undefined;
1160
1190
  }>, z.ZodObject<{
1161
1191
  action: z.ZodLiteral<"defer">;
@@ -1182,18 +1212,27 @@ declare const FabReviewInputShape: {
1182
1212
  maturity: z.ZodOptional<z.ZodEnum<["draft", "verified", "proven"]>>;
1183
1213
  tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1184
1214
  created_after: z.ZodOptional<z.ZodString>;
1215
+ include_rejected: z.ZodOptional<z.ZodBoolean>;
1216
+ include_deferred: z.ZodOptional<z.ZodBoolean>;
1217
+ include_body: z.ZodOptional<z.ZodBoolean>;
1185
1218
  }, "strip", z.ZodTypeAny, {
1186
1219
  layer?: "personal" | "team" | "both" | undefined;
1187
1220
  type?: "decisions" | "pitfalls" | "guidelines" | "models" | "processes" | undefined;
1188
1221
  maturity?: "draft" | "verified" | "proven" | undefined;
1189
1222
  tags?: string[] | undefined;
1190
1223
  created_after?: string | undefined;
1224
+ include_rejected?: boolean | undefined;
1225
+ include_deferred?: boolean | undefined;
1226
+ include_body?: boolean | undefined;
1191
1227
  }, {
1192
1228
  layer?: "personal" | "team" | "both" | undefined;
1193
1229
  type?: "decisions" | "pitfalls" | "guidelines" | "models" | "processes" | undefined;
1194
1230
  maturity?: "draft" | "verified" | "proven" | undefined;
1195
1231
  tags?: string[] | undefined;
1196
1232
  created_after?: string | undefined;
1233
+ include_rejected?: boolean | undefined;
1234
+ include_deferred?: boolean | undefined;
1235
+ include_body?: boolean | undefined;
1197
1236
  }>>;
1198
1237
  readonly pending_paths: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1199
1238
  readonly pending_path: z.ZodOptional<z.ZodString>;
@@ -1230,6 +1269,7 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1230
1269
  action: z.ZodLiteral<"list">;
1231
1270
  items: z.ZodArray<z.ZodObject<{
1232
1271
  pending_path: z.ZodString;
1272
+ pending_path_absolute: z.ZodOptional<z.ZodString>;
1233
1273
  type: z.ZodEnum<["decisions", "pitfalls", "guidelines", "models", "processes"]>;
1234
1274
  layer: z.ZodEnum<["team", "personal"]>;
1235
1275
  maturity: z.ZodEnum<["draft", "verified", "proven"]>;
@@ -1237,24 +1277,35 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1237
1277
  title: z.ZodOptional<z.ZodString>;
1238
1278
  summary: z.ZodOptional<z.ZodString>;
1239
1279
  origin: z.ZodOptional<z.ZodEnum<["team", "personal"]>>;
1280
+ status: z.ZodOptional<z.ZodEnum<["active", "rejected", "deferred"]>>;
1281
+ deferred_until: z.ZodOptional<z.ZodString>;
1282
+ body: z.ZodOptional<z.ZodString>;
1240
1283
  }, "strip", z.ZodTypeAny, {
1241
1284
  layer: "personal" | "team";
1242
1285
  pending_path: string;
1243
1286
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1244
1287
  maturity: "draft" | "verified" | "proven";
1288
+ status?: "active" | "rejected" | "deferred" | undefined;
1245
1289
  summary?: string | undefined;
1246
1290
  tags?: string[] | undefined;
1291
+ body?: string | undefined;
1247
1292
  title?: string | undefined;
1293
+ pending_path_absolute?: string | undefined;
1248
1294
  origin?: "personal" | "team" | undefined;
1295
+ deferred_until?: string | undefined;
1249
1296
  }, {
1250
1297
  layer: "personal" | "team";
1251
1298
  pending_path: string;
1252
1299
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1253
1300
  maturity: "draft" | "verified" | "proven";
1301
+ status?: "active" | "rejected" | "deferred" | undefined;
1254
1302
  summary?: string | undefined;
1255
1303
  tags?: string[] | undefined;
1304
+ body?: string | undefined;
1256
1305
  title?: string | undefined;
1306
+ pending_path_absolute?: string | undefined;
1257
1307
  origin?: "personal" | "team" | undefined;
1308
+ deferred_until?: string | undefined;
1258
1309
  }>, "many">;
1259
1310
  warnings: z.ZodOptional<z.ZodArray<z.ZodObject<{
1260
1311
  code: z.ZodString;
@@ -1279,10 +1330,14 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1279
1330
  pending_path: string;
1280
1331
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1281
1332
  maturity: "draft" | "verified" | "proven";
1333
+ status?: "active" | "rejected" | "deferred" | undefined;
1282
1334
  summary?: string | undefined;
1283
1335
  tags?: string[] | undefined;
1336
+ body?: string | undefined;
1284
1337
  title?: string | undefined;
1338
+ pending_path_absolute?: string | undefined;
1285
1339
  origin?: "personal" | "team" | undefined;
1340
+ deferred_until?: string | undefined;
1286
1341
  }[];
1287
1342
  warnings?: {
1288
1343
  file: string;
@@ -1297,10 +1352,14 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1297
1352
  pending_path: string;
1298
1353
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1299
1354
  maturity: "draft" | "verified" | "proven";
1355
+ status?: "active" | "rejected" | "deferred" | undefined;
1300
1356
  summary?: string | undefined;
1301
1357
  tags?: string[] | undefined;
1358
+ body?: string | undefined;
1302
1359
  title?: string | undefined;
1360
+ pending_path_absolute?: string | undefined;
1303
1361
  origin?: "personal" | "team" | undefined;
1362
+ deferred_until?: string | undefined;
1304
1363
  }[];
1305
1364
  warnings?: {
1306
1365
  file: string;
@@ -1444,6 +1503,7 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1444
1503
  action: z.ZodLiteral<"search">;
1445
1504
  items: z.ZodArray<z.ZodObject<{
1446
1505
  pending_path: z.ZodString;
1506
+ pending_path_absolute: z.ZodOptional<z.ZodString>;
1447
1507
  type: z.ZodEnum<["decisions", "pitfalls", "guidelines", "models", "processes"]>;
1448
1508
  layer: z.ZodEnum<["team", "personal"]>;
1449
1509
  maturity: z.ZodEnum<["draft", "verified", "proven"]>;
@@ -1451,24 +1511,35 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1451
1511
  title: z.ZodOptional<z.ZodString>;
1452
1512
  summary: z.ZodOptional<z.ZodString>;
1453
1513
  origin: z.ZodOptional<z.ZodEnum<["team", "personal"]>>;
1514
+ status: z.ZodOptional<z.ZodEnum<["active", "rejected", "deferred"]>>;
1515
+ deferred_until: z.ZodOptional<z.ZodString>;
1516
+ body: z.ZodOptional<z.ZodString>;
1454
1517
  }, "strip", z.ZodTypeAny, {
1455
1518
  layer: "personal" | "team";
1456
1519
  pending_path: string;
1457
1520
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1458
1521
  maturity: "draft" | "verified" | "proven";
1522
+ status?: "active" | "rejected" | "deferred" | undefined;
1459
1523
  summary?: string | undefined;
1460
1524
  tags?: string[] | undefined;
1525
+ body?: string | undefined;
1461
1526
  title?: string | undefined;
1527
+ pending_path_absolute?: string | undefined;
1462
1528
  origin?: "personal" | "team" | undefined;
1529
+ deferred_until?: string | undefined;
1463
1530
  }, {
1464
1531
  layer: "personal" | "team";
1465
1532
  pending_path: string;
1466
1533
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1467
1534
  maturity: "draft" | "verified" | "proven";
1535
+ status?: "active" | "rejected" | "deferred" | undefined;
1468
1536
  summary?: string | undefined;
1469
1537
  tags?: string[] | undefined;
1538
+ body?: string | undefined;
1470
1539
  title?: string | undefined;
1540
+ pending_path_absolute?: string | undefined;
1471
1541
  origin?: "personal" | "team" | undefined;
1542
+ deferred_until?: string | undefined;
1472
1543
  }>, "many">;
1473
1544
  warnings: z.ZodOptional<z.ZodArray<z.ZodObject<{
1474
1545
  code: z.ZodString;
@@ -1493,10 +1564,14 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1493
1564
  pending_path: string;
1494
1565
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1495
1566
  maturity: "draft" | "verified" | "proven";
1567
+ status?: "active" | "rejected" | "deferred" | undefined;
1496
1568
  summary?: string | undefined;
1497
1569
  tags?: string[] | undefined;
1570
+ body?: string | undefined;
1498
1571
  title?: string | undefined;
1572
+ pending_path_absolute?: string | undefined;
1499
1573
  origin?: "personal" | "team" | undefined;
1574
+ deferred_until?: string | undefined;
1500
1575
  }[];
1501
1576
  warnings?: {
1502
1577
  file: string;
@@ -1511,10 +1586,14 @@ declare const FabReviewOutputSchema: z.ZodDiscriminatedUnion<"action", [z.ZodObj
1511
1586
  pending_path: string;
1512
1587
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1513
1588
  maturity: "draft" | "verified" | "proven";
1589
+ status?: "active" | "rejected" | "deferred" | undefined;
1514
1590
  summary?: string | undefined;
1515
1591
  tags?: string[] | undefined;
1592
+ body?: string | undefined;
1516
1593
  title?: string | undefined;
1594
+ pending_path_absolute?: string | undefined;
1517
1595
  origin?: "personal" | "team" | undefined;
1596
+ deferred_until?: string | undefined;
1518
1597
  }[];
1519
1598
  warnings?: {
1520
1599
  file: string;
@@ -1565,6 +1644,7 @@ declare const FabReviewOutputShape: {
1565
1644
  readonly action: z.ZodEnum<["list", "approve", "reject", "modify", "search", "defer"]>;
1566
1645
  readonly items: z.ZodOptional<z.ZodArray<z.ZodObject<{
1567
1646
  pending_path: z.ZodString;
1647
+ pending_path_absolute: z.ZodOptional<z.ZodString>;
1568
1648
  type: z.ZodEnum<["decisions", "pitfalls", "guidelines", "models", "processes"]>;
1569
1649
  layer: z.ZodEnum<["team", "personal"]>;
1570
1650
  maturity: z.ZodEnum<["draft", "verified", "proven"]>;
@@ -1572,24 +1652,35 @@ declare const FabReviewOutputShape: {
1572
1652
  title: z.ZodOptional<z.ZodString>;
1573
1653
  summary: z.ZodOptional<z.ZodString>;
1574
1654
  origin: z.ZodOptional<z.ZodEnum<["team", "personal"]>>;
1655
+ status: z.ZodOptional<z.ZodEnum<["active", "rejected", "deferred"]>>;
1656
+ deferred_until: z.ZodOptional<z.ZodString>;
1657
+ body: z.ZodOptional<z.ZodString>;
1575
1658
  }, "strip", z.ZodTypeAny, {
1576
1659
  layer: "personal" | "team";
1577
1660
  pending_path: string;
1578
1661
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1579
1662
  maturity: "draft" | "verified" | "proven";
1663
+ status?: "active" | "rejected" | "deferred" | undefined;
1580
1664
  summary?: string | undefined;
1581
1665
  tags?: string[] | undefined;
1666
+ body?: string | undefined;
1582
1667
  title?: string | undefined;
1668
+ pending_path_absolute?: string | undefined;
1583
1669
  origin?: "personal" | "team" | undefined;
1670
+ deferred_until?: string | undefined;
1584
1671
  }, {
1585
1672
  layer: "personal" | "team";
1586
1673
  pending_path: string;
1587
1674
  type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes";
1588
1675
  maturity: "draft" | "verified" | "proven";
1676
+ status?: "active" | "rejected" | "deferred" | undefined;
1589
1677
  summary?: string | undefined;
1590
1678
  tags?: string[] | undefined;
1679
+ body?: string | undefined;
1591
1680
  title?: string | undefined;
1681
+ pending_path_absolute?: string | undefined;
1592
1682
  origin?: "personal" | "team" | undefined;
1683
+ deferred_until?: string | undefined;
1593
1684
  }>, "many">>;
1594
1685
  readonly approved: z.ZodOptional<z.ZodArray<z.ZodObject<{
1595
1686
  pending_path: z.ZodString;
@@ -36,7 +36,7 @@ import {
36
36
  planContextInputSchema,
37
37
  planContextOutputSchema,
38
38
  structuredWarningSchema
39
- } from "../chunk-3RSYWMQU.js";
39
+ } from "../chunk-G32HVF7H.js";
40
40
  export {
41
41
  FabExtractKnowledgeInputSchema,
42
42
  FabExtractKnowledgeInputShape,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-shared",
3
- "version": "2.0.0-rc.25",
3
+ "version": "2.0.0-rc.27",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",