@toolbaux/guardian 0.1.12 → 0.1.13
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/commands/mcp-serve.js +74 -7
- package/package.json +1 -1
|
@@ -103,27 +103,94 @@ const SKIP_SERVICES = new Set(["str", "dict", "int", "len", "float", "max", "joi
|
|
|
103
103
|
function compact(obj) {
|
|
104
104
|
return JSON.stringify(obj);
|
|
105
105
|
}
|
|
106
|
+
function normalize(p) {
|
|
107
|
+
return p.replace(/^\.\//, "").replace(/\/\//g, "/");
|
|
108
|
+
}
|
|
106
109
|
function findModule(data, file) {
|
|
107
|
-
|
|
110
|
+
const f = normalize(file);
|
|
111
|
+
return data.service_map?.find((m) => {
|
|
112
|
+
const mp = normalize(m.path || "");
|
|
113
|
+
return mp && (f.startsWith(mp + "/") || f === mp);
|
|
114
|
+
}) || data.service_map?.find((m) => {
|
|
115
|
+
// Fallback: match by module ID (handles doubled paths)
|
|
116
|
+
const mid = normalize(m.id || "");
|
|
117
|
+
return mid && f.includes(mid);
|
|
118
|
+
});
|
|
108
119
|
}
|
|
109
120
|
function findEndpointsInFile(data, file) {
|
|
110
|
-
const f = file
|
|
111
|
-
|
|
121
|
+
const f = normalize(file);
|
|
122
|
+
const basename = path.basename(f);
|
|
123
|
+
return Object.values(data.api_registry || {}).filter((ep) => {
|
|
124
|
+
const ef = normalize(ep.file || "");
|
|
125
|
+
return ef && (f.includes(ef) || ef.includes(f) || ef.endsWith(basename));
|
|
126
|
+
});
|
|
112
127
|
}
|
|
113
128
|
function findModelsInFile(data, file) {
|
|
114
|
-
const f = file
|
|
115
|
-
|
|
129
|
+
const f = normalize(file);
|
|
130
|
+
const basename = path.basename(f);
|
|
131
|
+
return Object.values(data.model_registry || {}).filter((m) => {
|
|
132
|
+
const mf = normalize(m.file || "");
|
|
133
|
+
return mf && (f.includes(mf) || mf.includes(f) || mf.endsWith(basename));
|
|
134
|
+
});
|
|
116
135
|
}
|
|
117
136
|
// ── Tool implementations (compact JSON, no redundancy) ──
|
|
118
137
|
async function orient() {
|
|
138
|
+
// Read architecture-context.md first — it has the richest summary
|
|
139
|
+
const contextPath = path.join(path.dirname(intelPath), "architecture-context.md");
|
|
140
|
+
try {
|
|
141
|
+
const raw = await fs.readFile(contextPath, "utf8");
|
|
142
|
+
// Extract the content between guardian:context markers
|
|
143
|
+
const match = raw.match(/<!-- guardian:context[^>]*-->([\s\S]*?)<!-- \/guardian:context -->/);
|
|
144
|
+
if (match) {
|
|
145
|
+
// Parse the markdown into compact structured data
|
|
146
|
+
const content = match[1];
|
|
147
|
+
const lines = content.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
148
|
+
// Extract key sections
|
|
149
|
+
const desc = raw.match(/Description: (.+)/)?.[1] || "";
|
|
150
|
+
const codeMap = lines.find((l) => l.startsWith("**Backend:**")) || "";
|
|
151
|
+
// Module map with exports
|
|
152
|
+
const moduleLines = lines.filter((l) => l.startsWith("- **backend/") || l.startsWith("- **frontend/"));
|
|
153
|
+
const modules = moduleLines.map((l) => {
|
|
154
|
+
const m = l.match(/\*\*([^*]+)\*\*\s*\(([^)]+)\)\s*[—–-]\s*(.*)/);
|
|
155
|
+
return m ? [m[1], m[2], m[3].slice(0, 60)] : null;
|
|
156
|
+
}).filter(Boolean);
|
|
157
|
+
// Dependencies
|
|
158
|
+
const deps = lines.filter((l) => l.includes("→")).map((l) => l.replace(/^- /, ""));
|
|
159
|
+
// High-coupling files
|
|
160
|
+
const coupling = lines.filter((l) => l.match(/score \d/)).map((l) => l.replace(/^- /, ""));
|
|
161
|
+
// Structural intelligence
|
|
162
|
+
const si = lines.filter((l) => l.includes("depth=")).map((l) => l.replace(/^- /, ""));
|
|
163
|
+
// Model-endpoint map
|
|
164
|
+
const modelEp = lines.filter((l) => l.includes("endpoints) ->")).map((l) => l.replace(/^- /, ""));
|
|
165
|
+
return compact({
|
|
166
|
+
desc: desc.slice(0, 120),
|
|
167
|
+
map: codeMap,
|
|
168
|
+
modules,
|
|
169
|
+
deps,
|
|
170
|
+
coupling: coupling.slice(0, 5),
|
|
171
|
+
si: si.slice(0, 5),
|
|
172
|
+
modelEp,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch { }
|
|
177
|
+
// Fallback: build from codebase-intelligence.json
|
|
119
178
|
const d = await loadIntel();
|
|
120
179
|
const c = d.meta?.counts || {};
|
|
180
|
+
// Compute endpoint counts from api_registry (service_map counts are often 0)
|
|
181
|
+
const epByMod = {};
|
|
182
|
+
for (const ep of Object.values(d.api_registry || {})) {
|
|
183
|
+
epByMod[ep.module] = (epByMod[ep.module] || 0) + 1;
|
|
184
|
+
}
|
|
121
185
|
const mods = (d.service_map || []).filter((m) => m.file_count > 0);
|
|
122
|
-
const topMods = mods
|
|
186
|
+
const topMods = mods
|
|
187
|
+
.map((m) => ({ ...m, ep_count: epByMod[m.id] || 0 }))
|
|
188
|
+
.sort((a, b) => b.ep_count - a.ep_count)
|
|
189
|
+
.slice(0, 6);
|
|
123
190
|
return compact({
|
|
124
191
|
p: d.meta?.project,
|
|
125
192
|
ep: c.endpoints, mod: c.models, pg: c.pages, m: c.modules,
|
|
126
|
-
top: topMods.map((m) => [m.id, m.
|
|
193
|
+
top: topMods.map((m) => [m.id, m.ep_count, m.layer]),
|
|
127
194
|
pages: (d.frontend_pages || []).map((p) => p.path),
|
|
128
195
|
});
|
|
129
196
|
}
|
package/package.json
CHANGED