@fenglimg/fabric-shared 2.0.0 → 2.1.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,12 @@
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-MDWTGOAY.js";
1
10
  import {
2
11
  PROTECTED_TOKENS,
3
12
  createTranslator,
@@ -5,29 +14,37 @@ import {
5
14
  detectNodeLocale,
6
15
  enMessages,
7
16
  normalizeLocale,
17
+ resolveFabricLocale,
8
18
  zhCNMessages
9
- } from "./chunk-U2SR2M4L.js";
19
+ } from "./chunk-R2J7DAED.js";
10
20
  import {
11
21
  FabExtractKnowledgeInputSchema,
12
22
  FabExtractKnowledgeInputShape,
13
23
  FabExtractKnowledgeOutputSchema,
14
24
  FabReviewInputSchema,
25
+ FabReviewInputShape,
15
26
  FabReviewOutputSchema,
27
+ FabReviewOutputShape,
16
28
  KNOWLEDGE_TYPE_CODES,
17
29
  KnowledgeEntryFrontmatterSchema,
18
30
  KnowledgeTypeSchema,
19
31
  LayerSchema,
20
32
  MaturitySchema,
33
+ ONBOARD_SLOT_NAMES,
34
+ ONBOARD_SLOT_TOTAL,
21
35
  PROPOSED_REASON_DESCRIPTIONS,
22
36
  ProposedReasonSchema,
23
37
  StableIdSchema,
24
38
  annotateIntentRequestSchema,
39
+ archiveScanAnnotations,
40
+ archiveScanInputSchema,
41
+ archiveScanOutputSchema,
42
+ citeContractMetricsSchema,
43
+ citeCoverageReportSchema,
44
+ citeLayerTypeBreakdownSchema,
25
45
  fabExtractKnowledgeAnnotations,
26
46
  fabReviewAnnotations,
27
47
  formatKnowledgeId,
28
- getKnowledgeAnnotations,
29
- getKnowledgeInputSchema,
30
- getKnowledgeOutputSchema,
31
48
  historyStateQuerySchema,
32
49
  humanLockApproveRequestSchema,
33
50
  humanLockFileParamsSchema,
@@ -36,19 +53,30 @@ import {
36
53
  knowledgeSectionsOutputSchema,
37
54
  ledgerQuerySchema,
38
55
  ledgerSourceSchema,
56
+ onboardSlotSchema,
39
57
  parseKnowledgeId,
40
58
  planContextAnnotations,
41
59
  planContextHintNarrowEntrySchema,
42
60
  planContextHintOutputSchema,
43
61
  planContextInputSchema,
44
62
  planContextOutputSchema,
63
+ recallAnnotations,
64
+ recallInputSchema,
65
+ recallOutputSchema,
45
66
  structuredWarningSchema
46
- } from "./chunk-VQDCDCJA.js";
67
+ } from "./chunk-WVPDH4BF.js";
47
68
  import "./chunk-LXNCAKJZ.js";
48
69
 
49
70
  // src/schemas/agents-meta.ts
50
71
  import { z } from "zod";
51
72
  var FABRIC_AGENTS_PREFIX = ".fabric/agents/";
73
+ var KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL = {
74
+ model: "models",
75
+ decision: "decisions",
76
+ guideline: "guidelines",
77
+ pitfall: "pitfalls",
78
+ process: "processes"
79
+ };
52
80
  var AGENTS_META_LAYERS = ["L0", "L1", "L2"];
53
81
  var AGENTS_META_TOPOLOGY_TYPES = ["mirror", "cross-cutting", "domain", "local", "global"];
54
82
  var AGENTS_META_IDENTITY_SOURCES = ["declared", "derived"];
@@ -64,7 +92,15 @@ var ruleDescriptionSchema = z.object({
64
92
  entities: z.array(z.string()).optional(),
65
93
  // v2.0 knowledge entry fields (TASK-002 schemas). All optional for backward compat.
66
94
  id: z.string().optional(),
67
- knowledge_type: z.enum(["model", "decision", "guideline", "pitfall", "process"]).optional(),
95
+ // rc.31 NEW-1: forward-compat for legacy on-disk agents.meta.json carrying
96
+ // singular knowledge_type values (model/decision/guideline/pitfall/process).
97
+ // Normalize to canonical plural form before enum validation so doctor and
98
+ // plan-context-hint can load pre-rc.28 meta files without aborting. Disk
99
+ // gets rewritten to plural on next reconcile (via knowledge-meta-builder).
100
+ knowledge_type: z.preprocess(
101
+ (value) => typeof value === "string" && value in KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL ? KNOWLEDGE_TYPE_SINGULAR_TO_PLURAL[value] : value,
102
+ z.enum(["models", "decisions", "guidelines", "pitfalls", "processes"])
103
+ ).optional(),
68
104
  maturity: z.enum(["draft", "verified", "proven"]).optional(),
69
105
  knowledge_layer: z.enum(["personal", "team"]).optional(),
70
106
  layer_reason: z.string().optional(),
@@ -134,8 +170,7 @@ function withDerivedAgentsMetaNodeDefaults(node) {
134
170
  const identitySource = isKnowledgeEntry ? "declared" : deriveAgentsMetaIdentitySource(node);
135
171
  return {
136
172
  ...node,
137
- layer: node.layer ?? node.level ?? deriveAgentsMetaLayer(node.file),
138
- level: node.level ?? node.layer ?? deriveAgentsMetaLayer(node.file),
173
+ level: node.level ?? deriveAgentsMetaLayer(node.file),
139
174
  topology_type: node.topology_type ?? deriveAgentsMetaTopologyType(node.file),
140
175
  stable_id: stableId,
141
176
  identity_source: identitySource
@@ -164,7 +199,7 @@ function defaultAgentsMetaCounters() {
164
199
  }
165
200
  function deriveAgentsMetaStableId(file) {
166
201
  const normalized = normalizePath(file);
167
- if (normalized === "AGENTS.md" || normalized === ".fabric/bootstrap/README.md") {
202
+ if (normalized === "AGENTS.md") {
168
203
  return "bootstrap";
169
204
  }
170
205
  return getDepthSource(normalized).replace(/\.md$/u, "");
@@ -181,7 +216,7 @@ function deriveAgentsMetaIdentitySource(node) {
181
216
  }
182
217
  function deriveAgentsMetaLayer(file) {
183
218
  const normalized = normalizePath(file);
184
- if (normalized === "AGENTS.md" || normalized === ".fabric/bootstrap/README.md") {
219
+ if (normalized === "AGENTS.md") {
185
220
  return "L0";
186
221
  }
187
222
  if (hasCrossCuttingSegment(normalized)) {
@@ -292,31 +327,139 @@ var humanLockFileSchema = z4.object({
292
327
  });
293
328
 
294
329
  // src/schemas/fabric-config.ts
330
+ import { z as z6 } from "zod";
331
+
332
+ // src/schemas/store.ts
295
333
  import { z as z5 } from "zod";
296
- var auditModeSchema = z5.enum(["strict", "warn", "off"]);
297
- var clientPathsSchema = z5.object({
298
- claudeCodeCLI: z5.string().optional(),
299
- claudeCodeDesktop: z5.string().optional(),
300
- cursor: z5.string().optional(),
301
- codexCLI: z5.string().optional()
334
+ var STORE_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
335
+ var storeUuidSchema = z5.string().regex(STORE_UUID_PATTERN, "store_uuid must be a canonical lowercase UUID");
336
+ var PERSONAL_STORE_SENTINEL = "$personal";
337
+ var storeIdentitySchema = z5.object({
338
+ // Intrinsic, immutable once minted. Read from store.json, never recomputed.
339
+ store_uuid: storeUuidSchema,
340
+ // ISO-8601. When the store was first initialized.
341
+ created_at: z5.string(),
342
+ // Optional human-facing canonical alias baked into the store (e.g. the
343
+ // team picks "platform-kb"). Local per-machine aliases are resolved by the
344
+ // StoreResolver from config and may differ; this is the suggested default.
345
+ canonical_alias: z5.string().optional(),
346
+ // Optional one-line description surfaced in `store list` / onboarding.
347
+ description: z5.string().optional(),
348
+ // The semantic scopes this store is *allowed* to hold. A shared (team)
349
+ // store MUST NOT list "personal" (R5#3 privacy boundary, enforced at write
350
+ // time in P2). Open coordinate strings — see schemas/scope.ts.
351
+ allowed_scopes: z5.array(z5.string()).optional()
352
+ }).strict();
353
+ var requiredStoreEntrySchema = z5.object({
354
+ id: z5.string().min(1),
355
+ suggested_remote: z5.union([z5.string().min(1), z5.literal(PERSONAL_STORE_SENTINEL)]).optional()
356
+ }).strict();
357
+ var STORE_KNOWLEDGE_TYPE_DIRS = [
358
+ "models",
359
+ "decisions",
360
+ "guidelines",
361
+ "pitfalls",
362
+ "processes"
363
+ ];
364
+ var STORE_LAYOUT = {
365
+ identityFile: "store.json",
366
+ knowledgeDir: "knowledge",
367
+ bindingsDir: "bindings",
368
+ stateDir: "state"
369
+ };
370
+ var STORES_ROOT_DIR = "stores";
371
+ var GLOBAL_STATE_DIR = "state";
372
+ var GLOBAL_BINDINGS_DIR = "bindings";
373
+ function storeKnowledgeTypeDir(type) {
374
+ return `${STORE_LAYOUT.knowledgeDir}/${type}`;
375
+ }
376
+ function storeRelativePath(storeUuid) {
377
+ return `${STORES_ROOT_DIR}/${storeUuid}`;
378
+ }
379
+ var mountedStoreSchema = z5.object({
380
+ // Intrinsic identity of the mounted store (matches its store.json).
381
+ store_uuid: storeUuidSchema,
382
+ // Local per-machine alias the user references this store by (resolver maps
383
+ // alias → uuid). May differ from the store's canonical_alias.
384
+ alias: z5.string().min(1),
385
+ // Git remote locator for this clone, if any. Absent = local-only store
386
+ // (valid; doctor nudges to add a remote for backup — R5#5, P6).
387
+ remote: z5.string().min(1).optional(),
388
+ // v2.1.0-rc.1 P3: marks the implicit personal store (the one minted by
389
+ // `install --global`). Exactly one mounted store carries personal=true; it
390
+ // is the write target for personal-scope entries (R5#3) and always in the
391
+ // read-set (S11). Optional (no default) so the output type stays a plain
392
+ // optional — consumers coalesce `?? false` when building resolver input.
393
+ personal: z5.boolean().optional(),
394
+ // Whether writes are accepted into this store from this machine. Optional;
395
+ // consumers coalesce `?? true`. Shared stores cloned read-only set false.
396
+ writable: z5.boolean().optional()
302
397
  }).strict();
303
- var mcpPayloadLimitsSchema = z5.object({
304
- warnBytes: z5.number().int().positive().optional(),
305
- hardBytes: z5.number().int().positive().optional()
398
+ var globalConfigSchema = z5.object({
399
+ // Machine/account identity. Personal-knowledge id namespace (S33/S27).
400
+ uid: z5.string().min(1),
401
+ // All stores mounted on this machine. The implicit personal store is
402
+ // included here once initialized. Default empty so a fresh global config
403
+ // (before `install --global`) parses cleanly.
404
+ stores: z5.array(mountedStoreSchema).optional().default([])
405
+ }).passthrough();
406
+
407
+ // src/schemas/fabric-config.ts
408
+ var auditModeSchema = z6.enum(["strict", "warn", "off"]);
409
+ var clientPathsSchema = z6.object({
410
+ claudeCodeCLI: z6.string().optional(),
411
+ claudeCodeDesktop: z6.string().optional(),
412
+ cursor: z6.string().optional(),
413
+ codexCLI: z6.string().optional()
414
+ }).strict();
415
+ var mcpPayloadLimitsSchema = z6.object({
416
+ warnBytes: z6.number().int().positive().optional(),
417
+ hardBytes: z6.number().int().positive().optional()
306
418
  }).optional();
307
- var knowledgeLanguageSchema = z5.enum(["match-existing", "zh-CN", "en"]);
308
- var defaultLayerFilterSchema = z5.enum(["team", "personal", "both"]);
309
- var fabricConfigSchema = z5.object({
419
+ var selectionTokenTtlMsSchema = z6.number().int().min(3e4).max(36e5);
420
+ var fabricLanguageSchema = z6.enum([
421
+ "match-existing",
422
+ "zh-CN",
423
+ "en",
424
+ "zh-CN-hybrid"
425
+ ]);
426
+ var defaultLayerFilterSchema = z6.enum(["team", "personal", "both"]);
427
+ var fabricConfigSchema = z6.object({
310
428
  clientPaths: clientPathsSchema.optional(),
311
- externalFixturePath: z5.string().optional(),
312
- scanIgnores: z5.array(z5.string()).optional(),
313
- auditMode: auditModeSchema.optional(),
429
+ // v2.1.0-rc.1 P0 (S13-projectid): the project's stable identity. A UUID
430
+ // bound at `fabric install` time; a remote-derived hash is only a SUGGESTED
431
+ // default, never authoritative (so re-homing the git remote does not change
432
+ // project identity). Optional under the zero-user clean-slate — pre-v2.1
433
+ // fabric-config.json files simply lack it and the ProjectRootResolver mints
434
+ // one on next install. `.fabric/fabric-config.json` carrying this field is
435
+ // also the upward marker the ProjectRootResolver searches for (S15/S32).
436
+ project_id: z6.string().optional(),
437
+ // v2.1.0-rc.1 P0 (S59/B3): the stores this repo expects mounted. Each entry
438
+ // names a store by alias/UUID with an optional suggested_remote (or the
439
+ // `$personal` sentinel). Drives the read-set (required_stores ∪ implicit
440
+ // personal, S11/S54) and `clone`'s missing-store onboarding (S51). Optional
441
+ // + absent → read-set is just the implicit personal store.
442
+ required_stores: z6.array(requiredStoreEntrySchema).optional(),
443
+ // v2.1.0-rc.1 P3 (S60 / `store switch-write`): alias of the store that
444
+ // non-personal-scope writes land in for this project. Set by
445
+ // `fabric store switch-write <alias>`; consumed as the resolver's
446
+ // activeWriteAlias. Absent → no active write store yet. Personal-scope
447
+ // writes always target the implicit personal store regardless (R5#3).
448
+ active_write_store: z6.string().optional(),
449
+ // rc.17 (R-cut): the dev/test fixture-path config field was removed
450
+ // end-to-end. The `EXTERNAL_FIXTURE_PATH` env var is now the sole source
451
+ // consumed by `resolveDevMode()`. No z.preprocess alias — pre-rc.17
452
+ // fabric-config.json files carrying the field will be silently dropped by
453
+ // the lenient root parser (no .strict() at root). Pre-user clean-slate per
454
+ // memory/feedback_clean_slate.md; mirrors the rc.12 hard-rename precedent
455
+ // documented above.
456
+ scanIgnores: z6.array(z6.string()).optional(),
314
457
  audit_mode: auditModeSchema.optional(),
315
458
  mcpPayloadLimits: mcpPayloadLimitsSchema,
316
459
  // Backward-compat: both fields are optional with defaults so existing
317
460
  // fabric-config.json files (pre-grill-followup) parse unchanged. The default
318
461
  // values themselves are load-bearing — see docs/data-schema.md.
319
- knowledge_language: knowledgeLanguageSchema.optional().default("match-existing"),
462
+ fabric_language: fabricLanguageSchema.optional().default("match-existing"),
320
463
  default_layer_filter: defaultLayerFilterSchema.optional().default("both"),
321
464
  // Cooldown for the fabric-hint Stop hook (formerly archive-hint, renamed in
322
465
  // rc.5 TASK-010). After ANY of the three signals (archive / review / import)
@@ -325,7 +468,7 @@ var fabricConfigSchema = z5.object({
325
468
  // day if the user keeps ignoring it." Set to 24 to align with the archive
326
469
  // trigger threshold. The legacy `archive_hint_` key is retained for backward
327
470
  // compat with existing user fabric-config.json files.
328
- archive_hint_cooldown_hours: z5.number().int().positive().optional().default(12),
471
+ archive_hint_cooldown_hours: z6.number().int().positive().optional().default(12),
329
472
  // Underseed-node threshold for the fabric-hint Stop hook's import signal
330
473
  // (rc.5 TASK-010). When the canonical knowledge node count is strictly less
331
474
  // than this value AND a successful `init_scan_completed` event happened at
@@ -334,7 +477,7 @@ var fabricConfigSchema = z5.object({
334
477
  // the rule-of-thumb that a workspace with fewer than ten knowledge entries
335
478
  // is below the floor for plan_context retrieval to be meaningful. Also
336
479
  // consumed by `doctor` lint #22 (knowledge_underseeded).
337
- underseed_node_threshold: z5.number().int().positive().optional().default(10),
480
+ underseed_node_threshold: z6.number().int().positive().optional().default(10),
338
481
  // Edit-count threshold for the fabric-hint Stop hook's Signal A
339
482
  // (rc.6 TASK-022 / E5). Signal A fires when EITHER (a) >=24h have elapsed
340
483
  // since the last `knowledge_proposed` event, OR (b) >=archive_edit_threshold
@@ -345,185 +488,1348 @@ var fabricConfigSchema = z5.object({
345
488
  // there is probably something worth archiving"; lowered values nag more
346
489
  // aggressively, higher values rely on the 24h fallback. Missing or absent
347
490
  // edit-counter file degrades safely to the 24h-only path.
348
- archive_edit_threshold: z5.number().int().positive().optional().default(20),
491
+ archive_edit_threshold: z6.number().int().positive().optional().default(20),
349
492
  // rc.7 T7: hours-since-last-knowledge_proposed cutoff for Signal A's
350
493
  // time branch. Was hardcoded as 24 in fabric-hint.cjs's THRESHOLD_HOURS;
351
494
  // externalized so chatty workspaces can lower the bar and quiet ones can
352
495
  // raise it. Default 24 preserves rc.6 behavior. See docs/configuration.md.
353
- archive_hint_hours: z5.number().int().positive().optional().default(24),
496
+ archive_hint_hours: z6.number().int().positive().optional().default(24),
354
497
  // rc.7 T7: pending-count cutoff for Signal B (review skill). Was
355
498
  // hardcoded as 10 in fabric-hint.cjs's THRESHOLD_PENDING_COUNT.
356
499
  // Default 10 preserves rc.6 behavior. See docs/configuration.md for
357
500
  // small/medium/large repo recommendations.
358
- review_hint_pending_count: z5.number().int().positive().optional().default(10),
501
+ review_hint_pending_count: z6.number().int().positive().optional().default(10),
359
502
  // rc.7 T7: pending-age cutoff (in days) for Signal B (review skill).
360
503
  // Was hardcoded as 7 in fabric-hint.cjs's THRESHOLD_PENDING_AGE_DAYS.
361
504
  // Default 7 preserves rc.6 behavior. See docs/configuration.md.
362
- review_hint_pending_age_days: z5.number().int().positive().optional().default(7),
505
+ review_hint_pending_age_days: z6.number().int().positive().optional().default(7),
363
506
  // rc.7 T7 + T10 pre-wiring: days-since-last-doctor cutoff for the future
364
507
  // Signal D (maintenance hint). T10 will consume this to decide when the
365
508
  // fabric-hint Stop hook surfaces a "run `fabric doctor`" reminder.
366
509
  // Default 14 reflects a fortnightly cadence — long enough to avoid nag,
367
510
  // short enough to catch index drift before it compounds.
368
- maintenance_hint_days: z5.number().int().positive().optional().default(14),
511
+ maintenance_hint_days: z6.number().int().positive().optional().default(14),
369
512
  // rc.7 T7 + T10 pre-wiring: cooldown between Signal D reminders, in
370
513
  // days. Once Signal D fires, it stays silent for this many days even if
371
514
  // the user doesn't run doctor. Default 7 keeps the reminder weekly at
372
515
  // worst — pairing 14d trigger + 7d cooldown means at most ~2 reminders
373
516
  // per month for a workspace that ignores them.
374
- maintenance_hint_cooldown_days: z5.number().int().positive().optional().default(7)
517
+ maintenance_hint_cooldown_days: z6.number().int().positive().optional().default(7),
518
+ // rc.9+ (skill-contract-fix B1): first-run import window in months. The
519
+ // `fabric-import` skill scans this many months of git history on the very
520
+ // first invocation (when no prior `import_run_completed` event exists).
521
+ // Default 60 (~5 years) captures the bulk of a mature repo's signal in
522
+ // one pass; small / fresh repos can lower to 12-24 with no loss.
523
+ import_window_first_run_months: z6.number().int().min(1).optional().default(60),
524
+ // rc.9+ (skill-contract-fix B1): rerun import window in months. After
525
+ // the first successful import, subsequent runs only scan this many
526
+ // recent months — assumed everything older has already been crystallized
527
+ // into pending or canonical knowledge. Default 2 keeps incremental cost
528
+ // low; raise to 6 if the workspace pauses fabric-import for long stretches.
529
+ import_window_rerun_months: z6.number().int().min(1).optional().default(2),
530
+ // rc.9+ (skill-contract-fix B1): hard cap on pending entries produced
531
+ // per fabric-import invocation. Prevents one run from dumping hundreds
532
+ // of proposals when a backfill window is wide open. Default 10 matches
533
+ // the rule-of-thumb "human can triage ~10 pending entries in one
534
+ // review pass." Range 1-50.
535
+ import_max_pending_per_run: z6.number().int().min(1).max(50).optional().default(10),
536
+ // rc.9+ (skill-contract-fix B1): hard cap on commits scanned per
537
+ // fabric-import invocation. Bounds runtime on monorepos with high
538
+ // commit velocity. Default 500 covers ~2 months of typical churn;
539
+ // range 50-2000. Hitting the cap mid-window is logged but non-fatal.
540
+ import_max_commits_scan: z6.number().int().min(50).max(2e3).optional().default(500),
541
+ // rc.9+ (skill-contract-fix B1): canonical-node count above which
542
+ // fabric-import's pre-flight should warn / suggest review instead of
543
+ // proceeding. A workspace with 50+ canonical entries usually benefits
544
+ // more from `fabric-review` to consolidate than from importing more.
545
+ // Default 50; raise to 100+ for large polyglot repos.
546
+ import_skip_canonical_threshold: z6.number().int().positive().optional().default(50),
547
+ // rc.9+ (skill-contract-fix B1): max candidate entries surfaced per
548
+ // fabric-archive batch (one invocation of the skill). Pagination knob
549
+ // for the archive UI flow. Default 8 keeps each batch reviewable in
550
+ // one sitting; raise for large repos with high archive throughput.
551
+ archive_max_candidates_per_batch: z6.number().int().positive().optional().default(8),
552
+ // rc.9+ (skill-contract-fix B1): max recently-touched paths included
553
+ // in fabric-archive's "relevant context" lookup. Limits the size of
554
+ // the path-relevance digest the skill emits when ranking candidates.
555
+ // Default 20; large repos with deep directory fan-out can raise to
556
+ // 50+ if archive candidates feel under-contextualized.
557
+ archive_max_recent_paths: z6.number().int().positive().optional().default(20),
558
+ // rc.9+ (skill-contract-fix B1): max prior fabric-archive sessions
559
+ // summarised in the digest the skill loads on start. Prevents the
560
+ // digest from ballooning past the model context budget on workspaces
561
+ // that have archived repeatedly. Default 10; lower if context pressure
562
+ // bites, raise if you want longer-range archive trend visibility.
563
+ archive_digest_max_sessions: z6.number().int().positive().optional().default(10),
564
+ // rc.9+ (skill-contract-fix B1): max review results returned per
565
+ // topic when `fabric-review` clusters pending entries. Pagination
566
+ // knob analogous to archive_max_candidates_per_batch but scoped to
567
+ // each topic cluster. Default 8; raise to 15-20 for large repos
568
+ // where each topic legitimately groups many pending entries.
569
+ review_topic_result_cap: z6.number().int().positive().optional().default(8),
570
+ // rc.9+ (skill-contract-fix B1): age threshold (in days) above which
571
+ // a pending entry is considered "stale" by fabric-review and surfaced
572
+ // for explicit resolve-or-drop decision. Default 14; tighter than the
573
+ // 7d Signal-B trigger because review specifically targets the long
574
+ // tail. Large repos with slower cadence can raise to 30.
575
+ review_stale_pending_days: z6.number().int().positive().optional().default(14),
576
+ // v2.0.0-rc.34 TASK-05: reverse-unarchive opt-in. When true, callers of the
577
+ // `unarchiveKnowledge` primitive (and any future doctor auto-detect lint built
578
+ // on top) will execute the file move + ledger emit. When false (default),
579
+ // the same callers MUST short-circuit before any mutation — the primitive is
580
+ // shipped but inert until explicitly enabled. Opt-in posture mirrors the
581
+ // archive-flow precedent: destructive-ish file moves stay behind a flag.
582
+ reverse_unarchive_enabled: z6.boolean().optional().default(false),
583
+ // v2.0.0-rc.34 TASK-05: forces `unarchiveKnowledge` into dry-run mode even
584
+ // when called with `options.dryRun=false`. Lets operators preview a
585
+ // restoration pass before flipping `reverse_unarchive_enabled` to true.
586
+ reverse_unarchive_dry_run: z6.boolean().optional().default(false),
587
+ // v2.0.0-rc.34 TASK-06: long-session cite-policy evict window in user-prompt
588
+ // turns. UserPromptSubmit hook (Claude Code only) maintains a per-session
589
+ // counter and re-injects the cite contract reminder via
590
+ // hookSpecificOutput.additionalContext when `turn_count % interval === 0`.
591
+ // Default 0 = OFF (opt-in). Recommend 10-20 for active sessions; 5 for
592
+ // high-contract-criticality projects. Other strategies (time-based,
593
+ // token-budget) deferred to rc.35 per plan locked-decisions 2026-05-26.
594
+ cite_evict_interval: z6.number().int().min(0).optional().default(0),
595
+ // v2.0.0-rc.22 Scope A T3: sliding-window retention (in days) for the
596
+ // event ledger rotation primitive (`rotateEventLedgerIfNeeded`). Lines
597
+ // whose `ts` is older than `now - fabric_event_retention_days * 86_400_000`
598
+ // are partitioned into `.fabric/events.archive/events-rotated-YYYY-MM-DD.jsonl`.
599
+ // Locked to 7/30/90 — three operator-friendly preset windows. Default 30
600
+ // is applied at the consumer site (rotateEventLedgerIfNeeded), so this
601
+ // field stays `.optional()` without a `.default()` to keep the schema
602
+ // surface honest: absence means "use the library default", not "schema
603
+ // default of 30 was injected." 7 = ~tight, 30 = balanced, 90 = forensic.
604
+ // Mirrors cite-policy precedent of locking enum-style numeric tunables
605
+ // to a small literal set (vs free `.positive()`) to prevent fat-finger
606
+ // misconfig.
607
+ fabric_event_retention_days: z6.union([z6.literal(7), z6.literal(30), z6.literal(90)]).optional(),
608
+ // v2.0.0-rc.23 TASK-014 (F8c): onboard slot opt-out list. Tracks slot
609
+ // names the user explicitly dismissed during fabric-archive's first-run
610
+ // onboard phase (or via `fabric config dismiss-slot <slot>`). Dismissed
611
+ // slots are excluded from `fabric onboard-coverage`'s `missing` set and the
612
+ // doctor `Onboard coverage` advisory's recompute, so the user is never
613
+ // re-prompted for slots they consciously declined.
614
+ //
615
+ // Re-opening a dismissed slot requires `fabric config onboard-reset <slot>`
616
+ // — a deliberate two-command UX to keep the dismiss intent reversible
617
+ // but never silently undone. Schema is intentionally `z.array(z.string())`
618
+ // rather than `z.array(onboardSlotSchema)` so historical configs survive
619
+ // a slot rename without a Zod parse error; downstream consumers
620
+ // intersect against ONBOARD_SLOT_NAMES at read time.
621
+ //
622
+ // Default `[]` keeps the field optional on existing configs — fresh
623
+ // installs land with no opt-outs.
624
+ onboard_slots_opted_out: z6.array(z6.string()).optional().default([]),
625
+ // v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the broad SessionStart hint
626
+ // banner emitted by knowledge-hint-broad.cjs. After plan-context-hint returns
627
+ // its full broad-scoped index, the hook slices the entries to this many
628
+ // before grouping/truncation rendering — keeps the banner from scrolling off
629
+ // screen on well-seeded repos (Werewolf-class projects routinely surface 40+
630
+ // broad entries which buried the actually-relevant top hits). Default 8 is
631
+ // calibrated against the rc.32 eval baseline (cite-coverage 3.1%): the
632
+ // banner needs to fit in ~1 screenful so the agent actually reads it.
633
+ // Range 1..50; values above 20 effectively disable the cap because the
634
+ // TRUNCATION_THRESHOLD=12 grouped-render kicks in. Mirrors the rc.7 T7 +
635
+ // archive_max_* pattern of externalizing previously-hardcoded thresholds.
636
+ hint_broad_top_k: z6.number().int().min(1).max(50).optional().default(8),
637
+ // v2.0.0-rc.37 NEW-16: durable per-signal dismiss for the fabric-hint Stop
638
+ // hook nudges. Any signal type listed here is suppressed at emit time across
639
+ // all sessions (the session-scoped sibling lives in a .fabric/.cache sidecar
640
+ // written on request). Mirrors the cite_evict_interval=0 opt-out convention —
641
+ // a knob for an existing surface, not a new feature. Unknown types ignored.
642
+ hint_dismiss_signals: z6.array(z6.enum(["archive", "review", "import", "maintenance"])).optional(),
643
+ // v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the narrow PreToolUse hint
644
+ // emitted by knowledge-hint-narrow.cjs. After filtering to entries whose
645
+ // `relevance_scope === "narrow"` (rc.27 TASK-005 audit §2.5 fix), the hook
646
+ // slices to this many before the E3 emit-gate / renderSummary pipeline.
647
+ // Default 5 keeps each per-Edit hint terse — five lines max so the agent's
648
+ // working memory is not displaced by an unwieldy banner. Range 1..20.
649
+ hint_narrow_top_k: z6.number().int().min(1).max(20).optional().default(5),
650
+ // v2.0.0-rc.33 W2-1 (P0-9): per-file dedup window (in PreToolUse turns) for
651
+ // the narrow hint. Same (file_path, stable_id) tuple stays silent for this
652
+ // many turns even when the E3 cross-session cache would otherwise re-emit.
653
+ // Closes the rc.32 eval finding that a single hot file (e.g. werewolf
654
+ // GameRoom.tsx edited 30 times in a row) re-fired the same narrow hint
655
+ // each time, training the agent to ignore it. Default 5; range 1..50.
656
+ // Storage: .fabric/.cache/narrow-dedup-window.json — distinct from session-
657
+ // hints cache so a window-only suppression does not poison cross-session
658
+ // dedupe semantics.
659
+ hint_narrow_dedup_window_turns: z6.number().int().min(1).max(50).optional().default(5),
660
+ // v2.0.0-rc.33 W2-5 (P1-8): cooldown between broad SessionStart hint emits,
661
+ // in hours. Distinct from the archive_hint_cooldown_hours that gates the
662
+ // fabric-hint Stop hook — knowledge-hint-broad re-fires on every
663
+ // SessionStart by default (compact / clear / new-window), which on long
664
+ // sessions becomes redundant noise. Setting to 1 means "emit the broad
665
+ // menu at most once per hour"; 0 means "no cooldown, current behavior."
666
+ // Range 0..168 (one week). Stored alongside fabric-hint's cooldown cache
667
+ // under a distinct knowledge-hint-broad key.
668
+ hint_broad_cooldown_hours: z6.number().int().min(0).max(168).optional().default(0),
669
+ // v2.0.0-rc.33 W2-5 (P1-8): cooldown for the narrow PreToolUse hint.
670
+ // Same shape as hint_broad_cooldown_hours but applies to per-Edit hint
671
+ // re-emission across the cooldown window — independent of E3 session-
672
+ // hints dedupe. Default 0 preserves rc.32 behavior; set to e.g. 1 to
673
+ // throttle hint frequency during rapid-fire editing sprints. Range
674
+ // 0..168 (one week).
675
+ hint_narrow_cooldown_hours: z6.number().int().min(0).max(168).optional().default(0),
676
+ // v2.0.0-rc.33 W4-B3 (T5 P2): per-maturity inactivity thresholds (days)
677
+ // driving orphan_demote. Hardcoded at stable=90/endorsed=30/draft=14 in
678
+ // rc.32; chatty workspaces want them tighter, slow ones want them looser.
679
+ // Each field optional; absent → defaults inside doctor.ts apply. Ranges
680
+ // chosen so a typo can't accidentally disable the lint (min 1).
681
+ orphan_demote_stable_days: z6.number().int().min(1).max(3650).optional(),
682
+ orphan_demote_endorsed_days: z6.number().int().min(1).max(3650).optional(),
683
+ orphan_demote_draft_days: z6.number().int().min(1).max(3650).optional(),
684
+ // v2.0.0-rc.33 W4-A3 (T4 P2): per-entry summary truncation length used by
685
+ // knowledge-hint-{broad,narrow}.cjs. Hard-coded at 80 chars in rc.32 — too
686
+ // short for entries with parameterized summaries (e.g. "Use bcrypt with
687
+ // cost=12 for password hashing"), too long for terse pitfalls. Range 40..240;
688
+ // default 80 preserves rc.32 behavior. Both hooks read the same key so the
689
+ // banner styling stays consistent across SessionStart + PreToolUse.
690
+ hint_summary_max_len: z6.number().int().min(40).max(240).optional().default(80),
691
+ // v2.0.0-rc.33 W2-6 (P0-7 + P0-8): when true, knowledge-hint hooks emit
692
+ // their banners as `hookSpecificOutput.additionalContext` JSON on stdout
693
+ // (per Claude Code PreToolUse hook contract — see
694
+ // https://docs.claude.com/en/docs/claude-code/hooks#preToolUse), so the
695
+ // agent receives them in-context instead of as stderr breadcrumbs the
696
+ // user may not surface to the model. Default true reflects the rc.33 cite-
697
+ // coverage focus (rc.32 baseline 3.1% → primary cause: reminders never
698
+ // entered model context). Set false to revert to legacy stderr-only mode
699
+ // for hosts that don't honor the JSON contract.
700
+ hint_reminder_to_context: z6.boolean().optional().default(true),
701
+ // v2.0.0-rc.29 TASK-008 (BUG-F3): selection-token TTL override. The
702
+ // `fab_plan_context` MCP tool hands clients a `selection_token` whose default
703
+ // 5-minute lifetime (`SELECTION_TOKEN_TTL_MS` at
704
+ // packages/server/src/services/plan-context.ts:91) was hard-coded and could
705
+ // not be tuned for slow review cycles. Operators on long-running sessions
706
+ // (manual paste-and-review flows, debugger pauses, etc.) reported tokens
707
+ // expiring mid-review. Override here; absence means "use the library default
708
+ // of 5*60*1000 ms." Range 30s..1h keeps the value useful — below 30s the
709
+ // token expires before MCP round-trips finish; above 1h it stops being a
710
+ // meaningful liveness signal for the plan-context cache.
711
+ //
712
+ // The single-field schema is exported separately (`selectionTokenTtlMsSchema`)
713
+ // so the server-side per-field reader can validate without re-running the
714
+ // whole fabricConfigSchema on every plan_context call — that lets a corrupt
715
+ // unrelated field stay isolated from the hot read path.
716
+ selection_token_ttl_ms: selectionTokenTtlMsSchema.optional()
717
+ });
718
+
719
+ // src/schemas/fabric-config-introspect.ts
720
+ import { z as z7 } from "zod";
721
+ var positiveIntSchema = z7.coerce.number().int().positive();
722
+ function makePositiveIntField(key, defaultValue) {
723
+ return {
724
+ key,
725
+ group: "B_hint_threshold",
726
+ widget: "text",
727
+ label_i18n_key: `cli.config.fields.${key}.label`,
728
+ description_i18n_key: `cli.config.fields.${key}.description`,
729
+ default: defaultValue,
730
+ validate(raw) {
731
+ const trimmed = raw.trim();
732
+ if (trimmed === "") {
733
+ return { ok: false, error: "Value is required (positive integer)." };
734
+ }
735
+ const parsed = positiveIntSchema.safeParse(trimmed);
736
+ if (!parsed.success) {
737
+ return {
738
+ ok: false,
739
+ error: "Must be a positive integer (e.g. 1, 12, 24)."
740
+ };
741
+ }
742
+ return { ok: true, value: parsed.data };
743
+ },
744
+ format_for_display(value) {
745
+ if (typeof value === "number") return String(value);
746
+ if (value === void 0 || value === null) return String(defaultValue);
747
+ return String(value);
748
+ }
749
+ };
750
+ }
751
+ function makeEnumField(key, group, enumValues, defaultValue) {
752
+ return {
753
+ key,
754
+ group,
755
+ widget: "select",
756
+ label_i18n_key: `cli.config.fields.${key}.label`,
757
+ description_i18n_key: `cli.config.fields.${key}.description`,
758
+ default: defaultValue,
759
+ enum_values: enumValues,
760
+ validate(raw) {
761
+ const trimmed = raw.trim();
762
+ if (!enumValues.includes(trimmed)) {
763
+ return {
764
+ ok: false,
765
+ error: `Must be one of: ${enumValues.join(", ")}.`
766
+ };
767
+ }
768
+ return { ok: true, value: trimmed };
769
+ },
770
+ format_for_display(value) {
771
+ if (typeof value === "string" && enumValues.includes(value)) return value;
772
+ if (value === void 0 || value === null) return defaultValue;
773
+ return String(value);
774
+ }
775
+ };
776
+ }
777
+ var SCHEMA_DEFAULTS = fabricConfigSchema.parse({});
778
+ function pickNumberDefault(key) {
779
+ const v = SCHEMA_DEFAULTS[key];
780
+ if (typeof v !== "number") {
781
+ throw new Error(
782
+ `fabric-config-introspect: expected numeric default for ${String(key)}, got ${typeof v}`
783
+ );
784
+ }
785
+ return v;
786
+ }
787
+ function pickStringDefault(key) {
788
+ const v = SCHEMA_DEFAULTS[key];
789
+ if (typeof v !== "string") {
790
+ throw new Error(
791
+ `fabric-config-introspect: expected string default for ${String(key)}, got ${typeof v}`
792
+ );
793
+ }
794
+ return v;
795
+ }
796
+ var AUDIT_MODE_PANEL_DEFAULT = "warn";
797
+ function getPanelFields() {
798
+ return PANEL_FIELDS;
799
+ }
800
+ function getPanelFieldByKey(key) {
801
+ return PANEL_FIELDS.find((f) => f.key === key);
802
+ }
803
+ var PANEL_FIELDS = [
804
+ // --- Group A: Locale (2) ---
805
+ makeEnumField(
806
+ "fabric_language",
807
+ "A_locale",
808
+ fabricLanguageSchema.options,
809
+ pickStringDefault("fabric_language")
810
+ ),
811
+ makeEnumField(
812
+ "default_layer_filter",
813
+ "A_locale",
814
+ defaultLayerFilterSchema.options,
815
+ pickStringDefault("default_layer_filter")
816
+ ),
817
+ // --- Group B: Hint thresholds (8 — see leading docstring for the
818
+ // 7-vs-8 reconciliation; archive_edit_threshold is the 8th key) ---
819
+ makePositiveIntField("archive_hint_hours", pickNumberDefault("archive_hint_hours")),
820
+ makePositiveIntField(
821
+ "archive_hint_cooldown_hours",
822
+ pickNumberDefault("archive_hint_cooldown_hours")
823
+ ),
824
+ makePositiveIntField(
825
+ "archive_edit_threshold",
826
+ pickNumberDefault("archive_edit_threshold")
827
+ ),
828
+ makePositiveIntField(
829
+ "underseed_node_threshold",
830
+ pickNumberDefault("underseed_node_threshold")
831
+ ),
832
+ makePositiveIntField(
833
+ "review_hint_pending_count",
834
+ pickNumberDefault("review_hint_pending_count")
835
+ ),
836
+ makePositiveIntField(
837
+ "review_hint_pending_age_days",
838
+ pickNumberDefault("review_hint_pending_age_days")
839
+ ),
840
+ makePositiveIntField(
841
+ "maintenance_hint_days",
842
+ pickNumberDefault("maintenance_hint_days")
843
+ ),
844
+ makePositiveIntField(
845
+ "maintenance_hint_cooldown_days",
846
+ pickNumberDefault("maintenance_hint_cooldown_days")
847
+ ),
848
+ // --- Group C: Audit (1) ---
849
+ makeEnumField(
850
+ "audit_mode",
851
+ "C_audit",
852
+ auditModeSchema.options,
853
+ AUDIT_MODE_PANEL_DEFAULT
854
+ )
855
+ ];
856
+
857
+ // src/schemas/scope.ts
858
+ import { z as z8 } from "zod";
859
+ var PERSONAL_SCOPE = "personal";
860
+ var KNOWN_SCOPE_PREFIXES = ["personal", "team", "project", "org"];
861
+ var SCOPE_COORDINATE_PATTERN = /^[a-z0-9_-]+(:[a-z0-9_-]+)*$/u;
862
+ var scopeCoordinateSchema = z8.string().min(1).regex(
863
+ SCOPE_COORDINATE_PATTERN,
864
+ "scope coordinate must be ':'-joined lowercase [a-z0-9_-] segments"
865
+ );
866
+ function scopeRoot(coordinate) {
867
+ const colon = coordinate.indexOf(":");
868
+ return colon === -1 ? coordinate : coordinate.slice(0, colon);
869
+ }
870
+ function isPersonalScope(coordinate) {
871
+ return scopeRoot(coordinate) === PERSONAL_SCOPE;
872
+ }
873
+ var entryScopeMetadataSchema = z8.object({
874
+ semantic_scope: scopeCoordinateSchema,
875
+ // Store alias or UUID. Validated as a non-empty string here; the resolver
876
+ // (P0.6) maps alias→UUID and verifies the store is in the read-set.
877
+ visibility_store: z8.string().min(1)
878
+ }).strict();
879
+
880
+ // src/schemas/store-stable-id.ts
881
+ import { z as z9 } from "zod";
882
+ var localKnowledgeIdSchema = StableIdSchema;
883
+ var UID_SEGMENT_PATTERN = /^[a-z0-9-]+$/u;
884
+ var uidSchema = z9.string().min(1).regex(UID_SEGMENT_PATTERN, "uid must be lowercase [a-z0-9-] segments");
885
+ var GLOBAL_REF_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(:[a-z0-9-]+)?:K[PT]-(MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u;
886
+ var globalRefSchema = z9.string().regex(GLOBAL_REF_PATTERN, "global_ref must be <store_uuid>[:<uid>]:<local_id>");
887
+ function formatGlobalRef(parts) {
888
+ const { store_uuid, uid, local_id } = parts;
889
+ return uid === void 0 ? `${store_uuid}:${local_id}` : `${store_uuid}:${uid}:${local_id}`;
890
+ }
891
+ function parseGlobalRef(ref) {
892
+ if (!GLOBAL_REF_PATTERN.test(ref)) {
893
+ return null;
894
+ }
895
+ const localMatch = ref.match(/K[PT]-(?:MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u);
896
+ if (localMatch === null) {
897
+ return null;
898
+ }
899
+ const local_id = localMatch[0];
900
+ const head = ref.slice(0, ref.length - local_id.length - 1);
901
+ const firstColon = head.indexOf(":");
902
+ if (firstColon === -1) {
903
+ return { store_uuid: head, local_id };
904
+ }
905
+ return {
906
+ store_uuid: head.slice(0, firstColon),
907
+ uid: head.slice(firstColon + 1),
908
+ local_id
909
+ };
910
+ }
911
+ var storeKnowledgeTypeCountersSchema = z9.object({
912
+ MOD: z9.number().int().nonnegative().default(0),
913
+ DEC: z9.number().int().nonnegative().default(0),
914
+ GLD: z9.number().int().nonnegative().default(0),
915
+ PIT: z9.number().int().nonnegative().default(0),
916
+ PRO: z9.number().int().nonnegative().default(0)
917
+ }).default({ MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 });
918
+ var storeCountersSchema = z9.object({
919
+ KP: storeKnowledgeTypeCountersSchema,
920
+ KT: storeKnowledgeTypeCountersSchema
921
+ }).default({
922
+ KP: { MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 },
923
+ KT: { MOD: 0, DEC: 0, GLD: 0, PIT: 0, PRO: 0 }
375
924
  });
376
925
 
926
+ // src/schemas/parity-matrix.ts
927
+ import { z as z10 } from "zod";
928
+ var PARITY_CLIENTS = ["claudeCode", "codexCLI", "cursor"];
929
+ var parityClientSchema = z10.enum(PARITY_CLIENTS);
930
+ var PARITY_SURFACES = ["skill", "hook", "mcp", "render"];
931
+ var paritySurfaceSchema = z10.enum(PARITY_SURFACES);
932
+ var parityClientExpectationSchema = z10.object({
933
+ supported: z10.boolean(),
934
+ mechanism: z10.string().optional(),
935
+ notes: z10.string().optional()
936
+ }).strict();
937
+ var parityCapabilitySchema = z10.object({
938
+ id: z10.string().min(1),
939
+ surface: paritySurfaceSchema,
940
+ description: z10.string().min(1),
941
+ clients: z10.object({
942
+ claudeCode: parityClientExpectationSchema,
943
+ codexCLI: parityClientExpectationSchema,
944
+ cursor: parityClientExpectationSchema
945
+ }).strict()
946
+ }).strict();
947
+ var parityMatrixSchema = z10.object({
948
+ // Schema/version tag of the matrix document itself.
949
+ version: z10.string().min(1),
950
+ // Free-form note on what release/milestone this matrix targets.
951
+ generated_for: z10.string().min(1),
952
+ capabilities: z10.array(parityCapabilitySchema).min(1)
953
+ }).strict();
954
+
955
+ // src/resolver/contracts.ts
956
+ import { z as z11 } from "zod";
957
+ var PROJECT_ROOT_SIGNALS = ["env", "marker", "cwd", "repo"];
958
+ var projectRootSignalSchema = z11.enum(PROJECT_ROOT_SIGNALS);
959
+ var projectRootSignalsSchema = z11.object({
960
+ // FABRIC_PROJECT_ROOT, if set.
961
+ env: z11.string().optional(),
962
+ // Nearest directory AT-OR-ABOVE cwd holding `.fabric/fabric-config.json`,
963
+ // if any (the upward marker search result; may equal cwd).
964
+ markerDir: z11.string().optional(),
965
+ // Always present — the process cwd.
966
+ cwd: z11.string().min(1),
967
+ // git repo root, if inside a repo.
968
+ repoRoot: z11.string().optional(),
969
+ // The `project_id` read from the winning root's fabric-config.json during
970
+ // (fs) signal collection. The pure resolver echoes it — it cannot invent a
971
+ // UUID. Worktrees of one repo share the committed config, hence the same
972
+ // project_id (S45 merge). Absent when no .fabric config exists at the root
973
+ // yet (fresh repo-fallback) → resolution still yields the root with a null
974
+ // projectId so the caller can mint+persist one at install time.
975
+ discoveredProjectId: z11.string().optional()
976
+ }).strict();
977
+ var projectRootResolutionSchema = z11.object({
978
+ // Absolute project root directory.
979
+ projectRoot: z11.string().min(1),
980
+ // Stable project identity. One repo = one .fabric = one project_id (S32);
981
+ // git worktrees of the same repo resolve to the SAME project_id (S45).
982
+ // Null when the resolved root has no fabric-config.json yet (fresh
983
+ // repo-fallback) — the caller mints + persists a UUID at install time.
984
+ projectId: z11.string().min(1).nullable(),
985
+ // Which signal won.
986
+ signalUsed: projectRootSignalSchema
987
+ }).strict();
988
+ var STORE_RESOLVER_WARNING_CODES = [
989
+ "missing_store",
990
+ // required_stores entry has no matching mounted store (S51)
991
+ "local_only_no_remote",
992
+ // mounted but local-only (R5#5 nudge, non-fatal)
993
+ "alias_unresolved"
994
+ // referenced alias maps to no mounted store
995
+ ];
996
+ var storeResolverWarningCodeSchema = z11.enum(STORE_RESOLVER_WARNING_CODES);
997
+ var storeResolverWarningSchema = z11.object({
998
+ code: storeResolverWarningCodeSchema,
999
+ // The alias/UUID/id the warning concerns.
1000
+ ref: z11.string().min(1),
1001
+ message: z11.string().min(1)
1002
+ }).strict();
1003
+ var readSetEntrySchema = z11.object({
1004
+ store_uuid: z11.string().min(1),
1005
+ alias: z11.string().min(1),
1006
+ remote: z11.string().min(1).optional(),
1007
+ // Whether this store accepts writes from the current context. Personal
1008
+ // store is writable; shared stores writable iff mounted with write intent.
1009
+ writable: z11.boolean()
1010
+ }).strict();
1011
+ var storeReadSetSchema = z11.object({
1012
+ stores: z11.array(readSetEntrySchema),
1013
+ warnings: z11.array(storeResolverWarningSchema)
1014
+ }).strict();
1015
+ var writeTargetSchema = z11.object({
1016
+ store_uuid: z11.string().min(1),
1017
+ alias: z11.string().min(1)
1018
+ }).strict();
1019
+ var storeResolveInputSchema = z11.object({
1020
+ // Machine identity (S33) — namespaces personal ids; identifies personal store.
1021
+ uid: z11.string().min(1),
1022
+ // Stores mounted on this machine (from global config).
1023
+ mountedStores: z11.array(
1024
+ z11.object({
1025
+ store_uuid: z11.string().min(1),
1026
+ alias: z11.string().min(1),
1027
+ remote: z11.string().min(1).optional(),
1028
+ writable: z11.boolean().default(true),
1029
+ // Marks the implicit personal store.
1030
+ personal: z11.boolean().default(false)
1031
+ }).strict()
1032
+ ),
1033
+ // The project's declared required_stores (ids/aliases + optional remote).
1034
+ requiredStores: z11.array(
1035
+ z11.object({
1036
+ id: z11.string().min(1),
1037
+ suggested_remote: z11.string().min(1).optional()
1038
+ }).strict()
1039
+ ),
1040
+ // Alias selected as the active write store for non-personal scopes, if any.
1041
+ activeWriteAlias: z11.string().min(1).optional()
1042
+ }).strict();
1043
+ var projectRootGoldenCaseSchema = z11.object({
1044
+ name: z11.string().min(1),
1045
+ note: z11.string().optional(),
1046
+ signals: projectRootSignalsSchema,
1047
+ // null expected = resolver should return no root for these signals.
1048
+ expected: projectRootResolutionSchema.nullable()
1049
+ }).strict();
1050
+ var projectRootGoldenFileSchema = z11.object({
1051
+ contract: z11.literal("project-root.golden"),
1052
+ cases: z11.array(projectRootGoldenCaseSchema).min(1)
1053
+ }).strict();
1054
+ var readSetGoldenCaseSchema = z11.object({
1055
+ name: z11.string().min(1),
1056
+ note: z11.string().optional(),
1057
+ input: storeResolveInputSchema,
1058
+ // Scope under test for the write-target expectation.
1059
+ writeScope: z11.string().min(1),
1060
+ expected: z11.object({
1061
+ readSet: storeReadSetSchema,
1062
+ writeTarget: writeTargetSchema.nullable(),
1063
+ writeWarnings: z11.array(storeResolverWarningSchema)
1064
+ }).strict()
1065
+ }).strict();
1066
+ var readSetGoldenFileSchema = z11.object({
1067
+ contract: z11.literal("read-set.golden"),
1068
+ cases: z11.array(readSetGoldenCaseSchema).min(1)
1069
+ }).strict();
1070
+
1071
+ // src/resolver/project-root-resolver.ts
1072
+ var ResolverNotImplementedError = class extends Error {
1073
+ constructor(what) {
1074
+ super(`${what} is not implemented yet (TDD target)`);
1075
+ this.name = "ResolverNotImplementedError";
1076
+ }
1077
+ };
1078
+ function createProjectRootResolver() {
1079
+ return {
1080
+ resolve(signals) {
1081
+ const projectId = signals.discoveredProjectId ?? null;
1082
+ if (signals.env !== void 0) {
1083
+ return { projectRoot: signals.env, projectId, signalUsed: "env" };
1084
+ }
1085
+ if (signals.markerDir !== void 0) {
1086
+ return {
1087
+ projectRoot: signals.markerDir,
1088
+ projectId,
1089
+ signalUsed: signals.markerDir === signals.cwd ? "cwd" : "marker"
1090
+ };
1091
+ }
1092
+ if (signals.repoRoot !== void 0) {
1093
+ return { projectRoot: signals.repoRoot, projectId, signalUsed: "repo" };
1094
+ }
1095
+ return null;
1096
+ }
1097
+ };
1098
+ }
1099
+
1100
+ // src/resolver/store-resolver.ts
1101
+ function findPersonal(input) {
1102
+ return input.mountedStores.find((s) => s.personal);
1103
+ }
1104
+ function personalEntry(input) {
1105
+ const p = findPersonal(input);
1106
+ if (p === void 0) {
1107
+ return void 0;
1108
+ }
1109
+ const entry = { store_uuid: p.store_uuid, alias: p.alias, writable: p.writable };
1110
+ if (p.remote !== void 0) {
1111
+ entry.remote = p.remote;
1112
+ }
1113
+ return entry;
1114
+ }
1115
+ function createStoreResolver() {
1116
+ return {
1117
+ resolveReadSet(input) {
1118
+ const stores = [];
1119
+ const warnings = [];
1120
+ for (const req of input.requiredStores) {
1121
+ const matched = input.mountedStores.find(
1122
+ (m) => !m.personal && (m.alias === req.id || m.store_uuid === req.id)
1123
+ );
1124
+ if (matched === void 0) {
1125
+ const suffix = req.suggested_remote === void 0 ? "" : ` (suggested remote: ${req.suggested_remote})`;
1126
+ warnings.push({
1127
+ code: "missing_store",
1128
+ ref: req.id,
1129
+ message: `required store '${req.id}' is not mounted; run \`fabric store add\`${suffix}`
1130
+ });
1131
+ continue;
1132
+ }
1133
+ const entry = {
1134
+ store_uuid: matched.store_uuid,
1135
+ alias: matched.alias,
1136
+ writable: matched.writable
1137
+ };
1138
+ if (matched.remote !== void 0) {
1139
+ entry.remote = matched.remote;
1140
+ } else {
1141
+ warnings.push({
1142
+ code: "local_only_no_remote",
1143
+ ref: matched.alias,
1144
+ message: `store '${matched.alias}' is local-only; add a git remote to back it up (\`fabric store ... \` / doctor nudge)`
1145
+ });
1146
+ }
1147
+ stores.push(entry);
1148
+ }
1149
+ const personal = personalEntry(input);
1150
+ if (personal !== void 0) {
1151
+ stores.push(personal);
1152
+ }
1153
+ return { stores, warnings };
1154
+ },
1155
+ resolveWriteTarget(input, scope) {
1156
+ if (isPersonalScope(scope)) {
1157
+ const p = findPersonal(input);
1158
+ if (p === void 0) {
1159
+ return {
1160
+ target: null,
1161
+ warnings: [
1162
+ {
1163
+ code: "missing_store",
1164
+ ref: "personal",
1165
+ message: "no personal store is mounted; run `fabric install --global` first"
1166
+ }
1167
+ ]
1168
+ };
1169
+ }
1170
+ return { target: { store_uuid: p.store_uuid, alias: p.alias }, warnings: [] };
1171
+ }
1172
+ const active = input.activeWriteAlias === void 0 ? void 0 : input.mountedStores.find((m) => m.writable && m.alias === input.activeWriteAlias);
1173
+ if (active === void 0) {
1174
+ return {
1175
+ target: null,
1176
+ warnings: [
1177
+ {
1178
+ code: "alias_unresolved",
1179
+ ref: input.activeWriteAlias ?? scope,
1180
+ message: `no writable store for scope '${scope}'; set an active write store with \`fabric store switch-write\``
1181
+ }
1182
+ ]
1183
+ };
1184
+ }
1185
+ return { target: { store_uuid: active.store_uuid, alias: active.alias }, warnings: [] };
1186
+ },
1187
+ aliasToUuid(input, alias) {
1188
+ return input.mountedStores.find((m) => m.alias === alias)?.store_uuid;
1189
+ }
1190
+ };
1191
+ }
1192
+
1193
+ // src/resolver/store-disk-reader.ts
1194
+ import { existsSync, readdirSync, readFileSync, statSync } from "fs";
1195
+ import { join } from "path";
1196
+ function readStoreIdentity(absDir) {
1197
+ const identityFile = join(absDir, STORE_LAYOUT.identityFile);
1198
+ if (!existsSync(identityFile)) {
1199
+ return null;
1200
+ }
1201
+ let raw;
1202
+ try {
1203
+ raw = JSON.parse(readFileSync(identityFile, "utf8"));
1204
+ } catch {
1205
+ return null;
1206
+ }
1207
+ const parsed = storeIdentitySchema.safeParse(raw);
1208
+ return parsed.success ? parsed.data : null;
1209
+ }
1210
+ function recognizeStoreDir(absDir) {
1211
+ return readStoreIdentity(absDir) !== null;
1212
+ }
1213
+ var SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([
1214
+ ".cjs",
1215
+ ".mjs",
1216
+ ".js",
1217
+ ".ts",
1218
+ ".sh",
1219
+ ".bash",
1220
+ ".zsh",
1221
+ ".py",
1222
+ ".rb",
1223
+ ".pl"
1224
+ ]);
1225
+ function hasScriptExtension(name) {
1226
+ const dot = name.lastIndexOf(".");
1227
+ return dot !== -1 && SCRIPT_EXTENSIONS.has(name.slice(dot).toLowerCase());
1228
+ }
1229
+ function findStoreExecutableViolations(absDir) {
1230
+ const violations = [];
1231
+ const walk = (dir, rel) => {
1232
+ let entries;
1233
+ try {
1234
+ entries = readdirSync(dir);
1235
+ } catch {
1236
+ return;
1237
+ }
1238
+ for (const entry of entries) {
1239
+ if (rel === "" && entry === ".git") {
1240
+ continue;
1241
+ }
1242
+ const abs = join(dir, entry);
1243
+ const relPath = rel === "" ? entry : `${rel}/${entry}`;
1244
+ let stat;
1245
+ try {
1246
+ stat = statSync(abs);
1247
+ } catch {
1248
+ continue;
1249
+ }
1250
+ if (stat.isDirectory()) {
1251
+ walk(abs, relPath);
1252
+ continue;
1253
+ }
1254
+ if ((stat.mode & 73) !== 0 || hasScriptExtension(entry)) {
1255
+ violations.push(relPath);
1256
+ }
1257
+ }
1258
+ };
1259
+ walk(absDir, "");
1260
+ return violations;
1261
+ }
1262
+
1263
+ // src/resolver/store-qualified-id.ts
1264
+ var LOCAL_ID = /^K[PT]-(MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u;
1265
+ function splitRef(ref) {
1266
+ const localMatch = ref.match(/K[PT]-(?:MOD|DEC|GLD|PIT|PRO)-\d{4,}$/u);
1267
+ if (localMatch === null) {
1268
+ return null;
1269
+ }
1270
+ const localId = localMatch[0];
1271
+ if (localId === ref) {
1272
+ return { storeQualifier: null, localId };
1273
+ }
1274
+ const head = ref.slice(0, ref.length - localId.length);
1275
+ if (!head.endsWith(":")) {
1276
+ return null;
1277
+ }
1278
+ return { storeQualifier: head.slice(0, -1), localId };
1279
+ }
1280
+ function resolveStoreQualifiedId(ref, candidates) {
1281
+ const split = splitRef(ref);
1282
+ if (split === null || !LOCAL_ID.test(split.localId)) {
1283
+ return { resolved: null, ambiguous: false, matches: [] };
1284
+ }
1285
+ const { storeQualifier, localId } = split;
1286
+ if (storeQualifier !== null) {
1287
+ const match = candidates.find(
1288
+ (c) => c.local_id === localId && (c.alias === storeQualifier || c.store_uuid === storeQualifier)
1289
+ );
1290
+ return match === void 0 ? { resolved: null, ambiguous: false, matches: [] } : { resolved: match, ambiguous: false, matches: [match] };
1291
+ }
1292
+ const matches = candidates.filter((c) => c.local_id === localId);
1293
+ if (matches.length === 1) {
1294
+ return { resolved: matches[0], ambiguous: false, matches };
1295
+ }
1296
+ return { resolved: null, ambiguous: matches.length > 1, matches };
1297
+ }
1298
+
1299
+ // src/resolver/resolution.ts
1300
+ function specificity(scope) {
1301
+ return scope.split(":").length;
1302
+ }
1303
+ function resolveCandidates(candidates, options = {}) {
1304
+ const storeOrder = options.storeOrder ?? [];
1305
+ const storeRank = (uuid) => {
1306
+ const idx = storeOrder.indexOf(uuid);
1307
+ return idx === -1 ? storeOrder.length : idx;
1308
+ };
1309
+ const seen = /* @__PURE__ */ new Set();
1310
+ const deduped = [];
1311
+ for (const c of candidates) {
1312
+ if (seen.has(c.global_ref)) {
1313
+ continue;
1314
+ }
1315
+ seen.add(c.global_ref);
1316
+ deduped.push(c);
1317
+ }
1318
+ const byLocal = /* @__PURE__ */ new Map();
1319
+ for (const c of deduped) {
1320
+ const stores = byLocal.get(c.local_id) ?? /* @__PURE__ */ new Set();
1321
+ stores.add(c.store_uuid);
1322
+ byLocal.set(c.local_id, stores);
1323
+ }
1324
+ const warnings = [];
1325
+ for (const [localId, stores] of byLocal) {
1326
+ if (stores.size > 1) {
1327
+ warnings.push({
1328
+ code: "shadowed_local_id",
1329
+ ref: localId,
1330
+ message: `local id '${localId}' exists in ${stores.size} stores; references must be store-qualified`
1331
+ });
1332
+ }
1333
+ }
1334
+ for (const uuid of options.unavailableRequiredStores ?? []) {
1335
+ warnings.push({
1336
+ code: "required_store_unavailable",
1337
+ ref: uuid,
1338
+ message: `required store '${uuid}' is unavailable; results may be incomplete (not silently degraded)`
1339
+ });
1340
+ }
1341
+ const sorted = [...deduped].sort((a, b) => {
1342
+ const specDiff = specificity(b.semantic_scope) - specificity(a.semantic_scope);
1343
+ if (specDiff !== 0) {
1344
+ return specDiff;
1345
+ }
1346
+ const rankDiff = storeRank(a.store_uuid) - storeRank(b.store_uuid);
1347
+ if (rankDiff !== 0) {
1348
+ return rankDiff;
1349
+ }
1350
+ return a.global_ref < b.global_ref ? -1 : a.global_ref > b.global_ref ? 1 : 0;
1351
+ });
1352
+ const resolved = sorted.map((c, i) => ({
1353
+ ...c,
1354
+ rank: i,
1355
+ reason: `scope '${scopeRoot(c.semantic_scope)}' (specificity ${specificity(
1356
+ c.semantic_scope
1357
+ )}), store '${c.alias}' (priority ${storeRank(c.store_uuid)})`
1358
+ }));
1359
+ return { resolved, warnings };
1360
+ }
1361
+
1362
+ // src/store/core.ts
1363
+ import { execFileSync } from "child_process";
1364
+ import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, writeFileSync } from "fs";
1365
+ import { join as join2 } from "path";
1366
+ var STORE_PENDING_DIR = "pending";
1367
+ var STORE_GITIGNORE = [
1368
+ "# v2.1 store \u2014 volatile / derived data is never committed",
1369
+ "state/",
1370
+ "agents.meta.json",
1371
+ ".cache/",
1372
+ ""
1373
+ ].join("\n");
1374
+ function git(cwd, args) {
1375
+ execFileSync("git", args, { cwd, stdio: ["ignore", "ignore", "pipe"] });
1376
+ }
1377
+ function initStore(absDir, identity, options = {}) {
1378
+ const parsed = storeIdentitySchema.parse(identity);
1379
+ const identityFile = join2(absDir, STORE_LAYOUT.identityFile);
1380
+ if (existsSync2(identityFile)) {
1381
+ throw new Error(`store already initialized at ${absDir} (store.json exists)`);
1382
+ }
1383
+ for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
1384
+ mkdirSync(join2(absDir, STORE_LAYOUT.knowledgeDir, type), { recursive: true });
1385
+ }
1386
+ mkdirSync(join2(absDir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR), { recursive: true });
1387
+ mkdirSync(join2(absDir, STORE_LAYOUT.bindingsDir), { recursive: true });
1388
+ mkdirSync(join2(absDir, STORE_LAYOUT.stateDir), { recursive: true });
1389
+ writeFileSync(identityFile, `${JSON.stringify(parsed, null, 2)}
1390
+ `, "utf8");
1391
+ writeFileSync(join2(absDir, ".gitignore"), STORE_GITIGNORE, "utf8");
1392
+ if (options.git !== false) {
1393
+ git(absDir, ["init", "-b", "main"]);
1394
+ }
1395
+ const readBack = readStoreIdentity(absDir);
1396
+ if (readBack === null) {
1397
+ throw new Error(`store init wrote an unrecognizable store.json at ${absDir}`);
1398
+ }
1399
+ return readBack;
1400
+ }
1401
+ function listMarkdown(dir) {
1402
+ if (!existsSync2(dir)) {
1403
+ return [];
1404
+ }
1405
+ return readdirSync2(dir).filter((name) => name.endsWith(".md")).sort().map((name) => join2(dir, name));
1406
+ }
1407
+ function listStoreKnowledge(store) {
1408
+ const refs = [];
1409
+ for (const type of STORE_KNOWLEDGE_TYPE_DIRS) {
1410
+ for (const file of listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, type))) {
1411
+ refs.push({ store_uuid: store.store_uuid, alias: store.alias, type, file });
1412
+ }
1413
+ }
1414
+ return refs;
1415
+ }
1416
+ function readKnowledgeAcrossStores(stores) {
1417
+ return stores.flatMap((store) => listStoreKnowledge(store));
1418
+ }
1419
+ function aggregatePendingAcrossStores(stores) {
1420
+ return stores.flatMap(
1421
+ (store) => listMarkdown(join2(store.dir, STORE_LAYOUT.knowledgeDir, STORE_PENDING_DIR)).map((file) => ({
1422
+ store_uuid: store.store_uuid,
1423
+ alias: store.alias,
1424
+ type: STORE_PENDING_DIR,
1425
+ file
1426
+ }))
1427
+ );
1428
+ }
1429
+
1430
+ // src/store/secret-scan.ts
1431
+ var SECRET_RULES = [
1432
+ { rule: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/ },
1433
+ { rule: "private-key-block", re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/ },
1434
+ { rule: "openai-api-key", re: /\bsk-[A-Za-z0-9]{20,}\b/ },
1435
+ { rule: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/ },
1436
+ { rule: "slack-token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/ },
1437
+ {
1438
+ rule: "credential-assignment",
1439
+ re: /(?:password|passwd|secret|api[_-]?key|access[_-]?token|token)\s*[:=]\s*['"][^'"\s]{8,}['"]/i
1440
+ }
1441
+ ];
1442
+ function scanForSecrets(content) {
1443
+ const findings = [];
1444
+ const lines = content.split(/\r?\n/u);
1445
+ for (let i = 0; i < lines.length; i++) {
1446
+ for (const { rule, re } of SECRET_RULES) {
1447
+ if (re.test(lines[i])) {
1448
+ findings.push({ rule, line: i + 1 });
1449
+ }
1450
+ }
1451
+ }
1452
+ return findings;
1453
+ }
1454
+ function hasSecrets(content) {
1455
+ return scanForSecrets(content).length > 0;
1456
+ }
1457
+ var REDACTION_PLACEHOLDER_PREFIX = "[REDACTED:";
1458
+ function redactSecrets(content) {
1459
+ let out = content;
1460
+ for (const { rule, re } of SECRET_RULES) {
1461
+ const flags = re.flags.includes("i") ? "gi" : "g";
1462
+ out = out.replace(new RegExp(re.source, flags), `${REDACTION_PLACEHOLDER_PREFIX}${rule}]`);
1463
+ }
1464
+ return out;
1465
+ }
1466
+
1467
+ // src/store/cross-store-lint.ts
1468
+ function lintCrossStoreReferences(input) {
1469
+ if (input.entryVisibility !== "shared") {
1470
+ return [];
1471
+ }
1472
+ const violations = [];
1473
+ for (const ref of input.referencedGlobalRefs) {
1474
+ const parsed = parseGlobalRef(ref);
1475
+ if (parsed === null) {
1476
+ continue;
1477
+ }
1478
+ if (input.storeVisibility[parsed.store_uuid] === "personal") {
1479
+ violations.push({
1480
+ code: "personal-ref-in-shared",
1481
+ ref,
1482
+ to_store_uuid: parsed.store_uuid,
1483
+ message: `shared-store entry references personal-store id '${ref}' \u2014 personal knowledge must not leak into a shared store`
1484
+ });
1485
+ }
1486
+ }
1487
+ return violations;
1488
+ }
1489
+ function isPersonalLeakIntoSharedStore(entryLayer, storeVisibility) {
1490
+ return entryLayer === "personal" && storeVisibility === "shared";
1491
+ }
1492
+
1493
+ // src/store/observability.ts
1494
+ function redactValue(value) {
1495
+ return typeof value === "string" ? redactSecrets(value) : value;
1496
+ }
1497
+ function buildFailureTrace(stage, error, context = {}, code) {
1498
+ const rawMessage = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
1499
+ const derivedCode = code ?? (error instanceof Error && error.name ? error.name : "error");
1500
+ const redactedContext = {};
1501
+ for (const [key, value] of Object.entries(context)) {
1502
+ redactedContext[key] = redactValue(value);
1503
+ }
1504
+ return {
1505
+ stage,
1506
+ code: derivedCode,
1507
+ message: redactSecrets(rawMessage),
1508
+ context: redactedContext
1509
+ };
1510
+ }
1511
+ function buildDebugBundle(input) {
1512
+ const redactDeep = (value) => {
1513
+ if (typeof value === "string") {
1514
+ return redactSecrets(value);
1515
+ }
1516
+ if (Array.isArray(value)) {
1517
+ return value.map(redactDeep);
1518
+ }
1519
+ if (value !== null && typeof value === "object") {
1520
+ const out = {};
1521
+ for (const [k, v] of Object.entries(value)) {
1522
+ out[k] = redactDeep(v);
1523
+ }
1524
+ return out;
1525
+ }
1526
+ return value;
1527
+ };
1528
+ return {
1529
+ version: 1,
1530
+ config: redactDeep(input.config),
1531
+ diagnostics: redactDeep(input.diagnostics) ?? [],
1532
+ events: input.includeEvents === true ? (input.events ?? []).map(redactSecrets) : [],
1533
+ redacted: true
1534
+ };
1535
+ }
1536
+
1537
+ // src/schemas/provenance.ts
1538
+ import { z as z12 } from "zod";
1539
+ var knowledgeProvenanceSchema = z12.object({
1540
+ store_uuid: storeUuidSchema,
1541
+ alias: z12.string().min(1),
1542
+ local_id: localKnowledgeIdSchema,
1543
+ global_ref: globalRefSchema,
1544
+ // Optional scope coordinate of the entry (resolution axis); present when the
1545
+ // surfacing tool has read the entry's frontmatter.
1546
+ semantic_scope: scopeCoordinateSchema.optional()
1547
+ }).strict();
1548
+
1549
+ // src/schemas/mcp-store-contracts.ts
1550
+ import { z as z13 } from "zod";
1551
+ var MCP_STORE_AWARE_TOOLS = [
1552
+ "fab_recall",
1553
+ "fab_plan_context",
1554
+ "fab_get_knowledge_sections",
1555
+ "fab_archive_scan",
1556
+ "fab_extract_knowledge",
1557
+ "fab_review"
1558
+ ];
1559
+ var storeAwareEntrySchema = z13.object({
1560
+ stable_id: z13.string(),
1561
+ global_ref: globalRefSchema,
1562
+ provenance: knowledgeProvenanceSchema
1563
+ }).strict();
1564
+ var writtenToStoreSchema = z13.object({
1565
+ store_uuid: storeUuidSchema,
1566
+ alias: z13.string().min(1)
1567
+ }).strict();
1568
+ var MCP_STORE_AWARE_CONTRACTS = {
1569
+ fab_recall: { tool: "fab_recall", surfacesEntries: true, echoesWrittenStore: false },
1570
+ fab_plan_context: { tool: "fab_plan_context", surfacesEntries: true, echoesWrittenStore: false },
1571
+ fab_get_knowledge_sections: {
1572
+ tool: "fab_get_knowledge_sections",
1573
+ surfacesEntries: true,
1574
+ echoesWrittenStore: false
1575
+ },
1576
+ fab_archive_scan: {
1577
+ tool: "fab_archive_scan",
1578
+ surfacesEntries: false,
1579
+ echoesWrittenStore: true
1580
+ },
1581
+ fab_extract_knowledge: {
1582
+ tool: "fab_extract_knowledge",
1583
+ surfacesEntries: false,
1584
+ echoesWrittenStore: true
1585
+ },
1586
+ fab_review: { tool: "fab_review", surfacesEntries: true, echoesWrittenStore: true }
1587
+ };
1588
+
1589
+ // src/schemas/bindings-snapshot.ts
1590
+ import { z as z14 } from "zod";
1591
+ var resolvedBindingsSnapshotSchema = z14.object({
1592
+ // Schema version of the snapshot document.
1593
+ version: z14.literal(1),
1594
+ // The project this snapshot is bound to (S13).
1595
+ project_id: z14.string().min(1),
1596
+ // ISO-8601 generation timestamp (provenance / staleness signal for doctor).
1597
+ generated_at: z14.string().min(1),
1598
+ // Pre-resolved read-set (required_stores ∪ implicit personal + warnings).
1599
+ read_set: storeReadSetSchema,
1600
+ // Pre-resolved active write target for non-personal scopes (null if none).
1601
+ write_target: writeTargetSchema.nullable()
1602
+ }).strict();
1603
+
1604
+ // src/store/bindings.ts
1605
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
1606
+ import { join as join3 } from "path";
1607
+ function bindingsSnapshotPath(globalRoot, projectId) {
1608
+ return join3(globalRoot, GLOBAL_STATE_DIR, GLOBAL_BINDINGS_DIR, `${projectId}_resolved.json`);
1609
+ }
1610
+ function writeBindingsSnapshot(options) {
1611
+ const resolver = createStoreResolver();
1612
+ const read_set = resolver.resolveReadSet(options.resolveInput);
1613
+ const { target } = resolver.resolveWriteTarget(options.resolveInput, options.writeScope);
1614
+ const snapshot = resolvedBindingsSnapshotSchema.parse({
1615
+ version: 1,
1616
+ project_id: options.projectId,
1617
+ generated_at: options.now,
1618
+ read_set,
1619
+ write_target: target
1620
+ });
1621
+ const path = bindingsSnapshotPath(options.globalRoot, options.projectId);
1622
+ mkdirSync2(join3(path, ".."), { recursive: true });
1623
+ writeFileSync2(path, `${JSON.stringify(snapshot, null, 2)}
1624
+ `, "utf8");
1625
+ return snapshot;
1626
+ }
1627
+ function readBindingsSnapshot(globalRoot, projectId) {
1628
+ const path = bindingsSnapshotPath(globalRoot, projectId);
1629
+ if (!existsSync3(path)) {
1630
+ return null;
1631
+ }
1632
+ try {
1633
+ const parsed = resolvedBindingsSnapshotSchema.safeParse(JSON.parse(readFileSync2(path, "utf8")));
1634
+ return parsed.success ? parsed.data : null;
1635
+ } catch {
1636
+ return null;
1637
+ }
1638
+ }
1639
+
1640
+ // src/store/store-lifecycle.ts
1641
+ function findMountedStore(config, aliasOrUuid) {
1642
+ return config.stores.find((s) => s.alias === aliasOrUuid || s.store_uuid === aliasOrUuid);
1643
+ }
1644
+ function addMountedStore(config, store) {
1645
+ const aliasClash = config.stores.find(
1646
+ (s) => s.alias === store.alias && s.store_uuid !== store.store_uuid
1647
+ );
1648
+ if (aliasClash !== void 0) {
1649
+ throw new Error(
1650
+ `alias '${store.alias}' already mounts store ${aliasClash.store_uuid}; choose another alias`
1651
+ );
1652
+ }
1653
+ const existing = config.stores.find((s) => s.store_uuid === store.store_uuid);
1654
+ const stores = existing === void 0 ? [...config.stores, store] : config.stores.map((s) => s.store_uuid === store.store_uuid ? store : s);
1655
+ return { ...config, stores };
1656
+ }
1657
+ function detachMountedStore(config, alias) {
1658
+ const detached = config.stores.find((s) => s.alias === alias) ?? null;
1659
+ if (detached === null) {
1660
+ return { config, detached: null };
1661
+ }
1662
+ return {
1663
+ config: { ...config, stores: config.stores.filter((s) => s.alias !== alias) },
1664
+ detached
1665
+ };
1666
+ }
1667
+ function bindRequiredStore(required, entry) {
1668
+ return required.some((r) => r.id === entry.id) ? required.map((r) => r.id === entry.id ? entry : r) : [...required, entry];
1669
+ }
1670
+ function explainStore(config, alias) {
1671
+ const store = findMountedStore(config, alias);
1672
+ if (store === void 0) {
1673
+ return null;
1674
+ }
1675
+ return {
1676
+ alias: store.alias,
1677
+ store_uuid: store.store_uuid,
1678
+ remote: store.remote ?? null,
1679
+ local_only: store.remote === void 0
1680
+ };
1681
+ }
1682
+
377
1683
  // src/schemas/forensic-report.ts
378
- import { z as z6 } from "zod";
379
- var forensicCodeSampleSchema = z6.object({
380
- path: z6.string(),
381
- lines: z6.string(),
382
- snippet: z6.string(),
383
- pattern_hint: z6.string()
384
- });
385
- var forensicEvidenceAnchorSchema = z6.object({
386
- file: z6.string(),
387
- line: z6.string(),
388
- snippet: z6.string()
389
- });
390
- var forensicAssertionCoverageSchema = z6.object({
391
- ratio: z6.number().min(0).max(1),
392
- total: z6.number().int().nonnegative(),
393
- matched: z6.number().int().nonnegative(),
394
- co_occurring_patterns: z6.array(z6.string())
395
- });
396
- var forensicAssertionSchema = z6.object({
397
- type: z6.enum(["framework", "pattern", "invariant", "domain"]),
398
- statement: z6.string(),
399
- confidence: z6.enum(["HIGH", "MEDIUM", "LOW"]),
400
- evidence: z6.array(forensicEvidenceAnchorSchema),
1684
+ import { z as z15 } from "zod";
1685
+ var forensicCodeSampleSchema = z15.object({
1686
+ path: z15.string(),
1687
+ lines: z15.string(),
1688
+ snippet: z15.string(),
1689
+ pattern_hint: z15.string()
1690
+ });
1691
+ var forensicEvidenceAnchorSchema = z15.object({
1692
+ file: z15.string(),
1693
+ line: z15.string(),
1694
+ snippet: z15.string()
1695
+ });
1696
+ var forensicAssertionCoverageSchema = z15.object({
1697
+ ratio: z15.number().min(0).max(1),
1698
+ total: z15.number().int().nonnegative(),
1699
+ matched: z15.number().int().nonnegative(),
1700
+ co_occurring_patterns: z15.array(z15.string())
1701
+ });
1702
+ var forensicAssertionSchema = z15.object({
1703
+ type: z15.enum(["framework", "pattern", "invariant", "domain"]),
1704
+ statement: z15.string(),
1705
+ confidence: z15.enum(["HIGH", "MEDIUM", "LOW"]),
1706
+ evidence: z15.array(forensicEvidenceAnchorSchema),
401
1707
  coverage: forensicAssertionCoverageSchema,
402
- proposed_rule: z6.string().optional(),
403
- alternatives: z6.array(z6.string()).optional()
404
- });
405
- var forensicTopologySchema = z6.object({
406
- total_files: z6.number().int().nonnegative(),
407
- by_ext: z6.record(z6.number().int().nonnegative()),
408
- key_dirs: z6.array(z6.string()),
409
- max_depth: z6.number().int().nonnegative()
410
- });
411
- var forensicEntryPointSchema = z6.object({
412
- path: z6.string(),
413
- reason: z6.string(),
414
- size_bytes: z6.number().int().nonnegative().optional()
415
- });
416
- var forensicFrameworkSchema = z6.object({
417
- kind: z6.string(),
418
- version: z6.string(),
419
- subkind: z6.string(),
420
- evidence: z6.array(z6.string())
421
- });
422
- var forensicReadmeSchema = z6.object({
423
- quality: z6.enum(["missing", "stub", "ok"]),
424
- line_count: z6.number().int().nonnegative(),
425
- has_contributing: z6.boolean()
426
- });
427
- var candidateFileEntrySchema = z6.object({
428
- path: z6.string(),
429
- family: z6.enum(["entry", "component", "config", "test", "domain"]),
430
- rationale: z6.string()
431
- });
432
- var forensicSamplingBudgetSchema = z6.object({
433
- max_files: z6.literal(15),
434
- max_lines_per_file: z6.literal(100)
435
- });
436
- var forensicReportSchema = z6.object({
437
- version: z6.string(),
438
- generated_at: z6.string(),
439
- generated_by: z6.string(),
440
- target: z6.string(),
441
- project_name: z6.string(),
1708
+ proposed_rule: z15.string().optional(),
1709
+ alternatives: z15.array(z15.string()).optional()
1710
+ });
1711
+ var forensicTopologySchema = z15.object({
1712
+ total_files: z15.number().int().nonnegative(),
1713
+ by_ext: z15.record(z15.number().int().nonnegative()),
1714
+ key_dirs: z15.array(z15.string()),
1715
+ max_depth: z15.number().int().nonnegative()
1716
+ });
1717
+ var forensicEntryPointSchema = z15.object({
1718
+ path: z15.string(),
1719
+ reason: z15.string(),
1720
+ size_bytes: z15.number().int().nonnegative().optional()
1721
+ });
1722
+ var forensicFrameworkSchema = z15.object({
1723
+ kind: z15.string(),
1724
+ version: z15.string(),
1725
+ subkind: z15.string(),
1726
+ evidence: z15.array(z15.string())
1727
+ });
1728
+ var forensicReadmeSchema = z15.object({
1729
+ quality: z15.enum(["missing", "stub", "ok"]),
1730
+ line_count: z15.number().int().nonnegative(),
1731
+ has_contributing: z15.boolean()
1732
+ });
1733
+ var candidateFileEntrySchema = z15.object({
1734
+ path: z15.string(),
1735
+ family: z15.enum(["entry", "component", "config", "test", "domain"]),
1736
+ rationale: z15.string()
1737
+ });
1738
+ var forensicSamplingBudgetSchema = z15.object({
1739
+ max_files: z15.literal(15),
1740
+ max_lines_per_file: z15.literal(100)
1741
+ });
1742
+ var forensicReportSchema = z15.object({
1743
+ version: z15.string(),
1744
+ generated_at: z15.string(),
1745
+ generated_by: z15.string(),
1746
+ target: z15.string(),
1747
+ project_name: z15.string(),
442
1748
  framework: forensicFrameworkSchema,
443
1749
  topology: forensicTopologySchema,
444
- entry_points: z6.array(forensicEntryPointSchema),
445
- code_samples: z6.array(forensicCodeSampleSchema),
446
- assertions: z6.array(forensicAssertionSchema),
447
- candidate_files: z6.array(candidateFileEntrySchema),
1750
+ entry_points: z15.array(forensicEntryPointSchema),
1751
+ code_samples: z15.array(forensicCodeSampleSchema),
1752
+ assertions: z15.array(forensicAssertionSchema),
1753
+ candidate_files: z15.array(candidateFileEntrySchema),
448
1754
  sampling_budget: forensicSamplingBudgetSchema,
449
1755
  readme: forensicReadmeSchema,
450
- recommendations_for_skill: z6.array(z6.string()).optional()
1756
+ recommendations_for_skill: z15.array(z15.string()).optional()
451
1757
  });
452
1758
 
453
1759
  // src/schemas/init-context.ts
454
- import { z as z7 } from "zod";
455
- var initContextFrameworkSchema = z7.object({
456
- kind: z7.string(),
457
- version: z7.string(),
458
- subkind: z7.string()
459
- });
460
- var initContextInvariantConfidenceSnapshotSchema = z7.object({
461
- confidence: z7.enum(["HIGH", "MEDIUM", "LOW"]),
462
- evidence_refs: z7.array(z7.string())
463
- });
464
- var initContextSourceEvidenceSchema = z7.object({
465
- file: z7.string(),
466
- lines: z7.string()
467
- });
468
- var initContextInvariantSchema = z7.object({
469
- type: z7.enum(["ban", "require", "protect"]),
470
- rule: z7.string(),
471
- rationale: z7.string().optional(),
1760
+ import { z as z16 } from "zod";
1761
+ var initContextFrameworkSchema = z16.object({
1762
+ kind: z16.string(),
1763
+ version: z16.string(),
1764
+ subkind: z16.string()
1765
+ });
1766
+ var initContextInvariantConfidenceSnapshotSchema = z16.object({
1767
+ confidence: z16.enum(["HIGH", "MEDIUM", "LOW"]),
1768
+ evidence_refs: z16.array(z16.string())
1769
+ });
1770
+ var initContextSourceEvidenceSchema = z16.object({
1771
+ file: z16.string(),
1772
+ lines: z16.string()
1773
+ });
1774
+ var initContextInvariantSchema = z16.object({
1775
+ type: z16.enum(["ban", "require", "protect"]),
1776
+ rule: z16.string(),
1777
+ rationale: z16.string().optional(),
472
1778
  confidence_snapshot: initContextInvariantConfidenceSnapshotSchema.optional(),
473
- source_evidence: z7.array(initContextSourceEvidenceSchema).optional()
474
- });
475
- var initContextDomainGroupSchema = z7.object({
476
- name: z7.string(),
477
- paths: z7.array(z7.string()),
478
- summary: z7.string().optional(),
479
- topology_type: z7.enum(["mirror", "cross-cutting"]).optional(),
480
- target_path: z7.string().optional()
481
- });
482
- var initContextInterviewTrailEntrySchema = z7.object({
483
- phase: z7.string(),
484
- question: z7.string(),
485
- answer: z7.string(),
486
- presentation: z7.string().optional(),
487
- user_corrections: z7.array(z7.string()).optional()
488
- });
489
- var initContextSchema = z7.object({
1779
+ source_evidence: z16.array(initContextSourceEvidenceSchema).optional()
1780
+ });
1781
+ var initContextDomainGroupSchema = z16.object({
1782
+ name: z16.string(),
1783
+ paths: z16.array(z16.string()),
1784
+ summary: z16.string().optional(),
1785
+ topology_type: z16.enum(["mirror", "cross-cutting"]).optional(),
1786
+ target_path: z16.string().optional()
1787
+ });
1788
+ var initContextInterviewTrailEntrySchema = z16.object({
1789
+ phase: z16.string(),
1790
+ question: z16.string(),
1791
+ answer: z16.string(),
1792
+ presentation: z16.string().optional(),
1793
+ user_corrections: z16.array(z16.string()).optional()
1794
+ });
1795
+ var initContextSchema = z16.object({
490
1796
  framework: initContextFrameworkSchema,
491
- architecture_patterns: z7.array(z7.string()),
492
- invariants: z7.array(initContextInvariantSchema),
493
- domain_groups: z7.array(initContextDomainGroupSchema),
494
- interview_trail: z7.array(initContextInterviewTrailEntrySchema),
495
- forensic_ref: z7.string()
1797
+ architecture_patterns: z16.array(z16.string()),
1798
+ invariants: z16.array(initContextInvariantSchema),
1799
+ domain_groups: z16.array(initContextDomainGroupSchema),
1800
+ interview_trail: z16.array(initContextInterviewTrailEntrySchema),
1801
+ forensic_ref: z16.string()
496
1802
  });
497
1803
 
498
1804
  // src/schemas/events.ts
499
- import { z as z8 } from "zod";
500
- var metaUpdatedEventSchema = z8.object({
501
- type: z8.literal("meta:updated"),
1805
+ import { z as z17 } from "zod";
1806
+ var metaUpdatedEventSchema = z17.object({
1807
+ type: z17.literal("meta:updated"),
502
1808
  payload: agentsMetaSchema
503
1809
  });
504
- var lockDriftEventSchema = z8.object({
505
- type: z8.literal("lock:drift"),
506
- payload: z8.object({
507
- locked: z8.array(humanLockEntrySchema),
508
- drifted: z8.array(humanLockEntrySchema)
1810
+ var lockDriftEventSchema = z17.object({
1811
+ type: z17.literal("lock:drift"),
1812
+ payload: z17.object({
1813
+ locked: z17.array(humanLockEntrySchema),
1814
+ drifted: z17.array(humanLockEntrySchema)
509
1815
  })
510
1816
  });
511
- var lockApprovedEventSchema = z8.object({
512
- type: z8.literal("lock:approved"),
513
- payload: z8.object({
514
- locked: z8.array(humanLockEntrySchema),
515
- approved: z8.array(humanLockEntrySchema)
1817
+ var lockApprovedEventSchema = z17.object({
1818
+ type: z17.literal("lock:approved"),
1819
+ payload: z17.object({
1820
+ locked: z17.array(humanLockEntrySchema),
1821
+ approved: z17.array(humanLockEntrySchema)
516
1822
  })
517
1823
  });
518
- var ledgerAppendedEventSchema = z8.object({
519
- type: z8.literal("ledger:appended"),
1824
+ var ledgerAppendedEventSchema = z17.object({
1825
+ type: z17.literal("ledger:appended"),
520
1826
  payload: ledgerEntrySchema
521
1827
  });
522
- var driftDetectedEventSchema = z8.object({
523
- type: z8.literal("drift:detected"),
1828
+ var driftDetectedEventSchema = z17.object({
1829
+ type: z17.literal("drift:detected"),
524
1830
  payload: forensicReportSchema
525
1831
  });
526
- var fabricEventSchema = z8.discriminatedUnion("type", [
1832
+ var fabricEventSchema = z17.discriminatedUnion("type", [
527
1833
  metaUpdatedEventSchema,
528
1834
  lockDriftEventSchema,
529
1835
  lockApprovedEventSchema,
@@ -532,271 +1838,541 @@ var fabricEventSchema = z8.discriminatedUnion("type", [
532
1838
  ]);
533
1839
 
534
1840
  // src/schemas/event-ledger.ts
535
- import { z as z9 } from "zod";
1841
+ import { z as z18 } from "zod";
1842
+
1843
+ // src/cite-line-parser.ts
1844
+ var ID_RE = /^K[TP]-[A-Z]+-\d+$/;
1845
+ var SENTINEL_RE = /^KB:\s*none\b\s*(?:\[[^\]]*\])?\s*$/i;
1846
+ var QUALIFIED_ID = String.raw`(?:[^\s,:]+:)?K[TP]-[A-Z]+-\d+`;
1847
+ var FULL_RE = new RegExp(
1848
+ String.raw`^KB:\s+(${QUALIFIED_ID}(?:\s*,\s*${QUALIFIED_ID})*)(?:\s+\(([^)]*)\))?(?:\s+\[([^\]]+)\])?(?:\s+→\s*(.+))?\s*$`
1849
+ );
1850
+ function splitStorePrefix(token) {
1851
+ const colon = token.lastIndexOf(":");
1852
+ return colon === -1 ? { store: null, id: token } : { store: token.slice(0, colon), id: token.slice(colon + 1) };
1853
+ }
1854
+ var CHAINED_FROM_ID_RE = /chained-from\s+(K[TP]-[A-Z]+-\d+)/i;
1855
+ var LEGACY_CITE_TAG_REMAP = {
1856
+ planned: "applied",
1857
+ recalled: "applied",
1858
+ "chained-from": "applied"
1859
+ };
1860
+ function normalizeCiteTag(rawTag) {
1861
+ const head = rawTag.trim().split(/[\s:]+/)[0].toLowerCase();
1862
+ if (head === "applied" || head === "dismissed" || head === "none") {
1863
+ return head;
1864
+ }
1865
+ return LEGACY_CITE_TAG_REMAP[head] ?? "none";
1866
+ }
1867
+ function parseTag(rawTag) {
1868
+ if (!rawTag) return "none";
1869
+ return normalizeCiteTag(rawTag);
1870
+ }
1871
+ function parseContractTail(tail) {
1872
+ const result = { operators: [], skip_reason: null };
1873
+ if (!tail) return result;
1874
+ const tokens = tail.trim().split(/\s+/).filter((t) => t.length > 0);
1875
+ for (const token of tokens) {
1876
+ const skipMatch = token.match(/^skip:(.+)$/i);
1877
+ if (skipMatch) {
1878
+ if (result.skip_reason === null) result.skip_reason = skipMatch[1];
1879
+ continue;
1880
+ }
1881
+ const notEditMatch = token.match(/^!edit:(.+)$/i);
1882
+ if (notEditMatch) {
1883
+ result.operators.push({ kind: "not_edit", target: notEditMatch[1] });
1884
+ continue;
1885
+ }
1886
+ const opMatch = token.match(/^(edit|require|forbid):(.+)$/i);
1887
+ if (opMatch) {
1888
+ result.operators.push({
1889
+ kind: opMatch[1].toLowerCase(),
1890
+ target: opMatch[2]
1891
+ });
1892
+ }
1893
+ }
1894
+ return result;
1895
+ }
1896
+ function parseLine(line) {
1897
+ const trimmed = line.trim();
1898
+ if (trimmed.length === 0) return null;
1899
+ if (SENTINEL_RE.test(trimmed)) {
1900
+ return { ids: [], stores: [], tag: "none", commitment: null };
1901
+ }
1902
+ const fullMatch = trimmed.match(FULL_RE);
1903
+ if (fullMatch) {
1904
+ const split = fullMatch[1].split(",").map((part) => part.trim()).filter((part) => part.length > 0).map(splitStorePrefix);
1905
+ if (split.some((entry) => !ID_RE.test(entry.id))) return null;
1906
+ const primaryIds = split.map((entry) => entry.id);
1907
+ const primaryStores = split.map((entry) => entry.store);
1908
+ const rawTag = fullMatch[3];
1909
+ const tag = parseTag(rawTag);
1910
+ const chainedIds = [];
1911
+ if (rawTag !== void 0) {
1912
+ const chained = CHAINED_FROM_ID_RE.exec(rawTag);
1913
+ if (chained !== null && ID_RE.test(chained[1])) {
1914
+ chainedIds.push(chained[1]);
1915
+ }
1916
+ }
1917
+ return {
1918
+ ids: [...primaryIds, ...chainedIds],
1919
+ // chained-from ids are never store-qualified → null per chained id.
1920
+ stores: [...primaryStores, ...chainedIds.map(() => null)],
1921
+ tag,
1922
+ commitment: parseContractTail(fullMatch[4])
1923
+ };
1924
+ }
1925
+ return null;
1926
+ }
1927
+ function parseCiteLine(raw) {
1928
+ const result = {
1929
+ cite_ids: [],
1930
+ cite_tags: [],
1931
+ cite_commitments: [],
1932
+ cite_stores: []
1933
+ };
1934
+ if (typeof raw !== "string") return result;
1935
+ for (const line of raw.split(/\r?\n/)) {
1936
+ const parsed = parseLine(line);
1937
+ if (!parsed) continue;
1938
+ result.cite_tags.push(parsed.tag);
1939
+ for (let i = 0; i < parsed.ids.length; i += 1) {
1940
+ result.cite_ids.push(parsed.ids[i]);
1941
+ result.cite_stores.push(parsed.stores[i] ?? null);
1942
+ }
1943
+ if (parsed.commitment !== null) {
1944
+ for (let i = 0; i < parsed.ids.length; i += 1) {
1945
+ result.cite_commitments.push(parsed.commitment);
1946
+ }
1947
+ }
1948
+ }
1949
+ return result;
1950
+ }
1951
+
1952
+ // src/schemas/event-ledger.ts
1953
+ var citeTagSchema = z18.preprocess(
1954
+ (value) => typeof value === "string" ? normalizeCiteTag(value) : value,
1955
+ z18.enum(["applied", "dismissed", "none"])
1956
+ );
536
1957
  var eventLedgerEnvelopeSchema = {
537
- kind: z9.literal("fabric-event"),
538
- id: z9.string(),
539
- ts: z9.number().int().nonnegative(),
540
- schema_version: z9.literal(1),
541
- correlation_id: z9.string().optional(),
542
- session_id: z9.string().optional()
1958
+ kind: z18.literal("fabric-event"),
1959
+ id: z18.string(),
1960
+ ts: z18.number().int().nonnegative(),
1961
+ schema_version: z18.literal(1),
1962
+ correlation_id: z18.string().optional(),
1963
+ session_id: z18.string().optional()
543
1964
  };
544
- var stringRecordSchema = z9.record(z9.string());
545
- var knowledgeContextPlannedEventSchema = z9.object({
546
- ...eventLedgerEnvelopeSchema,
547
- event_type: z9.literal("knowledge_context_planned"),
548
- target_paths: z9.array(z9.string()),
549
- required_stable_ids: z9.array(z9.string()),
550
- ai_selectable_stable_ids: z9.array(z9.string()),
551
- final_stable_ids: z9.array(z9.string()),
552
- selection_token: z9.string().optional(),
553
- client_hash: z9.string().optional(),
554
- intent: z9.string().optional(),
555
- known_tech: z9.array(z9.string()).optional(),
556
- diagnostics: z9.array(z9.unknown()).optional()
557
- });
558
- var knowledgeSelectionEventSchema = z9.object({
559
- ...eventLedgerEnvelopeSchema,
560
- event_type: z9.literal("knowledge_selection"),
561
- selection_token: z9.string(),
562
- target_paths: z9.array(z9.string()),
563
- required_stable_ids: z9.array(z9.string()),
564
- ai_selectable_stable_ids: z9.array(z9.string()),
565
- ai_selected_stable_ids: z9.array(z9.string()),
566
- final_stable_ids: z9.array(z9.string()),
1965
+ var stringRecordSchema = z18.record(z18.string());
1966
+ var knowledgeContextPlannedEventSchema = z18.object({
1967
+ ...eventLedgerEnvelopeSchema,
1968
+ event_type: z18.literal("knowledge_context_planned"),
1969
+ target_paths: z18.array(z18.string()),
1970
+ required_stable_ids: z18.array(z18.string()),
1971
+ ai_selectable_stable_ids: z18.array(z18.string()),
1972
+ final_stable_ids: z18.array(z18.string()),
1973
+ selection_token: z18.string().optional(),
1974
+ client_hash: z18.string().optional(),
1975
+ intent: z18.string().optional(),
1976
+ known_tech: z18.array(z18.string()).optional(),
1977
+ diagnostics: z18.array(z18.unknown()).optional()
1978
+ });
1979
+ var knowledgeSelectionEventSchema = z18.object({
1980
+ ...eventLedgerEnvelopeSchema,
1981
+ event_type: z18.literal("knowledge_selection"),
1982
+ selection_token: z18.string(),
1983
+ target_paths: z18.array(z18.string()),
1984
+ required_stable_ids: z18.array(z18.string()),
1985
+ ai_selectable_stable_ids: z18.array(z18.string()),
1986
+ ai_selected_stable_ids: z18.array(z18.string()),
1987
+ final_stable_ids: z18.array(z18.string()),
567
1988
  ai_selection_reasons: stringRecordSchema,
568
- rejected_stable_ids: z9.array(z9.string()),
569
- ignored_stable_ids: z9.array(z9.string())
570
- });
571
- var knowledgeSectionsFetchedEventSchema = z9.object({
572
- ...eventLedgerEnvelopeSchema,
573
- event_type: z9.literal("knowledge_sections_fetched"),
574
- selection_token: z9.string(),
575
- target_paths: z9.array(z9.string()).optional(),
576
- requested_sections: z9.array(z9.string()),
577
- final_stable_ids: z9.array(z9.string()),
578
- ai_selected_stable_ids: z9.array(z9.string()),
579
- diagnostics: z9.array(z9.unknown()).optional()
580
- });
581
- var editIntentCheckedEventSchema = z9.object({
582
- ...eventLedgerEnvelopeSchema,
583
- event_type: z9.literal("edit_intent_checked"),
584
- path: z9.string(),
585
- compliant: z9.boolean(),
586
- intent: z9.string(),
587
- ledger_entry_id: z9.string(),
588
- ledger_source: z9.enum(["ai", "human"]).optional(),
589
- commit_sha: z9.string().optional(),
590
- parent_sha: z9.string().optional(),
591
- parent_ledger_entry_id: z9.string().optional(),
592
- diff_stat: z9.string().optional(),
593
- annotation: z9.string().optional(),
594
- matched_rule_context_ts: z9.number().int().nonnegative().nullable(),
595
- window_ms: z9.number().int().nonnegative()
596
- });
597
- var knowledgeDriftDetectedEventSchema = z9.object({
598
- ...eventLedgerEnvelopeSchema,
599
- event_type: z9.literal("knowledge_drift_detected"),
600
- revision: z9.string().optional(),
601
- drifted_stable_ids: z9.array(z9.string()),
602
- missing_files: z9.array(z9.string()),
603
- stale_files: z9.array(z9.string()),
604
- details: z9.array(
605
- z9.object({
606
- file: z9.string(),
607
- stable_id: z9.string(),
608
- expected_hash: z9.string(),
609
- actual_hash: z9.string().nullable()
1989
+ rejected_stable_ids: z18.array(z18.string()),
1990
+ ignored_stable_ids: z18.array(z18.string())
1991
+ });
1992
+ var knowledgeSectionsFetchedEventSchema = z18.object({
1993
+ ...eventLedgerEnvelopeSchema,
1994
+ event_type: z18.literal("knowledge_sections_fetched"),
1995
+ selection_token: z18.string(),
1996
+ target_paths: z18.array(z18.string()).optional(),
1997
+ requested_sections: z18.array(z18.string()),
1998
+ final_stable_ids: z18.array(z18.string()),
1999
+ ai_selected_stable_ids: z18.array(z18.string()),
2000
+ diagnostics: z18.array(z18.unknown()).optional()
2001
+ });
2002
+ var editIntentCheckedEventSchema = z18.object({
2003
+ ...eventLedgerEnvelopeSchema,
2004
+ event_type: z18.literal("edit_intent_checked"),
2005
+ path: z18.string(),
2006
+ compliant: z18.boolean(),
2007
+ intent: z18.string(),
2008
+ ledger_entry_id: z18.string(),
2009
+ // rc.35 TASK-07 (P0-2): add "hook" — emitted by the PreToolUse narrow hook
2010
+ // for every Edit/Write/MultiEdit fire so cite-coverage doctor metrics see
2011
+ // actual edit signals (previously editsTouched was permanently 0 because
2012
+ // no production caller of appendLedgerEntry existed).
2013
+ ledger_source: z18.enum(["ai", "human", "hook"]).optional(),
2014
+ commit_sha: z18.string().optional(),
2015
+ parent_sha: z18.string().optional(),
2016
+ parent_ledger_entry_id: z18.string().optional(),
2017
+ diff_stat: z18.string().optional(),
2018
+ annotation: z18.string().optional(),
2019
+ matched_rule_context_ts: z18.number().int().nonnegative().nullable(),
2020
+ window_ms: z18.number().int().nonnegative()
2021
+ });
2022
+ var knowledgeDriftDetectedEventSchema = z18.object({
2023
+ ...eventLedgerEnvelopeSchema,
2024
+ event_type: z18.literal("knowledge_drift_detected"),
2025
+ revision: z18.string().optional(),
2026
+ drifted_stable_ids: z18.array(z18.string()),
2027
+ missing_files: z18.array(z18.string()),
2028
+ stale_files: z18.array(z18.string()),
2029
+ details: z18.array(
2030
+ z18.object({
2031
+ file: z18.string(),
2032
+ stable_id: z18.string(),
2033
+ expected_hash: z18.string(),
2034
+ actual_hash: z18.string().nullable()
610
2035
  })
611
2036
  ).optional()
612
2037
  });
613
- var mcpEventLedgerEventSchema = z9.object({
2038
+ var mcpEventLedgerEventSchema = z18.object({
2039
+ ...eventLedgerEnvelopeSchema,
2040
+ event_type: z18.literal("mcp_event"),
2041
+ mcp_event_id: z18.string(),
2042
+ stream_id: z18.string(),
2043
+ message: z18.unknown()
2044
+ });
2045
+ var reapplyCompletedEventSchema = z18.object({
2046
+ ...eventLedgerEnvelopeSchema,
2047
+ event_type: z18.literal("reapply_completed"),
2048
+ preserved_ledger: z18.boolean(),
2049
+ preserved_meta: z18.boolean(),
2050
+ rules_count: z18.number().int().nonnegative()
2051
+ });
2052
+ var installDiffAppliedEventSchema = z18.object({
614
2053
  ...eventLedgerEnvelopeSchema,
615
- event_type: z9.literal("mcp_event"),
616
- mcp_event_id: z9.string(),
617
- stream_id: z9.string(),
618
- message: z9.unknown()
2054
+ event_type: z18.literal("install_diff_applied"),
2055
+ applied: z18.array(z18.string()),
2056
+ canonical: z18.array(z18.string()),
2057
+ drifted: z18.array(z18.string())
619
2058
  });
620
- var reapplyCompletedEventSchema = z9.object({
2059
+ var eventLedgerTruncatedEventSchema = z18.object({
621
2060
  ...eventLedgerEnvelopeSchema,
622
- event_type: z9.literal("reapply_completed"),
623
- preserved_ledger: z9.boolean(),
624
- preserved_meta: z9.boolean(),
625
- rules_count: z9.number().int().nonnegative()
2061
+ event_type: z18.literal("event_ledger_truncated"),
2062
+ byte_offset: z18.number().int().nonnegative(),
2063
+ byte_length: z18.number().int().nonnegative(),
2064
+ corrupted_path: z18.string()
626
2065
  });
627
- var eventLedgerTruncatedEventSchema = z9.object({
2066
+ var mcpConfigMigratedEventSchema = z18.object({
628
2067
  ...eventLedgerEnvelopeSchema,
629
- event_type: z9.literal("event_ledger_truncated"),
630
- byte_offset: z9.number().int().nonnegative(),
631
- byte_length: z9.number().int().nonnegative(),
632
- corrupted_path: z9.string()
2068
+ event_type: z18.literal("mcp_config_migrated"),
2069
+ source: z18.literal("doctor_fix"),
2070
+ removed_from: z18.string()
633
2071
  });
634
- var mcpConfigMigratedEventSchema = z9.object({
2072
+ var bootstrapMarkerMigratedEventSchema = z18.object({
635
2073
  ...eventLedgerEnvelopeSchema,
636
- event_type: z9.literal("mcp_config_migrated"),
637
- source: z9.literal("doctor_fix"),
638
- removed_from: z9.string()
2074
+ event_type: z18.literal("bootstrap_marker_migrated"),
2075
+ path: z18.string(),
2076
+ migrated_count: z18.number().int().nonnegative(),
2077
+ legacy_marker: z18.literal("fabric:knowledge-base"),
2078
+ new_marker: z18.literal("fabric:bootstrap"),
2079
+ timestamp: z18.string()
639
2080
  });
640
- var metaReconciledOnStartupEventSchema = z9.object({
2081
+ var metaReconciledOnStartupEventSchema = z18.object({
641
2082
  ...eventLedgerEnvelopeSchema,
642
- event_type: z9.literal("meta_reconciled_on_startup"),
643
- reconciled_files: z9.array(z9.string()),
644
- duration_ms: z9.number().int().nonnegative(),
645
- source: z9.literal("reconcileKnowledge")
2083
+ event_type: z18.literal("meta_reconciled_on_startup"),
2084
+ reconciled_files: z18.array(z18.string()),
2085
+ duration_ms: z18.number().int().nonnegative(),
2086
+ source: z18.literal("reconcileKnowledge")
646
2087
  });
647
- var metaReconciledEventSchema = z9.object({
2088
+ var metaReconciledEventSchema = z18.object({
648
2089
  ...eventLedgerEnvelopeSchema,
649
- event_type: z9.literal("meta_reconciled"),
650
- reconciled_files: z9.array(z9.string()),
651
- duration_ms: z9.number().int().nonnegative(),
652
- trigger: z9.enum(["doctor", "manual"]),
653
- source: z9.literal("reconcileKnowledge")
2090
+ event_type: z18.literal("meta_reconciled"),
2091
+ reconciled_files: z18.array(z18.string()),
2092
+ duration_ms: z18.number().int().nonnegative(),
2093
+ // v2.0.0-rc.23 TASK-005 (a-B): added `auto-heal-description` trigger so the
2094
+ // read-path plan_context handler can drive a full reconcile when it detects
2095
+ // any node carrying `description === undefined` (legacy meta drift that the
2096
+ // revision-hash gate cannot catch — a missing description doesn't move the
2097
+ // revision). Symmetric to rc.22 D2 read-side auto-heal but covers the
2098
+ // description-undefined case which the revision drift gate misses.
2099
+ // v2.0.0-rc.27 TASK-001 (§2.9): `post-approve` / `post-modify` added so
2100
+ // `fab_review` write-actions can flush newly-promoted entries into
2101
+ // `agents.meta.json.nodes[id]` synchronously — without this the new entry
2102
+ // remains description-less until the next plan_context auto-heal.
2103
+ // v2.0.0-rc.29 TASK-005 (BUG-G1): `auto-heal-after-drift` added so
2104
+ // `ensureKnowledgeFresh` hot-path can chain a paired reconcile (closing the
2105
+ // drift→heal gap) when the caller opts in via `autoHealOnDrift: true`.
2106
+ trigger: z18.enum([
2107
+ "doctor",
2108
+ "manual",
2109
+ "auto-heal-description",
2110
+ "auto-heal-after-drift",
2111
+ "post-approve",
2112
+ "post-modify"
2113
+ ]),
2114
+ source: z18.literal("reconcileKnowledge"),
2115
+ // v2.0.0-rc.22 TASK-014 (Scope E): set when reconcileKnowledge forced a
2116
+ // writeKnowledgeMeta on revision drift alone (no per-file content drift).
2117
+ // Distinguishes top-level schema/revision repair from the standard per-file
2118
+ // drift path. Optional so existing emitters stay unchanged.
2119
+ force_write_reason: z18.enum(["revision_drift"]).optional()
654
2120
  });
655
- var claudeSkillPathMigratedEventSchema = z9.object({
2121
+ var claudeSkillPathMigratedEventSchema = z18.object({
656
2122
  ...eventLedgerEnvelopeSchema,
657
- event_type: z9.literal("claude_skill_path_migrated"),
658
- from: z9.string(),
659
- to: z9.string()
2123
+ event_type: z18.literal("claude_skill_path_migrated"),
2124
+ from: z18.string(),
2125
+ to: z18.string()
660
2126
  });
661
- var claudeHookPathMigratedEventSchema = z9.object({
2127
+ var claudeHookPathMigratedEventSchema = z18.object({
662
2128
  ...eventLedgerEnvelopeSchema,
663
- event_type: z9.literal("claude_hook_path_migrated"),
664
- from: z9.string(),
665
- to: z9.string()
2129
+ event_type: z18.literal("claude_hook_path_migrated"),
2130
+ from: z18.string(),
2131
+ to: z18.string()
666
2132
  });
667
- var codexSkillPathMigratedEventSchema = z9.object({
2133
+ var codexSkillPathMigratedEventSchema = z18.object({
668
2134
  ...eventLedgerEnvelopeSchema,
669
- event_type: z9.literal("codex_skill_path_migrated"),
670
- from: z9.string(),
671
- to: z9.string()
2135
+ event_type: z18.literal("codex_skill_path_migrated"),
2136
+ from: z18.string(),
2137
+ to: z18.string()
672
2138
  });
673
- var initScanCompletedEventSchema = z9.object({
2139
+ var initScanCompletedEventSchema = z18.object({
674
2140
  ...eventLedgerEnvelopeSchema,
675
- event_type: z9.literal("init_scan_completed"),
676
- written_stable_ids: z9.array(z9.string()),
677
- duration_ms: z9.number().int().nonnegative(),
678
- source: z9.enum(["init", "scan", "doctor_fix"]).optional()
2141
+ event_type: z18.literal("init_scan_completed"),
2142
+ written_stable_ids: z18.array(z18.string()),
2143
+ duration_ms: z18.number().int().nonnegative(),
2144
+ source: z18.enum(["init", "scan", "doctor_fix", "doctor-rescan"]).optional()
679
2145
  });
680
- var knowledgeProposedEventSchema = z9.object({
2146
+ var knowledgeProposedEventSchema = z18.object({
681
2147
  ...eventLedgerEnvelopeSchema,
682
- event_type: z9.literal("knowledge_proposed"),
683
- stable_id: z9.string().optional(),
684
- timestamp: z9.string().datetime(),
685
- reason: z9.string().optional()
2148
+ event_type: z18.literal("knowledge_proposed"),
2149
+ stable_id: z18.string().optional(),
2150
+ timestamp: z18.string().datetime(),
2151
+ reason: z18.string().optional()
686
2152
  });
687
- var knowledgePromoteStartedEventSchema = z9.object({
2153
+ var knowledgePromoteStartedEventSchema = z18.object({
688
2154
  ...eventLedgerEnvelopeSchema,
689
- event_type: z9.literal("knowledge_promote_started"),
690
- stable_id: z9.string().optional(),
691
- timestamp: z9.string().datetime(),
692
- reason: z9.string().optional()
2155
+ event_type: z18.literal("knowledge_promote_started"),
2156
+ stable_id: z18.string().optional(),
2157
+ timestamp: z18.string().datetime(),
2158
+ reason: z18.string().optional()
693
2159
  });
694
- var knowledgePromotedEventSchema = z9.object({
2160
+ var knowledgePromotedEventSchema = z18.object({
695
2161
  ...eventLedgerEnvelopeSchema,
696
- event_type: z9.literal("knowledge_promoted"),
697
- stable_id: z9.string().optional(),
698
- timestamp: z9.string().datetime(),
699
- reason: z9.string().optional()
2162
+ event_type: z18.literal("knowledge_promoted"),
2163
+ stable_id: z18.string().optional(),
2164
+ timestamp: z18.string().datetime(),
2165
+ reason: z18.string().optional()
700
2166
  });
701
- var knowledgePromoteFailedEventSchema = z9.object({
2167
+ var knowledgePromoteFailedEventSchema = z18.object({
702
2168
  ...eventLedgerEnvelopeSchema,
703
- event_type: z9.literal("knowledge_promote_failed"),
704
- stable_id: z9.string().optional(),
705
- timestamp: z9.string().datetime(),
706
- reason: z9.string()
2169
+ event_type: z18.literal("knowledge_promote_failed"),
2170
+ stable_id: z18.string().optional(),
2171
+ timestamp: z18.string().datetime(),
2172
+ reason: z18.string()
707
2173
  });
708
- var knowledgeLayerChangedEventSchema = z9.object({
2174
+ var knowledgeLayerChangedEventSchema = z18.object({
709
2175
  ...eventLedgerEnvelopeSchema,
710
- event_type: z9.literal("knowledge_layer_changed"),
711
- stable_id: z9.string().optional(),
712
- timestamp: z9.string().datetime(),
713
- reason: z9.string().optional(),
714
- from_layer: z9.enum(["team", "personal"]),
715
- to_layer: z9.enum(["team", "personal"])
2176
+ event_type: z18.literal("knowledge_layer_changed"),
2177
+ stable_id: z18.string().optional(),
2178
+ timestamp: z18.string().datetime(),
2179
+ reason: z18.string().optional(),
2180
+ from_layer: z18.enum(["team", "personal"]),
2181
+ to_layer: z18.enum(["team", "personal"]),
2182
+ // v2.0.0-rc.37 NEW-24: record the pre-flip stable_id so downstream consumers
2183
+ // (fab_plan_context redirect surface, fab_get_knowledge_sections.redirect_to)
2184
+ // can map a stale caller-held id back to the post-flip canonical id without
2185
+ // requiring the caller to re-issue plan-context. Optional for forward-
2186
+ // compatibility with rc ≤36 events that never carried this field.
2187
+ previous_stable_id: z18.string().optional()
716
2188
  });
717
- var knowledgeSlugRenamedEventSchema = z9.object({
2189
+ var knowledgeIdRedirectEventSchema = z18.object({
718
2190
  ...eventLedgerEnvelopeSchema,
719
- event_type: z9.literal("knowledge_slug_renamed"),
720
- stable_id: z9.string().optional(),
721
- timestamp: z9.string().datetime(),
722
- reason: z9.string().optional(),
723
- from_slug: z9.string(),
724
- to_slug: z9.string()
2191
+ event_type: z18.literal("knowledge_id_redirect"),
2192
+ timestamp: z18.string().datetime(),
2193
+ previous_stable_id: z18.string(),
2194
+ new_stable_id: z18.string(),
2195
+ reason: z18.string().optional()
725
2196
  });
726
- var knowledgeDemotedEventSchema = z9.object({
2197
+ var knowledgeSlugRenamedEventSchema = z18.object({
727
2198
  ...eventLedgerEnvelopeSchema,
728
- event_type: z9.literal("knowledge_demoted"),
729
- stable_id: z9.string().optional(),
730
- timestamp: z9.string().datetime(),
731
- reason: z9.string().optional()
2199
+ event_type: z18.literal("knowledge_slug_renamed"),
2200
+ stable_id: z18.string().optional(),
2201
+ timestamp: z18.string().datetime(),
2202
+ reason: z18.string().optional(),
2203
+ from_slug: z18.string(),
2204
+ to_slug: z18.string()
732
2205
  });
733
- var knowledgeArchivedEventSchema = z9.object({
2206
+ var knowledgeDemotedEventSchema = z18.object({
734
2207
  ...eventLedgerEnvelopeSchema,
735
- event_type: z9.literal("knowledge_archived"),
736
- stable_id: z9.string().optional(),
737
- timestamp: z9.string().datetime(),
738
- reason: z9.string().optional()
2208
+ event_type: z18.literal("knowledge_demoted"),
2209
+ stable_id: z18.string().optional(),
2210
+ timestamp: z18.string().datetime(),
2211
+ reason: z18.string().optional()
739
2212
  });
740
- var knowledgeArchiveAttemptedEventSchema = z9.object({
2213
+ var knowledgeArchivedEventSchema = z18.object({
741
2214
  ...eventLedgerEnvelopeSchema,
742
- event_type: z9.literal("knowledge_archive_attempted"),
743
- stable_id: z9.string().optional(),
744
- timestamp: z9.string().datetime(),
745
- reason: z9.string().optional()
2215
+ event_type: z18.literal("knowledge_archived"),
2216
+ stable_id: z18.string().optional(),
2217
+ timestamp: z18.string().datetime(),
2218
+ reason: z18.string().optional()
746
2219
  });
747
- var knowledgeDeferredEventSchema = z9.object({
2220
+ var knowledgeArchiveAttemptedEventSchema = z18.object({
748
2221
  ...eventLedgerEnvelopeSchema,
749
- event_type: z9.literal("knowledge_deferred"),
750
- stable_id: z9.string().optional(),
751
- timestamp: z9.string().datetime(),
752
- reason: z9.string().optional(),
753
- until: z9.string().datetime().optional()
2222
+ event_type: z18.literal("knowledge_archive_attempted"),
2223
+ stable_id: z18.string().optional(),
2224
+ timestamp: z18.string().datetime(),
2225
+ reason: z18.string().optional()
754
2226
  });
755
- var knowledgeRejectedEventSchema = z9.object({
2227
+ var knowledgeUnarchivedEventSchema = z18.object({
756
2228
  ...eventLedgerEnvelopeSchema,
757
- event_type: z9.literal("knowledge_rejected"),
758
- stable_id: z9.string().optional(),
759
- timestamp: z9.string().datetime(),
760
- reason: z9.string()
2229
+ event_type: z18.literal("knowledge_unarchived"),
2230
+ stable_id: z18.string().optional(),
2231
+ timestamp: z18.string().datetime(),
2232
+ reason: z18.string().optional(),
2233
+ // Pre-move archive path (e.g. ".fabric/.archive/decisions/KT-D-0007--single-cjs-hook.md").
2234
+ archive_path: z18.string().optional(),
2235
+ // Post-move canonical path (e.g. ".fabric/knowledge/team/decisions/KT-D-0007--single-cjs-hook.md").
2236
+ restored_to: z18.string().optional()
761
2237
  });
762
- var knowledgeConsumedEventSchema = z9.object({
2238
+ var knowledgeDeferredEventSchema = z18.object({
763
2239
  ...eventLedgerEnvelopeSchema,
764
- event_type: z9.literal("knowledge_consumed"),
765
- stable_id: z9.string(),
766
- consumed_at: z9.string().datetime(),
767
- client_hash: z9.string()
2240
+ event_type: z18.literal("knowledge_deferred"),
2241
+ stable_id: z18.string().optional(),
2242
+ timestamp: z18.string().datetime(),
2243
+ reason: z18.string().optional(),
2244
+ until: z18.string().datetime().optional()
768
2245
  });
769
- var knowledgeScopeDegradedEventSchema = z9.object({
2246
+ var knowledgeRejectedEventSchema = z18.object({
770
2247
  ...eventLedgerEnvelopeSchema,
771
- event_type: z9.literal("knowledge_scope_degraded"),
772
- stable_id: z9.string(),
773
- timestamp: z9.string().datetime(),
774
- from_scope: z9.enum(["narrow", "broad"]),
775
- to_scope: z9.enum(["narrow", "broad"]),
776
- reason: z9.string()
2248
+ event_type: z18.literal("knowledge_rejected"),
2249
+ stable_id: z18.string().optional(),
2250
+ timestamp: z18.string().datetime(),
2251
+ reason: z18.string()
777
2252
  });
778
- var doctorRunEventSchema = z9.object({
2253
+ var knowledgeConsumedEventSchema = z18.object({
779
2254
  ...eventLedgerEnvelopeSchema,
780
- event_type: z9.literal("doctor_run"),
781
- mode: z9.enum(["lint", "apply-lint"]),
782
- issues: z9.number().int().nonnegative(),
783
- mutations: z9.number().int().nonnegative().optional(),
784
- timestamp: z9.string().datetime()
2255
+ event_type: z18.literal("knowledge_consumed"),
2256
+ stable_id: z18.string(),
2257
+ consumed_at: z18.string().datetime(),
2258
+ client_hash: z18.string()
785
2259
  });
786
- var knowledgePathDangledEventSchema = z9.object({
2260
+ var knowledgeScopeDegradedEventSchema = z18.object({
787
2261
  ...eventLedgerEnvelopeSchema,
788
- event_type: z9.literal("knowledge_path_dangled"),
789
- stable_id: z9.string(),
790
- removed_glob: z9.string()
2262
+ event_type: z18.literal("knowledge_scope_degraded"),
2263
+ stable_id: z18.string(),
2264
+ timestamp: z18.string().datetime(),
2265
+ from_scope: z18.enum(["narrow", "broad"]),
2266
+ to_scope: z18.enum(["narrow", "broad"]),
2267
+ reason: z18.string()
791
2268
  });
792
- var pendingAutoArchivedEventSchema = z9.object({
2269
+ var doctorRunEventSchema = z18.object({
793
2270
  ...eventLedgerEnvelopeSchema,
794
- event_type: z9.literal("pending_auto_archived"),
795
- pending_path: z9.string(),
796
- archived_to: z9.string(),
797
- reason: z9.string()
2271
+ event_type: z18.literal("doctor_run"),
2272
+ mode: z18.enum(["lint", "fix-knowledge"]),
2273
+ issues: z18.number().int().nonnegative(),
2274
+ mutations: z18.number().int().nonnegative().optional(),
2275
+ timestamp: z18.string().datetime()
798
2276
  });
799
- var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
2277
+ var knowledgePathDangledEventSchema = z18.object({
2278
+ ...eventLedgerEnvelopeSchema,
2279
+ event_type: z18.literal("knowledge_path_dangled"),
2280
+ stable_id: z18.string(),
2281
+ removed_glob: z18.string()
2282
+ });
2283
+ var relevanceMigrationRunEventSchema = z18.object({
2284
+ ...eventLedgerEnvelopeSchema,
2285
+ event_type: z18.literal("relevance_migration_run"),
2286
+ timestamp: z18.string().datetime(),
2287
+ scanned_count: z18.number().int().nonnegative(),
2288
+ touched_count: z18.number().int().nonnegative()
2289
+ });
2290
+ var pendingAutoArchivedEventSchema = z18.object({
2291
+ ...eventLedgerEnvelopeSchema,
2292
+ event_type: z18.literal("pending_auto_archived"),
2293
+ pending_path: z18.string(),
2294
+ archived_to: z18.string(),
2295
+ reason: z18.string()
2296
+ });
2297
+ var assistantTurnObservedEventSchema = z18.object({
2298
+ ...eventLedgerEnvelopeSchema,
2299
+ event_type: z18.literal("assistant_turn_observed"),
2300
+ kb_line_raw: z18.string().nullable(),
2301
+ cite_ids: z18.array(z18.string()).default([]),
2302
+ cite_tags: z18.array(citeTagSchema).default([]),
2303
+ // v2.0.0-rc.24 TASK-01: per-cite contract commitments. Index-aligned with
2304
+ // cite_ids/cite_tags (commitments[i] belongs to cite_ids[i]). Each slot
2305
+ // carries `operators[]` (kind + glob target) or `skip_reason` when the cite
2306
+ // cannot be operator-ized. Old rc.20-rc.23 events naturally parse with an
2307
+ // empty array via `.default([])` and are excluded from contract-policy
2308
+ // audits by the marker-gate (see cite_contract_policy_activated below).
2309
+ // Mirrors the rc.20 cite_tags parallel-array evolution exactly.
2310
+ cite_commitments: z18.array(
2311
+ z18.object({
2312
+ operators: z18.array(
2313
+ z18.object({
2314
+ kind: z18.enum(["edit", "not_edit", "require", "forbid"]),
2315
+ target: z18.string()
2316
+ })
2317
+ ),
2318
+ skip_reason: z18.string().nullable()
2319
+ })
2320
+ ).default([]),
2321
+ client: z18.enum(["cc", "codex", "cursor"]).optional(),
2322
+ turn_id: z18.string(),
2323
+ envelope_index: z18.number().int().nonnegative().optional(),
2324
+ timestamp: z18.string().datetime()
2325
+ });
2326
+ var citePolicyActivatedEventSchema = z18.object({
2327
+ ...eventLedgerEnvelopeSchema,
2328
+ event_type: z18.literal("cite_policy_activated"),
2329
+ policy_version: z18.string(),
2330
+ timestamp: z18.string().datetime()
2331
+ });
2332
+ var citeContractPolicyActivatedEventSchema = z18.object({
2333
+ ...eventLedgerEnvelopeSchema,
2334
+ event_type: z18.literal("cite_contract_policy_activated")
2335
+ });
2336
+ var eventsRotatedEventSchema = z18.object({
2337
+ ...eventLedgerEnvelopeSchema,
2338
+ event_type: z18.literal("events_rotated"),
2339
+ cutoff_ts: z18.string().datetime(),
2340
+ archived_count: z18.number().int().nonnegative(),
2341
+ kept_count: z18.number().int().nonnegative(),
2342
+ archive_path: z18.string()
2343
+ });
2344
+ var knowledgeMetaAutoHealedEventSchema = z18.object({
2345
+ ...eventLedgerEnvelopeSchema,
2346
+ event_type: z18.literal("knowledge_meta_auto_healed"),
2347
+ previous_revision_hash: z18.string(),
2348
+ revision_hash: z18.string(),
2349
+ trigger: z18.literal("read"),
2350
+ caller: z18.enum(["planContext", "getKnowledgeSections", "getKnowledge", "extractKnowledge"]).optional()
2351
+ });
2352
+ var serveLockClearedEventSchema = z18.object({
2353
+ ...eventLedgerEnvelopeSchema,
2354
+ event_type: z18.literal("serve_lock_cleared"),
2355
+ pid: z18.number().int().nonnegative(),
2356
+ age_ms: z18.number().int().nonnegative(),
2357
+ timestamp: z18.string().datetime()
2358
+ });
2359
+ var knowledgeEnrichedEventSchema = z18.object({
2360
+ ...eventLedgerEnvelopeSchema,
2361
+ event_type: z18.literal("knowledge_enriched"),
2362
+ path: z18.string(),
2363
+ added_fields: z18.array(z18.enum(["intent_clues", "tech_stack", "impact", "must_read_if"])),
2364
+ mode: z18.enum(["auto", "preview", "readonly", "interactive"]),
2365
+ timestamp: z18.string().datetime()
2366
+ });
2367
+ var sessionArchiveAttemptedEventSchema = z18.object({
2368
+ ...eventLedgerEnvelopeSchema,
2369
+ event_type: z18.literal("session_archive_attempted"),
2370
+ outcome: z18.enum(["proposed", "viability_failed", "user_dismissed", "skipped_no_signal"]),
2371
+ covered_through_ts: z18.number().int().nonnegative(),
2372
+ candidates_proposed: z18.number().int().nonnegative().default(0),
2373
+ knowledge_proposed_ids: z18.array(z18.string()).default([])
2374
+ });
2375
+ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
800
2376
  knowledgeContextPlannedEventSchema,
801
2377
  knowledgeSelectionEventSchema,
802
2378
  knowledgeSectionsFetchedEventSchema,
@@ -804,8 +2380,12 @@ var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
804
2380
  knowledgeDriftDetectedEventSchema,
805
2381
  mcpEventLedgerEventSchema,
806
2382
  reapplyCompletedEventSchema,
2383
+ installDiffAppliedEventSchema,
807
2384
  eventLedgerTruncatedEventSchema,
808
2385
  mcpConfigMigratedEventSchema,
2386
+ // v2.0.0-rc.19 TASK-004: bootstrap_marker_migrated — one-time fabric:knowledge-base
2387
+ // → fabric:bootstrap marker rewrite emitted per file by `fabric doctor --fix`.
2388
+ bootstrapMarkerMigratedEventSchema,
809
2389
  metaReconciledOnStartupEventSchema,
810
2390
  metaReconciledEventSchema,
811
2391
  claudeSkillPathMigratedEventSchema,
@@ -818,10 +2398,14 @@ var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
818
2398
  knowledgePromotedEventSchema,
819
2399
  knowledgePromoteFailedEventSchema,
820
2400
  knowledgeLayerChangedEventSchema,
2401
+ // v2.0.0-rc.37 NEW-24: dedicated old→new stable_id mapping event
2402
+ knowledgeIdRedirectEventSchema,
821
2403
  knowledgeSlugRenamedEventSchema,
822
2404
  knowledgeDemotedEventSchema,
823
2405
  knowledgeArchivedEventSchema,
824
2406
  knowledgeArchiveAttemptedEventSchema,
2407
+ // v2.0.0-rc.34 TASK-05: reverse of knowledge_archived
2408
+ knowledgeUnarchivedEventSchema,
825
2409
  knowledgeDeferredEventSchema,
826
2410
  knowledgeRejectedEventSchema,
827
2411
  // v2.0 rc.5 TASK-014: knowledge_consumed (consumption tracking)
@@ -835,42 +2419,127 @@ var eventLedgerEventSchema = z9.discriminatedUnion("event_type", [
835
2419
  // #24 when a glob in relevance_paths resolves to zero filesystem matches.
836
2420
  knowledgePathDangledEventSchema,
837
2421
  // v2.0.0-rc.7 T10: doctor_run — emitted by `fabric doctor` to drive Signal D.
838
- doctorRunEventSchema
2422
+ doctorRunEventSchema,
2423
+ // v2.0.0-rc.9 TASK-003 (A3): relevance_migration_run — emitted by
2424
+ // `doctor --apply-lint` after the lint #26 frontmatter back-fill pass.
2425
+ relevanceMigrationRunEventSchema,
2426
+ // v2.0.0-rc.20 TASK-02: assistant_turn_observed — per-turn cite-policy
2427
+ // observation (raw KB: line text + parsed cite_ids/cite_tags + client).
2428
+ assistantTurnObservedEventSchema,
2429
+ // v2.0.0-rc.20 TASK-02: cite_policy_activated — session/policy-bump
2430
+ // marker recording when a given policy_version became active.
2431
+ citePolicyActivatedEventSchema,
2432
+ // v2.0.0-rc.24 TASK-01: cite_contract_policy_activated — drift-gated
2433
+ // idempotent marker opening the contract-policy audit window. Distinct
2434
+ // from cite_policy_activated so contract metrics get their own window.
2435
+ citeContractPolicyActivatedEventSchema,
2436
+ // v2.0.0-rc.22 Scope D T-D1: knowledge_meta_auto_healed — emitted by
2437
+ // loadActiveMeta when read-path drift triggers an in-place meta rebuild.
2438
+ knowledgeMetaAutoHealedEventSchema,
2439
+ // v2.0.0-rc.22 Scope A T3: events_rotated — emitted as the first line of
2440
+ // the post-rotation events.jsonl when sliding-window-by-age rotation moves
2441
+ // stale entries to events.archive/events-rotated-YYYY-MM-DD.jsonl.
2442
+ eventsRotatedEventSchema,
2443
+ // v2.0.0-rc.23 TASK-010 (e): serve_lock_cleared — emitted by
2444
+ // `fabric doctor --fix` when a stale `.fabric/.serve.lock` with a dead PID is
2445
+ // unlinked.
2446
+ serveLockClearedEventSchema,
2447
+ // v2.0.0-rc.23 TASK-007 (a-C2): knowledge_enriched — emitted by
2448
+ // `fabric doctor --enrich-descriptions` once per modified canonical knowledge
2449
+ // file when one or more of the four rc.23 description-grade frontmatter
2450
+ // fields is back-filled.
2451
+ knowledgeEnrichedEventSchema,
2452
+ // v2.0.0-rc.25 TASK-01: session_archive_attempted — emitted by the
2453
+ // fabric-archive skill at the end of every invocation. Drives Phase 0.0
2454
+ // cross-session digest, outcome-based rescan filter (skips user_dismissed),
2455
+ // covered_through_ts watermark, and `fabric doctor --archive-history`.
2456
+ sessionArchiveAttemptedEventSchema
839
2457
  ]);
840
2458
  export {
841
2459
  AGENTS_META_IDENTITY_SOURCES,
842
2460
  AGENTS_META_LAYERS,
843
2461
  AGENTS_META_TOPOLOGY_TYPES,
844
2462
  AgentsMetaCountersSchema,
2463
+ BOOTSTRAP_CANONICAL,
2464
+ BOOTSTRAP_MARKER_BEGIN,
2465
+ BOOTSTRAP_MARKER_END,
2466
+ BOOTSTRAP_REGEX,
845
2467
  FabExtractKnowledgeInputSchema,
846
2468
  FabExtractKnowledgeInputShape,
847
2469
  FabExtractKnowledgeOutputSchema,
848
2470
  FabReviewInputSchema,
2471
+ FabReviewInputShape,
849
2472
  FabReviewOutputSchema,
2473
+ FabReviewOutputShape,
2474
+ GLOBAL_BINDINGS_DIR,
2475
+ GLOBAL_REF_PATTERN,
2476
+ GLOBAL_STATE_DIR,
850
2477
  KNOWLEDGE_TEST_INDEX_SCHEMA_VERSION,
851
2478
  KNOWLEDGE_TYPE_CODES,
2479
+ KNOWN_SCOPE_PREFIXES,
852
2480
  KnowledgeEntryFrontmatterSchema,
853
2481
  KnowledgeTypeSchema,
2482
+ LEGACY_KB_MARKER_BEGIN,
2483
+ LEGACY_KB_MARKER_END,
2484
+ LEGACY_KB_REGEX,
854
2485
  LayerSchema,
2486
+ MCP_STORE_AWARE_CONTRACTS,
2487
+ MCP_STORE_AWARE_TOOLS,
855
2488
  MaturitySchema,
2489
+ ONBOARD_SLOT_NAMES,
2490
+ ONBOARD_SLOT_TOTAL,
2491
+ PARITY_CLIENTS,
2492
+ PARITY_SURFACES,
2493
+ PERSONAL_SCOPE,
2494
+ PERSONAL_STORE_SENTINEL,
2495
+ PROJECT_ROOT_SIGNALS,
856
2496
  PROPOSED_REASON_DESCRIPTIONS,
857
2497
  PROTECTED_TOKENS,
858
2498
  ProposedReasonSchema,
2499
+ REDACTION_PLACEHOLDER_PREFIX,
2500
+ ResolverNotImplementedError,
2501
+ SCOPE_COORDINATE_PATTERN,
2502
+ STORES_ROOT_DIR,
2503
+ STORE_GITIGNORE,
2504
+ STORE_KNOWLEDGE_TYPE_DIRS,
2505
+ STORE_LAYOUT,
2506
+ STORE_PENDING_DIR,
2507
+ STORE_RESOLVER_WARNING_CODES,
2508
+ STORE_UUID_PATTERN,
859
2509
  StableIdSchema,
2510
+ UID_SEGMENT_PATTERN,
2511
+ addMountedStore,
860
2512
  agentsIdentitySourceSchema,
861
2513
  agentsLayerSchema,
862
2514
  agentsMetaNodeSchema,
863
2515
  agentsMetaSchema,
864
2516
  agentsTopologyTypeSchema,
2517
+ aggregatePendingAcrossStores,
865
2518
  aiLedgerEntrySchema,
866
2519
  allocateKnowledgeId,
867
2520
  annotateIntentRequestSchema,
2521
+ archiveScanAnnotations,
2522
+ archiveScanInputSchema,
2523
+ archiveScanOutputSchema,
2524
+ assistantTurnObservedEventSchema,
868
2525
  auditModeSchema,
2526
+ bindRequiredStore,
2527
+ bindingsSnapshotPath,
2528
+ bootstrapMarkerMigratedEventSchema,
2529
+ buildDebugBundle,
2530
+ buildFailureTrace,
869
2531
  candidateFileEntrySchema,
2532
+ citeContractMetricsSchema,
2533
+ citeContractPolicyActivatedEventSchema,
2534
+ citeCoverageReportSchema,
2535
+ citeLayerTypeBreakdownSchema,
2536
+ citePolicyActivatedEventSchema,
870
2537
  claudeHookPathMigratedEventSchema,
871
2538
  claudeSkillPathMigratedEventSchema,
872
2539
  clientPathsSchema,
873
2540
  codexSkillPathMigratedEventSchema,
2541
+ createProjectRootResolver,
2542
+ createStoreResolver,
874
2543
  createTranslator,
875
2544
  defaultAgentsMetaCounters,
876
2545
  defaultLayerFilterSchema,
@@ -879,17 +2548,24 @@ export {
879
2548
  deriveAgentsMetaLayer,
880
2549
  deriveAgentsMetaStableId,
881
2550
  deriveAgentsMetaTopologyType,
2551
+ detachMountedStore,
882
2552
  detectNodeLocale,
883
2553
  doctorRunEventSchema,
884
2554
  driftDetectedEventSchema,
885
2555
  editIntentCheckedEventSchema,
886
2556
  enMessages,
2557
+ entryScopeMetadataSchema,
887
2558
  eventLedgerEventSchema,
888
2559
  eventLedgerTruncatedEventSchema,
2560
+ eventsRotatedEventSchema,
2561
+ explainStore,
889
2562
  fabExtractKnowledgeAnnotations,
890
2563
  fabReviewAnnotations,
891
2564
  fabricConfigSchema,
892
2565
  fabricEventSchema,
2566
+ fabricLanguageSchema,
2567
+ findMountedStore,
2568
+ findStoreExecutableViolations,
893
2569
  forensicAssertionCoverageSchema,
894
2570
  forensicAssertionSchema,
895
2571
  forensicCodeSampleSchema,
@@ -900,10 +2576,13 @@ export {
900
2576
  forensicReportSchema,
901
2577
  forensicSamplingBudgetSchema,
902
2578
  forensicTopologySchema,
2579
+ formatGlobalRef,
903
2580
  formatKnowledgeId,
904
- getKnowledgeAnnotations,
905
- getKnowledgeInputSchema,
906
- getKnowledgeOutputSchema,
2581
+ getPanelFieldByKey,
2582
+ getPanelFields,
2583
+ globalConfigSchema,
2584
+ globalRefSchema,
2585
+ hasSecrets,
907
2586
  historyStateQuerySchema,
908
2587
  humanLedgerEntrySchema,
909
2588
  humanLockApproveRequestSchema,
@@ -918,7 +2597,11 @@ export {
918
2597
  initContextSchema,
919
2598
  initContextSourceEvidenceSchema,
920
2599
  initScanCompletedEventSchema,
2600
+ initStore,
2601
+ installDiffAppliedEventSchema,
921
2602
  isKnowledgeStableId,
2603
+ isPersonalLeakIntoSharedStore,
2604
+ isPersonalScope,
922
2605
  knowledgeArchiveAttemptedEventSchema,
923
2606
  knowledgeArchivedEventSchema,
924
2607
  knowledgeConsumedEventSchema,
@@ -926,13 +2609,16 @@ export {
926
2609
  knowledgeDeferredEventSchema,
927
2610
  knowledgeDemotedEventSchema,
928
2611
  knowledgeDriftDetectedEventSchema,
929
- knowledgeLanguageSchema,
2612
+ knowledgeEnrichedEventSchema,
2613
+ knowledgeIdRedirectEventSchema,
930
2614
  knowledgeLayerChangedEventSchema,
2615
+ knowledgeMetaAutoHealedEventSchema,
931
2616
  knowledgePathDangledEventSchema,
932
2617
  knowledgePromoteFailedEventSchema,
933
2618
  knowledgePromoteStartedEventSchema,
934
2619
  knowledgePromotedEventSchema,
935
2620
  knowledgeProposedEventSchema,
2621
+ knowledgeProvenanceSchema,
936
2622
  knowledgeRejectedEventSchema,
937
2623
  knowledgeScopeDegradedEventSchema,
938
2624
  knowledgeSectionsAnnotations,
@@ -944,10 +2630,14 @@ export {
944
2630
  knowledgeTestIndexSchema,
945
2631
  knowledgeTestLinkSchema,
946
2632
  knowledgeTestOrphanAnnotationSchema,
2633
+ knowledgeUnarchivedEventSchema,
947
2634
  ledgerAppendedEventSchema,
948
2635
  ledgerEntrySchema,
949
2636
  ledgerQuerySchema,
950
2637
  ledgerSourceSchema,
2638
+ lintCrossStoreReferences,
2639
+ listStoreKnowledge,
2640
+ localKnowledgeIdSchema,
951
2641
  lockApprovedEventSchema,
952
2642
  lockDriftEventSchema,
953
2643
  mcpConfigMigratedEventSchema,
@@ -956,7 +2646,17 @@ export {
956
2646
  metaReconciledEventSchema,
957
2647
  metaReconciledOnStartupEventSchema,
958
2648
  metaUpdatedEventSchema,
2649
+ mountedStoreSchema,
2650
+ normalizeCiteTag,
959
2651
  normalizeLocale,
2652
+ onboardSlotSchema,
2653
+ parityCapabilitySchema,
2654
+ parityClientExpectationSchema,
2655
+ parityClientSchema,
2656
+ parityMatrixSchema,
2657
+ paritySurfaceSchema,
2658
+ parseCiteLine,
2659
+ parseGlobalRef,
960
2660
  parseKnowledgeId,
961
2661
  pendingAutoArchivedEventSchema,
962
2662
  planContextAnnotations,
@@ -964,10 +2664,52 @@ export {
964
2664
  planContextHintOutputSchema,
965
2665
  planContextInputSchema,
966
2666
  planContextOutputSchema,
2667
+ projectRootGoldenCaseSchema,
2668
+ projectRootGoldenFileSchema,
2669
+ projectRootResolutionSchema,
2670
+ projectRootSignalSchema,
2671
+ projectRootSignalsSchema,
2672
+ readBindingsSnapshot,
2673
+ readKnowledgeAcrossStores,
2674
+ readSetEntrySchema,
2675
+ readSetGoldenCaseSchema,
2676
+ readSetGoldenFileSchema,
2677
+ readStoreIdentity,
967
2678
  reapplyCompletedEventSchema,
2679
+ recallAnnotations,
2680
+ recallInputSchema,
2681
+ recallOutputSchema,
2682
+ recognizeStoreDir,
2683
+ redactSecrets,
2684
+ relevanceMigrationRunEventSchema,
2685
+ requiredStoreEntrySchema,
2686
+ resolveCandidates,
2687
+ resolveFabricLocale,
2688
+ resolveStoreQualifiedId,
2689
+ resolvedBindingsSnapshotSchema,
968
2690
  ruleDescriptionIndexItemSchema,
969
2691
  ruleDescriptionSchema,
2692
+ scanForSecrets,
2693
+ scopeCoordinateSchema,
2694
+ scopeRoot,
2695
+ selectionTokenTtlMsSchema,
2696
+ serveLockClearedEventSchema,
2697
+ sessionArchiveAttemptedEventSchema,
2698
+ storeAwareEntrySchema,
2699
+ storeCountersSchema,
2700
+ storeIdentitySchema,
2701
+ storeKnowledgeTypeDir,
2702
+ storeReadSetSchema,
2703
+ storeRelativePath,
2704
+ storeResolveInputSchema,
2705
+ storeResolverWarningCodeSchema,
2706
+ storeResolverWarningSchema,
2707
+ storeUuidSchema,
970
2708
  structuredWarningSchema,
2709
+ uidSchema,
971
2710
  withDerivedAgentsMetaNodeDefaults,
2711
+ writeBindingsSnapshot,
2712
+ writeTargetSchema,
2713
+ writtenToStoreSchema,
972
2714
  zhCNMessages
973
2715
  };