@fenglimg/fabric-server 2.0.0-rc.23 → 2.0.0-rc.25

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.
@@ -428,6 +428,27 @@ import {
428
428
  parseKnowledgeId
429
429
  } from "@fenglimg/fabric-shared";
430
430
  import { atomicWriteText as atomicWriteText3 } from "@fenglimg/fabric-shared/node/atomic-write";
431
+ async function loadKbIdTypeMap(projectRootInput) {
432
+ const projectRoot = normalizeProjectRoot(projectRootInput);
433
+ const metaPath = join4(projectRoot, ".fabric", "agents.meta.json");
434
+ const meta = await readExistingMeta(metaPath);
435
+ const map = /* @__PURE__ */ new Map();
436
+ if (meta === void 0) {
437
+ return map;
438
+ }
439
+ for (const node of Object.values(meta.nodes)) {
440
+ const stableId = node.stable_id;
441
+ if (stableId === void 0 || !isKnowledgeStableId(stableId)) {
442
+ continue;
443
+ }
444
+ const knowledgeType = node.description?.knowledge_type;
445
+ if (knowledgeType === void 0) {
446
+ continue;
447
+ }
448
+ map.set(stableId, knowledgeType);
449
+ }
450
+ return map;
451
+ }
431
452
  async function buildKnowledgeMeta(projectRootInput) {
432
453
  const projectRoot = normalizeProjectRoot(projectRootInput);
433
454
  assertExistingDirectory(projectRoot);
@@ -4963,6 +4984,40 @@ async function ensureCitePolicyActivatedMarker(projectRoot) {
4963
4984
  return { marker_ts: 0, emitted_now: false };
4964
4985
  }
4965
4986
  }
4987
+ async function ensureCiteContractPolicyActivatedMarker(projectRoot) {
4988
+ let driftStatus;
4989
+ try {
4990
+ const inspection = await inspectL1BootstrapSnapshotDrift(projectRoot);
4991
+ driftStatus = inspection.status;
4992
+ } catch {
4993
+ driftStatus = "drift";
4994
+ }
4995
+ if (driftStatus !== "ok") {
4996
+ return { marker_ts: 0, emitted_now: false, blocked_by: "bootstrap_drift" };
4997
+ }
4998
+ let existing;
4999
+ try {
5000
+ const { events } = await readEventLedger(projectRoot, {
5001
+ event_type: "cite_contract_policy_activated"
5002
+ });
5003
+ if (events.length > 0) {
5004
+ existing = events[0];
5005
+ }
5006
+ } catch {
5007
+ return { marker_ts: 0, emitted_now: false, blocked_by: null };
5008
+ }
5009
+ if (existing !== void 0) {
5010
+ return { marker_ts: existing.ts, emitted_now: false, blocked_by: null };
5011
+ }
5012
+ try {
5013
+ const stored = await appendEventLedgerEvent(projectRoot, {
5014
+ event_type: "cite_contract_policy_activated"
5015
+ });
5016
+ return { marker_ts: stored.ts, emitted_now: true, blocked_by: null };
5017
+ } catch {
5018
+ return { marker_ts: 0, emitted_now: false, blocked_by: null };
5019
+ }
5020
+ }
4966
5021
  function parseNoneSentinel(kbLineRaw) {
4967
5022
  if (typeof kbLineRaw !== "string" || kbLineRaw.length === 0) return "unspecified";
4968
5023
  const m = kbLineRaw.match(/^KB:\s*none\b\s*(?:\[([^\]]*)\])?\s*$/i);
@@ -5000,7 +5055,10 @@ function matchesRelevancePath(editPath, relevancePaths) {
5000
5055
  return false;
5001
5056
  }
5002
5057
  async function runDoctorCiteCoverage(projectRoot, options) {
5058
+ const layerFilter = options.layer ?? "all";
5003
5059
  const marker = await ensureCitePolicyActivatedMarker(projectRoot);
5060
+ const contractMarker = await ensureCiteContractPolicyActivatedMarker(projectRoot);
5061
+ const idTypeMap = await loadKbIdTypeMap(projectRoot);
5004
5062
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
5005
5063
  const zeroMetrics = {
5006
5064
  edits_touched: 0,
@@ -5009,6 +5067,20 @@ async function runDoctorCiteCoverage(projectRoot, options) {
5009
5067
  expected_but_missed: 0,
5010
5068
  total_turns: 0
5011
5069
  };
5070
+ const contractStatus = contractMarker.blocked_by === "bootstrap_drift" ? "skipped:bootstrap_drift" : contractMarker.marker_ts === 0 ? "awaiting_marker" : "ok";
5071
+ const zeroContractMetrics = {
5072
+ decisions_cited: 0,
5073
+ pitfalls_cited: 0,
5074
+ contract_with: 0,
5075
+ contract_missing: 0,
5076
+ hard_violated: 0,
5077
+ cite_id_unresolved: 0,
5078
+ skip_count: {}
5079
+ };
5080
+ const zeroLayerType = {
5081
+ team: {},
5082
+ personal: {}
5083
+ };
5012
5084
  if (marker.marker_ts === 0) {
5013
5085
  return {
5014
5086
  status: "skipped",
@@ -5016,11 +5088,17 @@ async function runDoctorCiteCoverage(projectRoot, options) {
5016
5088
  marker_emitted_now: false,
5017
5089
  since_ts: options.since,
5018
5090
  client_filter: options.client,
5091
+ layer_filter: layerFilter,
5019
5092
  metrics: zeroMetrics,
5093
+ contract_metrics_status: contractStatus,
5094
+ contract_metrics: zeroContractMetrics,
5095
+ per_layer_type: zeroLayerType,
5096
+ contract_marker_ts: contractMarker.marker_ts,
5020
5097
  generated_at: generatedAt
5021
5098
  };
5022
5099
  }
5023
5100
  const effectiveSince = Math.max(marker.marker_ts, options.since);
5101
+ const contractEffectiveSince = contractStatus === "ok" ? Math.max(contractMarker.marker_ts, options.since) : Number.POSITIVE_INFINITY;
5024
5102
  let ledgerEvents = [];
5025
5103
  try {
5026
5104
  const result = await readEventLedger(projectRoot, { since: effectiveSince });
@@ -5032,7 +5110,12 @@ async function runDoctorCiteCoverage(projectRoot, options) {
5032
5110
  marker_emitted_now: marker.emitted_now,
5033
5111
  since_ts: effectiveSince,
5034
5112
  client_filter: options.client,
5113
+ layer_filter: layerFilter,
5035
5114
  metrics: zeroMetrics,
5115
+ contract_metrics_status: contractStatus,
5116
+ contract_metrics: zeroContractMetrics,
5117
+ per_layer_type: zeroLayerType,
5118
+ contract_marker_ts: contractMarker.marker_ts,
5036
5119
  generated_at: generatedAt
5037
5120
  };
5038
5121
  }
@@ -5125,6 +5208,80 @@ async function runDoctorCiteCoverage(projectRoot, options) {
5125
5208
  perClientAccum.set(client, existing);
5126
5209
  };
5127
5210
  const sessionCitedKbs = /* @__PURE__ */ new Map();
5211
+ const sessionEditPaths = /* @__PURE__ */ new Map();
5212
+ for (const edit of editEvents) {
5213
+ const sid = edit.session_id;
5214
+ if (typeof sid !== "string" || sid.length === 0) continue;
5215
+ const list = sessionEditPaths.get(sid) ?? [];
5216
+ list.push(normalizePath(edit.path));
5217
+ sessionEditPaths.set(sid, list);
5218
+ }
5219
+ let decisionsCited = 0;
5220
+ let pitfallsCited = 0;
5221
+ let contractWith = 0;
5222
+ let contractMissing = 0;
5223
+ let hardViolated = 0;
5224
+ let citeIdUnresolved = 0;
5225
+ const skipCount = {};
5226
+ const layerTypeAccum = { team: {}, personal: {} };
5227
+ const bumpLayerType = (citeId, type) => {
5228
+ const layer = citeId.startsWith("KP-") ? "personal" : citeId.startsWith("KT-") ? "team" : null;
5229
+ if (layer === null) return;
5230
+ layerTypeAccum[layer][type] = (layerTypeAccum[layer][type] ?? 0) + 1;
5231
+ };
5232
+ const passesLayerFilter = (citeId) => {
5233
+ if (layerFilter === "all") return true;
5234
+ if (layerFilter === "team") return citeId.startsWith("KT-");
5235
+ return citeId.startsWith("KP-");
5236
+ };
5237
+ const evaluateOperatorViolation = (sessionId, operators) => {
5238
+ const editPaths = typeof sessionId === "string" && sessionId.length > 0 ? sessionEditPaths.get(sessionId) ?? [] : [];
5239
+ for (const op of operators) {
5240
+ switch (op.kind) {
5241
+ case "edit": {
5242
+ let matched = false;
5243
+ for (const p of editPaths) {
5244
+ if (minimatch(p, op.target, { dot: true, matchBase: false })) {
5245
+ matched = true;
5246
+ break;
5247
+ }
5248
+ }
5249
+ if (!matched) return true;
5250
+ break;
5251
+ }
5252
+ case "not_edit": {
5253
+ for (const p of editPaths) {
5254
+ if (minimatch(p, op.target, { dot: true, matchBase: false })) {
5255
+ return true;
5256
+ }
5257
+ }
5258
+ break;
5259
+ }
5260
+ case "require": {
5261
+ let found = false;
5262
+ for (const p of editPaths) {
5263
+ if (p.includes(op.target)) {
5264
+ found = true;
5265
+ break;
5266
+ }
5267
+ }
5268
+ if (!found) return true;
5269
+ break;
5270
+ }
5271
+ case "forbid": {
5272
+ for (const p of editPaths) {
5273
+ if (p.includes(op.target)) {
5274
+ return true;
5275
+ }
5276
+ }
5277
+ break;
5278
+ }
5279
+ default:
5280
+ break;
5281
+ }
5282
+ }
5283
+ return false;
5284
+ };
5128
5285
  let totalTurns = 0;
5129
5286
  let qualifyingCites = 0;
5130
5287
  let recalledUnverified = 0;
@@ -5174,6 +5331,40 @@ async function runDoctorCiteCoverage(projectRoot, options) {
5174
5331
  m.recalled_unverified += 1;
5175
5332
  });
5176
5333
  }
5334
+ if (contractStatus === "ok" && turn.ts >= contractEffectiveSince) {
5335
+ const commitments = turn.cite_commitments ?? [];
5336
+ for (let i = 0; i < turn.cite_ids.length; i += 1) {
5337
+ const citeId = turn.cite_ids[i];
5338
+ if (typeof citeId !== "string" || citeId.length === 0) continue;
5339
+ if (!passesLayerFilter(citeId)) continue;
5340
+ const kbType = idTypeMap.get(citeId);
5341
+ if (kbType === void 0) {
5342
+ citeIdUnresolved += 1;
5343
+ bumpLayerType(citeId, "unresolved");
5344
+ continue;
5345
+ }
5346
+ bumpLayerType(citeId, kbType);
5347
+ if (kbType === "decision" || kbType === "pitfall") {
5348
+ if (kbType === "decision") decisionsCited += 1;
5349
+ else pitfallsCited += 1;
5350
+ const commitment = commitments[i];
5351
+ const operators = commitment?.operators ?? [];
5352
+ const skipReason = commitment?.skip_reason ?? null;
5353
+ if (skipReason !== null) {
5354
+ skipCount[skipReason] = (skipCount[skipReason] ?? 0) + 1;
5355
+ continue;
5356
+ }
5357
+ if (operators.length === 0) {
5358
+ contractMissing += 1;
5359
+ continue;
5360
+ }
5361
+ contractWith += 1;
5362
+ if (evaluateOperatorViolation(sid, operators)) {
5363
+ hardViolated += 1;
5364
+ }
5365
+ }
5366
+ }
5367
+ }
5177
5368
  }
5178
5369
  let editsTouched = 0;
5179
5370
  let expectedButMissed = 0;
@@ -5208,19 +5399,96 @@ async function runDoctorCiteCoverage(projectRoot, options) {
5208
5399
  perClient[client] = m;
5209
5400
  }
5210
5401
  }
5402
+ const contractMetrics = {
5403
+ decisions_cited: decisionsCited,
5404
+ pitfalls_cited: pitfallsCited,
5405
+ contract_with: contractWith,
5406
+ contract_missing: contractMissing,
5407
+ hard_violated: hardViolated,
5408
+ cite_id_unresolved: citeIdUnresolved,
5409
+ skip_count: skipCount
5410
+ };
5211
5411
  return {
5212
5412
  status: "ok",
5213
5413
  marker_ts: marker.marker_ts,
5214
5414
  marker_emitted_now: marker.emitted_now,
5215
5415
  since_ts: effectiveSince,
5216
5416
  client_filter: options.client,
5417
+ layer_filter: layerFilter,
5217
5418
  metrics,
5218
5419
  ...perClient !== void 0 ? { per_client: perClient } : {},
5219
5420
  ...Object.keys(dismissedHistogram).length > 0 ? { dismissed_reason_histogram: dismissedHistogram } : {},
5220
5421
  ...Object.keys(noneHistogram).length > 0 ? { none_reason_histogram: noneHistogram } : {},
5422
+ contract_metrics_status: contractStatus,
5423
+ contract_metrics: contractMetrics,
5424
+ per_layer_type: layerTypeAccum,
5425
+ contract_marker_ts: contractMarker.marker_ts,
5221
5426
  generated_at: generatedAt
5222
5427
  };
5223
5428
  }
5429
+ async function runDoctorArchiveHistory(projectRoot, options) {
5430
+ const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
5431
+ const nowMs = Date.now();
5432
+ let events = [];
5433
+ try {
5434
+ const result = await readEventLedger(projectRoot, {
5435
+ event_type: "session_archive_attempted",
5436
+ since: options.since
5437
+ });
5438
+ events = result.events;
5439
+ } catch {
5440
+ return {
5441
+ entries: [],
5442
+ total: 0,
5443
+ since_ms: options.since,
5444
+ generated_at: generatedAt
5445
+ };
5446
+ }
5447
+ const mostRecentBySession = /* @__PURE__ */ new Map();
5448
+ for (const event of events) {
5449
+ if (event.event_type !== "session_archive_attempted") {
5450
+ continue;
5451
+ }
5452
+ const sessionId = event.session_id;
5453
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
5454
+ continue;
5455
+ }
5456
+ const prior = mostRecentBySession.get(sessionId);
5457
+ if (prior === void 0 || event.ts > prior.ts) {
5458
+ mostRecentBySession.set(sessionId, event);
5459
+ }
5460
+ }
5461
+ const entries = [];
5462
+ for (const [sessionId, event] of mostRecentBySession.entries()) {
5463
+ const ageHours = Math.max(
5464
+ 0,
5465
+ Math.floor((nowMs - event.covered_through_ts) / 36e5)
5466
+ );
5467
+ entries.push({
5468
+ session_id_short: truncateSessionId(sessionId),
5469
+ last_attempted_at: new Date(event.ts).toISOString(),
5470
+ outcome: event.outcome,
5471
+ candidates_proposed: event.candidates_proposed,
5472
+ covered_through_ts: event.covered_through_ts,
5473
+ age_since_covered_hours: ageHours
5474
+ });
5475
+ }
5476
+ entries.sort(
5477
+ (a, b) => a.last_attempted_at < b.last_attempted_at ? 1 : a.last_attempted_at > b.last_attempted_at ? -1 : 0
5478
+ );
5479
+ return {
5480
+ entries,
5481
+ total: entries.length,
5482
+ since_ms: options.since,
5483
+ generated_at: generatedAt
5484
+ };
5485
+ }
5486
+ function truncateSessionId(sessionId) {
5487
+ if (sessionId.length <= 8) {
5488
+ return sessionId;
5489
+ }
5490
+ return `${sessionId.slice(0, 8)}...`;
5491
+ }
5224
5492
  function createFixMessage(fixed, report) {
5225
5493
  const fixedText = fixed.length === 0 ? "No deterministic doctor fixes were needed." : `Applied ${fixed.length} deterministic doctor fix${fixed.length === 1 ? "" : "es"}.`;
5226
5494
  const manualText = report.manual_errors.length === 0 ? "No manual errors remain." : `${report.manual_errors.length} manual error${report.manual_errors.length === 1 ? "" : "s"} remain.`;
@@ -5734,6 +6002,7 @@ export {
5734
6002
  appendEventLedgerEvent,
5735
6003
  readEventLedger,
5736
6004
  flushAndSyncEventLedger,
6005
+ loadKbIdTypeMap,
5737
6006
  buildKnowledgeMeta,
5738
6007
  writeKnowledgeMeta,
5739
6008
  computeKnowledgeBasedAgentsMeta,
@@ -5758,5 +6027,6 @@ export {
5758
6027
  runDoctorFix,
5759
6028
  runDoctorApplyLint,
5760
6029
  runDoctorCiteCoverage,
6030
+ runDoctorArchiveHistory,
5761
6031
  enrichDescriptions
5762
6032
  };
@@ -14,7 +14,7 @@ import {
14
14
  readEventLedger,
15
15
  runDoctorReport,
16
16
  sha256
17
- } from "./chunk-IRB77C6E.js";
17
+ } from "./chunk-HAXROPQM.js";
18
18
 
19
19
  // src/http.ts
20
20
  import { randomUUID as randomUUID2 } from "crypto";
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Server } from 'node:http';
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { AgentsMeta, KnowledgeTestIndex, AgentsLayer, AgentsTopologyType, Layer, KnowledgeType, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem } from '@fenglimg/fabric-shared';
3
+ import { AgentsMeta, KnowledgeTestIndex, AgentsLayer, AgentsTopologyType, KnowledgeType, Layer, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem } from '@fenglimg/fabric-shared';
4
4
  import { FabExtractKnowledgeInput, FabExtractKnowledgeOutput, FabReviewInput, FabReviewOutput } from '@fenglimg/fabric-shared/schemas/api-contracts';
5
5
  import { IOFabricError } from '@fenglimg/fabric-shared/errors';
6
6
 
@@ -97,12 +97,26 @@ type DoctorApplyLintReport = {
97
97
  declare function runDoctorReport(target: string): Promise<DoctorReport>;
98
98
  declare function runDoctorFix(target: string): Promise<DoctorFixReport>;
99
99
  declare function runDoctorApplyLint(target: string): Promise<DoctorApplyLintReport>;
100
+ type CiteContractMetrics = {
101
+ decisions_cited: number;
102
+ pitfalls_cited: number;
103
+ contract_with: number;
104
+ contract_missing: number;
105
+ hard_violated: number;
106
+ cite_id_unresolved: number;
107
+ skip_count: Record<string, number>;
108
+ };
109
+ type CiteLayerTypeBreakdown = {
110
+ team: Record<string, number>;
111
+ personal: Record<string, number>;
112
+ };
100
113
  type CiteCoverageReport = {
101
114
  status: "ok" | "skipped";
102
115
  marker_ts: number;
103
116
  marker_emitted_now: boolean;
104
117
  since_ts: number;
105
118
  client_filter: "cc" | "codex" | "cursor" | "all";
119
+ layer_filter?: "team" | "personal" | "all";
106
120
  metrics: {
107
121
  edits_touched: number;
108
122
  qualifying_cites: number;
@@ -113,12 +127,34 @@ type CiteCoverageReport = {
113
127
  per_client?: Record<string, Partial<CiteCoverageReport["metrics"]>>;
114
128
  dismissed_reason_histogram?: Record<string, number>;
115
129
  none_reason_histogram?: Record<string, number>;
130
+ contract_metrics_status?: "ok" | "skipped:bootstrap_drift" | "awaiting_marker";
131
+ contract_metrics?: CiteContractMetrics;
132
+ per_layer_type?: CiteLayerTypeBreakdown;
133
+ contract_marker_ts?: number;
116
134
  generated_at: string;
117
135
  };
118
136
  declare function runDoctorCiteCoverage(projectRoot: string, options: {
119
137
  since: number;
120
138
  client: "cc" | "codex" | "cursor" | "all";
139
+ layer?: "team" | "personal" | "all";
121
140
  }): Promise<CiteCoverageReport>;
141
+ type ArchiveHistoryEntry = {
142
+ session_id_short: string;
143
+ last_attempted_at: string;
144
+ outcome: "proposed" | "viability_failed" | "user_dismissed" | "skipped_no_signal";
145
+ candidates_proposed: number;
146
+ covered_through_ts: number;
147
+ age_since_covered_hours: number;
148
+ };
149
+ type ArchiveHistoryReport = {
150
+ entries: ArchiveHistoryEntry[];
151
+ total: number;
152
+ since_ms: number;
153
+ generated_at: string;
154
+ };
155
+ declare function runDoctorArchiveHistory(projectRoot: string, options: {
156
+ since: number;
157
+ }): Promise<ArchiveHistoryReport>;
122
158
  type EnrichDescriptionsMode = "auto" | "interactive";
123
159
  type EnrichDescriptionsCandidate = {
124
160
  path: string;
@@ -149,6 +185,31 @@ type KnowledgeMetaBuildResult = {
149
185
  type WriteKnowledgeMetaOptions = {
150
186
  source: KnowledgeMetaBuildSource;
151
187
  };
188
+ /**
189
+ * v2.0-rc.24 TASK-07: Load a Map<stable_id, knowledge_type> from the
190
+ * project's `.fabric/agents.meta.json`. Consumed by the doctor cite-coverage
191
+ * routing (TASK-08) to dispatch cites to the correct policy bucket
192
+ * (decision/pitfall = strict contract / model = reference-only /
193
+ * guideline+process = deferred to rc.25 LLM-judge). Cited ids absent from
194
+ * this map fall into the `cite_id_unresolved` bucket.
195
+ *
196
+ * **Singular knowledge_type contract (rc.24 lock):** the returned map values
197
+ * are the SINGULAR `KnowledgeType` enum (`"model" | "decision" | "guideline"
198
+ * | "pitfall" | "process"`) — matching both the on-disk `agents.meta.json`
199
+ * storage AND the canonical `KnowledgeTypeSchema` exported from
200
+ * `@fenglimg/fabric-shared`. No normalization happens at this boundary; the
201
+ * loader is a thin extract over engine-maintained meta. Downstream callers
202
+ * (TASK-08 doctor) must match against the singular enum.
203
+ *
204
+ * Both team (KT-*) and personal (KP-*) entries are included — they live in
205
+ * the same `meta.nodes` map.
206
+ *
207
+ * Graceful on failure: a missing meta file, malformed JSON, or schema
208
+ * validation failure all yield an empty Map (no throw). The doctor will then
209
+ * surface every cite as `cite_id_unresolved`, which is the safe degraded
210
+ * mode.
211
+ */
212
+ declare function loadKbIdTypeMap(projectRootInput: string): Promise<Map<string, KnowledgeType>>;
152
213
  declare function buildKnowledgeMeta(projectRootInput: string): Promise<KnowledgeMetaBuildResult>;
153
214
  declare function writeKnowledgeMeta(projectRootInput: string, options: WriteKnowledgeMetaOptions): Promise<KnowledgeMetaBuildResult>;
154
215
  declare function computeKnowledgeBasedAgentsMeta(projectRootInput: string, existingMeta?: AgentsMeta): Promise<AgentsMeta>;
@@ -435,4 +496,4 @@ declare function startHttpServer(options: {
435
496
  authToken?: string;
436
497
  }): Promise<Server>;
437
498
 
438
- export { AGENTS_MD_RESOURCE_URI, type AcquireOptions, type CiteCoverageReport, type DoctorApplyLintMutation, type DoctorApplyLintMutationKind, type DoctorApplyLintReport, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type EnrichDescriptionsCandidate, type EnrichDescriptionsMode, type EnrichDescriptionsReport, type InFlightTracker, KnowledgeIdAllocator, type KnowledgeMetaBuildResult, type KnowledgeMetaBuildSource, type KnowledgeSyncLedgerEvent, type KnowledgeSyncOptions, type KnowledgeSyncReport, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, type LockState, type PlanContextInput, type PlanContextResult, type ReconcileKnowledgeOptions, type RequirementProfile, type SelectionTokenState, ServeLockHeldError, type ShutdownHandlerDeps, type StructuredWarning, type WriteKnowledgeMetaOptions, acquireLock, appendEventLedgerEvent, buildKnowledgeMeta, checkLockOrThrow, computeKnowledgeBasedAgentsMeta, computeKnowledgeTestIndex, createFabricServer, createInFlightTracker, createShutdownHandler, deriveKnowledgeMetaLayer, deriveKnowledgeMetaTopologyType, enrichDescriptions, ensureKnowledgeFresh, extractKnowledge, flushAndSyncEventLedger, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, isSameKnowledgeTestIndex, planContext, readLockState, readSelectionToken, reconcileKnowledge, releaseLock, reviewKnowledge, runDoctorApplyLint, runDoctorCiteCoverage, runDoctorFix, runDoctorReport, stableStringify, startHttpServer, startStdioServer, writeKnowledgeMeta };
499
+ export { AGENTS_MD_RESOURCE_URI, type AcquireOptions, 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, type InFlightTracker, KnowledgeIdAllocator, type KnowledgeMetaBuildResult, type KnowledgeMetaBuildSource, type KnowledgeSyncLedgerEvent, type KnowledgeSyncOptions, type KnowledgeSyncReport, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, type LockState, type PlanContextInput, type PlanContextResult, type ReconcileKnowledgeOptions, type RequirementProfile, type SelectionTokenState, ServeLockHeldError, type ShutdownHandlerDeps, type StructuredWarning, type WriteKnowledgeMetaOptions, acquireLock, appendEventLedgerEvent, buildKnowledgeMeta, checkLockOrThrow, computeKnowledgeBasedAgentsMeta, computeKnowledgeTestIndex, createFabricServer, createInFlightTracker, createShutdownHandler, deriveKnowledgeMetaLayer, deriveKnowledgeMetaTopologyType, enrichDescriptions, ensureKnowledgeFresh, extractKnowledge, flushAndSyncEventLedger, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, isSameKnowledgeTestIndex, loadKbIdTypeMap, planContext, readLockState, readSelectionToken, reconcileKnowledge, releaseLock, reviewKnowledge, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorFix, runDoctorReport, stableStringify, startHttpServer, startStdioServer, writeKnowledgeMeta };
package/dist/index.js CHANGED
@@ -23,19 +23,21 @@ import {
23
23
  isSameKnowledgeTestIndex,
24
24
  loadActiveMeta,
25
25
  loadActiveMetaOrStale,
26
+ loadKbIdTypeMap,
26
27
  normalizeKnowledgePath,
27
28
  readLockState,
28
29
  reconcileKnowledge,
29
30
  releaseLock,
30
31
  resolveProjectRoot,
31
32
  runDoctorApplyLint,
33
+ runDoctorArchiveHistory,
32
34
  runDoctorCiteCoverage,
33
35
  runDoctorFix,
34
36
  runDoctorReport,
35
37
  sha256,
36
38
  stableStringify,
37
39
  writeKnowledgeMeta
38
- } from "./chunk-IRB77C6E.js";
40
+ } from "./chunk-HAXROPQM.js";
39
41
 
40
42
  // src/index.ts
41
43
  import { existsSync as existsSync4 } from "fs";
@@ -1892,7 +1894,7 @@ function formatPreexistingRootMessage(projectRoot) {
1892
1894
  function createFabricServer(tracker) {
1893
1895
  const server = new McpServer({
1894
1896
  name: "fabric-knowledge-server",
1895
- version: "2.0.0-rc.23"
1897
+ version: "2.0.0-rc.25"
1896
1898
  });
1897
1899
  registerPlanContext(server, tracker);
1898
1900
  registerKnowledgeSections(server, tracker);
@@ -2000,7 +2002,7 @@ function createShutdownHandler(deps) {
2000
2002
  };
2001
2003
  }
2002
2004
  async function startHttpServer(options) {
2003
- const { createFabricHttpApp } = await import("./http-ZBV6YUHD.js");
2005
+ const { createFabricHttpApp } = await import("./http-QBGLHCHA.js");
2004
2006
  const { port, projectRoot, host = "127.0.0.1", authToken } = options;
2005
2007
  const app = createFabricHttpApp({ projectRoot, host, authToken });
2006
2008
  return await new Promise((resolveServer, rejectServer) => {
@@ -2052,6 +2054,7 @@ export {
2052
2054
  getLedgerPath,
2053
2055
  getLegacyLedgerPath,
2054
2056
  isSameKnowledgeTestIndex,
2057
+ loadKbIdTypeMap,
2055
2058
  planContext,
2056
2059
  readLockState,
2057
2060
  readSelectionToken,
@@ -2059,6 +2062,7 @@ export {
2059
2062
  releaseLock,
2060
2063
  reviewKnowledge,
2061
2064
  runDoctorApplyLint,
2065
+ runDoctorArchiveHistory,
2062
2066
  runDoctorCiteCoverage,
2063
2067
  runDoctorFix,
2064
2068
  runDoctorReport,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-server",
3
- "version": "2.0.0-rc.23",
3
+ "version": "2.0.0-rc.25",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "express": "^5.2.1",
14
14
  "minimatch": "^10.0.1",
15
15
  "zod": "^3.25.0",
16
- "@fenglimg/fabric-shared": "2.0.0-rc.23"
16
+ "@fenglimg/fabric-shared": "2.0.0-rc.25"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/express": "^5.0.6",