@fenglimg/fabric-server 2.2.0-rc.3 → 2.2.0-rc.8
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 +3 -4
- package/dist/index.d.ts +122 -252
- package/dist/index.js +5954 -8878
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# @fenglimg/fabric-server
|
|
2
2
|
|
|
3
|
-
Fabric MCP knowledge server. Runs over stdio transport and serves Claude Code
|
|
3
|
+
Fabric MCP knowledge server. Runs over stdio transport and serves Claude Code and Codex CLI from a single `.fabric/` directory.
|
|
4
4
|
|
|
5
5
|
## Tools exposed
|
|
6
6
|
|
|
7
|
-
- `
|
|
8
|
-
- `
|
|
9
|
-
- `fab_recall` — combined one-call recall (plan + sections), the rc.37+ default
|
|
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
|
+
- `fab_archive_scan` — scan recent work for archive-worthy knowledge candidates
|
|
10
9
|
- `fab_extract_knowledge` — persist a pending knowledge entry
|
|
11
10
|
- `fab_review` — list / approve / reject / modify / defer pending entries
|
|
12
11
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { AgentsMeta, KnowledgeTestIndex, AgentsLayer, AgentsTopologyType, KnowledgeType, Layer, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem, LedgerEntry } from '@fenglimg/fabric-shared';
|
|
3
2
|
import { FabExtractKnowledgeInput, FabExtractKnowledgeOutput, FabReviewInput, FabReviewOutput } from '@fenglimg/fabric-shared/schemas/api-contracts';
|
|
3
|
+
import { EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem, LedgerEntry, AgentsMeta } from '@fenglimg/fabric-shared';
|
|
4
|
+
import { PayloadGuardOptions } from '@fenglimg/fabric-shared/node/mcp-payload-guard';
|
|
4
5
|
|
|
5
6
|
interface InFlightTracker {
|
|
6
7
|
enter(requestId: string): void;
|
|
@@ -22,6 +23,67 @@ declare function getLegacyLedgerPath(projectRoot: string): string;
|
|
|
22
23
|
declare function getEventLedgerPath(projectRoot: string): string;
|
|
23
24
|
declare function getMetricsLedgerPath(projectRoot: string): string;
|
|
24
25
|
|
|
26
|
+
type DoctorHealth = {
|
|
27
|
+
score: number;
|
|
28
|
+
grade: "A" | "B" | "C" | "D" | "F";
|
|
29
|
+
penalties: {
|
|
30
|
+
manual_errors: number;
|
|
31
|
+
fixable_errors: number;
|
|
32
|
+
warnings: number;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
interface AlwaysActiveBody {
|
|
37
|
+
/** store-qualified id (`<alias>:<stableId>`). */
|
|
38
|
+
stable_id: string;
|
|
39
|
+
/** knowledge_type — one of ALWAYS_ACTIVE_TYPES. */
|
|
40
|
+
type: string;
|
|
41
|
+
layer: "team" | "personal";
|
|
42
|
+
/** description.summary — the overflow-degrade fallback when the body cannot
|
|
43
|
+
* fit the injection char budget (the budget is enforced hook-side, D10). */
|
|
44
|
+
summary: string;
|
|
45
|
+
/** frontmatter-stripped markdown body. */
|
|
46
|
+
body: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Collect the always-active (guidelines + models) entries from the project's
|
|
50
|
+
* read-set, project-filtered identically to recall (filterByActiveProject), with
|
|
51
|
+
* their frontmatter-stripped bodies. The SessionStart hook injects these bodies
|
|
52
|
+
* into the AI context and renders category counts for the on-demand remainder.
|
|
53
|
+
*
|
|
54
|
+
* Returns [] (never throws) on any read-set resolution failure — the SessionStart
|
|
55
|
+
* banner must degrade gracefully, never crash session start.
|
|
56
|
+
*/
|
|
57
|
+
interface KnowledgeCensus {
|
|
58
|
+
/** knowledge_type → count (decisions/pitfalls/guidelines/models/processes). */
|
|
59
|
+
by_type: Record<string, number>;
|
|
60
|
+
by_layer: {
|
|
61
|
+
team: number;
|
|
62
|
+
personal: number;
|
|
63
|
+
project: number;
|
|
64
|
+
};
|
|
65
|
+
/** entries专属 to OTHER projects that filterByActiveProject removed. */
|
|
66
|
+
dropped_other_project: number;
|
|
67
|
+
/** kept (post-filter) total. */
|
|
68
|
+
total: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Build the read-set census (project-filtered counts + dropped-other-project).
|
|
72
|
+
* Reuses the cached read-set walk, so calling alongside buildAlwaysActiveBodies
|
|
73
|
+
* in one SessionStart fire costs a single walk. Never throws — degrades to an
|
|
74
|
+
* all-zero census so the banner stays renderable.
|
|
75
|
+
*/
|
|
76
|
+
declare function buildKnowledgeCensus(projectRoot: string): Promise<KnowledgeCensus>;
|
|
77
|
+
declare function buildAlwaysActiveBodies(projectRoot: string): Promise<AlwaysActiveBody[]>;
|
|
78
|
+
|
|
79
|
+
interface UnboundProjectViolation {
|
|
80
|
+
/** The store already bound as the active write target. */
|
|
81
|
+
alias: string;
|
|
82
|
+
/** Which project-scope fields are absent: `project_id` and/or `active_project`. */
|
|
83
|
+
missing: string[];
|
|
84
|
+
}
|
|
85
|
+
declare function detectUnboundProject(projectRoot: string): UnboundProjectViolation | null;
|
|
86
|
+
|
|
25
87
|
/**
|
|
26
88
|
* O(1) in-memory increment for a named counter. Safe to call from any MCP
|
|
27
89
|
* tool handler; no I/O happens until the next `flushMetrics()` call.
|
|
@@ -81,11 +143,15 @@ type MetricsRow = {
|
|
|
81
143
|
counters: Record<string, number>;
|
|
82
144
|
};
|
|
83
145
|
/**
|
|
84
|
-
* Canonical metric counter names
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
146
|
+
* Canonical metric counter names. rc.37 Wave B added a metrics.jsonl counter
|
|
147
|
+
* rollup for each (the forward-compatible signal), but — contrary to the
|
|
148
|
+
* original "these left events.jsonl" plan — every one is ALSO still appended to
|
|
149
|
+
* the audit ledger as a structured event, because a doctor lint consumes its
|
|
150
|
+
* per-id / per-path payload (see LEDGER_DUAL_WRITE_METRIC_NAMES below). The
|
|
151
|
+
* promised counter-only cutover (rc.38+; tracked by the G11 invariant test) has
|
|
152
|
+
* not happened. Centralized here so the B5 hard-gate (`metric_event_in_jsonl`)
|
|
153
|
+
* can grep for these exact strings; the gate only flags names NOT in the
|
|
154
|
+
* dual-write allowlist below.
|
|
89
155
|
*/
|
|
90
156
|
declare const METRIC_COUNTER_NAMES: {
|
|
91
157
|
readonly knowledge_consumed: "knowledge_consumed";
|
|
@@ -113,7 +179,7 @@ type CiteCoverageReport = {
|
|
|
113
179
|
marker_ts: number;
|
|
114
180
|
marker_emitted_now: boolean;
|
|
115
181
|
since_ts: number;
|
|
116
|
-
client_filter: "cc" | "codex" | "
|
|
182
|
+
client_filter: "cc" | "codex" | "all";
|
|
117
183
|
layer_filter?: "team" | "personal" | "all";
|
|
118
184
|
metrics: {
|
|
119
185
|
edits_touched: number;
|
|
@@ -162,7 +228,7 @@ type CiteCoverageReport = {
|
|
|
162
228
|
};
|
|
163
229
|
declare function runDoctorCiteCoverage(projectRoot: string, options: {
|
|
164
230
|
since: number;
|
|
165
|
-
client: "cc" | "codex" | "
|
|
231
|
+
client: "cc" | "codex" | "all";
|
|
166
232
|
layer?: "team" | "personal" | "all";
|
|
167
233
|
until?: number;
|
|
168
234
|
recallWindowMs?: number;
|
|
@@ -250,15 +316,6 @@ type DoctorSummary = {
|
|
|
250
316
|
payload_limits: DoctorPayloadLimits;
|
|
251
317
|
health: DoctorHealth;
|
|
252
318
|
};
|
|
253
|
-
type DoctorHealth = {
|
|
254
|
-
score: number;
|
|
255
|
-
grade: "A" | "B" | "C" | "D" | "F";
|
|
256
|
-
penalties: {
|
|
257
|
-
manual_errors: number;
|
|
258
|
-
fixable_errors: number;
|
|
259
|
-
warnings: number;
|
|
260
|
-
};
|
|
261
|
-
};
|
|
262
319
|
type DoctorReport = {
|
|
263
320
|
status: DoctorStatus;
|
|
264
321
|
checks: DoctorCheck[];
|
|
@@ -287,6 +344,7 @@ type DoctorApplyLintMutation = {
|
|
|
287
344
|
type DoctorApplyLintReport = {
|
|
288
345
|
changed: boolean;
|
|
289
346
|
mutations: DoctorApplyLintMutation[];
|
|
347
|
+
warnings: DoctorIssue[];
|
|
290
348
|
manual_errors: DoctorIssue[];
|
|
291
349
|
aborted: boolean;
|
|
292
350
|
abort_reason?: string;
|
|
@@ -296,6 +354,7 @@ type DoctorApplyLintReport = {
|
|
|
296
354
|
declare function runDoctorReport(target: string): Promise<DoctorReport>;
|
|
297
355
|
declare function runDoctorFix(target: string): Promise<DoctorFixReport>;
|
|
298
356
|
declare function runDoctorApplyLint(target: string): Promise<DoctorApplyLintReport>;
|
|
357
|
+
|
|
299
358
|
type EnrichDescriptionsMode = "auto" | "preview" | "readonly" | "interactive";
|
|
300
359
|
type EnrichDescriptionsCandidate = {
|
|
301
360
|
path: string;
|
|
@@ -421,10 +480,12 @@ interface ConflictLintReport {
|
|
|
421
480
|
pairs: ConflictPair[];
|
|
422
481
|
}
|
|
423
482
|
/**
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
483
|
+
* v2.2 W5 R6 (读侧 cutover): load canonical knowledge entries with bodies from
|
|
484
|
+
* the read-set STORES (cross-store on-the-fly) instead of the retired
|
|
485
|
+
* co-location agents.meta node index. Skips pending/draft staging entries
|
|
486
|
+
* (conflict detection targets the curated corpus) and any entry missing a
|
|
487
|
+
* knowledge_type. collectStoreCanonicalEntries already reads each store entry's
|
|
488
|
+
* body + parsed frontmatter and degrades to [] when no store is in the read-set.
|
|
428
489
|
*/
|
|
429
490
|
declare function loadConflictEntries(projectRoot: string): Promise<ConflictEntry[]>;
|
|
430
491
|
/**
|
|
@@ -441,85 +502,6 @@ declare function runDoctorConflictLint(projectRoot: string, opts?: {
|
|
|
441
502
|
judge?: ConflictJudge;
|
|
442
503
|
}): Promise<ConflictLintReport>;
|
|
443
504
|
|
|
444
|
-
type KnowledgeMetaBuildSource = "doctor_fix" | "sync_meta";
|
|
445
|
-
type KnowledgeMetaBuildResult = {
|
|
446
|
-
meta: AgentsMeta;
|
|
447
|
-
knowledgeTestIndex: KnowledgeTestIndex;
|
|
448
|
-
changed: boolean;
|
|
449
|
-
};
|
|
450
|
-
type WriteKnowledgeMetaOptions = {
|
|
451
|
-
source: KnowledgeMetaBuildSource;
|
|
452
|
-
};
|
|
453
|
-
/**
|
|
454
|
-
* v2.0-rc.24 TASK-07: Load a Map<stable_id, knowledge_type> from the
|
|
455
|
-
* project's `.fabric/agents.meta.json`. Consumed by the doctor cite-coverage
|
|
456
|
-
* routing (TASK-08) to dispatch cites to the correct policy bucket
|
|
457
|
-
* (decision/pitfall = strict contract / model = reference-only /
|
|
458
|
-
* guideline+process = deferred to rc.25 LLM-judge). Cited ids absent from
|
|
459
|
-
* this map fall into the `cite_id_unresolved` bucket.
|
|
460
|
-
*
|
|
461
|
-
* **Plural knowledge_type contract (rc.29 BUG-C1 unification):** the returned
|
|
462
|
-
* map values are the PLURAL `KnowledgeType` enum (`"models" | "decisions" |
|
|
463
|
-
* "guidelines" | "pitfalls" | "processes"`) — matching disk frontmatter,
|
|
464
|
-
* filesystem layout, MCP I/O surface, and the canonical `KnowledgeTypeSchema`
|
|
465
|
-
* exported from `@fenglimg/fabric-shared`. Legacy singular frontmatter is
|
|
466
|
-
* normalized at parse time (see `SINGULAR_TO_PLURAL` in `parseFrontmatter`);
|
|
467
|
-
* downstream callers (TASK-08 doctor) match against the plural enum.
|
|
468
|
-
*
|
|
469
|
-
* Both team (KT-*) and personal (KP-*) entries are included — they live in
|
|
470
|
-
* the same `meta.nodes` map.
|
|
471
|
-
*
|
|
472
|
-
* Graceful on failure: a missing meta file, malformed JSON, or schema
|
|
473
|
-
* validation failure all yield an empty Map (no throw). The doctor will then
|
|
474
|
-
* surface every cite as `cite_id_unresolved`, which is the safe degraded
|
|
475
|
-
* mode.
|
|
476
|
-
*/
|
|
477
|
-
declare function loadKbIdTypeMap(projectRootInput: string): Promise<Map<string, KnowledgeType>>;
|
|
478
|
-
declare function buildKnowledgeMeta(projectRootInput: string): Promise<KnowledgeMetaBuildResult>;
|
|
479
|
-
declare function writeKnowledgeMeta(projectRootInput: string, options: WriteKnowledgeMetaOptions): Promise<KnowledgeMetaBuildResult>;
|
|
480
|
-
declare function computeKnowledgeBasedAgentsMeta(projectRootInput: string, existingMeta?: AgentsMeta): Promise<AgentsMeta>;
|
|
481
|
-
declare function computeKnowledgeTestIndex(projectRootInput: string, computedMeta: AgentsMeta, previousIndex?: KnowledgeTestIndex): Promise<KnowledgeTestIndex>;
|
|
482
|
-
declare function deriveKnowledgeMetaLayer(relativePath: string): AgentsLayer;
|
|
483
|
-
declare function deriveKnowledgeMetaTopologyType(relativePath: string): AgentsTopologyType;
|
|
484
|
-
declare function isSameKnowledgeTestIndex(left: KnowledgeTestIndex, right: KnowledgeTestIndex): boolean;
|
|
485
|
-
declare function stableStringify(value: unknown): string;
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* v2.0 KnowledgeIdAllocator
|
|
489
|
-
*
|
|
490
|
-
* Wraps the pure `allocateKnowledgeId` allocator with persistence: it reads
|
|
491
|
-
* `agents.meta.json`, advances the counter for the requested (layer, type)
|
|
492
|
-
* pair, and writes the updated meta atomically (write-to-tmp + rename) so
|
|
493
|
-
* concurrent readers always see a consistent file.
|
|
494
|
-
*
|
|
495
|
-
* Counters are MONOTONIC across the lifetime of the meta file: deleting a
|
|
496
|
-
* knowledge entry does NOT free its counter slot, so previously-allocated
|
|
497
|
-
* stable_ids remain unique even after their files are removed.
|
|
498
|
-
*
|
|
499
|
-
* Key invariants:
|
|
500
|
-
* - Counters envelope is initialized to zeros if absent (v1.x meta compat).
|
|
501
|
-
* - Each allocate() call performs read → mutate → atomic-write in sequence.
|
|
502
|
-
* - The returned id is guaranteed to differ from every previously-returned
|
|
503
|
-
* id for the same meta path.
|
|
504
|
-
*/
|
|
505
|
-
declare class KnowledgeIdAllocator {
|
|
506
|
-
private readonly metaPath;
|
|
507
|
-
constructor(metaPath: string);
|
|
508
|
-
/**
|
|
509
|
-
* Allocate the next stable_id for the given (layer, type) pair and persist
|
|
510
|
-
* the advanced counter to `agents.meta.json`.
|
|
511
|
-
*/
|
|
512
|
-
allocate(layer: Layer, type: KnowledgeType): Promise<StableId>;
|
|
513
|
-
/**
|
|
514
|
-
* Returns the current counters envelope, defaulting to all-zero slots when
|
|
515
|
-
* the meta file is absent or pre-v2.0 (counters key missing).
|
|
516
|
-
*/
|
|
517
|
-
getCounters(): Promise<AgentsMetaCounters>;
|
|
518
|
-
private readMeta;
|
|
519
|
-
private normalizeCounters;
|
|
520
|
-
private writeMetaAtomic;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
505
|
/**
|
|
524
506
|
* Append-evidence-on-collision service for fab_extract_knowledge.
|
|
525
507
|
*
|
|
@@ -606,11 +588,26 @@ type PlanContextInput = {
|
|
|
606
588
|
target_paths?: string[];
|
|
607
589
|
layer_filter?: "team" | "personal" | "both";
|
|
608
590
|
include_related?: boolean;
|
|
591
|
+
/**
|
|
592
|
+
* Internal MCP presentation budget. When supplied by the tool layer,
|
|
593
|
+
* candidates are byte-trimmed before the selection token is cached so the
|
|
594
|
+
* token cannot reference candidates omitted from the response.
|
|
595
|
+
*/
|
|
596
|
+
payload_budget?: PlanContextPayloadBudget;
|
|
597
|
+
};
|
|
598
|
+
type PlanContextPayloadWarning = {
|
|
599
|
+
code: string;
|
|
600
|
+
file?: string;
|
|
601
|
+
action_hint?: string;
|
|
602
|
+
};
|
|
603
|
+
type PlanContextPayloadBudget = {
|
|
604
|
+
limits?: PayloadGuardOptions;
|
|
605
|
+
warnings?: PlanContextPayloadWarning[];
|
|
606
|
+
trim_warning?: PlanContextPayloadWarning;
|
|
609
607
|
};
|
|
610
608
|
type RequirementProfile = {
|
|
611
609
|
target_path: string;
|
|
612
610
|
known_tech: string[];
|
|
613
|
-
user_intent: string;
|
|
614
611
|
detected_entities: string[];
|
|
615
612
|
};
|
|
616
613
|
type PlanContextEntry = {
|
|
@@ -629,6 +626,7 @@ type PlanContextResult = {
|
|
|
629
626
|
stale: boolean;
|
|
630
627
|
selection_token: string;
|
|
631
628
|
entries: PlanContextEntry[];
|
|
629
|
+
intent?: string;
|
|
632
630
|
candidates: RuleDescriptionIndexItem[];
|
|
633
631
|
omitted_candidate_count?: number;
|
|
634
632
|
preflight_diagnostics: PreflightDiagnostic[];
|
|
@@ -636,6 +634,10 @@ type PlanContextResult = {
|
|
|
636
634
|
previous_revision_hash?: string;
|
|
637
635
|
redirects?: Record<string, string>;
|
|
638
636
|
related_appended?: Record<string, string>;
|
|
637
|
+
/** Internal service→tool signal; stripped before MCP output. */
|
|
638
|
+
payload_trimmed?: boolean;
|
|
639
|
+
/** Internal service→tool signal; stripped before MCP output. */
|
|
640
|
+
payload_over_budget?: boolean;
|
|
639
641
|
};
|
|
640
642
|
type SelectionTokenState = {
|
|
641
643
|
token: string;
|
|
@@ -651,45 +653,33 @@ declare function readSelectionToken(token: string, now?: number): SelectionToken
|
|
|
651
653
|
|
|
652
654
|
type RecallInput = PlanContextInput & {
|
|
653
655
|
/**
|
|
654
|
-
* Optional explicit set of stable_ids to
|
|
655
|
-
*
|
|
656
|
-
* index
|
|
657
|
-
*
|
|
656
|
+
* Optional explicit set of stable_ids to SCOPE the returned read paths to.
|
|
657
|
+
* When omitted, `paths` carries one entry per surfaced candidate. The candidate
|
|
658
|
+
* DESCRIPTION index is always returned in full for discovery — `ids` only narrows
|
|
659
|
+
* which read paths are surfaced (e.g. `recall(ids)` when the agent already knows
|
|
660
|
+
* which entries it wants to Read). Stale (pre layer-flip) ids are redirect-rewritten
|
|
661
|
+
* before the match.
|
|
658
662
|
*/
|
|
659
663
|
ids?: string[];
|
|
660
664
|
/**
|
|
661
|
-
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
* (every candidate is already fetched) or no related edges resolve in-corpus.
|
|
665
|
+
* When true, forwarded to planContext, which appends the one-hop `related` graph
|
|
666
|
+
* neighbours (H2) of the surfaced set to the candidate index (descriptions only —
|
|
667
|
+
* NO body). Their read paths are included in `paths` like any other candidate
|
|
668
|
+
* (W1-3 / KT-DEC-0031: surface the related id, do not fetch its body).
|
|
666
669
|
*/
|
|
667
670
|
include_related?: boolean;
|
|
668
671
|
};
|
|
669
|
-
type
|
|
670
|
-
|
|
671
|
-
|
|
672
|
+
type RecallPath = {
|
|
673
|
+
stable_id: string;
|
|
674
|
+
path: string;
|
|
675
|
+
store?: {
|
|
676
|
+
alias: string;
|
|
677
|
+
};
|
|
672
678
|
};
|
|
673
|
-
type RecallResult = PlanContextResult & {
|
|
674
|
-
|
|
675
|
-
stable_id: string;
|
|
676
|
-
level: "L0" | "L1" | "L2";
|
|
677
|
-
path: string;
|
|
678
|
-
body: string;
|
|
679
|
-
store?: {
|
|
680
|
-
alias: string;
|
|
681
|
-
};
|
|
682
|
-
}>;
|
|
683
|
-
selected_stable_ids: string[];
|
|
684
|
-
diagnostics: Array<{
|
|
685
|
-
code: "missing_knowledge_metadata" | "unresolved_selected_id";
|
|
686
|
-
severity: "warn";
|
|
687
|
-
stable_id: string;
|
|
688
|
-
message: string;
|
|
689
|
-
}>;
|
|
679
|
+
type RecallResult = Omit<PlanContextResult, "selection_token" | "payload_trimmed" | "payload_over_budget"> & {
|
|
680
|
+
paths: RecallPath[];
|
|
690
681
|
directive: string;
|
|
691
682
|
next_steps?: string[];
|
|
692
|
-
truncation?: RecallTruncation;
|
|
693
683
|
};
|
|
694
684
|
declare function recall(projectRoot: string, input: RecallInput): Promise<RecallResult>;
|
|
695
685
|
|
|
@@ -757,92 +747,6 @@ declare class ContextCache {
|
|
|
757
747
|
}
|
|
758
748
|
declare const contextCache: ContextCache;
|
|
759
749
|
|
|
760
|
-
interface KnowledgeSyncOptions {
|
|
761
|
-
mode?: "incremental" | "full";
|
|
762
|
-
/** When true, invalid frontmatter throws RuleValidationError (default: false — collect as warning). */
|
|
763
|
-
throwOnInvalidFrontmatter?: boolean;
|
|
764
|
-
/**
|
|
765
|
-
* v2.0.0-rc.29 TASK-005 (BUG-G1): when true, `ensureKnowledgeFresh`
|
|
766
|
-
* synchronously follows a drift detection with a `reconcileKnowledge`
|
|
767
|
-
* call to materialize the auto-heal (rewrite agents.meta.json + emit a
|
|
768
|
-
* paired `knowledge_meta_auto_healed` event). Default false preserves
|
|
769
|
-
* the rc.28 hot-path semantics where drift detection never blocks the
|
|
770
|
-
* MCP read on a meta rebuild. Opt-in is intended for callers that can
|
|
771
|
-
* tolerate ~tens-of-ms extra latency in exchange for the invariant
|
|
772
|
-
* "every knowledge_drift_detected has a paired heal event in the same
|
|
773
|
-
* tail window." Audit (BUG-G1) found 5/72 drifts healed on this repo
|
|
774
|
-
* (~7%) because the hot path emitted detect-only events.
|
|
775
|
-
*/
|
|
776
|
-
autoHealOnDrift?: boolean;
|
|
777
|
-
}
|
|
778
|
-
interface StructuredWarning {
|
|
779
|
-
code: string;
|
|
780
|
-
file: string;
|
|
781
|
-
line?: number;
|
|
782
|
-
action_hint: string;
|
|
783
|
-
}
|
|
784
|
-
/**
|
|
785
|
-
* Granular ledger event shape for knowledge-sync operations.
|
|
786
|
-
* These are returned in KnowledgeSyncReport and also appended to the event ledger
|
|
787
|
-
* using the nearest available ledger event type (knowledge_drift_detected).
|
|
788
|
-
* The shape below is what callers receive in `.events`.
|
|
789
|
-
*/
|
|
790
|
-
interface KnowledgeSyncLedgerEvent {
|
|
791
|
-
type: "rule_content_changed" | "rule_added" | "rule_removed";
|
|
792
|
-
stable_id: string;
|
|
793
|
-
path: string;
|
|
794
|
-
prev_hash: string | null;
|
|
795
|
-
new_hash: string | null;
|
|
796
|
-
changed_fields: string[];
|
|
797
|
-
source: "ensureKnowledgeFresh" | "reconcileKnowledge";
|
|
798
|
-
}
|
|
799
|
-
/** Alias so the public API says LedgerEvent (as documented). */
|
|
800
|
-
type LedgerEvent = KnowledgeSyncLedgerEvent;
|
|
801
|
-
interface KnowledgeSyncReport {
|
|
802
|
-
status: "fresh" | "reconciled" | "errors";
|
|
803
|
-
events: LedgerEvent[];
|
|
804
|
-
warnings: StructuredWarning[];
|
|
805
|
-
reconciled_files?: string[];
|
|
806
|
-
}
|
|
807
|
-
/**
|
|
808
|
-
* Clear the knowledge-sync cooldown for a projectRoot so the next ensureKnowledgeFresh
|
|
809
|
-
* call performs a real I/O scan. Called by the chokidar watcher when a rule
|
|
810
|
-
* file changes (see http.ts handleCacheWatcherEvent).
|
|
811
|
-
*/
|
|
812
|
-
declare function invalidateKnowledgeSyncCooldown(projectRoot: string): void;
|
|
813
|
-
/**
|
|
814
|
-
* Detects drift between disk and agents.meta.json, emits ledger events, and
|
|
815
|
-
* invalidates the cache. Does NOT rewrite agents.meta.json. Optimised for
|
|
816
|
-
* hot-path consumers (MCP tools).
|
|
817
|
-
*/
|
|
818
|
-
declare function ensureKnowledgeFresh(projectRoot: string, opts?: KnowledgeSyncOptions): Promise<KnowledgeSyncReport>;
|
|
819
|
-
interface ReconcileKnowledgeOptions {
|
|
820
|
-
/**
|
|
821
|
-
* Identifies who triggered the reconcile; controls which summary ledger event is written.
|
|
822
|
-
*
|
|
823
|
-
* v2.0.0-rc.23 TASK-005 (a-B): `auto-heal-description` added so plan_context
|
|
824
|
-
* can drive a full reconcile when it detects nodes with `description === undefined`
|
|
825
|
-
* (legacy meta drift the revision-hash gate cannot detect).
|
|
826
|
-
*
|
|
827
|
-
* v2.0.0-rc.27 TASK-001 (§2.9 root): `post-approve` / `post-modify` added so
|
|
828
|
-
* `fab_review` approve/modify-layer-flip can drive an immediate meta rebuild
|
|
829
|
-
* — without this the new entry's `nodes[id]` stays empty until the next
|
|
830
|
-
* plan_context call's auto-heal, which leaves the entry undiscoverable in
|
|
831
|
-
* the description_index window between approve and the next hint call.
|
|
832
|
-
*/
|
|
833
|
-
trigger?: "startup" | "doctor" | "manual" | "auto-heal-description" | "auto-heal-after-drift" | "post-approve" | "post-modify";
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Full scan + rewrites agents.meta.json with ground-truth disk state + emits
|
|
837
|
-
* ledger events. Used by startup (TASK-022) and doctor repair (TASK-023).
|
|
838
|
-
* Returns reconciled_files listing all paths whose meta was updated.
|
|
839
|
-
*
|
|
840
|
-
* When `opts.trigger` is `'startup'`, a `meta_reconciled_on_startup` summary
|
|
841
|
-
* ledger event is appended after per-file drift events. Other trigger values
|
|
842
|
-
* append a `meta_reconciled` event. Omitting the trigger skips the summary.
|
|
843
|
-
*/
|
|
844
|
-
declare function reconcileKnowledge(projectRoot: string, opts?: ReconcileKnowledgeOptions): Promise<KnowledgeSyncReport>;
|
|
845
|
-
|
|
846
750
|
type LedgerSourceFilter = "ai" | "human";
|
|
847
751
|
type StoredLedgerEntry = LedgerEntry & {
|
|
848
752
|
id: string;
|
|
@@ -877,40 +781,6 @@ type RehydratedAgentsMetaSnapshot = {
|
|
|
877
781
|
};
|
|
878
782
|
declare function rehydrateAgentsMetaAt(projectRoot: string, target: RehydrateTarget): Promise<RehydratedAgentsMetaSnapshot>;
|
|
879
783
|
|
|
880
|
-
declare function readAgentsMeta(projectRoot: string): Promise<AgentsMeta>;
|
|
881
|
-
|
|
882
|
-
type KnowledgeEntryItem = {
|
|
883
|
-
path: string;
|
|
884
|
-
content: string;
|
|
885
|
-
};
|
|
886
|
-
type DescriptionStub = {
|
|
887
|
-
path: string;
|
|
888
|
-
description: string;
|
|
889
|
-
};
|
|
890
|
-
type HumanLockedNearby = {
|
|
891
|
-
file: string;
|
|
892
|
-
excerpt: string;
|
|
893
|
-
};
|
|
894
|
-
type KnowledgePayload = {
|
|
895
|
-
L0: string;
|
|
896
|
-
L1: KnowledgeEntryItem[];
|
|
897
|
-
L2: KnowledgeEntryItem[];
|
|
898
|
-
human_locked_nearby: HumanLockedNearby[];
|
|
899
|
-
description_stubs?: DescriptionStub[];
|
|
900
|
-
};
|
|
901
|
-
type GetKnowledgeInput = {
|
|
902
|
-
path: string;
|
|
903
|
-
client_hash?: string;
|
|
904
|
-
correlation_id?: string;
|
|
905
|
-
session_id?: string;
|
|
906
|
-
};
|
|
907
|
-
type GetKnowledgeResult = {
|
|
908
|
-
revision_hash: string;
|
|
909
|
-
stale: boolean;
|
|
910
|
-
rules: KnowledgePayload;
|
|
911
|
-
};
|
|
912
|
-
declare function getKnowledge(projectRoot: string, input: GetKnowledgeInput): Promise<GetKnowledgeResult>;
|
|
913
|
-
|
|
914
784
|
/**
|
|
915
785
|
* Shared constants used across the server package.
|
|
916
786
|
*/
|
|
@@ -953,4 +823,4 @@ interface ShutdownHandlerDeps {
|
|
|
953
823
|
*/
|
|
954
824
|
declare function createShutdownHandler(deps: ShutdownHandlerDeps): () => void;
|
|
955
825
|
|
|
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,
|
|
826
|
+
export { AGENTS_MD_RESOURCE_URI, type AlwaysActiveBody, 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, 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, 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 };
|