@fenglimg/fabric-server 2.0.0-rc.1 → 2.0.0

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.
@@ -5,16 +5,16 @@ import {
5
5
  appendEventLedgerEvent,
6
6
  contextCache,
7
7
  getEventLedgerPath,
8
+ getKnowledge,
8
9
  getLedgerPath,
9
10
  getLegacyLedgerPath,
10
- getRules,
11
- invalidateRuleSyncCooldown,
11
+ invalidateKnowledgeSyncCooldown,
12
12
  isNodeError,
13
13
  readAgentsMeta,
14
14
  readEventLedger,
15
15
  runDoctorReport,
16
16
  sha256
17
- } from "./chunk-NRWDWAVO.js";
17
+ } from "./chunk-AR2HV5JT.js";
18
18
 
19
19
  // src/http.ts
20
20
  import { randomUUID as randomUUID2 } from "crypto";
@@ -86,7 +86,6 @@ import { join } from "path";
86
86
  import {
87
87
  agentsMetaSchema,
88
88
  fabricEventSchema,
89
- forensicReportSchema,
90
89
  ledgerEntrySchema as ledgerEntrySchema2
91
90
  } from "@fenglimg/fabric-shared";
92
91
  import { eventLedgerEventSchema } from "@fenglimg/fabric-shared";
@@ -131,34 +130,6 @@ async function readLegacyLedger(projectRoot) {
131
130
  }
132
131
  return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line, index) => parseLedgerLine(line, index)).filter((entry) => entry !== null);
133
132
  }
134
- async function appendLedgerEntry(projectRoot, entry) {
135
- const nextEntry = createStoredLedgerEntry(entry);
136
- for (const affectedPath of nextEntry.affected_paths) {
137
- await appendEventLedgerEvent(projectRoot, {
138
- event_type: "edit_intent_checked",
139
- ts: nextEntry.ts,
140
- path: affectedPath,
141
- compliant: true,
142
- intent: nextEntry.intent,
143
- ledger_entry_id: nextEntry.id,
144
- ledger_source: nextEntry.source,
145
- commit_sha: nextEntry.source === "ai" ? nextEntry.commit_sha : void 0,
146
- parent_sha: nextEntry.source === "human" ? nextEntry.parent_sha : void 0,
147
- parent_ledger_entry_id: nextEntry.source === "human" ? nextEntry.parent_ledger_entry_id : void 0,
148
- diff_stat: nextEntry.source === "human" ? nextEntry.diff_stat : void 0,
149
- annotation: nextEntry.source === "human" ? nextEntry.annotation : void 0,
150
- matched_rule_context_ts: null,
151
- window_ms: 0
152
- });
153
- }
154
- return nextEntry;
155
- }
156
- function createStoredLedgerEntry(entry) {
157
- return ledgerEntrySchema.parse({
158
- ...entry,
159
- id: entry.id ?? `ledger:${randomUUID()}`
160
- });
161
- }
162
133
  function parseLedgerLine(line, index) {
163
134
  try {
164
135
  const parsed = JSON.parse(line);
@@ -253,10 +224,8 @@ async function pathExists(path) {
253
224
 
254
225
  // src/api/events.ts
255
226
  var AGENTS_META_PATH = ".fabric/agents.meta.json";
256
- var FORENSIC_PATH = ".fabric/forensic.json";
257
227
  var WATCHED_PATHS = [
258
228
  AGENTS_META_PATH,
259
- FORENSIC_PATH,
260
229
  EVENT_LEDGER_PATH,
261
230
  LEDGER_PATH,
262
231
  LEGACY_LEDGER_PATH
@@ -437,10 +406,6 @@ async function readEventsForFile(state, projectRoot, relativePath) {
437
406
  const event = await readMetaUpdatedEvent(projectRoot);
438
407
  return event === null ? [] : [event];
439
408
  }
440
- if (relativePath === FORENSIC_PATH) {
441
- const event = await readDriftDetectedEvent(projectRoot);
442
- return event === null ? [] : [event];
443
- }
444
409
  if (relativePath === EVENT_LEDGER_PATH) {
445
410
  return await readEventLedgerAppendedEvents(state, projectRoot);
446
411
  }
@@ -461,18 +426,6 @@ async function readMetaUpdatedEvent(projectRoot) {
461
426
  payload: parsed
462
427
  };
463
428
  }
464
- async function readDriftDetectedEvent(projectRoot) {
465
- const filePath = join(projectRoot, FORENSIC_PATH);
466
- const raw = await readUtf8File(filePath);
467
- if (raw === null) {
468
- return null;
469
- }
470
- const parsed = forensicReportSchema.parse(JSON.parse(raw));
471
- return {
472
- type: "drift:detected",
473
- payload: parsed
474
- };
475
- }
476
429
  async function readLedgerAppendedEvents(state, projectRoot) {
477
430
  const ledgerState = await resolveLedgerWatchState(projectRoot);
478
431
  const ledgerPath = ledgerState.path;
@@ -829,60 +782,6 @@ function registerHistoryApi(app, projectRoot) {
829
782
  });
830
783
  }
831
784
 
832
- // src/api/intent.ts
833
- import { annotateIntentRequestSchema } from "@fenglimg/fabric-shared";
834
-
835
- // src/services/annotate-intent.ts
836
- async function annotateIntent(projectRoot, input) {
837
- const entries = await readLedger(projectRoot);
838
- const parentEntry = entries.find((entry2) => entry2.id === input.ledger_entry_id);
839
- if (parentEntry === void 0) {
840
- throw new LedgerEntryNotFoundError(`Cannot find ledger entry: ${input.ledger_entry_id}`);
841
- }
842
- const lastEntry = entries[entries.length - 1];
843
- if (lastEntry?.source === "human" && lastEntry.parent_ledger_entry_id === input.ledger_entry_id && lastEntry.annotation === input.annotation) {
844
- return {
845
- created: false,
846
- entry: lastEntry
847
- };
848
- }
849
- const entry = await appendLedgerEntry(projectRoot, createAnnotationEntry(parentEntry, input));
850
- return {
851
- created: true,
852
- entry
853
- };
854
- }
855
- function createAnnotationEntry(parentEntry, input) {
856
- return {
857
- ts: Date.now(),
858
- source: "human",
859
- parent_sha: input.ledger_entry_id,
860
- parent_ledger_entry_id: input.ledger_entry_id,
861
- intent: input.annotation,
862
- annotation: input.annotation,
863
- affected_paths: parentEntry.affected_paths,
864
- diff_stat: "annotation"
865
- };
866
- }
867
-
868
- // src/api/intent.ts
869
- function registerIntentApi(app, projectRoot) {
870
- app.post("/api/intent/annotate", async (req, res) => {
871
- const validation = annotateIntentRequestSchema.safeParse(req.body);
872
- if (!validation.success) {
873
- sendValidationError(res, "Invalid intent annotation payload", validation.error.flatten());
874
- return;
875
- }
876
- try {
877
- await readAgentsMeta(projectRoot);
878
- const result = await annotateIntent(projectRoot, validation.data);
879
- res.status(result.created ? 201 : 200).json(result);
880
- } catch (error) {
881
- sendUnknownError(res, error);
882
- }
883
- });
884
- }
885
-
886
785
  // src/api/ledger.ts
887
786
  import { ledgerQuerySchema } from "@fenglimg/fabric-shared";
888
787
  function registerLedgerApi(app, projectRoot) {
@@ -904,8 +803,8 @@ function registerLedgerApi(app, projectRoot) {
904
803
  });
905
804
  }
906
805
 
907
- // src/api/rules.ts
908
- function registerRulesApi(app, projectRoot) {
806
+ // src/api/knowledge.ts
807
+ function registerKnowledgeApi(app, projectRoot) {
909
808
  app.get("/api/rules", async (_req, res) => {
910
809
  try {
911
810
  res.json(await readAgentsMeta(projectRoot));
@@ -915,8 +814,8 @@ function registerRulesApi(app, projectRoot) {
915
814
  });
916
815
  }
917
816
 
918
- // src/api/rules-context.ts
919
- function registerRulesContextApi(app, projectRoot) {
817
+ // src/api/knowledge-context.ts
818
+ function registerKnowledgeContextApi(app, projectRoot) {
920
819
  app.get("/api/rules/context", async (req, res) => {
921
820
  const path = typeof req.query.path === "string" ? req.query.path.trim() : "";
922
821
  if (path.length === 0) {
@@ -928,7 +827,7 @@ function registerRulesContextApi(app, projectRoot) {
928
827
  return;
929
828
  }
930
829
  try {
931
- const result = await getRules(projectRoot, { path });
830
+ const result = await getKnowledge(projectRoot, { path });
932
831
  res.json(result.rules);
933
832
  } catch (error) {
934
833
  sendUnknownError(res, error);
@@ -1059,42 +958,6 @@ function buildRecommendations(input) {
1059
958
  return recommendations;
1060
959
  }
1061
960
 
1062
- // src/api/static.ts
1063
- import { existsSync as existsSync2 } from "fs";
1064
- import { dirname, resolve as resolve2 } from "path";
1065
- import { fileURLToPath } from "url";
1066
- import express from "express";
1067
- var DEFAULT_STATIC_DIR = resolve2(dirname(fileURLToPath(import.meta.url)), "static");
1068
- function registerDashboardStatic(app, options = {}) {
1069
- if (options.dev ?? process.env.NODE_ENV === "development") {
1070
- return;
1071
- }
1072
- const staticDir = resolve2(options.dashboardDistPath ?? DEFAULT_STATIC_DIR);
1073
- const indexPath = resolve2(staticDir, "index.html");
1074
- if (!existsSync2(indexPath)) {
1075
- warnMissingDashboard(staticDir);
1076
- app.get("/", (_req, res) => {
1077
- res.status(404).json({
1078
- error: {
1079
- code: "DASHBOARD_DIST_MISSING",
1080
- message: `Fabric dashboard dist was not found at ${staticDir}. Run pnpm --filter @fenglimg/fabric-dashboard build.`
1081
- }
1082
- });
1083
- });
1084
- return;
1085
- }
1086
- app.use("/", express.static(staticDir, { index: "index.html", fallthrough: true }));
1087
- app.get(/^\/(?!api(?:\/|$)|mcp(?:\/|$)|events(?:\/|$)).*/, (_req, res) => {
1088
- res.sendFile(indexPath);
1089
- });
1090
- }
1091
- function warnMissingDashboard(staticDir) {
1092
- process.stderr.write(
1093
- `[fabric-server] dashboard dist missing at ${staticDir}; '/' will return 404 until dashboard assets are built.
1094
- `
1095
- );
1096
- }
1097
-
1098
961
  // src/middleware/bearer-auth.ts
1099
962
  import { createHash, timingSafeEqual } from "crypto";
1100
963
  function createBearerAuthMiddleware(token) {
@@ -1222,11 +1085,11 @@ function handleCacheWatcherEvent(relativePath, projectRoot, sessions, timers) {
1222
1085
  }
1223
1086
  if (normalized.startsWith(".fabric/knowledge/") && normalized.endsWith(".md")) {
1224
1087
  contextCache.invalidate("file_watch", projectRoot);
1225
- invalidateRuleSyncCooldown(projectRoot);
1088
+ invalidateKnowledgeSyncCooldown(projectRoot);
1226
1089
  }
1227
1090
  }
1228
1091
  function createFabricHttpApp(options) {
1229
- const { projectRoot, host = DEFAULT_HOST, authToken, dashboardDistPath, dev } = options;
1092
+ const { projectRoot, host = DEFAULT_HOST, authToken } = options;
1230
1093
  const app = createMcpExpressApp({ host });
1231
1094
  const eventStore = new JsonlEventStore(projectRoot);
1232
1095
  const sessions = /* @__PURE__ */ new Map();
@@ -1280,13 +1143,12 @@ function createFabricHttpApp(options) {
1280
1143
  app.use("/events", bearerAuth);
1281
1144
  app.use("/mcp", bearerAuth);
1282
1145
  }
1283
- registerRulesApi(app, projectRoot);
1284
- registerRulesContextApi(app, projectRoot);
1146
+ registerKnowledgeApi(app, projectRoot);
1147
+ registerKnowledgeContextApi(app, projectRoot);
1285
1148
  registerLedgerApi(app, projectRoot);
1286
1149
  registerHistoryApi(app, projectRoot);
1287
1150
  registerScanApi(app, projectRoot);
1288
1151
  registerDoctorApi(app, projectRoot);
1289
- registerIntentApi(app, projectRoot);
1290
1152
  app.get("/events", createEventsHandler({ projectRoot }));
1291
1153
  app.all("/mcp", async (req, res) => {
1292
1154
  const sessionId = readHeader(req.headers["mcp-session-id"]);
@@ -1306,7 +1168,6 @@ function createFabricHttpApp(options) {
1306
1168
  const session = await createSession(eventStore, sessions);
1307
1169
  await session.transport.handleRequest(req, res, req.body);
1308
1170
  });
1309
- registerDashboardStatic(app, { dashboardDistPath, dev });
1310
1171
  return app;
1311
1172
  }
1312
1173
  function notifyAllSessions(sessions, kind, uri) {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Server } from 'node:http';
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { AgentsMeta, RuleTestIndex, AgentsLayer, AgentsTopologyType, Layer, KnowledgeType, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent } from '@fenglimg/fabric-shared';
3
+ import { AgentsMeta, KnowledgeTestIndex, AgentsLayer, AgentsTopologyType, Layer, KnowledgeType, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem } from '@fenglimg/fabric-shared';
4
+ import { FabExtractKnowledgeInput, FabExtractKnowledgeOutput, FabReviewInput, FabReviewOutput } from '@fenglimg/fabric-shared/schemas/api-contracts';
4
5
  import { IOFabricError } from '@fenglimg/fabric-shared/errors';
5
6
 
6
7
  interface InFlightTracker {
@@ -76,25 +77,43 @@ type DoctorFixReport = {
76
77
  message: string;
77
78
  report: DoctorReport;
78
79
  };
80
+ type DoctorApplyLintMutationKind = "knowledge_orphan_demote_required" | "knowledge_stale_archive_required" | "knowledge_index_drift" | "knowledge_pending_auto_archive" | "knowledge_session_hints_stale_cleanup";
81
+ type DoctorApplyLintMutation = {
82
+ kind: DoctorApplyLintMutationKind;
83
+ path: string;
84
+ detail: string;
85
+ applied: boolean;
86
+ error?: string;
87
+ };
88
+ type DoctorApplyLintReport = {
89
+ changed: boolean;
90
+ mutations: DoctorApplyLintMutation[];
91
+ manual_errors: DoctorIssue[];
92
+ aborted: boolean;
93
+ abort_reason?: string;
94
+ message: string;
95
+ report: DoctorReport;
96
+ };
79
97
  declare function runDoctorReport(target: string): Promise<DoctorReport>;
80
98
  declare function runDoctorFix(target: string): Promise<DoctorFixReport>;
99
+ declare function runDoctorApplyLint(target: string): Promise<DoctorApplyLintReport>;
81
100
 
82
- type RuleMetaBuildSource = "doctor_fix" | "sync_meta";
83
- type RuleMetaBuildResult = {
101
+ type KnowledgeMetaBuildSource = "doctor_fix" | "sync_meta";
102
+ type KnowledgeMetaBuildResult = {
84
103
  meta: AgentsMeta;
85
- ruleTestIndex: RuleTestIndex;
104
+ knowledgeTestIndex: KnowledgeTestIndex;
86
105
  changed: boolean;
87
106
  };
88
- type WriteRuleMetaOptions = {
89
- source: RuleMetaBuildSource;
107
+ type WriteKnowledgeMetaOptions = {
108
+ source: KnowledgeMetaBuildSource;
90
109
  };
91
- declare function buildRuleMeta(projectRootInput: string): Promise<RuleMetaBuildResult>;
92
- declare function writeRuleMeta(projectRootInput: string, options: WriteRuleMetaOptions): Promise<RuleMetaBuildResult>;
93
- declare function computeRulesBasedAgentsMeta(projectRootInput: string, existingMeta?: AgentsMeta): Promise<AgentsMeta>;
94
- declare function computeRuleTestIndex(projectRootInput: string, computedMeta: AgentsMeta, previousIndex?: RuleTestIndex): Promise<RuleTestIndex>;
95
- declare function deriveRuleMetaLayer(relativePath: string): AgentsLayer;
96
- declare function deriveRuleMetaTopologyType(relativePath: string): AgentsTopologyType;
97
- declare function isSameRuleTestIndex(left: RuleTestIndex, right: RuleTestIndex): boolean;
110
+ declare function buildKnowledgeMeta(projectRootInput: string): Promise<KnowledgeMetaBuildResult>;
111
+ declare function writeKnowledgeMeta(projectRootInput: string, options: WriteKnowledgeMetaOptions): Promise<KnowledgeMetaBuildResult>;
112
+ declare function computeKnowledgeBasedAgentsMeta(projectRootInput: string, existingMeta?: AgentsMeta): Promise<AgentsMeta>;
113
+ declare function computeKnowledgeTestIndex(projectRootInput: string, computedMeta: AgentsMeta, previousIndex?: KnowledgeTestIndex): Promise<KnowledgeTestIndex>;
114
+ declare function deriveKnowledgeMetaLayer(relativePath: string): AgentsLayer;
115
+ declare function deriveKnowledgeMetaTopologyType(relativePath: string): AgentsTopologyType;
116
+ declare function isSameKnowledgeTestIndex(left: KnowledgeTestIndex, right: KnowledgeTestIndex): boolean;
98
117
  declare function stableStringify(value: unknown): string;
99
118
 
100
119
  /**
@@ -133,6 +152,39 @@ declare class KnowledgeIdAllocator {
133
152
  private writeMetaAtomic;
134
153
  }
135
154
 
155
+ /**
156
+ * Append-evidence-on-collision service for fab_extract_knowledge.
157
+ *
158
+ * Idempotency_key = sha256({source_session, type, slug}). When the same
159
+ * triple hits an existing pending file (verified by frontmatter
160
+ * `x-fabric-idempotency-key`), the body is preserved and a fresh
161
+ * `## Evidence (call N)` section is appended — LLM-regenerated summaries
162
+ * stay observable without overwriting prior context.
163
+ *
164
+ * NO `id` frontmatter is written — Q2 late-bind delegates id allocation
165
+ * to rc.3 fab_review approve. See planning-context.md "NO id frontmatter".
166
+ */
167
+ declare function extractKnowledge(projectRoot: string, input: FabExtractKnowledgeInput): Promise<FabExtractKnowledgeOutput>;
168
+
169
+ /**
170
+ * v2.0 rc.3 fab_review service.
171
+ *
172
+ * Pure async dispatcher over a discriminated union of 6 actions (list, approve,
173
+ * reject, modify, search, defer). All branches are implemented as of TASK-002.
174
+ *
175
+ * Approve performs late-bind id allocation (KP-/KT- + type-code + monotonic
176
+ * counter via KnowledgeIdAllocator), emits 2-phase events (knowledge_promote_started
177
+ * → knowledge_promoted | knowledge_promote_failed), and uses git mv to preserve
178
+ * file history when the target lives in the team layer (same repo). Personal
179
+ * layer files use plain fs.rename because they live under ~/.fabric/ outside
180
+ * the project's git tree.
181
+ *
182
+ * Modify implements the only legal stable_id mutation: layer-flip across
183
+ * KP/KT counter spaces. Allocates a new id under the target layer, renames
184
+ * the file across layer roots, emits knowledge_layer_changed.
185
+ */
186
+ declare function reviewKnowledge(projectRoot: string, input: FabReviewInput): Promise<FabReviewOutput>;
187
+
136
188
  type StoredEventLedgerEvent = EventLedgerEvent;
137
189
  declare function appendEventLedgerEvent(projectRoot: string, event: EventLedgerEventInput): Promise<StoredEventLedgerEvent>;
138
190
  /**
@@ -145,6 +197,57 @@ declare function appendEventLedgerEvent(projectRoot: string, event: EventLedgerE
145
197
  */
146
198
  declare function flushAndSyncEventLedger(projectRoot: string): void;
147
199
 
200
+ type PlanContextInput = {
201
+ paths: string[];
202
+ intent?: string;
203
+ known_tech?: string[];
204
+ detected_entities?: Record<string, string[]>;
205
+ client_hash?: string;
206
+ correlation_id?: string;
207
+ session_id?: string;
208
+ target_paths?: string[];
209
+ };
210
+ type RequirementProfile = {
211
+ target_path: string;
212
+ path_segments: string[];
213
+ extension: string;
214
+ known_tech: string[];
215
+ user_intent: string;
216
+ detected_entities: string[];
217
+ };
218
+ type PlanContextEntry = {
219
+ path: string;
220
+ requirement_profile: RequirementProfile;
221
+ description_index: RuleDescriptionIndexItem[];
222
+ };
223
+ type PlanContextResult = {
224
+ revision_hash: string;
225
+ stale: boolean;
226
+ selection_token: string;
227
+ entries: PlanContextEntry[];
228
+ shared: {
229
+ description_index: RuleDescriptionIndexItem[];
230
+ preflight_diagnostics: Array<{
231
+ code: "missing_description";
232
+ severity: "warn";
233
+ message: string;
234
+ stable_ids?: string[];
235
+ path?: string;
236
+ }>;
237
+ };
238
+ };
239
+ type SelectionTokenState = {
240
+ token: string;
241
+ revision_hash: string;
242
+ target_paths: string[];
243
+ required_stable_ids: string[];
244
+ ai_selectable_stable_ids: string[];
245
+ created_at: number;
246
+ expires_at: number;
247
+ };
248
+ declare function planContext(projectRoot: string, input: PlanContextInput): Promise<PlanContextResult>;
249
+ declare function readSelectionToken(token: string, now?: number): SelectionTokenState | undefined;
250
+
148
251
  /**
149
252
  * Shared constants used across the server package.
150
253
  */
@@ -152,21 +255,21 @@ declare function flushAndSyncEventLedger(projectRoot: string): void;
152
255
  declare const AGENTS_MD_RESOURCE_URI = "fabric://bootstrap-readme";
153
256
 
154
257
  /**
155
- * rule-sync.ts — Rule-sync orchestrator framework (R28, TASK-011)
258
+ * knowledge-sync.ts — Rule-sync orchestrator framework (R28, TASK-011)
156
259
  *
157
- * Public surface: ensureRulesFresh, reconcileRules + exported types.
260
+ * Public surface: ensureKnowledgeFresh, reconcileKnowledge + exported types.
158
261
  * Internal helpers are co-located in this file.
159
262
  * Does NOT wire any consumers (MCP tools, doctor, watchers).
160
263
  *
161
264
  * Distinction between the two public entry points:
162
265
  *
163
- * - `ensureRulesFresh`: detects drift, emits ledger events, invalidates cache.
266
+ * - `ensureKnowledgeFresh`: detects drift, emits ledger events, invalidates cache.
164
267
  * Does NOT rewrite agents.meta.json. Optimised for hot-path consumers (MCP tools).
165
268
  *
166
- * - `reconcileRules`: full scan + rewrites agents.meta.json (via rule-meta-builder)
269
+ * - `reconcileKnowledge`: full scan + rewrites agents.meta.json (via knowledge-meta-builder)
167
270
  * + emits ledger events. Used by startup (TASK-022) and doctor repair (TASK-023).
168
271
  */
169
- interface RuleSyncOptions {
272
+ interface KnowledgeSyncOptions {
170
273
  mode?: "incremental" | "full";
171
274
  /** When true, invalid frontmatter throws RuleValidationError (default: false — collect as warning). */
172
275
  throwOnInvalidFrontmatter?: boolean;
@@ -178,23 +281,23 @@ interface StructuredWarning {
178
281
  action_hint: string;
179
282
  }
180
283
  /**
181
- * Granular ledger event shape for rule-sync operations.
182
- * These are returned in RuleSyncReport and also appended to the event ledger
284
+ * Granular ledger event shape for knowledge-sync operations.
285
+ * These are returned in KnowledgeSyncReport and also appended to the event ledger
183
286
  * using the nearest available ledger event type (knowledge_drift_detected).
184
287
  * The shape below is what callers receive in `.events`.
185
288
  */
186
- interface RuleSyncLedgerEvent {
289
+ interface KnowledgeSyncLedgerEvent {
187
290
  type: "rule_content_changed" | "rule_added" | "rule_removed";
188
291
  stable_id: string;
189
292
  path: string;
190
293
  prev_hash: string | null;
191
294
  new_hash: string | null;
192
295
  changed_fields: string[];
193
- source: "ensureRulesFresh" | "reconcileRules";
296
+ source: "ensureKnowledgeFresh" | "reconcileKnowledge";
194
297
  }
195
298
  /** Alias so the public API says LedgerEvent (as documented). */
196
- type LedgerEvent = RuleSyncLedgerEvent;
197
- interface RuleSyncReport {
299
+ type LedgerEvent = KnowledgeSyncLedgerEvent;
300
+ interface KnowledgeSyncReport {
198
301
  status: "fresh" | "reconciled" | "errors";
199
302
  events: LedgerEvent[];
200
303
  warnings: StructuredWarning[];
@@ -205,8 +308,8 @@ interface RuleSyncReport {
205
308
  * invalidates the cache. Does NOT rewrite agents.meta.json. Optimised for
206
309
  * hot-path consumers (MCP tools).
207
310
  */
208
- declare function ensureRulesFresh(projectRoot: string, opts?: RuleSyncOptions): Promise<RuleSyncReport>;
209
- interface ReconcileRulesOptions {
311
+ declare function ensureKnowledgeFresh(projectRoot: string, opts?: KnowledgeSyncOptions): Promise<KnowledgeSyncReport>;
312
+ interface ReconcileKnowledgeOptions {
210
313
  /** Identifies who triggered the reconcile; controls which summary ledger event is written. */
211
314
  trigger?: "startup" | "doctor" | "manual";
212
315
  }
@@ -219,7 +322,7 @@ interface ReconcileRulesOptions {
219
322
  * ledger event is appended after per-file drift events. Other trigger values
220
323
  * append a `meta_reconciled` event. Omitting the trigger skips the summary.
221
324
  */
222
- declare function reconcileRules(projectRoot: string, opts?: ReconcileRulesOptions): Promise<RuleSyncReport>;
325
+ declare function reconcileKnowledge(projectRoot: string, opts?: ReconcileKnowledgeOptions): Promise<KnowledgeSyncReport>;
223
326
 
224
327
  declare class ServeLockHeldError extends IOFabricError {
225
328
  readonly code = "SERVE_LOCK_HELD";
@@ -277,8 +380,6 @@ declare function startHttpServer(options: {
277
380
  projectRoot: string;
278
381
  host?: string;
279
382
  authToken?: string;
280
- dashboardDistPath?: string;
281
- dev?: boolean;
282
383
  }): Promise<Server>;
283
384
 
284
- export { AGENTS_MD_RESOURCE_URI, type AcquireOptions, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type InFlightTracker, KnowledgeIdAllocator, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, type LockState, type ReconcileRulesOptions, type RuleMetaBuildResult, type RuleMetaBuildSource, type RuleSyncLedgerEvent, type RuleSyncOptions, type RuleSyncReport, ServeLockHeldError, type ShutdownHandlerDeps, type StructuredWarning, type WriteRuleMetaOptions, acquireLock, appendEventLedgerEvent, buildRuleMeta, checkLockOrThrow, computeRuleTestIndex, computeRulesBasedAgentsMeta, createFabricServer, createInFlightTracker, createShutdownHandler, deriveRuleMetaLayer, deriveRuleMetaTopologyType, ensureRulesFresh, flushAndSyncEventLedger, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, isSameRuleTestIndex, readLockState, reconcileRules, releaseLock, runDoctorFix, runDoctorReport, stableStringify, startHttpServer, startStdioServer, writeRuleMeta };
385
+ export { AGENTS_MD_RESOURCE_URI, type AcquireOptions, type DoctorApplyLintMutation, type DoctorApplyLintMutationKind, type DoctorApplyLintReport, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, 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, ensureKnowledgeFresh, extractKnowledge, flushAndSyncEventLedger, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, isSameKnowledgeTestIndex, planContext, readLockState, readSelectionToken, reconcileKnowledge, releaseLock, reviewKnowledge, runDoctorApplyLint, runDoctorFix, runDoctorReport, stableStringify, startHttpServer, startStdioServer, writeKnowledgeMeta };