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

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/README.md CHANGED
@@ -6,7 +6,7 @@ Fabric MCP knowledge server. Runs over stdio transport and serves Claude Code an
6
6
 
7
7
  - `fab_recall` — single-step recall: returns candidate descriptions + native read paths (no body delivery over MCP; read a body on demand via a native Read of the returned path)
8
8
  - `fab_archive_scan` — scan recent work for archive-worthy knowledge candidates
9
- - `fab_extract_knowledge` — persist a pending knowledge entry
9
+ - `fab_propose` — persist a pending knowledge entry
10
10
  - `fab_review` — list / approve / reject / modify / defer pending entries
11
11
 
12
12
  ## Install
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { FabExtractKnowledgeInput, FabExtractKnowledgeOutput, FabReviewInput, FabReviewOutput } from '@fenglimg/fabric-shared/schemas/api-contracts';
2
+ import { FabExtractKnowledgeInput, FabExtractKnowledgeOutput, FabReviewInput, FabReviewOutput, FabPendingInput, FabPendingOutput } from '@fenglimg/fabric-shared/schemas/api-contracts';
3
3
  import { EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem, LedgerEntry, AgentsMeta } from '@fenglimg/fabric-shared';
4
4
  import { PayloadGuardOptions } from '@fenglimg/fabric-shared/node/mcp-payload-guard';
5
5
 
@@ -379,24 +379,26 @@ declare function enrichDescriptions(projectRoot: string, opts?: {
379
379
  dryRun?: boolean;
380
380
  }): Promise<EnrichDescriptionsReport>;
381
381
 
382
+ type Bm25Field = "title" | "summary" | "tags" | "body";
382
383
  interface Bm25Document {
383
384
  id: string;
384
- tokens: string[];
385
+ /** Pre-tokenized terms per field. Omitted/empty fields contribute nothing. */
386
+ fields: Record<Bm25Field, string[]>;
385
387
  }
386
388
  interface Bm25Model {
387
389
  /**
388
- * BM25 score of document `id` against the (pre-tokenized) query terms.
389
- * Returns 0 for an unknown id, an empty document, no query terms, or no
390
- * term overlap. Query-term duplicates are collapsed — repeating a term in
391
- * the query does not inflate the score (term frequency is a document
392
- * property, not a query property).
390
+ * BM25F score of document `id` against the (pre-tokenized) query terms.
391
+ * Returns 0 for an unknown id, no query terms, or no term overlap in any
392
+ * field. Query-term duplicates are collapsed — repeating a term in the query
393
+ * does not inflate the score (term frequency is a document property, not a
394
+ * query property).
393
395
  */
394
396
  scoreDoc(id: string, queryTerms: string[]): number;
395
397
  }
396
398
  /**
397
- * Build a BM25 model over `docs`. The corpus statistics (document frequency,
398
- * average document length) are computed once here; `scoreDoc` is then O(query
399
- * terms) per call.
399
+ * Build a BM25F model over `docs`. Corpus statistics (per-field document
400
+ * frequency over the union of fields, per-field average length) are computed
401
+ * once here; `scoreDoc` is then O(query terms × fields) per call.
400
402
  */
401
403
  declare function buildBm25Model(docs: Bm25Document[]): Bm25Model;
402
404
 
@@ -505,8 +507,51 @@ declare function runDoctorConflictLint(projectRoot: string, opts?: {
505
507
  judge?: ConflictJudge;
506
508
  }): Promise<ConflictLintReport>;
507
509
 
510
+ interface RetiredToken {
511
+ /** The exact dead token as it appears in agent-facing text. */
512
+ token: string;
513
+ /** What replaced it (shown in the remediation), or null when simply removed. */
514
+ replacement: string | null;
515
+ /** Short why-retired note. */
516
+ reason: string;
517
+ }
518
+ declare const RETIRED_TOKENS: readonly RetiredToken[];
519
+ interface RetiredReferenceHit {
520
+ /** Project-relative POSIX path of the offending file. */
521
+ path: string;
522
+ token: string;
523
+ line: number;
524
+ replacement: string | null;
525
+ }
526
+ interface RetiredReferenceInspection {
527
+ status: "ok" | "warn" | "skipped";
528
+ scannedFiles: number;
529
+ hits: RetiredReferenceHit[];
530
+ }
531
+ declare function inspectRetiredReferences(projectRoot: string): Promise<RetiredReferenceInspection>;
532
+
533
+ type SurfaceVerdict = "not_found" | "store_unbound" | "project_mismatch" | "narrow_timing" | "should_surface";
534
+ interface WhyNotSurfacedResult {
535
+ /** The id exactly as queried. */
536
+ query: string;
537
+ /** Normalized LOCAL stable id (store-qualified `alias:ID` → `ID`). */
538
+ localId: string;
539
+ verdict: SurfaceVerdict;
540
+ /** Store the entry physically lives in, or null when not found. */
541
+ storeAlias: string | null;
542
+ /** Whether that store is in this project's read-set (null when not found). */
543
+ storeBound: boolean | null;
544
+ /** Entry's semantic_scope coordinate (audience axis), or null. */
545
+ semanticScope: string | null;
546
+ /** This repo's bound project coordinate segment, or null when unbound. */
547
+ activeProject: string | null;
548
+ /** Entry's relevance_scope (timing axis); defaults to "broad" when absent. */
549
+ relevanceScope: "broad" | "narrow" | null;
550
+ }
551
+ declare function explainWhyNotSurfaced(projectRoot: string, query: string): Promise<WhyNotSurfacedResult>;
552
+
508
553
  /**
509
- * Append-evidence-on-collision service for fab_extract_knowledge.
554
+ * Append-evidence-on-collision service for fab_propose.
510
555
  *
511
556
  * Idempotency_key = sha256({source_session: source_sessions[0], type, slug}).
512
557
  * The `source_session` key inside the hash payload is FROZEN for backward
@@ -523,10 +568,12 @@ declare function runDoctorConflictLint(projectRoot: string, opts?: {
523
568
  declare function extractKnowledge(projectRoot: string, input: FabExtractKnowledgeInput): Promise<FabExtractKnowledgeOutput>;
524
569
 
525
570
  /**
526
- * v2.0 rc.3 fab_review service.
571
+ * v2.0 rc.3 fab_review service (W3-K K2: WRITE-only).
527
572
  *
528
- * Pure async dispatcher over a discriminated union of 6 actions (list, approve,
529
- * reject, modify, search, defer). All branches are implemented as of TASK-002.
573
+ * Pure async dispatcher over a discriminated union of 6 WRITE actions (approve,
574
+ * reject, modify, modify-content, modify-layer, defer). The two READ actions
575
+ * (list / search) were lifted out into `reviewPending` (the fab_pending tool) —
576
+ * pure relocation, ZERO behavior change.
530
577
  *
531
578
  * Approve performs late-bind id allocation (KP-/KT- + type-code + monotonic
532
579
  * counter via KnowledgeIdAllocator), emits 2-phase events (knowledge_promote_started
@@ -540,6 +587,17 @@ declare function extractKnowledge(projectRoot: string, input: FabExtractKnowledg
540
587
  * the file across layer roots, emits knowledge_layer_changed.
541
588
  */
542
589
  declare function reviewKnowledge(projectRoot: string, input: FabReviewInput): Promise<FabReviewOutput>;
590
+ /**
591
+ * fab_pending service (W3-K K2: READ-only).
592
+ *
593
+ * Pure async dispatcher over the two READ actions (list / search) relocated
594
+ * from `reviewKnowledge`. list browses the store-backed pending backlog;
595
+ * search ranges over BOTH pending and canonical knowledge. Neither mutates
596
+ * state — the fab_pending tool is registered readOnlyHint:true / idempotentHint:true.
597
+ * The underlying listPending / searchEntries helpers are unchanged (verbatim
598
+ * relocation), so behavior is identical to the prior fab_review list/search.
599
+ */
600
+ declare function reviewPending(projectRoot: string, input: FabPendingInput): Promise<FabPendingOutput>;
543
601
 
544
602
  /** A summary to be cold-judged, keyed by its stable_id. */
545
603
  interface ColdEvalCandidate {
@@ -662,7 +720,10 @@ type PlanContextResult = {
662
720
  entries: PlanContextEntry[];
663
721
  intent?: string;
664
722
  candidates: RuleDescriptionIndexItem[];
665
- omitted_candidate_count?: number;
723
+ dropped?: {
724
+ id: string;
725
+ reason: "retrieval_budget" | "payload_budget";
726
+ }[];
666
727
  preflight_diagnostics: PreflightDiagnostic[];
667
728
  auto_healed?: boolean;
668
729
  previous_revision_hash?: string;
@@ -703,15 +764,18 @@ type RecallInput = PlanContextInput & {
703
764
  */
704
765
  include_related?: boolean;
705
766
  };
706
- type RecallPath = {
767
+ type RecallEntry = {
707
768
  stable_id: string;
708
- path: string;
769
+ rank: number;
770
+ description: PlanContextResult["candidates"][number]["description"];
771
+ read_path?: string;
709
772
  store?: {
710
773
  alias: string;
711
774
  };
775
+ body_in_context?: boolean;
712
776
  };
713
- type RecallResult = Omit<PlanContextResult, "selection_token" | "payload_trimmed" | "payload_over_budget"> & {
714
- paths: RecallPath[];
777
+ type RecallResult = Omit<PlanContextResult, "selection_token" | "payload_trimmed" | "payload_over_budget" | "entries" | "candidates"> & {
778
+ entries: RecallEntry[];
715
779
  directive: string;
716
780
  next_steps?: string[];
717
781
  };
@@ -857,4 +921,4 @@ interface ShutdownHandlerDeps {
857
921
  */
858
922
  declare function createShutdownHandler(deps: ShutdownHandlerDeps): () => void;
859
923
 
860
- export { AGENTS_MD_RESOURCE_URI, type AlwaysActiveBody, type ArchiveHistoryEntry, type ArchiveHistoryReport, COLD_EVAL_RUBRIC, type CiteCoverageReport, type ColdEvalBatch, type ColdEvalCandidate, type ColdEvalVerdict, 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, type KnowledgeCensus, LEDGER_PATH, LEGACY_LEDGER_PATH, METRICS_LEDGER_PATH, METRIC_COUNTER_NAMES, type MetricCounterName, type MetricsRow, type PlanContextInput, type PlanContextResult, type RecallInput, type RecallResult, type RequirementProfile, type SelectionTokenState, type ShutdownHandlerDeps, type UnboundProjectViolation, appendEventLedgerEvent, buildAlwaysActiveBodies, buildColdEvalBatch, buildKnowledgeCensus, bumpCounter, contextCache, createFabricServer, createInFlightTracker, createShutdownHandler, detectUnboundProject, drainCounters, enrichDescriptions, extractKnowledge, findConflictCandidates, flushAndSyncEventLedger, flushMetrics, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, getMetricsLedgerPath, lintConflicts, loadConflictEntries, pairSimilarity, planContext, readEventLedger, readLedger, readMetrics, readSelectionToken, recall, rehydrateAgentsMetaAt, resolveLedgerPaths, reviewKnowledge, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorConflictLint, runDoctorFix, runDoctorHistoryAll, runDoctorReport, startMetricsFlush, startRotationTick, startStdioServer, stopMetricsFlush, stopRotationTick };
924
+ export { AGENTS_MD_RESOURCE_URI, type AlwaysActiveBody, type ArchiveHistoryEntry, type ArchiveHistoryReport, COLD_EVAL_RUBRIC, type CiteCoverageReport, type ColdEvalBatch, type ColdEvalCandidate, type ColdEvalVerdict, 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, type KnowledgeCensus, LEDGER_PATH, LEGACY_LEDGER_PATH, METRICS_LEDGER_PATH, METRIC_COUNTER_NAMES, type MetricCounterName, type MetricsRow, type PlanContextInput, type PlanContextResult, RETIRED_TOKENS, type RecallInput, type RecallResult, type RequirementProfile, type RetiredReferenceHit, type RetiredReferenceInspection, type RetiredToken, type SelectionTokenState, type ShutdownHandlerDeps, type SurfaceVerdict, type UnboundProjectViolation, type WhyNotSurfacedResult, appendEventLedgerEvent, buildAlwaysActiveBodies, buildColdEvalBatch, buildKnowledgeCensus, bumpCounter, contextCache, createFabricServer, createInFlightTracker, createShutdownHandler, detectUnboundProject, drainCounters, enrichDescriptions, explainWhyNotSurfaced, extractKnowledge, findConflictCandidates, flushAndSyncEventLedger, flushMetrics, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, getMetricsLedgerPath, inspectRetiredReferences, lintConflicts, loadConflictEntries, pairSimilarity, planContext, readEventLedger, readLedger, readMetrics, readSelectionToken, recall, rehydrateAgentsMetaAt, resolveLedgerPaths, reviewKnowledge, reviewPending, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorConflictLint, runDoctorFix, runDoctorHistoryAll, runDoctorReport, startMetricsFlush, startRotationTick, startStdioServer, stopMetricsFlush, stopRotationTick };