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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +152 -2
  2. package/dist/index.js +1039 -340
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -125,6 +125,25 @@ type CiteCoverageReport = {
125
125
  compliant_cites?: number;
126
126
  noncompliant_cites?: number;
127
127
  uncorrelatable_edits?: number;
128
+ recall_backed_edits?: number;
129
+ recall_coverage_rate?: number | null;
130
+ exposed_and_mutated?: {
131
+ count: number;
132
+ ids?: string[];
133
+ };
134
+ mutations_observed?: {
135
+ count: number;
136
+ };
137
+ mutation_pool?: {
138
+ attributed: number;
139
+ unattributed_workspace_dirty: number;
140
+ };
141
+ sessions_closed?: {
142
+ count: number;
143
+ };
144
+ by_store?: Record<string, {
145
+ qualifying_cites: number;
146
+ }>;
128
147
  };
129
148
  per_client?: Record<string, Partial<CiteCoverageReport["metrics"]>>;
130
149
  dismissed_reason_histogram?: Record<string, number>;
@@ -146,6 +165,7 @@ declare function runDoctorCiteCoverage(projectRoot: string, options: {
146
165
  client: "cc" | "codex" | "cursor" | "all";
147
166
  layer?: "team" | "personal" | "all";
148
167
  until?: number;
168
+ recallWindowMs?: number;
149
169
  }): Promise<CiteCoverageReport>;
150
170
  type ArchiveHistoryEntry = {
151
171
  session_id_short: string;
@@ -297,6 +317,130 @@ declare function enrichDescriptions(projectRoot: string, opts?: {
297
317
  dryRun?: boolean;
298
318
  }): Promise<EnrichDescriptionsReport>;
299
319
 
320
+ interface Bm25Document {
321
+ id: string;
322
+ tokens: string[];
323
+ }
324
+ interface Bm25Model {
325
+ /**
326
+ * BM25 score of document `id` against the (pre-tokenized) query terms.
327
+ * Returns 0 for an unknown id, an empty document, no query terms, or no
328
+ * term overlap. Query-term duplicates are collapsed — repeating a term in
329
+ * the query does not inflate the score (term frequency is a document
330
+ * property, not a query property).
331
+ */
332
+ scoreDoc(id: string, queryTerms: string[]): number;
333
+ }
334
+ /**
335
+ * Build a BM25 model over `docs`. The corpus statistics (document frequency,
336
+ * average document length) are computed once here; `scoreDoc` is then O(query
337
+ * terms) per call.
338
+ */
339
+ declare function buildBm25Model(docs: Bm25Document[]): Bm25Model;
340
+
341
+ interface ConflictEntry {
342
+ stable_id: string;
343
+ /** Plural knowledge_type ("decisions" | "pitfalls" | "guidelines" | "models" | "processes"). */
344
+ knowledge_type: string;
345
+ /** "team" | "personal". Conflicts are only meaningful within one layer. */
346
+ layer: string;
347
+ /** Title + body (or any text used for similarity). */
348
+ text: string;
349
+ }
350
+ type ConflictVerdict = "conflict" | "similar" | "unknown";
351
+ interface ConflictPair {
352
+ a: string;
353
+ b: string;
354
+ knowledge_type: string;
355
+ layer: string;
356
+ /** Symmetric normalized bm25 similarity in [0,1]. */
357
+ similarity: number;
358
+ /**
359
+ * "unknown" until a judge classifies it (cheap pass leaves it unknown =
360
+ * needs-human-review). "conflict" = the judge ruled a real contradiction
361
+ * (escalates to error). "similar" = judged not-a-conflict (stays a warn /
362
+ * possible duplicate).
363
+ */
364
+ verdict: ConflictVerdict;
365
+ rationale?: string;
366
+ }
367
+ type ConflictJudge = (a: ConflictEntry, b: ConflictEntry) => Promise<{
368
+ isConflict: boolean;
369
+ rationale: string;
370
+ }>;
371
+ declare const DEFAULT_CONFLICT_SIMILARITY_THRESHOLD = 0.5;
372
+ /**
373
+ * Symmetric, [0,1]-normalized bm25 similarity between two docs sharing a model.
374
+ * For each direction we measure how much of the target doc's self-relevance the
375
+ * other doc's terms recover (scoreDoc(target, otherTokens) / scoreDoc(target,
376
+ * targetTokens)), then take the MIN of both directions — conservative: both
377
+ * entries must strongly overlap, so a short entry incidentally contained in a
378
+ * long one does not over-fire.
379
+ */
380
+ declare function pairSimilarity(model: ReturnType<typeof buildBm25Model>, a: {
381
+ id: string;
382
+ tokens: string[];
383
+ }, b: {
384
+ id: string;
385
+ tokens: string[];
386
+ }): number;
387
+ /**
388
+ * Cheap deterministic pass: candidate conflicting/duplicate pairs. Compares
389
+ * only entries sharing (type, layer), via bm25 similarity ≥ threshold. Returns
390
+ * pairs sorted by similarity descending (stable_id-tie-broken for determinism).
391
+ * Every returned pair has verdict "unknown" — the cheap pass cannot tell a
392
+ * conflict from a benign duplicate; that is the judge's job.
393
+ *
394
+ * O(G · n_g²) where G = groups and n_g = entries per group. Conflicts only make
395
+ * sense within one (type, layer), so the quadratic stays bounded to small
396
+ * same-bucket sets, not the whole corpus.
397
+ */
398
+ declare function findConflictCandidates(entries: ConflictEntry[], opts?: {
399
+ threshold?: number;
400
+ }): ConflictPair[];
401
+ /**
402
+ * Full lint. Always runs the cheap pass; when `judge` is supplied (deep mode)
403
+ * each candidate is classified into conflict/similar. A judge throw leaves the
404
+ * pair as "unknown" (degrade-safe — a flaky judge never crashes doctor).
405
+ *
406
+ * Entry lookup for the judge is by stable_id from the same `entries` array.
407
+ */
408
+ declare function lintConflicts(entries: ConflictEntry[], opts?: {
409
+ threshold?: number;
410
+ judge?: ConflictJudge;
411
+ }): Promise<ConflictPair[]>;
412
+
413
+ interface ConflictLintReport {
414
+ status: "ok";
415
+ threshold: number;
416
+ deep: boolean;
417
+ /** Total candidate pairs (similarity ≥ threshold). */
418
+ candidate_count: number;
419
+ /** Subset judged a real contradiction (deep mode only). */
420
+ conflict_count: number;
421
+ pairs: ConflictPair[];
422
+ }
423
+ /**
424
+ * Load canonical knowledge entries with bodies from the agents.meta node index.
425
+ * Skips pending/draft staging entries (conflict detection targets the curated
426
+ * corpus) and any node missing a stable_id or knowledge_type. Bodies are read
427
+ * best-effort — an unreadable file contributes no entry.
428
+ */
429
+ declare function loadConflictEntries(projectRoot: string): Promise<ConflictEntry[]>;
430
+ /**
431
+ * Run the knowledge-conflict lint. Always runs the cheap bm25 candidate pass;
432
+ * when `deep` is set AND a judge is supplied, escalates candidates to
433
+ * conflict/similar verdicts via the injected LLM judge.
434
+ *
435
+ * threshold resolution: opts.threshold → fabric-config
436
+ * conflict_lint_similarity_threshold → DEFAULT_CONFLICT_SIMILARITY_THRESHOLD.
437
+ */
438
+ declare function runDoctorConflictLint(projectRoot: string, opts?: {
439
+ threshold?: number;
440
+ deep?: boolean;
441
+ judge?: ConflictJudge;
442
+ }): Promise<ConflictLintReport>;
443
+
300
444
  type KnowledgeMetaBuildSource = "doctor_fix" | "sync_meta";
301
445
  type KnowledgeMetaBuildResult = {
302
446
  meta: AgentsMeta;
@@ -460,6 +604,8 @@ type PlanContextInput = {
460
604
  correlation_id?: string;
461
605
  session_id?: string;
462
606
  target_paths?: string[];
607
+ layer_filter?: "team" | "personal" | "both";
608
+ include_related?: boolean;
463
609
  };
464
610
  type RequirementProfile = {
465
611
  target_path: string;
@@ -489,6 +635,7 @@ type PlanContextResult = {
489
635
  auto_healed?: boolean;
490
636
  previous_revision_hash?: string;
491
637
  redirects?: Record<string, string>;
638
+ related_appended?: Record<string, string>;
492
639
  };
493
640
  type SelectionTokenState = {
494
641
  token: string;
@@ -529,10 +676,13 @@ type RecallResult = PlanContextResult & {
529
676
  level: "L0" | "L1" | "L2";
530
677
  path: string;
531
678
  body: string;
679
+ store?: {
680
+ alias: string;
681
+ };
532
682
  }>;
533
683
  selected_stable_ids: string[];
534
684
  diagnostics: Array<{
535
- code: "missing_knowledge_metadata";
685
+ code: "missing_knowledge_metadata" | "unresolved_selected_id";
536
686
  severity: "warn";
537
687
  stable_id: string;
538
688
  message: string;
@@ -803,4 +953,4 @@ interface ShutdownHandlerDeps {
803
953
  */
804
954
  declare function createShutdownHandler(deps: ShutdownHandlerDeps): () => void;
805
955
 
806
- export { AGENTS_MD_RESOURCE_URI, type ArchiveHistoryEntry, type ArchiveHistoryReport, type CiteCoverageReport, type DoctorApplyLintMutation, type DoctorApplyLintMutationKind, type DoctorApplyLintReport, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type EnrichDescriptionsCandidate, type EnrichDescriptionsMode, type EnrichDescriptionsReport, FABRIC_SERVER_INSTRUCTIONS, type HistoryAllReport, type HistoryDayRow, type InFlightTracker, KnowledgeIdAllocator, type KnowledgeMetaBuildResult, type KnowledgeMetaBuildSource, type KnowledgeSyncLedgerEvent, type KnowledgeSyncOptions, type KnowledgeSyncReport, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, METRICS_LEDGER_PATH, METRIC_COUNTER_NAMES, type MetricCounterName, type MetricsRow, type PlanContextInput, type PlanContextResult, type RecallInput, type RecallResult, type ReconcileKnowledgeOptions, type RequirementProfile, type SelectionTokenState, type ShutdownHandlerDeps, type StructuredWarning, type WriteKnowledgeMetaOptions, appendEventLedgerEvent, buildKnowledgeMeta, bumpCounter, computeKnowledgeBasedAgentsMeta, computeKnowledgeTestIndex, contextCache, createFabricServer, createInFlightTracker, createShutdownHandler, deriveKnowledgeMetaLayer, deriveKnowledgeMetaTopologyType, drainCounters, enrichDescriptions, ensureKnowledgeFresh, extractKnowledge, flushAndSyncEventLedger, flushMetrics, formatPreexistingRootMessage, getEventLedgerPath, getKnowledge, getLedgerPath, getLegacyLedgerPath, getMetricsLedgerPath, invalidateKnowledgeSyncCooldown, isSameKnowledgeTestIndex, loadKbIdTypeMap, planContext, readAgentsMeta, readEventLedger, readLedger, readMetrics, readSelectionToken, recall, reconcileKnowledge, rehydrateAgentsMetaAt, resolveLedgerPaths, reviewKnowledge, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorFix, runDoctorHistoryAll, runDoctorReport, stableStringify, startMetricsFlush, startRotationTick, startStdioServer, stopMetricsFlush, stopRotationTick, writeKnowledgeMeta };
956
+ export { AGENTS_MD_RESOURCE_URI, type ArchiveHistoryEntry, type ArchiveHistoryReport, type CiteCoverageReport, type ConflictEntry, type ConflictJudge, type ConflictLintReport, type ConflictPair, type ConflictVerdict, DEFAULT_CONFLICT_SIMILARITY_THRESHOLD, type DoctorApplyLintMutation, type DoctorApplyLintMutationKind, type DoctorApplyLintReport, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type EnrichDescriptionsCandidate, type EnrichDescriptionsMode, type EnrichDescriptionsReport, FABRIC_SERVER_INSTRUCTIONS, type HistoryAllReport, type HistoryDayRow, type InFlightTracker, KnowledgeIdAllocator, type KnowledgeMetaBuildResult, type KnowledgeMetaBuildSource, type KnowledgeSyncLedgerEvent, type KnowledgeSyncOptions, type KnowledgeSyncReport, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, METRICS_LEDGER_PATH, METRIC_COUNTER_NAMES, type MetricCounterName, type MetricsRow, type PlanContextInput, type PlanContextResult, type RecallInput, type RecallResult, type ReconcileKnowledgeOptions, type RequirementProfile, type SelectionTokenState, type ShutdownHandlerDeps, type StructuredWarning, type WriteKnowledgeMetaOptions, appendEventLedgerEvent, buildKnowledgeMeta, bumpCounter, computeKnowledgeBasedAgentsMeta, computeKnowledgeTestIndex, contextCache, createFabricServer, createInFlightTracker, createShutdownHandler, deriveKnowledgeMetaLayer, deriveKnowledgeMetaTopologyType, drainCounters, enrichDescriptions, ensureKnowledgeFresh, extractKnowledge, findConflictCandidates, flushAndSyncEventLedger, flushMetrics, formatPreexistingRootMessage, getEventLedgerPath, getKnowledge, getLedgerPath, getLegacyLedgerPath, getMetricsLedgerPath, invalidateKnowledgeSyncCooldown, isSameKnowledgeTestIndex, lintConflicts, loadConflictEntries, loadKbIdTypeMap, pairSimilarity, planContext, readAgentsMeta, readEventLedger, readLedger, readMetrics, readSelectionToken, recall, reconcileKnowledge, rehydrateAgentsMetaAt, resolveLedgerPaths, reviewKnowledge, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorConflictLint, runDoctorFix, runDoctorHistoryAll, runDoctorReport, stableStringify, startMetricsFlush, startRotationTick, startStdioServer, stopMetricsFlush, stopRotationTick, writeKnowledgeMeta };