@fenglimg/fabric-server 1.8.0-rc.3 → 2.0.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.
@@ -1,5 +1,4 @@
1
1
  import {
2
- AGENTS_MD_RESOURCE_URI,
3
2
  EVENT_LEDGER_PATH,
4
3
  LEDGER_PATH,
5
4
  LEGACY_LEDGER_PATH,
@@ -15,7 +14,7 @@ import {
15
14
  readEventLedger,
16
15
  runDoctorReport,
17
16
  sha256
18
- } from "./chunk-ZZGARZL5.js";
17
+ } from "./chunk-NRWDWAVO.js";
19
18
 
20
19
  // src/http.ts
21
20
  import { randomUUID as randomUUID2 } from "crypto";
@@ -967,7 +966,7 @@ async function createScanReport(targetInput = process.cwd()) {
967
966
  const framework = detectFramework(target);
968
967
  const readmeQuality = getReadmeQuality(target);
969
968
  const hasContributing = existsSync(join2(target, "CONTRIBUTING.md"));
970
- const hasExistingFabric = existsSync(join2(target, ".fabric", "bootstrap", "README.md")) || existsSync(join2(target, ".fabric"));
969
+ const hasExistingFabric = existsSync(join2(target, ".fabric"));
971
970
  const walkResult = walkFiles(target, DEFAULT_IGNORES);
972
971
  return {
973
972
  target,
@@ -1044,13 +1043,13 @@ function toPosixPath(path) {
1044
1043
  function buildRecommendations(input) {
1045
1044
  const recommendations = [];
1046
1045
  if (!input.hasExistingFabric) {
1047
- recommendations.push("L0: Run fab init to scaffold .fabric/bootstrap/README.md with TODO markers.");
1046
+ recommendations.push("L0: Run `fab init` to scaffold the .fabric/ knowledge layout (decisions, pitfalls, guidelines, models, processes).");
1048
1047
  }
1049
1048
  if (input.readmeQuality === "stub") {
1050
- recommendations.push("L0: Expand README.md before promoting project facts into Fabric references.");
1049
+ recommendations.push("L0: Expand README.md before promoting project facts into Fabric knowledge entries.");
1051
1050
  }
1052
1051
  if (!input.hasContributing) {
1053
- recommendations.push("L0: Add CONTRIBUTING.md or leave a bootstrap TODO reference for contribution flow.");
1052
+ recommendations.push("L0: Add CONTRIBUTING.md or capture contribution-flow guidance under .fabric/knowledge/processes/.");
1054
1053
  }
1055
1054
  if (input.framework.kind === "unknown") {
1056
1055
  recommendations.push("L1: Add tech-stack TODOs manually because no framework marker was detected.");
@@ -1221,17 +1220,7 @@ function handleCacheWatcherEvent(relativePath, projectRoot, sessions, timers) {
1221
1220
  );
1222
1221
  return;
1223
1222
  }
1224
- if (normalized === ".fabric/bootstrap/README.md") {
1225
- contextCache.invalidate("file_watch", projectRoot);
1226
- clearTimeout(timers.getAgentsMdTimer());
1227
- timers.setAgentsMdTimer(
1228
- setTimeout(() => {
1229
- notifyAllSessions(sessions, "resource_updated", AGENTS_MD_RESOURCE_URI);
1230
- }, NOTIFY_DEBOUNCE_MS)
1231
- );
1232
- return;
1233
- }
1234
- if (normalized.startsWith(".fabric/rules/") && normalized.endsWith(".md")) {
1223
+ if (normalized.startsWith(".fabric/knowledge/") && normalized.endsWith(".md")) {
1235
1224
  contextCache.invalidate("file_watch", projectRoot);
1236
1225
  invalidateRuleSyncCooldown(projectRoot);
1237
1226
  }
@@ -1245,8 +1234,8 @@ function createFabricHttpApp(options) {
1245
1234
  const cacheWatcher = chokidar2.watch(
1246
1235
  [
1247
1236
  ".fabric/agents.meta.json",
1248
- ".fabric/bootstrap/README.md",
1249
- ".fabric/rules/**/*.md"
1237
+ ".fabric/knowledge/**/*.md",
1238
+ ".fabric/knowledge/pending/**/*.md"
1250
1239
  ],
1251
1240
  {
1252
1241
  cwd: projectRoot,
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, RuleTestIndex, AgentsLayer, AgentsTopologyType } from '@fenglimg/fabric-shared';
3
+ import { AgentsMeta, RuleTestIndex, AgentsLayer, AgentsTopologyType, Layer, KnowledgeType, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent } from '@fenglimg/fabric-shared';
4
4
  import { IOFabricError } from '@fenglimg/fabric-shared/errors';
5
5
 
6
6
  interface InFlightTracker {
@@ -98,11 +98,43 @@ declare function isSameRuleTestIndex(left: RuleTestIndex, right: RuleTestIndex):
98
98
  declare function stableStringify(value: unknown): string;
99
99
 
100
100
  /**
101
- * Shared constants used across the server package.
101
+ * v2.0 KnowledgeIdAllocator
102
+ *
103
+ * Wraps the pure `allocateKnowledgeId` allocator with persistence: it reads
104
+ * `agents.meta.json`, advances the counter for the requested (layer, type)
105
+ * pair, and writes the updated meta atomically (write-to-tmp + rename) so
106
+ * concurrent readers always see a consistent file.
107
+ *
108
+ * Counters are MONOTONIC across the lifetime of the meta file: deleting a
109
+ * knowledge entry does NOT free its counter slot, so previously-allocated
110
+ * stable_ids remain unique even after their files are removed.
111
+ *
112
+ * Key invariants:
113
+ * - Counters envelope is initialized to zeros if absent (v1.x meta compat).
114
+ * - Each allocate() call performs read → mutate → atomic-write in sequence.
115
+ * - The returned id is guaranteed to differ from every previously-returned
116
+ * id for the same meta path.
102
117
  */
103
- /** MCP resource URI for the project's bootstrap README (L0 rules) file. */
104
- declare const AGENTS_MD_RESOURCE_URI = "fabric://bootstrap-readme";
118
+ declare class KnowledgeIdAllocator {
119
+ private readonly metaPath;
120
+ constructor(metaPath: string);
121
+ /**
122
+ * Allocate the next stable_id for the given (layer, type) pair and persist
123
+ * the advanced counter to `agents.meta.json`.
124
+ */
125
+ allocate(layer: Layer, type: KnowledgeType): Promise<StableId>;
126
+ /**
127
+ * Returns the current counters envelope, defaulting to all-zero slots when
128
+ * the meta file is absent or pre-v2.0 (counters key missing).
129
+ */
130
+ getCounters(): Promise<AgentsMetaCounters>;
131
+ private readMeta;
132
+ private normalizeCounters;
133
+ private writeMetaAtomic;
134
+ }
105
135
 
136
+ type StoredEventLedgerEvent = EventLedgerEvent;
137
+ declare function appendEventLedgerEvent(projectRoot: string, event: EventLedgerEventInput): Promise<StoredEventLedgerEvent>;
106
138
  /**
107
139
  * Synchronously fsync the event ledger file to ensure OS page-cache buffers are
108
140
  * flushed to durable storage. Must be called AFTER in-flight drain but BEFORE
@@ -113,6 +145,12 @@ declare const AGENTS_MD_RESOURCE_URI = "fabric://bootstrap-readme";
113
145
  */
114
146
  declare function flushAndSyncEventLedger(projectRoot: string): void;
115
147
 
148
+ /**
149
+ * Shared constants used across the server package.
150
+ */
151
+ /** MCP resource URI for the project's bootstrap README (L0 rules) file. */
152
+ declare const AGENTS_MD_RESOURCE_URI = "fabric://bootstrap-readme";
153
+
116
154
  /**
117
155
  * rule-sync.ts — Rule-sync orchestrator framework (R28, TASK-011)
118
156
  *
@@ -142,8 +180,8 @@ interface StructuredWarning {
142
180
  /**
143
181
  * Granular ledger event shape for rule-sync operations.
144
182
  * These are returned in RuleSyncReport and also appended to the event ledger
145
- * using the nearest available ledger event type (rule_drift_detected /
146
- * baseline_synced). The shape below is what callers receive in `.events`.
183
+ * using the nearest available ledger event type (knowledge_drift_detected).
184
+ * The shape below is what callers receive in `.events`.
147
185
  */
148
186
  interface RuleSyncLedgerEvent {
149
187
  type: "rule_content_changed" | "rule_added" | "rule_removed";
@@ -243,4 +281,4 @@ declare function startHttpServer(options: {
243
281
  dev?: boolean;
244
282
  }): Promise<Server>;
245
283
 
246
- export { AGENTS_MD_RESOURCE_URI, type AcquireOptions, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type InFlightTracker, 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, 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 };
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 };