@fenglimg/fabric-server 2.0.1 → 2.1.0-rc.2
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/dist/index.js +38 -41
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1829,6 +1829,7 @@ import { join as join7, relative as relative2 } from "path";
|
|
|
1829
1829
|
import {
|
|
1830
1830
|
PROPOSED_REASON_DESCRIPTIONS
|
|
1831
1831
|
} from "@fenglimg/fabric-shared/schemas/api-contracts";
|
|
1832
|
+
import { hasSecrets } from "@fenglimg/fabric-shared";
|
|
1832
1833
|
|
|
1833
1834
|
// src/services/load-active-meta.ts
|
|
1834
1835
|
async function loadActiveMeta(projectRoot, opts = {}) {
|
|
@@ -2074,6 +2075,25 @@ async function extractKnowledge(projectRoot, input) {
|
|
|
2074
2075
|
idempotency_key: idempotencyKey
|
|
2075
2076
|
};
|
|
2076
2077
|
}
|
|
2078
|
+
const secretScanTarget = [
|
|
2079
|
+
input.user_messages_summary ?? "",
|
|
2080
|
+
input.session_context ?? "",
|
|
2081
|
+
input.must_read_if ?? "",
|
|
2082
|
+
...input.intent_clues ?? []
|
|
2083
|
+
].join("\n");
|
|
2084
|
+
if (hasSecrets(secretScanTarget)) {
|
|
2085
|
+
await emitEventBestEffort(projectRoot, {
|
|
2086
|
+
event_type: "knowledge_archive_attempted",
|
|
2087
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2088
|
+
correlation_id: primarySession,
|
|
2089
|
+
session_id: primarySession,
|
|
2090
|
+
reason: `extract_knowledge:${sanitizedSlug || input.slug}:secret_detected`
|
|
2091
|
+
});
|
|
2092
|
+
return {
|
|
2093
|
+
pending_path: "",
|
|
2094
|
+
idempotency_key: idempotencyKey
|
|
2095
|
+
};
|
|
2096
|
+
}
|
|
2077
2097
|
const layer = input.layer ?? "team";
|
|
2078
2098
|
let relevanceScope = input.relevance_scope;
|
|
2079
2099
|
let relevancePaths = input.relevance_paths;
|
|
@@ -5905,58 +5925,37 @@ async function inspectCiteGoodhart(projectRoot) {
|
|
|
5905
5925
|
if (turns.length === 0) {
|
|
5906
5926
|
return { status: "ok", fired: [] };
|
|
5907
5927
|
}
|
|
5908
|
-
const
|
|
5909
|
-
const recalledCount = /* @__PURE__ */ new Map();
|
|
5928
|
+
const appliedCount = /* @__PURE__ */ new Map();
|
|
5910
5929
|
for (const turn of turns) {
|
|
5911
5930
|
for (let i = 0; i < turn.cite_ids.length; i += 1) {
|
|
5912
|
-
if (
|
|
5931
|
+
if (turn.cite_tags[i] === "applied") {
|
|
5913
5932
|
const key = turn.cite_ids[i];
|
|
5914
|
-
|
|
5933
|
+
appliedCount.set(key, (appliedCount.get(key) ?? 0) + 1);
|
|
5915
5934
|
}
|
|
5916
5935
|
}
|
|
5917
5936
|
}
|
|
5918
|
-
for (const [id, n] of
|
|
5937
|
+
for (const [id, n] of appliedCount.entries()) {
|
|
5919
5938
|
if (n > RITUAL_REPEAT_THRESHOLD) {
|
|
5920
|
-
fired.push({ pattern: "G1", detail: `${id} repeated as [applied
|
|
5939
|
+
fired.push({ pattern: "G1", detail: `${id} repeated as [applied] ${n}x in 7d` });
|
|
5921
5940
|
break;
|
|
5922
5941
|
}
|
|
5923
5942
|
}
|
|
5924
|
-
let
|
|
5925
|
-
let
|
|
5943
|
+
let appliedTotal = 0;
|
|
5944
|
+
let appliedWithSkip = 0;
|
|
5926
5945
|
for (const turn of turns) {
|
|
5927
5946
|
for (let i = 0; i < turn.cite_ids.length; i += 1) {
|
|
5928
|
-
if (
|
|
5929
|
-
|
|
5947
|
+
if (turn.cite_tags[i] !== "applied") continue;
|
|
5948
|
+
appliedTotal += 1;
|
|
5930
5949
|
const commitment = turn.cite_commitments[i];
|
|
5931
5950
|
if (commitment && typeof commitment.skip_reason === "string" && commitment.skip_reason.length > 0) {
|
|
5932
|
-
|
|
5951
|
+
appliedWithSkip += 1;
|
|
5933
5952
|
}
|
|
5934
5953
|
}
|
|
5935
5954
|
}
|
|
5936
|
-
if (
|
|
5955
|
+
if (appliedTotal >= 5 && appliedWithSkip / appliedTotal > DISMISSAL_ABUSE_RATIO) {
|
|
5937
5956
|
fired.push({
|
|
5938
5957
|
pattern: "G2",
|
|
5939
|
-
detail: `${
|
|
5940
|
-
});
|
|
5941
|
-
}
|
|
5942
|
-
let chainedFromMisuse = 0;
|
|
5943
|
-
for (const turn of turns) {
|
|
5944
|
-
for (let i = 0; i < turn.cite_ids.length; i += 1) {
|
|
5945
|
-
if (turn.cite_tags[i] !== "chained-from") continue;
|
|
5946
|
-
const commitment = turn.cite_commitments[i];
|
|
5947
|
-
if (!commitment) {
|
|
5948
|
-
chainedFromMisuse += 1;
|
|
5949
|
-
continue;
|
|
5950
|
-
}
|
|
5951
|
-
const hasOps = Array.isArray(commitment.operators) && commitment.operators.length > 0;
|
|
5952
|
-
const hasSkip = typeof commitment.skip_reason === "string" && commitment.skip_reason.length > 0;
|
|
5953
|
-
if (!hasOps && !hasSkip) chainedFromMisuse += 1;
|
|
5954
|
-
}
|
|
5955
|
-
}
|
|
5956
|
-
if (chainedFromMisuse > RITUAL_REPEAT_THRESHOLD) {
|
|
5957
|
-
fired.push({
|
|
5958
|
-
pattern: "G3",
|
|
5959
|
-
detail: `${chainedFromMisuse} chained-from cites with no commitment (operators=[] + skip_reason=null) in 7d`
|
|
5958
|
+
detail: `${appliedWithSkip}/${appliedTotal} applied cites used skip:<reason> (> ${Math.round(DISMISSAL_ABUSE_RATIO * 100)}%)`
|
|
5960
5959
|
});
|
|
5961
5960
|
}
|
|
5962
5961
|
let placeholderCount = 0;
|
|
@@ -9868,7 +9867,7 @@ function parseNoneSentinel(kbLineRaw) {
|
|
|
9868
9867
|
return "unspecified";
|
|
9869
9868
|
}
|
|
9870
9869
|
function categorizeCiteTag(tag) {
|
|
9871
|
-
if (tag === "
|
|
9870
|
+
if (tag === "applied" || tag === "none") {
|
|
9872
9871
|
return { category: tag };
|
|
9873
9872
|
}
|
|
9874
9873
|
if (tag === "dismissed") {
|
|
@@ -10160,18 +10159,16 @@ async function runDoctorCiteCoverage(projectRoot, options) {
|
|
|
10160
10159
|
}
|
|
10161
10160
|
sessionCitedKbs.set(sid, set);
|
|
10162
10161
|
}
|
|
10163
|
-
let
|
|
10162
|
+
let turnHadApplied = false;
|
|
10164
10163
|
for (const tag of turn.cite_tags) {
|
|
10165
10164
|
const { category, reason } = categorizeCiteTag(tag);
|
|
10166
10165
|
switch (category) {
|
|
10167
|
-
case "
|
|
10168
|
-
case "recalled":
|
|
10169
|
-
case "chained-from":
|
|
10166
|
+
case "applied":
|
|
10170
10167
|
qualifyingCites += 1;
|
|
10171
10168
|
bumpClient(turn.client, (m) => {
|
|
10172
10169
|
m.qualifying_cites += 1;
|
|
10173
10170
|
});
|
|
10174
|
-
|
|
10171
|
+
turnHadApplied = true;
|
|
10175
10172
|
break;
|
|
10176
10173
|
case "dismissed": {
|
|
10177
10174
|
const key = reason ?? "unspecified";
|
|
@@ -10187,7 +10184,7 @@ async function runDoctorCiteCoverage(projectRoot, options) {
|
|
|
10187
10184
|
break;
|
|
10188
10185
|
}
|
|
10189
10186
|
}
|
|
10190
|
-
if (
|
|
10187
|
+
if (turnHadApplied && !isRecallVerified(turn)) {
|
|
10191
10188
|
recalledUnverified += 1;
|
|
10192
10189
|
bumpClient(turn.client, (m) => {
|
|
10193
10190
|
m.recalled_unverified += 1;
|
|
@@ -10825,7 +10822,7 @@ function formatPreexistingRootMessage(projectRoot) {
|
|
|
10825
10822
|
function createFabricServer(tracker) {
|
|
10826
10823
|
const server = new McpServer({
|
|
10827
10824
|
name: "fabric-knowledge-server",
|
|
10828
|
-
version: "2.0.
|
|
10825
|
+
version: "2.1.0-rc.2"
|
|
10829
10826
|
});
|
|
10830
10827
|
registerPlanContext(server, tracker);
|
|
10831
10828
|
registerKnowledgeSections(server, tracker);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fenglimg/fabric-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-rc.2",
|
|
4
4
|
"description": "Fabric MCP knowledge server — stdio transport for Claude Code / Cursor / Codex CLI, manages .fabric/ knowledge base + agents.meta.json + event ledger.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "wangzhichao <fenglimg90@gmail.com>",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
39
39
|
"minimatch": "^10.0.1",
|
|
40
40
|
"zod": "^3.25.0",
|
|
41
|
-
"@fenglimg/fabric-shared": "2.0.
|
|
41
|
+
"@fenglimg/fabric-shared": "2.1.0-rc.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.15.0",
|