@fenglimg/fabric-shared 2.0.1 → 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
@@ -6,7 +6,7 @@ import {
6
6
  LEGACY_KB_MARKER_BEGIN,
7
7
  LEGACY_KB_MARKER_END,
8
8
  LEGACY_KB_REGEX
9
- } from "./chunk-LTDB2UDN.js";
9
+ } from "./chunk-MDWTGOAY.js";
10
10
  import {
11
11
  PROTECTED_TOKENS,
12
12
  createTranslator,
@@ -16,7 +16,7 @@ import {
16
16
  normalizeLocale,
17
17
  resolveFabricLocale,
18
18
  zhCNMessages
19
- } from "./chunk-7CX32MYL.js";
19
+ } from "./chunk-R2J7DAED.js";
20
20
  import {
21
21
  FabExtractKnowledgeInputSchema,
22
22
  FabExtractKnowledgeInputShape,
@@ -327,28 +327,125 @@ var humanLockFileSchema = z4.object({
327
327
  });
328
328
 
329
329
  // src/schemas/fabric-config.ts
330
+ import { z as z6 } from "zod";
331
+
332
+ // src/schemas/store.ts
330
333
  import { z as z5 } from "zod";
331
- var auditModeSchema = z5.enum(["strict", "warn", "off"]);
332
- var clientPathsSchema = z5.object({
333
- claudeCodeCLI: z5.string().optional(),
334
- claudeCodeDesktop: z5.string().optional(),
335
- cursor: z5.string().optional(),
336
- 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()
397
+ }).strict();
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()
337
414
  }).strict();
338
- var mcpPayloadLimitsSchema = z5.object({
339
- warnBytes: z5.number().int().positive().optional(),
340
- hardBytes: z5.number().int().positive().optional()
415
+ var mcpPayloadLimitsSchema = z6.object({
416
+ warnBytes: z6.number().int().positive().optional(),
417
+ hardBytes: z6.number().int().positive().optional()
341
418
  }).optional();
342
- var selectionTokenTtlMsSchema = z5.number().int().min(3e4).max(36e5);
343
- var fabricLanguageSchema = z5.enum([
419
+ var selectionTokenTtlMsSchema = z6.number().int().min(3e4).max(36e5);
420
+ var fabricLanguageSchema = z6.enum([
344
421
  "match-existing",
345
422
  "zh-CN",
346
423
  "en",
347
424
  "zh-CN-hybrid"
348
425
  ]);
349
- var defaultLayerFilterSchema = z5.enum(["team", "personal", "both"]);
350
- var fabricConfigSchema = z5.object({
426
+ var defaultLayerFilterSchema = z6.enum(["team", "personal", "both"]);
427
+ var fabricConfigSchema = z6.object({
351
428
  clientPaths: clientPathsSchema.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(),
352
449
  // rc.17 (R-cut): the dev/test fixture-path config field was removed
353
450
  // end-to-end. The `EXTERNAL_FIXTURE_PATH` env var is now the sole source
354
451
  // consumed by `resolveDevMode()`. No z.preprocess alias — pre-rc.17
@@ -356,7 +453,7 @@ var fabricConfigSchema = z5.object({
356
453
  // the lenient root parser (no .strict() at root). Pre-user clean-slate per
357
454
  // memory/feedback_clean_slate.md; mirrors the rc.12 hard-rename precedent
358
455
  // documented above.
359
- scanIgnores: z5.array(z5.string()).optional(),
456
+ scanIgnores: z6.array(z6.string()).optional(),
360
457
  audit_mode: auditModeSchema.optional(),
361
458
  mcpPayloadLimits: mcpPayloadLimitsSchema,
362
459
  // Backward-compat: both fields are optional with defaults so existing
@@ -371,7 +468,7 @@ var fabricConfigSchema = z5.object({
371
468
  // day if the user keeps ignoring it." Set to 24 to align with the archive
372
469
  // trigger threshold. The legacy `archive_hint_` key is retained for backward
373
470
  // compat with existing user fabric-config.json files.
374
- archive_hint_cooldown_hours: z5.number().int().positive().optional().default(12),
471
+ archive_hint_cooldown_hours: z6.number().int().positive().optional().default(12),
375
472
  // Underseed-node threshold for the fabric-hint Stop hook's import signal
376
473
  // (rc.5 TASK-010). When the canonical knowledge node count is strictly less
377
474
  // than this value AND a successful `init_scan_completed` event happened at
@@ -380,7 +477,7 @@ var fabricConfigSchema = z5.object({
380
477
  // the rule-of-thumb that a workspace with fewer than ten knowledge entries
381
478
  // is below the floor for plan_context retrieval to be meaningful. Also
382
479
  // consumed by `doctor` lint #22 (knowledge_underseeded).
383
- underseed_node_threshold: z5.number().int().positive().optional().default(10),
480
+ underseed_node_threshold: z6.number().int().positive().optional().default(10),
384
481
  // Edit-count threshold for the fabric-hint Stop hook's Signal A
385
482
  // (rc.6 TASK-022 / E5). Signal A fires when EITHER (a) >=24h have elapsed
386
483
  // since the last `knowledge_proposed` event, OR (b) >=archive_edit_threshold
@@ -391,102 +488,102 @@ var fabricConfigSchema = z5.object({
391
488
  // there is probably something worth archiving"; lowered values nag more
392
489
  // aggressively, higher values rely on the 24h fallback. Missing or absent
393
490
  // edit-counter file degrades safely to the 24h-only path.
394
- archive_edit_threshold: z5.number().int().positive().optional().default(20),
491
+ archive_edit_threshold: z6.number().int().positive().optional().default(20),
395
492
  // rc.7 T7: hours-since-last-knowledge_proposed cutoff for Signal A's
396
493
  // time branch. Was hardcoded as 24 in fabric-hint.cjs's THRESHOLD_HOURS;
397
494
  // externalized so chatty workspaces can lower the bar and quiet ones can
398
495
  // raise it. Default 24 preserves rc.6 behavior. See docs/configuration.md.
399
- archive_hint_hours: z5.number().int().positive().optional().default(24),
496
+ archive_hint_hours: z6.number().int().positive().optional().default(24),
400
497
  // rc.7 T7: pending-count cutoff for Signal B (review skill). Was
401
498
  // hardcoded as 10 in fabric-hint.cjs's THRESHOLD_PENDING_COUNT.
402
499
  // Default 10 preserves rc.6 behavior. See docs/configuration.md for
403
500
  // small/medium/large repo recommendations.
404
- review_hint_pending_count: z5.number().int().positive().optional().default(10),
501
+ review_hint_pending_count: z6.number().int().positive().optional().default(10),
405
502
  // rc.7 T7: pending-age cutoff (in days) for Signal B (review skill).
406
503
  // Was hardcoded as 7 in fabric-hint.cjs's THRESHOLD_PENDING_AGE_DAYS.
407
504
  // Default 7 preserves rc.6 behavior. See docs/configuration.md.
408
- 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),
409
506
  // rc.7 T7 + T10 pre-wiring: days-since-last-doctor cutoff for the future
410
507
  // Signal D (maintenance hint). T10 will consume this to decide when the
411
508
  // fabric-hint Stop hook surfaces a "run `fabric doctor`" reminder.
412
509
  // Default 14 reflects a fortnightly cadence — long enough to avoid nag,
413
510
  // short enough to catch index drift before it compounds.
414
- maintenance_hint_days: z5.number().int().positive().optional().default(14),
511
+ maintenance_hint_days: z6.number().int().positive().optional().default(14),
415
512
  // rc.7 T7 + T10 pre-wiring: cooldown between Signal D reminders, in
416
513
  // days. Once Signal D fires, it stays silent for this many days even if
417
514
  // the user doesn't run doctor. Default 7 keeps the reminder weekly at
418
515
  // worst — pairing 14d trigger + 7d cooldown means at most ~2 reminders
419
516
  // per month for a workspace that ignores them.
420
- maintenance_hint_cooldown_days: z5.number().int().positive().optional().default(7),
517
+ maintenance_hint_cooldown_days: z6.number().int().positive().optional().default(7),
421
518
  // rc.9+ (skill-contract-fix B1): first-run import window in months. The
422
519
  // `fabric-import` skill scans this many months of git history on the very
423
520
  // first invocation (when no prior `import_run_completed` event exists).
424
521
  // Default 60 (~5 years) captures the bulk of a mature repo's signal in
425
522
  // one pass; small / fresh repos can lower to 12-24 with no loss.
426
- import_window_first_run_months: z5.number().int().min(1).optional().default(60),
523
+ import_window_first_run_months: z6.number().int().min(1).optional().default(60),
427
524
  // rc.9+ (skill-contract-fix B1): rerun import window in months. After
428
525
  // the first successful import, subsequent runs only scan this many
429
526
  // recent months — assumed everything older has already been crystallized
430
527
  // into pending or canonical knowledge. Default 2 keeps incremental cost
431
528
  // low; raise to 6 if the workspace pauses fabric-import for long stretches.
432
- import_window_rerun_months: z5.number().int().min(1).optional().default(2),
529
+ import_window_rerun_months: z6.number().int().min(1).optional().default(2),
433
530
  // rc.9+ (skill-contract-fix B1): hard cap on pending entries produced
434
531
  // per fabric-import invocation. Prevents one run from dumping hundreds
435
532
  // of proposals when a backfill window is wide open. Default 10 matches
436
533
  // the rule-of-thumb "human can triage ~10 pending entries in one
437
534
  // review pass." Range 1-50.
438
- import_max_pending_per_run: z5.number().int().min(1).max(50).optional().default(10),
535
+ import_max_pending_per_run: z6.number().int().min(1).max(50).optional().default(10),
439
536
  // rc.9+ (skill-contract-fix B1): hard cap on commits scanned per
440
537
  // fabric-import invocation. Bounds runtime on monorepos with high
441
538
  // commit velocity. Default 500 covers ~2 months of typical churn;
442
539
  // range 50-2000. Hitting the cap mid-window is logged but non-fatal.
443
- import_max_commits_scan: z5.number().int().min(50).max(2e3).optional().default(500),
540
+ import_max_commits_scan: z6.number().int().min(50).max(2e3).optional().default(500),
444
541
  // rc.9+ (skill-contract-fix B1): canonical-node count above which
445
542
  // fabric-import's pre-flight should warn / suggest review instead of
446
543
  // proceeding. A workspace with 50+ canonical entries usually benefits
447
544
  // more from `fabric-review` to consolidate than from importing more.
448
545
  // Default 50; raise to 100+ for large polyglot repos.
449
- import_skip_canonical_threshold: z5.number().int().positive().optional().default(50),
546
+ import_skip_canonical_threshold: z6.number().int().positive().optional().default(50),
450
547
  // rc.9+ (skill-contract-fix B1): max candidate entries surfaced per
451
548
  // fabric-archive batch (one invocation of the skill). Pagination knob
452
549
  // for the archive UI flow. Default 8 keeps each batch reviewable in
453
550
  // one sitting; raise for large repos with high archive throughput.
454
- archive_max_candidates_per_batch: z5.number().int().positive().optional().default(8),
551
+ archive_max_candidates_per_batch: z6.number().int().positive().optional().default(8),
455
552
  // rc.9+ (skill-contract-fix B1): max recently-touched paths included
456
553
  // in fabric-archive's "relevant context" lookup. Limits the size of
457
554
  // the path-relevance digest the skill emits when ranking candidates.
458
555
  // Default 20; large repos with deep directory fan-out can raise to
459
556
  // 50+ if archive candidates feel under-contextualized.
460
- archive_max_recent_paths: z5.number().int().positive().optional().default(20),
557
+ archive_max_recent_paths: z6.number().int().positive().optional().default(20),
461
558
  // rc.9+ (skill-contract-fix B1): max prior fabric-archive sessions
462
559
  // summarised in the digest the skill loads on start. Prevents the
463
560
  // digest from ballooning past the model context budget on workspaces
464
561
  // that have archived repeatedly. Default 10; lower if context pressure
465
562
  // bites, raise if you want longer-range archive trend visibility.
466
- archive_digest_max_sessions: z5.number().int().positive().optional().default(10),
563
+ archive_digest_max_sessions: z6.number().int().positive().optional().default(10),
467
564
  // rc.9+ (skill-contract-fix B1): max review results returned per
468
565
  // topic when `fabric-review` clusters pending entries. Pagination
469
566
  // knob analogous to archive_max_candidates_per_batch but scoped to
470
567
  // each topic cluster. Default 8; raise to 15-20 for large repos
471
568
  // where each topic legitimately groups many pending entries.
472
- review_topic_result_cap: z5.number().int().positive().optional().default(8),
569
+ review_topic_result_cap: z6.number().int().positive().optional().default(8),
473
570
  // rc.9+ (skill-contract-fix B1): age threshold (in days) above which
474
571
  // a pending entry is considered "stale" by fabric-review and surfaced
475
572
  // for explicit resolve-or-drop decision. Default 14; tighter than the
476
573
  // 7d Signal-B trigger because review specifically targets the long
477
574
  // tail. Large repos with slower cadence can raise to 30.
478
- review_stale_pending_days: z5.number().int().positive().optional().default(14),
575
+ review_stale_pending_days: z6.number().int().positive().optional().default(14),
479
576
  // v2.0.0-rc.34 TASK-05: reverse-unarchive opt-in. When true, callers of the
480
577
  // `unarchiveKnowledge` primitive (and any future doctor auto-detect lint built
481
578
  // on top) will execute the file move + ledger emit. When false (default),
482
579
  // the same callers MUST short-circuit before any mutation — the primitive is
483
580
  // shipped but inert until explicitly enabled. Opt-in posture mirrors the
484
581
  // archive-flow precedent: destructive-ish file moves stay behind a flag.
485
- reverse_unarchive_enabled: z5.boolean().optional().default(false),
582
+ reverse_unarchive_enabled: z6.boolean().optional().default(false),
486
583
  // v2.0.0-rc.34 TASK-05: forces `unarchiveKnowledge` into dry-run mode even
487
584
  // when called with `options.dryRun=false`. Lets operators preview a
488
585
  // restoration pass before flipping `reverse_unarchive_enabled` to true.
489
- reverse_unarchive_dry_run: z5.boolean().optional().default(false),
586
+ reverse_unarchive_dry_run: z6.boolean().optional().default(false),
490
587
  // v2.0.0-rc.34 TASK-06: long-session cite-policy evict window in user-prompt
491
588
  // turns. UserPromptSubmit hook (Claude Code only) maintains a per-session
492
589
  // counter and re-injects the cite contract reminder via
@@ -494,7 +591,7 @@ var fabricConfigSchema = z5.object({
494
591
  // Default 0 = OFF (opt-in). Recommend 10-20 for active sessions; 5 for
495
592
  // high-contract-criticality projects. Other strategies (time-based,
496
593
  // token-budget) deferred to rc.35 per plan locked-decisions 2026-05-26.
497
- cite_evict_interval: z5.number().int().min(0).optional().default(0),
594
+ cite_evict_interval: z6.number().int().min(0).optional().default(0),
498
595
  // v2.0.0-rc.22 Scope A T3: sliding-window retention (in days) for the
499
596
  // event ledger rotation primitive (`rotateEventLedgerIfNeeded`). Lines
500
597
  // whose `ts` is older than `now - fabric_event_retention_days * 86_400_000`
@@ -507,7 +604,7 @@ var fabricConfigSchema = z5.object({
507
604
  // Mirrors cite-policy precedent of locking enum-style numeric tunables
508
605
  // to a small literal set (vs free `.positive()`) to prevent fat-finger
509
606
  // misconfig.
510
- fabric_event_retention_days: z5.union([z5.literal(7), z5.literal(30), z5.literal(90)]).optional(),
607
+ fabric_event_retention_days: z6.union([z6.literal(7), z6.literal(30), z6.literal(90)]).optional(),
511
608
  // v2.0.0-rc.23 TASK-014 (F8c): onboard slot opt-out list. Tracks slot
512
609
  // names the user explicitly dismissed during fabric-archive's first-run
513
610
  // onboard phase (or via `fabric config dismiss-slot <slot>`). Dismissed
@@ -524,7 +621,7 @@ var fabricConfigSchema = z5.object({
524
621
  //
525
622
  // Default `[]` keeps the field optional on existing configs — fresh
526
623
  // installs land with no opt-outs.
527
- onboard_slots_opted_out: z5.array(z5.string()).optional().default([]),
624
+ onboard_slots_opted_out: z6.array(z6.string()).optional().default([]),
528
625
  // v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the broad SessionStart hint
529
626
  // banner emitted by knowledge-hint-broad.cjs. After plan-context-hint returns
530
627
  // its full broad-scoped index, the hook slices the entries to this many
@@ -536,20 +633,20 @@ var fabricConfigSchema = z5.object({
536
633
  // Range 1..50; values above 20 effectively disable the cap because the
537
634
  // TRUNCATION_THRESHOLD=12 grouped-render kicks in. Mirrors the rc.7 T7 +
538
635
  // archive_max_* pattern of externalizing previously-hardcoded thresholds.
539
- hint_broad_top_k: z5.number().int().min(1).max(50).optional().default(8),
636
+ hint_broad_top_k: z6.number().int().min(1).max(50).optional().default(8),
540
637
  // v2.0.0-rc.37 NEW-16: durable per-signal dismiss for the fabric-hint Stop
541
638
  // hook nudges. Any signal type listed here is suppressed at emit time across
542
639
  // all sessions (the session-scoped sibling lives in a .fabric/.cache sidecar
543
640
  // written on request). Mirrors the cite_evict_interval=0 opt-out convention —
544
641
  // a knob for an existing surface, not a new feature. Unknown types ignored.
545
- hint_dismiss_signals: z5.array(z5.enum(["archive", "review", "import", "maintenance"])).optional(),
642
+ hint_dismiss_signals: z6.array(z6.enum(["archive", "review", "import", "maintenance"])).optional(),
546
643
  // v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the narrow PreToolUse hint
547
644
  // emitted by knowledge-hint-narrow.cjs. After filtering to entries whose
548
645
  // `relevance_scope === "narrow"` (rc.27 TASK-005 audit §2.5 fix), the hook
549
646
  // slices to this many before the E3 emit-gate / renderSummary pipeline.
550
647
  // Default 5 keeps each per-Edit hint terse — five lines max so the agent's
551
648
  // working memory is not displaced by an unwieldy banner. Range 1..20.
552
- hint_narrow_top_k: z5.number().int().min(1).max(20).optional().default(5),
649
+ hint_narrow_top_k: z6.number().int().min(1).max(20).optional().default(5),
553
650
  // v2.0.0-rc.33 W2-1 (P0-9): per-file dedup window (in PreToolUse turns) for
554
651
  // the narrow hint. Same (file_path, stable_id) tuple stays silent for this
555
652
  // many turns even when the E3 cross-session cache would otherwise re-emit.
@@ -559,7 +656,7 @@ var fabricConfigSchema = z5.object({
559
656
  // Storage: .fabric/.cache/narrow-dedup-window.json — distinct from session-
560
657
  // hints cache so a window-only suppression does not poison cross-session
561
658
  // dedupe semantics.
562
- hint_narrow_dedup_window_turns: z5.number().int().min(1).max(50).optional().default(5),
659
+ hint_narrow_dedup_window_turns: z6.number().int().min(1).max(50).optional().default(5),
563
660
  // v2.0.0-rc.33 W2-5 (P1-8): cooldown between broad SessionStart hint emits,
564
661
  // in hours. Distinct from the archive_hint_cooldown_hours that gates the
565
662
  // fabric-hint Stop hook — knowledge-hint-broad re-fires on every
@@ -568,29 +665,29 @@ var fabricConfigSchema = z5.object({
568
665
  // menu at most once per hour"; 0 means "no cooldown, current behavior."
569
666
  // Range 0..168 (one week). Stored alongside fabric-hint's cooldown cache
570
667
  // under a distinct knowledge-hint-broad key.
571
- hint_broad_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
668
+ hint_broad_cooldown_hours: z6.number().int().min(0).max(168).optional().default(0),
572
669
  // v2.0.0-rc.33 W2-5 (P1-8): cooldown for the narrow PreToolUse hint.
573
670
  // Same shape as hint_broad_cooldown_hours but applies to per-Edit hint
574
671
  // re-emission across the cooldown window — independent of E3 session-
575
672
  // hints dedupe. Default 0 preserves rc.32 behavior; set to e.g. 1 to
576
673
  // throttle hint frequency during rapid-fire editing sprints. Range
577
674
  // 0..168 (one week).
578
- hint_narrow_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
675
+ hint_narrow_cooldown_hours: z6.number().int().min(0).max(168).optional().default(0),
579
676
  // v2.0.0-rc.33 W4-B3 (T5 P2): per-maturity inactivity thresholds (days)
580
677
  // driving orphan_demote. Hardcoded at stable=90/endorsed=30/draft=14 in
581
678
  // rc.32; chatty workspaces want them tighter, slow ones want them looser.
582
679
  // Each field optional; absent → defaults inside doctor.ts apply. Ranges
583
680
  // chosen so a typo can't accidentally disable the lint (min 1).
584
- orphan_demote_stable_days: z5.number().int().min(1).max(3650).optional(),
585
- orphan_demote_endorsed_days: z5.number().int().min(1).max(3650).optional(),
586
- orphan_demote_draft_days: z5.number().int().min(1).max(3650).optional(),
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(),
587
684
  // v2.0.0-rc.33 W4-A3 (T4 P2): per-entry summary truncation length used by
588
685
  // knowledge-hint-{broad,narrow}.cjs. Hard-coded at 80 chars in rc.32 — too
589
686
  // short for entries with parameterized summaries (e.g. "Use bcrypt with
590
687
  // cost=12 for password hashing"), too long for terse pitfalls. Range 40..240;
591
688
  // default 80 preserves rc.32 behavior. Both hooks read the same key so the
592
689
  // banner styling stays consistent across SessionStart + PreToolUse.
593
- hint_summary_max_len: z5.number().int().min(40).max(240).optional().default(80),
690
+ hint_summary_max_len: z6.number().int().min(40).max(240).optional().default(80),
594
691
  // v2.0.0-rc.33 W2-6 (P0-7 + P0-8): when true, knowledge-hint hooks emit
595
692
  // their banners as `hookSpecificOutput.additionalContext` JSON on stdout
596
693
  // (per Claude Code PreToolUse hook contract — see
@@ -600,7 +697,7 @@ var fabricConfigSchema = z5.object({
600
697
  // coverage focus (rc.32 baseline 3.1% → primary cause: reminders never
601
698
  // entered model context). Set false to revert to legacy stderr-only mode
602
699
  // for hosts that don't honor the JSON contract.
603
- hint_reminder_to_context: z5.boolean().optional().default(true),
700
+ hint_reminder_to_context: z6.boolean().optional().default(true),
604
701
  // v2.0.0-rc.29 TASK-008 (BUG-F3): selection-token TTL override. The
605
702
  // `fab_plan_context` MCP tool hands clients a `selection_token` whose default
606
703
  // 5-minute lifetime (`SELECTION_TOKEN_TTL_MS` at
@@ -620,8 +717,8 @@ var fabricConfigSchema = z5.object({
620
717
  });
621
718
 
622
719
  // src/schemas/fabric-config-introspect.ts
623
- import { z as z6 } from "zod";
624
- var positiveIntSchema = z6.coerce.number().int().positive();
720
+ import { z as z7 } from "zod";
721
+ var positiveIntSchema = z7.coerce.number().int().positive();
625
722
  function makePositiveIntField(key, defaultValue) {
626
723
  return {
627
724
  key,
@@ -757,156 +854,982 @@ var PANEL_FIELDS = [
757
854
  )
758
855
  ];
759
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 }
924
+ });
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
+
760
1683
  // src/schemas/forensic-report.ts
761
- import { z as z7 } from "zod";
762
- var forensicCodeSampleSchema = z7.object({
763
- path: z7.string(),
764
- lines: z7.string(),
765
- snippet: z7.string(),
766
- pattern_hint: z7.string()
767
- });
768
- var forensicEvidenceAnchorSchema = z7.object({
769
- file: z7.string(),
770
- line: z7.string(),
771
- snippet: z7.string()
772
- });
773
- var forensicAssertionCoverageSchema = z7.object({
774
- ratio: z7.number().min(0).max(1),
775
- total: z7.number().int().nonnegative(),
776
- matched: z7.number().int().nonnegative(),
777
- co_occurring_patterns: z7.array(z7.string())
778
- });
779
- var forensicAssertionSchema = z7.object({
780
- type: z7.enum(["framework", "pattern", "invariant", "domain"]),
781
- statement: z7.string(),
782
- confidence: z7.enum(["HIGH", "MEDIUM", "LOW"]),
783
- evidence: z7.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),
784
1707
  coverage: forensicAssertionCoverageSchema,
785
- proposed_rule: z7.string().optional(),
786
- alternatives: z7.array(z7.string()).optional()
787
- });
788
- var forensicTopologySchema = z7.object({
789
- total_files: z7.number().int().nonnegative(),
790
- by_ext: z7.record(z7.number().int().nonnegative()),
791
- key_dirs: z7.array(z7.string()),
792
- max_depth: z7.number().int().nonnegative()
793
- });
794
- var forensicEntryPointSchema = z7.object({
795
- path: z7.string(),
796
- reason: z7.string(),
797
- size_bytes: z7.number().int().nonnegative().optional()
798
- });
799
- var forensicFrameworkSchema = z7.object({
800
- kind: z7.string(),
801
- version: z7.string(),
802
- subkind: z7.string(),
803
- evidence: z7.array(z7.string())
804
- });
805
- var forensicReadmeSchema = z7.object({
806
- quality: z7.enum(["missing", "stub", "ok"]),
807
- line_count: z7.number().int().nonnegative(),
808
- has_contributing: z7.boolean()
809
- });
810
- var candidateFileEntrySchema = z7.object({
811
- path: z7.string(),
812
- family: z7.enum(["entry", "component", "config", "test", "domain"]),
813
- rationale: z7.string()
814
- });
815
- var forensicSamplingBudgetSchema = z7.object({
816
- max_files: z7.literal(15),
817
- max_lines_per_file: z7.literal(100)
818
- });
819
- var forensicReportSchema = z7.object({
820
- version: z7.string(),
821
- generated_at: z7.string(),
822
- generated_by: z7.string(),
823
- target: z7.string(),
824
- project_name: z7.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(),
825
1748
  framework: forensicFrameworkSchema,
826
1749
  topology: forensicTopologySchema,
827
- entry_points: z7.array(forensicEntryPointSchema),
828
- code_samples: z7.array(forensicCodeSampleSchema),
829
- assertions: z7.array(forensicAssertionSchema),
830
- candidate_files: z7.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),
831
1754
  sampling_budget: forensicSamplingBudgetSchema,
832
1755
  readme: forensicReadmeSchema,
833
- recommendations_for_skill: z7.array(z7.string()).optional()
1756
+ recommendations_for_skill: z15.array(z15.string()).optional()
834
1757
  });
835
1758
 
836
1759
  // src/schemas/init-context.ts
837
- import { z as z8 } from "zod";
838
- var initContextFrameworkSchema = z8.object({
839
- kind: z8.string(),
840
- version: z8.string(),
841
- subkind: z8.string()
842
- });
843
- var initContextInvariantConfidenceSnapshotSchema = z8.object({
844
- confidence: z8.enum(["HIGH", "MEDIUM", "LOW"]),
845
- evidence_refs: z8.array(z8.string())
846
- });
847
- var initContextSourceEvidenceSchema = z8.object({
848
- file: z8.string(),
849
- lines: z8.string()
850
- });
851
- var initContextInvariantSchema = z8.object({
852
- type: z8.enum(["ban", "require", "protect"]),
853
- rule: z8.string(),
854
- rationale: z8.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(),
855
1778
  confidence_snapshot: initContextInvariantConfidenceSnapshotSchema.optional(),
856
- source_evidence: z8.array(initContextSourceEvidenceSchema).optional()
857
- });
858
- var initContextDomainGroupSchema = z8.object({
859
- name: z8.string(),
860
- paths: z8.array(z8.string()),
861
- summary: z8.string().optional(),
862
- topology_type: z8.enum(["mirror", "cross-cutting"]).optional(),
863
- target_path: z8.string().optional()
864
- });
865
- var initContextInterviewTrailEntrySchema = z8.object({
866
- phase: z8.string(),
867
- question: z8.string(),
868
- answer: z8.string(),
869
- presentation: z8.string().optional(),
870
- user_corrections: z8.array(z8.string()).optional()
871
- });
872
- var initContextSchema = z8.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({
873
1796
  framework: initContextFrameworkSchema,
874
- architecture_patterns: z8.array(z8.string()),
875
- invariants: z8.array(initContextInvariantSchema),
876
- domain_groups: z8.array(initContextDomainGroupSchema),
877
- interview_trail: z8.array(initContextInterviewTrailEntrySchema),
878
- forensic_ref: z8.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()
879
1802
  });
880
1803
 
881
1804
  // src/schemas/events.ts
882
- import { z as z9 } from "zod";
883
- var metaUpdatedEventSchema = z9.object({
884
- type: z9.literal("meta:updated"),
1805
+ import { z as z17 } from "zod";
1806
+ var metaUpdatedEventSchema = z17.object({
1807
+ type: z17.literal("meta:updated"),
885
1808
  payload: agentsMetaSchema
886
1809
  });
887
- var lockDriftEventSchema = z9.object({
888
- type: z9.literal("lock:drift"),
889
- payload: z9.object({
890
- locked: z9.array(humanLockEntrySchema),
891
- drifted: z9.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)
892
1815
  })
893
1816
  });
894
- var lockApprovedEventSchema = z9.object({
895
- type: z9.literal("lock:approved"),
896
- payload: z9.object({
897
- locked: z9.array(humanLockEntrySchema),
898
- approved: z9.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)
899
1822
  })
900
1823
  });
901
- var ledgerAppendedEventSchema = z9.object({
902
- type: z9.literal("ledger:appended"),
1824
+ var ledgerAppendedEventSchema = z17.object({
1825
+ type: z17.literal("ledger:appended"),
903
1826
  payload: ledgerEntrySchema
904
1827
  });
905
- var driftDetectedEventSchema = z9.object({
906
- type: z9.literal("drift:detected"),
1828
+ var driftDetectedEventSchema = z17.object({
1829
+ type: z17.literal("drift:detected"),
907
1830
  payload: forensicReportSchema
908
1831
  });
909
- var fabricEventSchema = z9.discriminatedUnion("type", [
1832
+ var fabricEventSchema = z17.discriminatedUnion("type", [
910
1833
  metaUpdatedEventSchema,
911
1834
  lockDriftEventSchema,
912
1835
  lockApprovedEventSchema,
@@ -915,143 +1838,258 @@ var fabricEventSchema = z9.discriminatedUnion("type", [
915
1838
  ]);
916
1839
 
917
1840
  // src/schemas/event-ledger.ts
918
- import { z as z10 } 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
+ );
919
1957
  var eventLedgerEnvelopeSchema = {
920
- kind: z10.literal("fabric-event"),
921
- id: z10.string(),
922
- ts: z10.number().int().nonnegative(),
923
- schema_version: z10.literal(1),
924
- correlation_id: z10.string().optional(),
925
- session_id: z10.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()
926
1964
  };
927
- var stringRecordSchema = z10.record(z10.string());
928
- var knowledgeContextPlannedEventSchema = z10.object({
1965
+ var stringRecordSchema = z18.record(z18.string());
1966
+ var knowledgeContextPlannedEventSchema = z18.object({
929
1967
  ...eventLedgerEnvelopeSchema,
930
- event_type: z10.literal("knowledge_context_planned"),
931
- target_paths: z10.array(z10.string()),
932
- required_stable_ids: z10.array(z10.string()),
933
- ai_selectable_stable_ids: z10.array(z10.string()),
934
- final_stable_ids: z10.array(z10.string()),
935
- selection_token: z10.string().optional(),
936
- client_hash: z10.string().optional(),
937
- intent: z10.string().optional(),
938
- known_tech: z10.array(z10.string()).optional(),
939
- diagnostics: z10.array(z10.unknown()).optional()
940
- });
941
- var knowledgeSelectionEventSchema = z10.object({
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({
942
1980
  ...eventLedgerEnvelopeSchema,
943
- event_type: z10.literal("knowledge_selection"),
944
- selection_token: z10.string(),
945
- target_paths: z10.array(z10.string()),
946
- required_stable_ids: z10.array(z10.string()),
947
- ai_selectable_stable_ids: z10.array(z10.string()),
948
- ai_selected_stable_ids: z10.array(z10.string()),
949
- final_stable_ids: z10.array(z10.string()),
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()),
950
1988
  ai_selection_reasons: stringRecordSchema,
951
- rejected_stable_ids: z10.array(z10.string()),
952
- ignored_stable_ids: z10.array(z10.string())
1989
+ rejected_stable_ids: z18.array(z18.string()),
1990
+ ignored_stable_ids: z18.array(z18.string())
953
1991
  });
954
- var knowledgeSectionsFetchedEventSchema = z10.object({
1992
+ var knowledgeSectionsFetchedEventSchema = z18.object({
955
1993
  ...eventLedgerEnvelopeSchema,
956
- event_type: z10.literal("knowledge_sections_fetched"),
957
- selection_token: z10.string(),
958
- target_paths: z10.array(z10.string()).optional(),
959
- requested_sections: z10.array(z10.string()),
960
- final_stable_ids: z10.array(z10.string()),
961
- ai_selected_stable_ids: z10.array(z10.string()),
962
- diagnostics: z10.array(z10.unknown()).optional()
963
- });
964
- var editIntentCheckedEventSchema = z10.object({
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({
965
2003
  ...eventLedgerEnvelopeSchema,
966
- event_type: z10.literal("edit_intent_checked"),
967
- path: z10.string(),
968
- compliant: z10.boolean(),
969
- intent: z10.string(),
970
- ledger_entry_id: z10.string(),
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(),
971
2009
  // rc.35 TASK-07 (P0-2): add "hook" — emitted by the PreToolUse narrow hook
972
2010
  // for every Edit/Write/MultiEdit fire so cite-coverage doctor metrics see
973
2011
  // actual edit signals (previously editsTouched was permanently 0 because
974
2012
  // no production caller of appendLedgerEntry existed).
975
- ledger_source: z10.enum(["ai", "human", "hook"]).optional(),
976
- commit_sha: z10.string().optional(),
977
- parent_sha: z10.string().optional(),
978
- parent_ledger_entry_id: z10.string().optional(),
979
- diff_stat: z10.string().optional(),
980
- annotation: z10.string().optional(),
981
- matched_rule_context_ts: z10.number().int().nonnegative().nullable(),
982
- window_ms: z10.number().int().nonnegative()
983
- });
984
- var knowledgeDriftDetectedEventSchema = z10.object({
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({
985
2023
  ...eventLedgerEnvelopeSchema,
986
- event_type: z10.literal("knowledge_drift_detected"),
987
- revision: z10.string().optional(),
988
- drifted_stable_ids: z10.array(z10.string()),
989
- missing_files: z10.array(z10.string()),
990
- stale_files: z10.array(z10.string()),
991
- details: z10.array(
992
- z10.object({
993
- file: z10.string(),
994
- stable_id: z10.string(),
995
- expected_hash: z10.string(),
996
- actual_hash: z10.string().nullable()
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()
997
2035
  })
998
2036
  ).optional()
999
2037
  });
1000
- var mcpEventLedgerEventSchema = z10.object({
2038
+ var mcpEventLedgerEventSchema = z18.object({
1001
2039
  ...eventLedgerEnvelopeSchema,
1002
- event_type: z10.literal("mcp_event"),
1003
- mcp_event_id: z10.string(),
1004
- stream_id: z10.string(),
1005
- message: z10.unknown()
2040
+ event_type: z18.literal("mcp_event"),
2041
+ mcp_event_id: z18.string(),
2042
+ stream_id: z18.string(),
2043
+ message: z18.unknown()
1006
2044
  });
1007
- var reapplyCompletedEventSchema = z10.object({
2045
+ var reapplyCompletedEventSchema = z18.object({
1008
2046
  ...eventLedgerEnvelopeSchema,
1009
- event_type: z10.literal("reapply_completed"),
1010
- preserved_ledger: z10.boolean(),
1011
- preserved_meta: z10.boolean(),
1012
- rules_count: z10.number().int().nonnegative()
2047
+ event_type: z18.literal("reapply_completed"),
2048
+ preserved_ledger: z18.boolean(),
2049
+ preserved_meta: z18.boolean(),
2050
+ rules_count: z18.number().int().nonnegative()
1013
2051
  });
1014
- var installDiffAppliedEventSchema = z10.object({
2052
+ var installDiffAppliedEventSchema = z18.object({
1015
2053
  ...eventLedgerEnvelopeSchema,
1016
- event_type: z10.literal("install_diff_applied"),
1017
- applied: z10.array(z10.string()),
1018
- canonical: z10.array(z10.string()),
1019
- drifted: z10.array(z10.string())
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())
1020
2058
  });
1021
- var eventLedgerTruncatedEventSchema = z10.object({
2059
+ var eventLedgerTruncatedEventSchema = z18.object({
1022
2060
  ...eventLedgerEnvelopeSchema,
1023
- event_type: z10.literal("event_ledger_truncated"),
1024
- byte_offset: z10.number().int().nonnegative(),
1025
- byte_length: z10.number().int().nonnegative(),
1026
- corrupted_path: z10.string()
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()
1027
2065
  });
1028
- var mcpConfigMigratedEventSchema = z10.object({
2066
+ var mcpConfigMigratedEventSchema = z18.object({
1029
2067
  ...eventLedgerEnvelopeSchema,
1030
- event_type: z10.literal("mcp_config_migrated"),
1031
- source: z10.literal("doctor_fix"),
1032
- removed_from: z10.string()
2068
+ event_type: z18.literal("mcp_config_migrated"),
2069
+ source: z18.literal("doctor_fix"),
2070
+ removed_from: z18.string()
1033
2071
  });
1034
- var bootstrapMarkerMigratedEventSchema = z10.object({
2072
+ var bootstrapMarkerMigratedEventSchema = z18.object({
1035
2073
  ...eventLedgerEnvelopeSchema,
1036
- event_type: z10.literal("bootstrap_marker_migrated"),
1037
- path: z10.string(),
1038
- migrated_count: z10.number().int().nonnegative(),
1039
- legacy_marker: z10.literal("fabric:knowledge-base"),
1040
- new_marker: z10.literal("fabric:bootstrap"),
1041
- timestamp: z10.string()
1042
- });
1043
- var metaReconciledOnStartupEventSchema = z10.object({
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()
2080
+ });
2081
+ var metaReconciledOnStartupEventSchema = z18.object({
1044
2082
  ...eventLedgerEnvelopeSchema,
1045
- event_type: z10.literal("meta_reconciled_on_startup"),
1046
- reconciled_files: z10.array(z10.string()),
1047
- duration_ms: z10.number().int().nonnegative(),
1048
- source: z10.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")
1049
2087
  });
1050
- var metaReconciledEventSchema = z10.object({
2088
+ var metaReconciledEventSchema = z18.object({
1051
2089
  ...eventLedgerEnvelopeSchema,
1052
- event_type: z10.literal("meta_reconciled"),
1053
- reconciled_files: z10.array(z10.string()),
1054
- duration_ms: z10.number().int().nonnegative(),
2090
+ event_type: z18.literal("meta_reconciled"),
2091
+ reconciled_files: z18.array(z18.string()),
2092
+ duration_ms: z18.number().int().nonnegative(),
1055
2093
  // v2.0.0-rc.23 TASK-005 (a-B): added `auto-heal-description` trigger so the
1056
2094
  // read-path plan_context handler can drive a full reconcile when it detects
1057
2095
  // any node carrying `description === undefined` (legacy meta drift that the
@@ -1065,7 +2103,7 @@ var metaReconciledEventSchema = z10.object({
1065
2103
  // v2.0.0-rc.29 TASK-005 (BUG-G1): `auto-heal-after-drift` added so
1066
2104
  // `ensureKnowledgeFresh` hot-path can chain a paired reconcile (closing the
1067
2105
  // drift→heal gap) when the caller opts in via `autoHealOnDrift: true`.
1068
- trigger: z10.enum([
2106
+ trigger: z18.enum([
1069
2107
  "doctor",
1070
2108
  "manual",
1071
2109
  "auto-heal-description",
@@ -1073,195 +2111,195 @@ var metaReconciledEventSchema = z10.object({
1073
2111
  "post-approve",
1074
2112
  "post-modify"
1075
2113
  ]),
1076
- source: z10.literal("reconcileKnowledge"),
2114
+ source: z18.literal("reconcileKnowledge"),
1077
2115
  // v2.0.0-rc.22 TASK-014 (Scope E): set when reconcileKnowledge forced a
1078
2116
  // writeKnowledgeMeta on revision drift alone (no per-file content drift).
1079
2117
  // Distinguishes top-level schema/revision repair from the standard per-file
1080
2118
  // drift path. Optional so existing emitters stay unchanged.
1081
- force_write_reason: z10.enum(["revision_drift"]).optional()
2119
+ force_write_reason: z18.enum(["revision_drift"]).optional()
1082
2120
  });
1083
- var claudeSkillPathMigratedEventSchema = z10.object({
2121
+ var claudeSkillPathMigratedEventSchema = z18.object({
1084
2122
  ...eventLedgerEnvelopeSchema,
1085
- event_type: z10.literal("claude_skill_path_migrated"),
1086
- from: z10.string(),
1087
- to: z10.string()
2123
+ event_type: z18.literal("claude_skill_path_migrated"),
2124
+ from: z18.string(),
2125
+ to: z18.string()
1088
2126
  });
1089
- var claudeHookPathMigratedEventSchema = z10.object({
2127
+ var claudeHookPathMigratedEventSchema = z18.object({
1090
2128
  ...eventLedgerEnvelopeSchema,
1091
- event_type: z10.literal("claude_hook_path_migrated"),
1092
- from: z10.string(),
1093
- to: z10.string()
2129
+ event_type: z18.literal("claude_hook_path_migrated"),
2130
+ from: z18.string(),
2131
+ to: z18.string()
1094
2132
  });
1095
- var codexSkillPathMigratedEventSchema = z10.object({
2133
+ var codexSkillPathMigratedEventSchema = z18.object({
1096
2134
  ...eventLedgerEnvelopeSchema,
1097
- event_type: z10.literal("codex_skill_path_migrated"),
1098
- from: z10.string(),
1099
- to: z10.string()
2135
+ event_type: z18.literal("codex_skill_path_migrated"),
2136
+ from: z18.string(),
2137
+ to: z18.string()
1100
2138
  });
1101
- var initScanCompletedEventSchema = z10.object({
2139
+ var initScanCompletedEventSchema = z18.object({
1102
2140
  ...eventLedgerEnvelopeSchema,
1103
- event_type: z10.literal("init_scan_completed"),
1104
- written_stable_ids: z10.array(z10.string()),
1105
- duration_ms: z10.number().int().nonnegative(),
1106
- source: z10.enum(["init", "scan", "doctor_fix", "doctor-rescan"]).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()
1107
2145
  });
1108
- var knowledgeProposedEventSchema = z10.object({
2146
+ var knowledgeProposedEventSchema = z18.object({
1109
2147
  ...eventLedgerEnvelopeSchema,
1110
- event_type: z10.literal("knowledge_proposed"),
1111
- stable_id: z10.string().optional(),
1112
- timestamp: z10.string().datetime(),
1113
- reason: z10.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()
1114
2152
  });
1115
- var knowledgePromoteStartedEventSchema = z10.object({
2153
+ var knowledgePromoteStartedEventSchema = z18.object({
1116
2154
  ...eventLedgerEnvelopeSchema,
1117
- event_type: z10.literal("knowledge_promote_started"),
1118
- stable_id: z10.string().optional(),
1119
- timestamp: z10.string().datetime(),
1120
- reason: z10.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()
1121
2159
  });
1122
- var knowledgePromotedEventSchema = z10.object({
2160
+ var knowledgePromotedEventSchema = z18.object({
1123
2161
  ...eventLedgerEnvelopeSchema,
1124
- event_type: z10.literal("knowledge_promoted"),
1125
- stable_id: z10.string().optional(),
1126
- timestamp: z10.string().datetime(),
1127
- reason: z10.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()
1128
2166
  });
1129
- var knowledgePromoteFailedEventSchema = z10.object({
2167
+ var knowledgePromoteFailedEventSchema = z18.object({
1130
2168
  ...eventLedgerEnvelopeSchema,
1131
- event_type: z10.literal("knowledge_promote_failed"),
1132
- stable_id: z10.string().optional(),
1133
- timestamp: z10.string().datetime(),
1134
- reason: z10.string()
2169
+ event_type: z18.literal("knowledge_promote_failed"),
2170
+ stable_id: z18.string().optional(),
2171
+ timestamp: z18.string().datetime(),
2172
+ reason: z18.string()
1135
2173
  });
1136
- var knowledgeLayerChangedEventSchema = z10.object({
2174
+ var knowledgeLayerChangedEventSchema = z18.object({
1137
2175
  ...eventLedgerEnvelopeSchema,
1138
- event_type: z10.literal("knowledge_layer_changed"),
1139
- stable_id: z10.string().optional(),
1140
- timestamp: z10.string().datetime(),
1141
- reason: z10.string().optional(),
1142
- from_layer: z10.enum(["team", "personal"]),
1143
- to_layer: z10.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"]),
1144
2182
  // v2.0.0-rc.37 NEW-24: record the pre-flip stable_id so downstream consumers
1145
2183
  // (fab_plan_context redirect surface, fab_get_knowledge_sections.redirect_to)
1146
2184
  // can map a stale caller-held id back to the post-flip canonical id without
1147
2185
  // requiring the caller to re-issue plan-context. Optional for forward-
1148
2186
  // compatibility with rc ≤36 events that never carried this field.
1149
- previous_stable_id: z10.string().optional()
2187
+ previous_stable_id: z18.string().optional()
1150
2188
  });
1151
- var knowledgeIdRedirectEventSchema = z10.object({
2189
+ var knowledgeIdRedirectEventSchema = z18.object({
1152
2190
  ...eventLedgerEnvelopeSchema,
1153
- event_type: z10.literal("knowledge_id_redirect"),
1154
- timestamp: z10.string().datetime(),
1155
- previous_stable_id: z10.string(),
1156
- new_stable_id: z10.string(),
1157
- reason: z10.string().optional()
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()
1158
2196
  });
1159
- var knowledgeSlugRenamedEventSchema = z10.object({
2197
+ var knowledgeSlugRenamedEventSchema = z18.object({
1160
2198
  ...eventLedgerEnvelopeSchema,
1161
- event_type: z10.literal("knowledge_slug_renamed"),
1162
- stable_id: z10.string().optional(),
1163
- timestamp: z10.string().datetime(),
1164
- reason: z10.string().optional(),
1165
- from_slug: z10.string(),
1166
- to_slug: z10.string()
1167
- });
1168
- var knowledgeDemotedEventSchema = z10.object({
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()
2205
+ });
2206
+ var knowledgeDemotedEventSchema = z18.object({
1169
2207
  ...eventLedgerEnvelopeSchema,
1170
- event_type: z10.literal("knowledge_demoted"),
1171
- stable_id: z10.string().optional(),
1172
- timestamp: z10.string().datetime(),
1173
- reason: z10.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()
1174
2212
  });
1175
- var knowledgeArchivedEventSchema = z10.object({
2213
+ var knowledgeArchivedEventSchema = z18.object({
1176
2214
  ...eventLedgerEnvelopeSchema,
1177
- event_type: z10.literal("knowledge_archived"),
1178
- stable_id: z10.string().optional(),
1179
- timestamp: z10.string().datetime(),
1180
- reason: z10.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()
1181
2219
  });
1182
- var knowledgeArchiveAttemptedEventSchema = z10.object({
2220
+ var knowledgeArchiveAttemptedEventSchema = z18.object({
1183
2221
  ...eventLedgerEnvelopeSchema,
1184
- event_type: z10.literal("knowledge_archive_attempted"),
1185
- stable_id: z10.string().optional(),
1186
- timestamp: z10.string().datetime(),
1187
- reason: z10.string().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()
1188
2226
  });
1189
- var knowledgeUnarchivedEventSchema = z10.object({
2227
+ var knowledgeUnarchivedEventSchema = z18.object({
1190
2228
  ...eventLedgerEnvelopeSchema,
1191
- event_type: z10.literal("knowledge_unarchived"),
1192
- stable_id: z10.string().optional(),
1193
- timestamp: z10.string().datetime(),
1194
- reason: z10.string().optional(),
2229
+ event_type: z18.literal("knowledge_unarchived"),
2230
+ stable_id: z18.string().optional(),
2231
+ timestamp: z18.string().datetime(),
2232
+ reason: z18.string().optional(),
1195
2233
  // Pre-move archive path (e.g. ".fabric/.archive/decisions/KT-D-0007--single-cjs-hook.md").
1196
- archive_path: z10.string().optional(),
2234
+ archive_path: z18.string().optional(),
1197
2235
  // Post-move canonical path (e.g. ".fabric/knowledge/team/decisions/KT-D-0007--single-cjs-hook.md").
1198
- restored_to: z10.string().optional()
2236
+ restored_to: z18.string().optional()
1199
2237
  });
1200
- var knowledgeDeferredEventSchema = z10.object({
2238
+ var knowledgeDeferredEventSchema = z18.object({
1201
2239
  ...eventLedgerEnvelopeSchema,
1202
- event_type: z10.literal("knowledge_deferred"),
1203
- stable_id: z10.string().optional(),
1204
- timestamp: z10.string().datetime(),
1205
- reason: z10.string().optional(),
1206
- until: z10.string().datetime().optional()
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()
1207
2245
  });
1208
- var knowledgeRejectedEventSchema = z10.object({
2246
+ var knowledgeRejectedEventSchema = z18.object({
1209
2247
  ...eventLedgerEnvelopeSchema,
1210
- event_type: z10.literal("knowledge_rejected"),
1211
- stable_id: z10.string().optional(),
1212
- timestamp: z10.string().datetime(),
1213
- reason: z10.string()
2248
+ event_type: z18.literal("knowledge_rejected"),
2249
+ stable_id: z18.string().optional(),
2250
+ timestamp: z18.string().datetime(),
2251
+ reason: z18.string()
1214
2252
  });
1215
- var knowledgeConsumedEventSchema = z10.object({
2253
+ var knowledgeConsumedEventSchema = z18.object({
1216
2254
  ...eventLedgerEnvelopeSchema,
1217
- event_type: z10.literal("knowledge_consumed"),
1218
- stable_id: z10.string(),
1219
- consumed_at: z10.string().datetime(),
1220
- client_hash: z10.string()
2255
+ event_type: z18.literal("knowledge_consumed"),
2256
+ stable_id: z18.string(),
2257
+ consumed_at: z18.string().datetime(),
2258
+ client_hash: z18.string()
1221
2259
  });
1222
- var knowledgeScopeDegradedEventSchema = z10.object({
2260
+ var knowledgeScopeDegradedEventSchema = z18.object({
1223
2261
  ...eventLedgerEnvelopeSchema,
1224
- event_type: z10.literal("knowledge_scope_degraded"),
1225
- stable_id: z10.string(),
1226
- timestamp: z10.string().datetime(),
1227
- from_scope: z10.enum(["narrow", "broad"]),
1228
- to_scope: z10.enum(["narrow", "broad"]),
1229
- reason: z10.string()
1230
- });
1231
- var doctorRunEventSchema = z10.object({
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()
2268
+ });
2269
+ var doctorRunEventSchema = z18.object({
1232
2270
  ...eventLedgerEnvelopeSchema,
1233
- event_type: z10.literal("doctor_run"),
1234
- mode: z10.enum(["lint", "fix-knowledge"]),
1235
- issues: z10.number().int().nonnegative(),
1236
- mutations: z10.number().int().nonnegative().optional(),
1237
- timestamp: z10.string().datetime()
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()
1238
2276
  });
1239
- var knowledgePathDangledEventSchema = z10.object({
2277
+ var knowledgePathDangledEventSchema = z18.object({
1240
2278
  ...eventLedgerEnvelopeSchema,
1241
- event_type: z10.literal("knowledge_path_dangled"),
1242
- stable_id: z10.string(),
1243
- removed_glob: z10.string()
2279
+ event_type: z18.literal("knowledge_path_dangled"),
2280
+ stable_id: z18.string(),
2281
+ removed_glob: z18.string()
1244
2282
  });
1245
- var relevanceMigrationRunEventSchema = z10.object({
2283
+ var relevanceMigrationRunEventSchema = z18.object({
1246
2284
  ...eventLedgerEnvelopeSchema,
1247
- event_type: z10.literal("relevance_migration_run"),
1248
- timestamp: z10.string().datetime(),
1249
- scanned_count: z10.number().int().nonnegative(),
1250
- touched_count: z10.number().int().nonnegative()
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()
1251
2289
  });
1252
- var pendingAutoArchivedEventSchema = z10.object({
2290
+ var pendingAutoArchivedEventSchema = z18.object({
1253
2291
  ...eventLedgerEnvelopeSchema,
1254
- event_type: z10.literal("pending_auto_archived"),
1255
- pending_path: z10.string(),
1256
- archived_to: z10.string(),
1257
- reason: z10.string()
2292
+ event_type: z18.literal("pending_auto_archived"),
2293
+ pending_path: z18.string(),
2294
+ archived_to: z18.string(),
2295
+ reason: z18.string()
1258
2296
  });
1259
- var assistantTurnObservedEventSchema = z10.object({
2297
+ var assistantTurnObservedEventSchema = z18.object({
1260
2298
  ...eventLedgerEnvelopeSchema,
1261
- event_type: z10.literal("assistant_turn_observed"),
1262
- kb_line_raw: z10.string().nullable(),
1263
- cite_ids: z10.array(z10.string()).default([]),
1264
- cite_tags: z10.array(z10.enum(["planned", "recalled", "chained-from", "dismissed", "none"])).default([]),
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([]),
1265
2303
  // v2.0.0-rc.24 TASK-01: per-cite contract commitments. Index-aligned with
1266
2304
  // cite_ids/cite_tags (commitments[i] belongs to cite_ids[i]). Each slot
1267
2305
  // carries `operators[]` (kind + glob target) or `skip_reason` when the cite
@@ -1269,72 +2307,72 @@ var assistantTurnObservedEventSchema = z10.object({
1269
2307
  // empty array via `.default([])` and are excluded from contract-policy
1270
2308
  // audits by the marker-gate (see cite_contract_policy_activated below).
1271
2309
  // Mirrors the rc.20 cite_tags parallel-array evolution exactly.
1272
- cite_commitments: z10.array(
1273
- z10.object({
1274
- operators: z10.array(
1275
- z10.object({
1276
- kind: z10.enum(["edit", "not_edit", "require", "forbid"]),
1277
- target: z10.string()
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()
1278
2316
  })
1279
2317
  ),
1280
- skip_reason: z10.string().nullable()
2318
+ skip_reason: z18.string().nullable()
1281
2319
  })
1282
2320
  ).default([]),
1283
- client: z10.enum(["cc", "codex", "cursor"]).optional(),
1284
- turn_id: z10.string(),
1285
- envelope_index: z10.number().int().nonnegative().optional(),
1286
- timestamp: z10.string().datetime()
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()
1287
2325
  });
1288
- var citePolicyActivatedEventSchema = z10.object({
2326
+ var citePolicyActivatedEventSchema = z18.object({
1289
2327
  ...eventLedgerEnvelopeSchema,
1290
- event_type: z10.literal("cite_policy_activated"),
1291
- policy_version: z10.string(),
1292
- timestamp: z10.string().datetime()
2328
+ event_type: z18.literal("cite_policy_activated"),
2329
+ policy_version: z18.string(),
2330
+ timestamp: z18.string().datetime()
1293
2331
  });
1294
- var citeContractPolicyActivatedEventSchema = z10.object({
2332
+ var citeContractPolicyActivatedEventSchema = z18.object({
1295
2333
  ...eventLedgerEnvelopeSchema,
1296
- event_type: z10.literal("cite_contract_policy_activated")
2334
+ event_type: z18.literal("cite_contract_policy_activated")
1297
2335
  });
1298
- var eventsRotatedEventSchema = z10.object({
2336
+ var eventsRotatedEventSchema = z18.object({
1299
2337
  ...eventLedgerEnvelopeSchema,
1300
- event_type: z10.literal("events_rotated"),
1301
- cutoff_ts: z10.string().datetime(),
1302
- archived_count: z10.number().int().nonnegative(),
1303
- kept_count: z10.number().int().nonnegative(),
1304
- archive_path: z10.string()
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()
1305
2343
  });
1306
- var knowledgeMetaAutoHealedEventSchema = z10.object({
2344
+ var knowledgeMetaAutoHealedEventSchema = z18.object({
1307
2345
  ...eventLedgerEnvelopeSchema,
1308
- event_type: z10.literal("knowledge_meta_auto_healed"),
1309
- previous_revision_hash: z10.string(),
1310
- revision_hash: z10.string(),
1311
- trigger: z10.literal("read"),
1312
- caller: z10.enum(["planContext", "getKnowledgeSections", "getKnowledge", "extractKnowledge"]).optional()
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()
1313
2351
  });
1314
- var serveLockClearedEventSchema = z10.object({
2352
+ var serveLockClearedEventSchema = z18.object({
1315
2353
  ...eventLedgerEnvelopeSchema,
1316
- event_type: z10.literal("serve_lock_cleared"),
1317
- pid: z10.number().int().nonnegative(),
1318
- age_ms: z10.number().int().nonnegative(),
1319
- timestamp: z10.string().datetime()
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()
1320
2358
  });
1321
- var knowledgeEnrichedEventSchema = z10.object({
2359
+ var knowledgeEnrichedEventSchema = z18.object({
1322
2360
  ...eventLedgerEnvelopeSchema,
1323
- event_type: z10.literal("knowledge_enriched"),
1324
- path: z10.string(),
1325
- added_fields: z10.array(z10.enum(["intent_clues", "tech_stack", "impact", "must_read_if"])),
1326
- mode: z10.enum(["auto", "preview", "readonly", "interactive"]),
1327
- timestamp: z10.string().datetime()
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()
1328
2366
  });
1329
- var sessionArchiveAttemptedEventSchema = z10.object({
2367
+ var sessionArchiveAttemptedEventSchema = z18.object({
1330
2368
  ...eventLedgerEnvelopeSchema,
1331
- event_type: z10.literal("session_archive_attempted"),
1332
- outcome: z10.enum(["proposed", "viability_failed", "user_dismissed", "skipped_no_signal"]),
1333
- covered_through_ts: z10.number().int().nonnegative(),
1334
- candidates_proposed: z10.number().int().nonnegative().default(0),
1335
- knowledge_proposed_ids: z10.array(z10.string()).default([])
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([])
1336
2374
  });
1337
- var eventLedgerEventSchema = z10.discriminatedUnion("event_type", [
2375
+ var eventLedgerEventSchema = z18.discriminatedUnion("event_type", [
1338
2376
  knowledgeContextPlannedEventSchema,
1339
2377
  knowledgeSelectionEventSchema,
1340
2378
  knowledgeSectionsFetchedEventSchema,
@@ -1417,98 +2455,6 @@ var eventLedgerEventSchema = z10.discriminatedUnion("event_type", [
1417
2455
  // covered_through_ts watermark, and `fabric doctor --archive-history`.
1418
2456
  sessionArchiveAttemptedEventSchema
1419
2457
  ]);
1420
-
1421
- // src/cite-line-parser.ts
1422
- var ID_RE = /^K[TP]-[A-Z]+-\d+$/;
1423
- var SENTINEL_RE = /^KB:\s*none\b\s*(?:\[[^\]]*\])?\s*$/i;
1424
- var FULL_RE = /^KB:\s+(K[TP]-[A-Z]+-\d+(?:\s*,\s*K[TP]-[A-Z]+-\d+)*)(?:\s+\(([^)]*)\))?(?:\s+\[([^\]]+)\])?(?:\s+→\s*(.+))?\s*$/;
1425
- var CHAINED_FROM_ID_RE = /chained-from\s+(K[TP]-[A-Z]+-\d+)/i;
1426
- var ALLOWED_TAGS = /* @__PURE__ */ new Set([
1427
- "planned",
1428
- "recalled",
1429
- "chained-from",
1430
- "dismissed",
1431
- "none"
1432
- ]);
1433
- function parseTag(rawTag) {
1434
- if (!rawTag) return "none";
1435
- const head = rawTag.trim().split(/[\s:]+/)[0].toLowerCase();
1436
- return ALLOWED_TAGS.has(head) ? head : "none";
1437
- }
1438
- function parseContractTail(tail) {
1439
- const result = { operators: [], skip_reason: null };
1440
- if (!tail) return result;
1441
- const tokens = tail.trim().split(/\s+/).filter((t) => t.length > 0);
1442
- for (const token of tokens) {
1443
- const skipMatch = token.match(/^skip:(.+)$/i);
1444
- if (skipMatch) {
1445
- if (result.skip_reason === null) result.skip_reason = skipMatch[1];
1446
- continue;
1447
- }
1448
- const notEditMatch = token.match(/^!edit:(.+)$/i);
1449
- if (notEditMatch) {
1450
- result.operators.push({ kind: "not_edit", target: notEditMatch[1] });
1451
- continue;
1452
- }
1453
- const opMatch = token.match(/^(edit|require|forbid):(.+)$/i);
1454
- if (opMatch) {
1455
- result.operators.push({
1456
- kind: opMatch[1].toLowerCase(),
1457
- target: opMatch[2]
1458
- });
1459
- }
1460
- }
1461
- return result;
1462
- }
1463
- function parseLine(line) {
1464
- const trimmed = line.trim();
1465
- if (trimmed.length === 0) return null;
1466
- if (SENTINEL_RE.test(trimmed)) {
1467
- return { ids: [], tag: "none", commitment: null };
1468
- }
1469
- const fullMatch = trimmed.match(FULL_RE);
1470
- if (fullMatch) {
1471
- const primaryIds = fullMatch[1].split(",").map((part) => part.trim()).filter((part) => part.length > 0);
1472
- if (primaryIds.some((id) => !ID_RE.test(id))) return null;
1473
- const rawTag = fullMatch[3];
1474
- const tag = parseTag(rawTag);
1475
- const chainedIds = [];
1476
- if (rawTag !== void 0) {
1477
- const chained = CHAINED_FROM_ID_RE.exec(rawTag);
1478
- if (chained !== null && ID_RE.test(chained[1])) {
1479
- chainedIds.push(chained[1]);
1480
- }
1481
- }
1482
- return {
1483
- ids: [...primaryIds, ...chainedIds],
1484
- tag,
1485
- commitment: parseContractTail(fullMatch[4])
1486
- };
1487
- }
1488
- return null;
1489
- }
1490
- function parseCiteLine(raw) {
1491
- const result = {
1492
- cite_ids: [],
1493
- cite_tags: [],
1494
- cite_commitments: []
1495
- };
1496
- if (typeof raw !== "string") return result;
1497
- for (const line of raw.split(/\r?\n/)) {
1498
- const parsed = parseLine(line);
1499
- if (!parsed) continue;
1500
- result.cite_tags.push(parsed.tag);
1501
- for (const id of parsed.ids) {
1502
- result.cite_ids.push(id);
1503
- }
1504
- if (parsed.commitment !== null) {
1505
- for (let i = 0; i < parsed.ids.length; i += 1) {
1506
- result.cite_commitments.push(parsed.commitment);
1507
- }
1508
- }
1509
- }
1510
- return result;
1511
- }
1512
2458
  export {
1513
2459
  AGENTS_META_IDENTITY_SOURCES,
1514
2460
  AGENTS_META_LAYERS,
@@ -1525,26 +2471,50 @@ export {
1525
2471
  FabReviewInputShape,
1526
2472
  FabReviewOutputSchema,
1527
2473
  FabReviewOutputShape,
2474
+ GLOBAL_BINDINGS_DIR,
2475
+ GLOBAL_REF_PATTERN,
2476
+ GLOBAL_STATE_DIR,
1528
2477
  KNOWLEDGE_TEST_INDEX_SCHEMA_VERSION,
1529
2478
  KNOWLEDGE_TYPE_CODES,
2479
+ KNOWN_SCOPE_PREFIXES,
1530
2480
  KnowledgeEntryFrontmatterSchema,
1531
2481
  KnowledgeTypeSchema,
1532
2482
  LEGACY_KB_MARKER_BEGIN,
1533
2483
  LEGACY_KB_MARKER_END,
1534
2484
  LEGACY_KB_REGEX,
1535
2485
  LayerSchema,
2486
+ MCP_STORE_AWARE_CONTRACTS,
2487
+ MCP_STORE_AWARE_TOOLS,
1536
2488
  MaturitySchema,
1537
2489
  ONBOARD_SLOT_NAMES,
1538
2490
  ONBOARD_SLOT_TOTAL,
2491
+ PARITY_CLIENTS,
2492
+ PARITY_SURFACES,
2493
+ PERSONAL_SCOPE,
2494
+ PERSONAL_STORE_SENTINEL,
2495
+ PROJECT_ROOT_SIGNALS,
1539
2496
  PROPOSED_REASON_DESCRIPTIONS,
1540
2497
  PROTECTED_TOKENS,
1541
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,
1542
2509
  StableIdSchema,
2510
+ UID_SEGMENT_PATTERN,
2511
+ addMountedStore,
1543
2512
  agentsIdentitySourceSchema,
1544
2513
  agentsLayerSchema,
1545
2514
  agentsMetaNodeSchema,
1546
2515
  agentsMetaSchema,
1547
2516
  agentsTopologyTypeSchema,
2517
+ aggregatePendingAcrossStores,
1548
2518
  aiLedgerEntrySchema,
1549
2519
  allocateKnowledgeId,
1550
2520
  annotateIntentRequestSchema,
@@ -1553,7 +2523,11 @@ export {
1553
2523
  archiveScanOutputSchema,
1554
2524
  assistantTurnObservedEventSchema,
1555
2525
  auditModeSchema,
2526
+ bindRequiredStore,
2527
+ bindingsSnapshotPath,
1556
2528
  bootstrapMarkerMigratedEventSchema,
2529
+ buildDebugBundle,
2530
+ buildFailureTrace,
1557
2531
  candidateFileEntrySchema,
1558
2532
  citeContractMetricsSchema,
1559
2533
  citeContractPolicyActivatedEventSchema,
@@ -1564,6 +2538,8 @@ export {
1564
2538
  claudeSkillPathMigratedEventSchema,
1565
2539
  clientPathsSchema,
1566
2540
  codexSkillPathMigratedEventSchema,
2541
+ createProjectRootResolver,
2542
+ createStoreResolver,
1567
2543
  createTranslator,
1568
2544
  defaultAgentsMetaCounters,
1569
2545
  defaultLayerFilterSchema,
@@ -1572,19 +2548,24 @@ export {
1572
2548
  deriveAgentsMetaLayer,
1573
2549
  deriveAgentsMetaStableId,
1574
2550
  deriveAgentsMetaTopologyType,
2551
+ detachMountedStore,
1575
2552
  detectNodeLocale,
1576
2553
  doctorRunEventSchema,
1577
2554
  driftDetectedEventSchema,
1578
2555
  editIntentCheckedEventSchema,
1579
2556
  enMessages,
2557
+ entryScopeMetadataSchema,
1580
2558
  eventLedgerEventSchema,
1581
2559
  eventLedgerTruncatedEventSchema,
1582
2560
  eventsRotatedEventSchema,
2561
+ explainStore,
1583
2562
  fabExtractKnowledgeAnnotations,
1584
2563
  fabReviewAnnotations,
1585
2564
  fabricConfigSchema,
1586
2565
  fabricEventSchema,
1587
2566
  fabricLanguageSchema,
2567
+ findMountedStore,
2568
+ findStoreExecutableViolations,
1588
2569
  forensicAssertionCoverageSchema,
1589
2570
  forensicAssertionSchema,
1590
2571
  forensicCodeSampleSchema,
@@ -1595,9 +2576,13 @@ export {
1595
2576
  forensicReportSchema,
1596
2577
  forensicSamplingBudgetSchema,
1597
2578
  forensicTopologySchema,
2579
+ formatGlobalRef,
1598
2580
  formatKnowledgeId,
1599
2581
  getPanelFieldByKey,
1600
2582
  getPanelFields,
2583
+ globalConfigSchema,
2584
+ globalRefSchema,
2585
+ hasSecrets,
1601
2586
  historyStateQuerySchema,
1602
2587
  humanLedgerEntrySchema,
1603
2588
  humanLockApproveRequestSchema,
@@ -1612,8 +2597,11 @@ export {
1612
2597
  initContextSchema,
1613
2598
  initContextSourceEvidenceSchema,
1614
2599
  initScanCompletedEventSchema,
2600
+ initStore,
1615
2601
  installDiffAppliedEventSchema,
1616
2602
  isKnowledgeStableId,
2603
+ isPersonalLeakIntoSharedStore,
2604
+ isPersonalScope,
1617
2605
  knowledgeArchiveAttemptedEventSchema,
1618
2606
  knowledgeArchivedEventSchema,
1619
2607
  knowledgeConsumedEventSchema,
@@ -1630,6 +2618,7 @@ export {
1630
2618
  knowledgePromoteStartedEventSchema,
1631
2619
  knowledgePromotedEventSchema,
1632
2620
  knowledgeProposedEventSchema,
2621
+ knowledgeProvenanceSchema,
1633
2622
  knowledgeRejectedEventSchema,
1634
2623
  knowledgeScopeDegradedEventSchema,
1635
2624
  knowledgeSectionsAnnotations,
@@ -1646,6 +2635,9 @@ export {
1646
2635
  ledgerEntrySchema,
1647
2636
  ledgerQuerySchema,
1648
2637
  ledgerSourceSchema,
2638
+ lintCrossStoreReferences,
2639
+ listStoreKnowledge,
2640
+ localKnowledgeIdSchema,
1649
2641
  lockApprovedEventSchema,
1650
2642
  lockDriftEventSchema,
1651
2643
  mcpConfigMigratedEventSchema,
@@ -1654,9 +2646,17 @@ export {
1654
2646
  metaReconciledEventSchema,
1655
2647
  metaReconciledOnStartupEventSchema,
1656
2648
  metaUpdatedEventSchema,
2649
+ mountedStoreSchema,
2650
+ normalizeCiteTag,
1657
2651
  normalizeLocale,
1658
2652
  onboardSlotSchema,
2653
+ parityCapabilitySchema,
2654
+ parityClientExpectationSchema,
2655
+ parityClientSchema,
2656
+ parityMatrixSchema,
2657
+ paritySurfaceSchema,
1659
2658
  parseCiteLine,
2659
+ parseGlobalRef,
1660
2660
  parseKnowledgeId,
1661
2661
  pendingAutoArchivedEventSchema,
1662
2662
  planContextAnnotations,
@@ -1664,18 +2664,52 @@ export {
1664
2664
  planContextHintOutputSchema,
1665
2665
  planContextInputSchema,
1666
2666
  planContextOutputSchema,
2667
+ projectRootGoldenCaseSchema,
2668
+ projectRootGoldenFileSchema,
2669
+ projectRootResolutionSchema,
2670
+ projectRootSignalSchema,
2671
+ projectRootSignalsSchema,
2672
+ readBindingsSnapshot,
2673
+ readKnowledgeAcrossStores,
2674
+ readSetEntrySchema,
2675
+ readSetGoldenCaseSchema,
2676
+ readSetGoldenFileSchema,
2677
+ readStoreIdentity,
1667
2678
  reapplyCompletedEventSchema,
1668
2679
  recallAnnotations,
1669
2680
  recallInputSchema,
1670
2681
  recallOutputSchema,
2682
+ recognizeStoreDir,
2683
+ redactSecrets,
1671
2684
  relevanceMigrationRunEventSchema,
2685
+ requiredStoreEntrySchema,
2686
+ resolveCandidates,
1672
2687
  resolveFabricLocale,
2688
+ resolveStoreQualifiedId,
2689
+ resolvedBindingsSnapshotSchema,
1673
2690
  ruleDescriptionIndexItemSchema,
1674
2691
  ruleDescriptionSchema,
2692
+ scanForSecrets,
2693
+ scopeCoordinateSchema,
2694
+ scopeRoot,
1675
2695
  selectionTokenTtlMsSchema,
1676
2696
  serveLockClearedEventSchema,
1677
2697
  sessionArchiveAttemptedEventSchema,
2698
+ storeAwareEntrySchema,
2699
+ storeCountersSchema,
2700
+ storeIdentitySchema,
2701
+ storeKnowledgeTypeDir,
2702
+ storeReadSetSchema,
2703
+ storeRelativePath,
2704
+ storeResolveInputSchema,
2705
+ storeResolverWarningCodeSchema,
2706
+ storeResolverWarningSchema,
2707
+ storeUuidSchema,
1678
2708
  structuredWarningSchema,
2709
+ uidSchema,
1679
2710
  withDerivedAgentsMetaNodeDefaults,
2711
+ writeBindingsSnapshot,
2712
+ writeTargetSchema,
2713
+ writtenToStoreSchema,
1680
2714
  zhCNMessages
1681
2715
  };