secufusion-mcp 2.2.9 → 2.4.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.
- package/.claude-plugin/plugin.json +1 -1
- package/mcp/dist/server.js +45 -4
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "secufusion-mcp",
|
|
3
3
|
"description": "SecuFusion MSSP platform dev agent — project-level spec driven, tenant-isolation enforced, zero-trust guardrails. 5 Core Slash Commands: /sfn-init (dynamic DNA + architecture diagram + watcher), /sfn-plan (philosophy check + intent WHY + classify + plan), /sfn-code (spec-driven implementation), /sfn-review (zero-tolerance 3-tier PR gate), /sfn-explore (on-demand service graph or blast-radius analysis).",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Motivity Labs"
|
|
7
7
|
},
|
package/mcp/dist/server.js
CHANGED
|
@@ -1556,15 +1556,31 @@ server.tool("philosophy_check", "MANDATORY PHASE -1 STEP — runs BEFORE classif
|
|
|
1556
1556
|
// Check cache
|
|
1557
1557
|
const philosophyDir = resolve(".secufusion/philosophy");
|
|
1558
1558
|
const philosophyFile = path.join(philosophyDir, `${work_item_id}.json`);
|
|
1559
|
+
let cached = null;
|
|
1559
1560
|
if (fs.existsSync(philosophyFile)) {
|
|
1560
1561
|
try {
|
|
1561
|
-
|
|
1562
|
+
cached = JSON.parse(readFileSafe(philosophyFile) || "null");
|
|
1562
1563
|
if (cached && (cached.philosophy_verdict === "PHILOSOPHY_PASS" || cached.philosophy_verdict === "PHILOSOPHY_ADVISORY")) {
|
|
1563
1564
|
return appendTelemetry({ content: [{ type: "text", text: `[PHILOSOPHY CACHED] ${work_item_id} — verdict: ${cached.philosophy_verdict}\n\n${cached.developer_message}` }] }, inputChars);
|
|
1564
1565
|
}
|
|
1565
1566
|
}
|
|
1566
1567
|
catch { }
|
|
1567
1568
|
}
|
|
1569
|
+
// Mandatory interview for features/stories
|
|
1570
|
+
if ((task_type === "feature" || task_type === "user_story") && (!cached || !cached.interview_completed)) {
|
|
1571
|
+
const interviewText = `[PHILOSOPHY FAIL] ${work_item_id}\n\nBefore I help you build this, talk to me.\n\nWhat problem is this solving?\nWalk me through what the user is experiencing today\nwithout this feature. What's broken? What's painful?\nWhat happens if we don't build this at all?\n\nWho will actually use this and how often?\nIs this solving a problem for 1 client or all tenants?\n\nI see you said WHO: CONFIRMED —\nbut confirmed by whom exactly?\nIs that a verbal yes in a meeting or\na written requirement from the client?\nThose are very different things.\n\nDo NOT call classify_task. Re-run philosophy_check after resolving.`;
|
|
1572
|
+
if (!fs.existsSync(philosophyDir))
|
|
1573
|
+
fs.mkdirSync(philosophyDir, { recursive: true });
|
|
1574
|
+
try {
|
|
1575
|
+
writeFile(philosophyFile, JSON.stringify({
|
|
1576
|
+
work_item_id,
|
|
1577
|
+
philosophy_verdict: "PHILOSOPHY_FAIL",
|
|
1578
|
+
interview_completed: true
|
|
1579
|
+
}, null, 2));
|
|
1580
|
+
}
|
|
1581
|
+
catch { }
|
|
1582
|
+
return appendTelemetry({ content: [{ type: "text", text: interviewText }] }, inputChars);
|
|
1583
|
+
}
|
|
1568
1584
|
const wsRoot = getWorkspaceRoot();
|
|
1569
1585
|
let rejectedPatterns = [];
|
|
1570
1586
|
const rejRaw = readFileSafe(resolve(REJECTED_FILE));
|
|
@@ -2033,15 +2049,40 @@ server.tool("classify_task", "MANDATORY FIRST STEP for every task without except
|
|
|
2033
2049
|
}
|
|
2034
2050
|
// ── Step 4: Signal scoring ────────────────────────────────────────────
|
|
2035
2051
|
const corpus = (title + " " + description).toLowerCase();
|
|
2036
|
-
|
|
2037
|
-
|
|
2052
|
+
// Structural backend terms — always a reliable signal of backend work regardless of task type
|
|
2053
|
+
const BACKEND_STRUCTURAL = [
|
|
2038
2054
|
"migration", "kafka", "consumer", "producer", "topic",
|
|
2039
|
-
"
|
|
2055
|
+
"database", "db", "repository", "backend",
|
|
2056
|
+
];
|
|
2057
|
+
// Contextual backend terms — these appear naturally when *describing* a bug symptom
|
|
2058
|
+
// ("the events API returns X", "service returns wrong value") without implying
|
|
2059
|
+
// backend work is needed. Counted for non-bugs only, OR for bugs that also contain
|
|
2060
|
+
// explicit backend-change language (see BACKEND_CHANGE_PHRASES below).
|
|
2061
|
+
const BACKEND_CONTEXTUAL = [
|
|
2062
|
+
"api", "endpoint", "service", "server", "rest",
|
|
2063
|
+
"json response", "payload", "query", "schema",
|
|
2064
|
+
];
|
|
2065
|
+
// Explicit backend-change phrases: these restore contextual terms even for bugs,
|
|
2066
|
+
// because they signal genuine backend scope rather than symptom description.
|
|
2067
|
+
const BACKEND_CHANGE_PHRASES = [
|
|
2068
|
+
"change the api", "update the api", "fix the api", "api contract",
|
|
2069
|
+
"update endpoint", "change endpoint", "fix endpoint", "new endpoint",
|
|
2070
|
+
"modify schema", "update schema", "alter table", "add column",
|
|
2071
|
+
"api change", "breaking change", "response contract", "request body",
|
|
2072
|
+
"fix the service", "update the service",
|
|
2073
|
+
];
|
|
2074
|
+
const hasExplicitBackendChange = BACKEND_CHANGE_PHRASES.some(p => corpus.includes(p));
|
|
2075
|
+
const isBugOrHotfix = task_type === "bug" || task_type === "hotfix";
|
|
2076
|
+
const BACKEND_SIGNALS = [
|
|
2077
|
+
...BACKEND_STRUCTURAL,
|
|
2078
|
+
// For bugs: contextual terms only re-admitted when description explicitly calls for backend change
|
|
2079
|
+
...(isBugOrHotfix && !hasExplicitBackendChange ? [] : BACKEND_CONTEXTUAL),
|
|
2040
2080
|
...learnedSignals.backend, ...learnedSignals.phrase, ...learnedSignals.bug_category
|
|
2041
2081
|
];
|
|
2042
2082
|
const FRONTEND_SIGNALS = [
|
|
2043
2083
|
"ui", "frontend", "react", "component", "page", "screen", "button",
|
|
2044
2084
|
"modal", "layout", "style", "css", "web ui", "browser ui", "render",
|
|
2085
|
+
"timestamp", "date format", "timezone", "display", "label", "icon", "text",
|
|
2045
2086
|
...learnedSignals.frontend
|
|
2046
2087
|
];
|
|
2047
2088
|
const EXTENSION_SIGNALS = [
|
package/package.json
CHANGED