@arcbridge/mcp-server 0.1.5 → 0.2.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/README.md +2 -1
- package/dist/index.js +194 -129
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -40,8 +40,8 @@ function registerInitProject(server, ctx) {
|
|
|
40
40
|
"Initialize ArcBridge in a project directory. Creates .arcbridge/ with arc42 documentation, phase plan, agent roles, SQLite database, and platform-specific configs.",
|
|
41
41
|
{
|
|
42
42
|
name: z.string().min(1).describe("Project name"),
|
|
43
|
-
template: z.enum(["nextjs-app-router", "react-vite", "api-service", "dotnet-webapi"]).default("nextjs-app-router").describe(
|
|
44
|
-
"Project template: nextjs-app-router (Next.js with App Router, SSR/SSG), react-vite (React SPA with Vite, client-only), api-service (Node.js API with Express/Fastify/Hono), dotnet-webapi (ASP.NET Core Web API, C#)"
|
|
43
|
+
template: z.enum(["nextjs-app-router", "react-vite", "api-service", "dotnet-webapi", "unity-game"]).default("nextjs-app-router").describe(
|
|
44
|
+
"Project template: nextjs-app-router (Next.js with App Router, SSR/SSG), react-vite (React SPA with Vite, client-only), api-service (Node.js API with Express/Fastify/Hono), dotnet-webapi (ASP.NET Core Web API, C#), unity-game (Unity game project, C#, code-heavy)"
|
|
45
45
|
),
|
|
46
46
|
features: z.array(z.enum(["auth", "database", "api"])).default([]).describe("Features to scaffold"),
|
|
47
47
|
quality_priorities: z.array(z.string()).default(["security", "performance", "accessibility", "maintainability"]).describe("Quality priorities in order"),
|
|
@@ -1104,16 +1104,80 @@ function registerDeleteTask(server, ctx) {
|
|
|
1104
1104
|
);
|
|
1105
1105
|
}
|
|
1106
1106
|
|
|
1107
|
-
// src/tools/
|
|
1107
|
+
// src/tools/create-phase.ts
|
|
1108
1108
|
import { z as z11 } from "zod";
|
|
1109
|
+
import { addPhaseToYaml, refreshFromDocs as refreshFromDocs4 } from "@arcbridge/core";
|
|
1110
|
+
function registerCreatePhase(server, ctx) {
|
|
1111
|
+
server.tool(
|
|
1112
|
+
"arcbridge_create_phase",
|
|
1113
|
+
"Create a new phase in the project plan. Use this to add phases beyond the initial 4-phase template when the project scope requires it.",
|
|
1114
|
+
{
|
|
1115
|
+
target_dir: z11.string().describe("Absolute path to the project directory"),
|
|
1116
|
+
name: z11.string().min(1).describe("Phase name (e.g., 'Integrations', 'Performance Optimization')"),
|
|
1117
|
+
description: z11.string().min(1).describe("What this phase covers"),
|
|
1118
|
+
phase_number: z11.number().int().min(0).optional().describe("Phase number (default: next after highest existing phase)"),
|
|
1119
|
+
gate_requirements: z11.array(z11.string()).default([]).describe("Requirements that must be met to complete this phase")
|
|
1120
|
+
},
|
|
1121
|
+
async (params) => {
|
|
1122
|
+
const db = ensureDb(ctx, params.target_dir);
|
|
1123
|
+
if (!db) return notInitialized();
|
|
1124
|
+
refreshFromDocs4(db, params.target_dir);
|
|
1125
|
+
const maxPhase = db.prepare("SELECT MAX(phase_number) as max FROM phases").get();
|
|
1126
|
+
const phaseNumber = params.phase_number ?? (maxPhase.max ?? -1) + 1;
|
|
1127
|
+
const existing = db.prepare("SELECT id FROM phases WHERE phase_number = ?").get(phaseNumber);
|
|
1128
|
+
if (existing) {
|
|
1129
|
+
return textResult(
|
|
1130
|
+
`Phase number ${phaseNumber} already exists (\`${existing.id}\`). Choose a different number or omit to auto-assign.`
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
const slug = params.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 30) || "unnamed";
|
|
1134
|
+
const phaseId = `phase-${phaseNumber}-${slug}`;
|
|
1135
|
+
const yamlResult = addPhaseToYaml(params.target_dir, {
|
|
1136
|
+
id: phaseId,
|
|
1137
|
+
name: params.name,
|
|
1138
|
+
phase_number: phaseNumber,
|
|
1139
|
+
description: params.description,
|
|
1140
|
+
gate_requirements: params.gate_requirements
|
|
1141
|
+
});
|
|
1142
|
+
if (!yamlResult.success) {
|
|
1143
|
+
return textResult(
|
|
1144
|
+
`Failed to create phase: ${yamlResult.warning ?? "YAML update failed"}`
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
refreshFromDocs4(db, params.target_dir);
|
|
1148
|
+
const lines = [
|
|
1149
|
+
`Phase created: **${phaseId}**`,
|
|
1150
|
+
"",
|
|
1151
|
+
`**Name:** ${params.name}`,
|
|
1152
|
+
`**Number:** ${phaseNumber}`,
|
|
1153
|
+
`**Status:** planned`,
|
|
1154
|
+
`**Description:** ${params.description}`
|
|
1155
|
+
];
|
|
1156
|
+
if (params.gate_requirements.length > 0) {
|
|
1157
|
+
lines.push("", "**Gate requirements:**");
|
|
1158
|
+
for (const r of params.gate_requirements) {
|
|
1159
|
+
lines.push(`- [ ] ${r}`);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
lines.push(
|
|
1163
|
+
"",
|
|
1164
|
+
`Use \`arcbridge_create_task\` with phase ID \`${phaseId}\` to add tasks.`
|
|
1165
|
+
);
|
|
1166
|
+
return textResult(lines.join("\n"));
|
|
1167
|
+
}
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// src/tools/get-relevant-adrs.ts
|
|
1172
|
+
import { z as z12 } from "zod";
|
|
1109
1173
|
function registerGetRelevantAdrs(server, ctx) {
|
|
1110
1174
|
server.tool(
|
|
1111
1175
|
"arcbridge_get_relevant_adrs",
|
|
1112
1176
|
"Get architectural decision records (ADRs) relevant to a specific file path or building block.",
|
|
1113
1177
|
{
|
|
1114
|
-
target_dir:
|
|
1115
|
-
file_path:
|
|
1116
|
-
building_block:
|
|
1178
|
+
target_dir: z12.string().describe("Absolute path to the project directory"),
|
|
1179
|
+
file_path: z12.string().optional().describe("File path to find relevant ADRs for"),
|
|
1180
|
+
building_block: z12.string().optional().describe("Building block ID to find relevant ADRs for")
|
|
1117
1181
|
},
|
|
1118
1182
|
async (params) => {
|
|
1119
1183
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -1197,24 +1261,24 @@ function formatAdrs(adrs, title) {
|
|
|
1197
1261
|
}
|
|
1198
1262
|
|
|
1199
1263
|
// src/tools/reindex.ts
|
|
1200
|
-
import { z as
|
|
1201
|
-
import { indexProject as indexProject2, refreshFromDocs as
|
|
1264
|
+
import { z as z13 } from "zod";
|
|
1265
|
+
import { indexProject as indexProject2, refreshFromDocs as refreshFromDocs5 } from "@arcbridge/core";
|
|
1202
1266
|
function registerReindex(server, ctx) {
|
|
1203
1267
|
server.tool(
|
|
1204
1268
|
"arcbridge_reindex",
|
|
1205
1269
|
"Re-index the project: refreshes architecture docs from arc42/YAML files, then reindexes code symbols (TypeScript & C#/.NET). This is the first step of the sync pipeline \u2014 use it to pick up manual doc edits and code changes.",
|
|
1206
1270
|
{
|
|
1207
|
-
target_dir:
|
|
1208
|
-
tsconfig_path:
|
|
1209
|
-
service:
|
|
1210
|
-
language:
|
|
1271
|
+
target_dir: z13.string().describe("Absolute path to the project directory"),
|
|
1272
|
+
tsconfig_path: z13.string().optional().describe("Override tsconfig.json path (default: auto-detect). Only used for TypeScript projects."),
|
|
1273
|
+
service: z13.string().optional().describe("Service name for monorepo projects (default: 'main')"),
|
|
1274
|
+
language: z13.enum(["typescript", "csharp", "auto"]).optional().describe("Project language. 'auto' detects from project files (default: 'auto')")
|
|
1211
1275
|
},
|
|
1212
1276
|
async (params) => {
|
|
1213
1277
|
const start = Date.now();
|
|
1214
1278
|
const db = ensureDb(ctx, params.target_dir);
|
|
1215
1279
|
if (!db) return notInitialized();
|
|
1216
1280
|
try {
|
|
1217
|
-
const docWarnings =
|
|
1281
|
+
const docWarnings = refreshFromDocs5(db, params.target_dir);
|
|
1218
1282
|
const result = await indexProject2(db, {
|
|
1219
1283
|
projectRoot: params.target_dir,
|
|
1220
1284
|
tsconfigPath: params.tsconfig_path,
|
|
@@ -1253,16 +1317,16 @@ function registerReindex(server, ctx) {
|
|
|
1253
1317
|
}
|
|
1254
1318
|
|
|
1255
1319
|
// src/tools/search-symbols.ts
|
|
1256
|
-
import { z as
|
|
1320
|
+
import { z as z14 } from "zod";
|
|
1257
1321
|
function registerSearchSymbols(server, ctx) {
|
|
1258
1322
|
server.tool(
|
|
1259
1323
|
"arcbridge_search_symbols",
|
|
1260
1324
|
"Search code symbols by name, kind, file path, or building block. Supports TypeScript and C#. Returns matching symbols with type signatures.",
|
|
1261
1325
|
{
|
|
1262
|
-
target_dir:
|
|
1263
|
-
query:
|
|
1264
|
-
service:
|
|
1265
|
-
kind:
|
|
1326
|
+
target_dir: z14.string().describe("Absolute path to the project directory"),
|
|
1327
|
+
query: z14.string().optional().describe("Search term to match against symbol names"),
|
|
1328
|
+
service: z14.string().optional().describe("Filter by service name (for multi-project solutions). Omit to search all services."),
|
|
1329
|
+
kind: z14.enum([
|
|
1266
1330
|
"function",
|
|
1267
1331
|
"class",
|
|
1268
1332
|
"type",
|
|
@@ -1274,10 +1338,10 @@ function registerSearchSymbols(server, ctx) {
|
|
|
1274
1338
|
"hook",
|
|
1275
1339
|
"context"
|
|
1276
1340
|
]).optional().describe("Filter by symbol kind"),
|
|
1277
|
-
file_path:
|
|
1278
|
-
is_exported:
|
|
1279
|
-
building_block:
|
|
1280
|
-
limit:
|
|
1341
|
+
file_path: z14.string().optional().describe("Filter by file path (prefix match)"),
|
|
1342
|
+
is_exported: z14.boolean().optional().describe("Filter by export status"),
|
|
1343
|
+
building_block: z14.string().optional().describe("Filter by building block ID (matches against code_paths)"),
|
|
1344
|
+
limit: z14.number().int().min(1).max(200).default(50).describe("Maximum results to return (default: 50)")
|
|
1281
1345
|
},
|
|
1282
1346
|
async (params) => {
|
|
1283
1347
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -1364,7 +1428,7 @@ function registerSearchSymbols(server, ctx) {
|
|
|
1364
1428
|
}
|
|
1365
1429
|
|
|
1366
1430
|
// src/tools/get-symbol.ts
|
|
1367
|
-
import { z as
|
|
1431
|
+
import { z as z15 } from "zod";
|
|
1368
1432
|
import { readFileSync, existsSync as existsSync3 } from "fs";
|
|
1369
1433
|
import { join as join3 } from "path";
|
|
1370
1434
|
function registerGetSymbol(server, ctx) {
|
|
@@ -1372,11 +1436,11 @@ function registerGetSymbol(server, ctx) {
|
|
|
1372
1436
|
"arcbridge_get_symbol",
|
|
1373
1437
|
"Get detailed information about a specific TypeScript symbol including its source code, type signature, and relationships.",
|
|
1374
1438
|
{
|
|
1375
|
-
target_dir:
|
|
1376
|
-
symbol_id:
|
|
1439
|
+
target_dir: z15.string().describe("Absolute path to the project directory"),
|
|
1440
|
+
symbol_id: z15.string().describe(
|
|
1377
1441
|
"Symbol ID (e.g. 'src/utils.ts::formatName#function')"
|
|
1378
1442
|
),
|
|
1379
|
-
include_source:
|
|
1443
|
+
include_source: z15.boolean().default(true).describe("Include source code snippet (default: true)")
|
|
1380
1444
|
},
|
|
1381
1445
|
async (params) => {
|
|
1382
1446
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -1474,21 +1538,21 @@ Use \`arcbridge_search_symbols\` to find symbols by name.`
|
|
|
1474
1538
|
}
|
|
1475
1539
|
|
|
1476
1540
|
// src/tools/get-dependency-graph.ts
|
|
1477
|
-
import { z as
|
|
1541
|
+
import { z as z16 } from "zod";
|
|
1478
1542
|
function registerGetDependencyGraph(server, ctx) {
|
|
1479
1543
|
server.tool(
|
|
1480
1544
|
"arcbridge_get_dependency_graph",
|
|
1481
1545
|
"Get the dependency graph for a module or file. Shows imports, calls, type usage, and inheritance relationships between symbols.",
|
|
1482
1546
|
{
|
|
1483
|
-
target_dir:
|
|
1484
|
-
module:
|
|
1547
|
+
target_dir: z16.string().describe("Absolute path to the project directory"),
|
|
1548
|
+
module: z16.string().describe(
|
|
1485
1549
|
"Module path relative to project root (e.g. 'src/lib/auth')"
|
|
1486
1550
|
),
|
|
1487
|
-
direction:
|
|
1551
|
+
direction: z16.enum(["dependencies", "dependents", "both"]).default("both").describe(
|
|
1488
1552
|
"Graph direction: 'dependencies' (what this module uses), 'dependents' (what uses this module), or 'both'"
|
|
1489
1553
|
),
|
|
1490
|
-
depth:
|
|
1491
|
-
service:
|
|
1554
|
+
depth: z16.number().int().min(1).max(5).default(1).describe("How many levels to traverse (default: 1, max: 5)"),
|
|
1555
|
+
service: z16.string().optional().describe("Filter by service name (for multi-project solutions). Omit to search all services.")
|
|
1492
1556
|
},
|
|
1493
1557
|
async (params) => {
|
|
1494
1558
|
const maybeDb = ensureDb(ctx, params.target_dir);
|
|
@@ -1635,16 +1699,16 @@ function formatEdges(edges, modulePath, direction) {
|
|
|
1635
1699
|
}
|
|
1636
1700
|
|
|
1637
1701
|
// src/tools/get-component-graph.ts
|
|
1638
|
-
import { z as
|
|
1702
|
+
import { z as z17 } from "zod";
|
|
1639
1703
|
function registerGetComponentGraph(server, ctx) {
|
|
1640
1704
|
server.tool(
|
|
1641
1705
|
"arcbridge_get_component_graph",
|
|
1642
1706
|
"Get the React component graph: component hierarchy, props, state, context usage, and server/client boundaries.",
|
|
1643
1707
|
{
|
|
1644
|
-
target_dir:
|
|
1645
|
-
file_path:
|
|
1646
|
-
client_only:
|
|
1647
|
-
with_state:
|
|
1708
|
+
target_dir: z17.string().describe("Absolute path to the project directory"),
|
|
1709
|
+
file_path: z17.string().optional().describe("Filter to components in a specific file or directory prefix"),
|
|
1710
|
+
client_only: z17.boolean().optional().describe("Only show client components ('use client')"),
|
|
1711
|
+
with_state: z17.boolean().optional().describe("Only show components that use state (useState/useReducer)")
|
|
1648
1712
|
},
|
|
1649
1713
|
async (params) => {
|
|
1650
1714
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -1748,16 +1812,16 @@ function registerGetComponentGraph(server, ctx) {
|
|
|
1748
1812
|
}
|
|
1749
1813
|
|
|
1750
1814
|
// src/tools/get-route-map.ts
|
|
1751
|
-
import { z as
|
|
1815
|
+
import { z as z18 } from "zod";
|
|
1752
1816
|
function registerGetRouteMap(server, ctx) {
|
|
1753
1817
|
server.tool(
|
|
1754
1818
|
"arcbridge_get_route_map",
|
|
1755
1819
|
"Get the route map: pages, layouts, API routes, and their hierarchy. Works with Next.js, ASP.NET controllers, and minimal APIs.",
|
|
1756
1820
|
{
|
|
1757
|
-
target_dir:
|
|
1758
|
-
kind:
|
|
1759
|
-
route_prefix:
|
|
1760
|
-
service:
|
|
1821
|
+
target_dir: z18.string().describe("Absolute path to the project directory"),
|
|
1822
|
+
kind: z18.enum(["page", "layout", "loading", "error", "not-found", "api-route", "middleware"]).optional().describe("Filter by route kind"),
|
|
1823
|
+
route_prefix: z18.string().optional().describe("Filter by route path prefix (e.g. '/dashboard' or '/api/orders')"),
|
|
1824
|
+
service: z18.string().optional().describe("Filter by service name (for multi-project solutions). Omit to show all services.")
|
|
1761
1825
|
},
|
|
1762
1826
|
async (params) => {
|
|
1763
1827
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -1833,13 +1897,13 @@ function registerGetRouteMap(server, ctx) {
|
|
|
1833
1897
|
}
|
|
1834
1898
|
|
|
1835
1899
|
// src/tools/get-boundary-analysis.ts
|
|
1836
|
-
import { z as
|
|
1900
|
+
import { z as z19 } from "zod";
|
|
1837
1901
|
function registerGetBoundaryAnalysis(server, ctx) {
|
|
1838
1902
|
server.tool(
|
|
1839
1903
|
"arcbridge_get_boundary_analysis",
|
|
1840
1904
|
"Analyze server/client boundaries in a Next.js project. Identifies client components, server components, server actions, and potential boundary violations.",
|
|
1841
1905
|
{
|
|
1842
|
-
target_dir:
|
|
1906
|
+
target_dir: z19.string().describe("Absolute path to the project directory")
|
|
1843
1907
|
},
|
|
1844
1908
|
async (params) => {
|
|
1845
1909
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -1943,15 +2007,15 @@ function registerGetBoundaryAnalysis(server, ctx) {
|
|
|
1943
2007
|
}
|
|
1944
2008
|
|
|
1945
2009
|
// src/tools/check-drift.ts
|
|
1946
|
-
import { z as
|
|
2010
|
+
import { z as z20 } from "zod";
|
|
1947
2011
|
import { detectDrift, writeDriftLog } from "@arcbridge/core";
|
|
1948
2012
|
function registerCheckDrift(server, ctx) {
|
|
1949
2013
|
server.tool(
|
|
1950
2014
|
"arcbridge_check_drift",
|
|
1951
2015
|
"Detect architecture drift: undocumented modules, missing code paths, cross-block dependency violations, and stale ADR references.",
|
|
1952
2016
|
{
|
|
1953
|
-
target_dir:
|
|
1954
|
-
persist:
|
|
2017
|
+
target_dir: z20.string().describe("Absolute path to the project directory"),
|
|
2018
|
+
persist: z20.boolean().default(true).describe("Write findings to drift_log table (default: true)")
|
|
1955
2019
|
},
|
|
1956
2020
|
async (params) => {
|
|
1957
2021
|
const start = Date.now();
|
|
@@ -2023,16 +2087,16 @@ function registerCheckDrift(server, ctx) {
|
|
|
2023
2087
|
}
|
|
2024
2088
|
|
|
2025
2089
|
// src/tools/get-guidance.ts
|
|
2026
|
-
import { z as
|
|
2090
|
+
import { z as z21 } from "zod";
|
|
2027
2091
|
import { loadConfig as loadConfig3 } from "@arcbridge/core";
|
|
2028
2092
|
function registerGetGuidance(server, ctx) {
|
|
2029
2093
|
server.tool(
|
|
2030
2094
|
"arcbridge_get_guidance",
|
|
2031
2095
|
"Get context-aware architectural guidance for a code change. Surfaces relevant quality scenarios, patterns, constraints, and questions to consider.",
|
|
2032
2096
|
{
|
|
2033
|
-
target_dir:
|
|
2034
|
-
file_path:
|
|
2035
|
-
action:
|
|
2097
|
+
target_dir: z21.string().describe("Absolute path to the project directory"),
|
|
2098
|
+
file_path: z21.string().optional().describe("File path you're working on (to determine building block and context)"),
|
|
2099
|
+
action: z21.enum([
|
|
2036
2100
|
"adding-component",
|
|
2037
2101
|
"adding-api-route",
|
|
2038
2102
|
"adding-hook",
|
|
@@ -2230,14 +2294,14 @@ function getActionGuidance(action, projectType) {
|
|
|
2230
2294
|
}
|
|
2231
2295
|
|
|
2232
2296
|
// src/tools/get-open-questions.ts
|
|
2233
|
-
import { z as
|
|
2297
|
+
import { z as z22 } from "zod";
|
|
2234
2298
|
function registerGetOpenQuestions(server, ctx) {
|
|
2235
2299
|
server.tool(
|
|
2236
2300
|
"arcbridge_get_open_questions",
|
|
2237
2301
|
"Surface architectural gaps: untested quality scenarios, building blocks without boundaries, unresolved drift, and tasks missing acceptance criteria.",
|
|
2238
2302
|
{
|
|
2239
|
-
target_dir:
|
|
2240
|
-
scope:
|
|
2303
|
+
target_dir: z22.string().describe("Absolute path to the project directory"),
|
|
2304
|
+
scope: z22.string().optional().describe("Focus scope: 'current-phase', 'building-block:<id>', or omit for project-wide")
|
|
2241
2305
|
},
|
|
2242
2306
|
async (params) => {
|
|
2243
2307
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -2347,7 +2411,7 @@ function registerGetOpenQuestions(server, ctx) {
|
|
|
2347
2411
|
}
|
|
2348
2412
|
|
|
2349
2413
|
// src/tools/propose-arc42-update.ts
|
|
2350
|
-
import { z as
|
|
2414
|
+
import { z as z23 } from "zod";
|
|
2351
2415
|
import {
|
|
2352
2416
|
resolveRef,
|
|
2353
2417
|
getChangedFiles,
|
|
@@ -2359,9 +2423,9 @@ function registerProposeArc42Update(server, ctx) {
|
|
|
2359
2423
|
"arcbridge_propose_arc42_update",
|
|
2360
2424
|
"Analyze code changes since a reference point and generate specific, actionable proposals for updating arc42 documentation.",
|
|
2361
2425
|
{
|
|
2362
|
-
target_dir:
|
|
2363
|
-
changes_since:
|
|
2364
|
-
update_sync_point:
|
|
2426
|
+
target_dir: z23.string().describe("Absolute path to the project directory"),
|
|
2427
|
+
changes_since: z23.string().default("last-sync").describe("Reference point: 'last-commit', 'last-sync', 'last-phase', or a git ref"),
|
|
2428
|
+
update_sync_point: z23.boolean().default(false).describe("Update the stored sync commit to HEAD after generating proposals")
|
|
2365
2429
|
},
|
|
2366
2430
|
async (params) => {
|
|
2367
2431
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -2549,7 +2613,7 @@ function findCrossBlockConsumers(db, symbolId, sourceBlockId, blocks) {
|
|
|
2549
2613
|
}
|
|
2550
2614
|
|
|
2551
2615
|
// src/tools/get-practice-review.ts
|
|
2552
|
-
import { z as
|
|
2616
|
+
import { z as z24 } from "zod";
|
|
2553
2617
|
import {
|
|
2554
2618
|
resolveRef as resolveRef2,
|
|
2555
2619
|
getChangedFiles as getChangedFiles2,
|
|
@@ -2561,8 +2625,8 @@ function registerGetPracticeReview(server, ctx) {
|
|
|
2561
2625
|
"arcbridge_get_practice_review",
|
|
2562
2626
|
"Structured, practice-aware review of recent code changes across 5 dimensions: Architecture, Security, Testing, Documentation, and Complexity.",
|
|
2563
2627
|
{
|
|
2564
|
-
target_dir:
|
|
2565
|
-
since:
|
|
2628
|
+
target_dir: z24.string().describe("Absolute path to the project directory"),
|
|
2629
|
+
since: z24.string().default("last-commit").describe("Reference point: 'last-commit', 'last-session', or 'last-phase'")
|
|
2566
2630
|
},
|
|
2567
2631
|
async (params) => {
|
|
2568
2632
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -2878,7 +2942,7 @@ function reviewComplexity(db, changedFiles, findings) {
|
|
|
2878
2942
|
}
|
|
2879
2943
|
|
|
2880
2944
|
// src/tools/complete-phase.ts
|
|
2881
|
-
import { z as
|
|
2945
|
+
import { z as z25 } from "zod";
|
|
2882
2946
|
import {
|
|
2883
2947
|
detectDrift as detectDrift3,
|
|
2884
2948
|
writeDriftLog as writeDriftLog2,
|
|
@@ -2888,7 +2952,7 @@ import {
|
|
|
2888
2952
|
applyInferences,
|
|
2889
2953
|
verifyScenarios,
|
|
2890
2954
|
loadConfig as loadConfig4,
|
|
2891
|
-
refreshFromDocs as
|
|
2955
|
+
refreshFromDocs as refreshFromDocs6,
|
|
2892
2956
|
syncPhaseToYaml,
|
|
2893
2957
|
transaction
|
|
2894
2958
|
} from "@arcbridge/core";
|
|
@@ -2897,17 +2961,17 @@ function registerCompletePhase(server, ctx) {
|
|
|
2897
2961
|
"arcbridge_complete_phase",
|
|
2898
2962
|
"Attempt to complete a phase by validating all gates: tasks done, no critical drift, quality scenarios passing. Transitions the phase to 'complete' if all gates pass.",
|
|
2899
2963
|
{
|
|
2900
|
-
target_dir:
|
|
2901
|
-
phase_id:
|
|
2902
|
-
notes:
|
|
2903
|
-
auto_infer:
|
|
2904
|
-
run_tests:
|
|
2964
|
+
target_dir: z25.string().describe("Absolute path to the project directory"),
|
|
2965
|
+
phase_id: z25.string().optional().describe("Phase ID to complete (defaults to current in-progress phase)"),
|
|
2966
|
+
notes: z25.string().optional().describe("Optional notes about this phase completion"),
|
|
2967
|
+
auto_infer: z25.boolean().default(true).describe("Automatically infer task statuses from code state before checking gates"),
|
|
2968
|
+
run_tests: z25.boolean().default(false).describe("Run linked tests for quality scenarios before checking the quality gate")
|
|
2905
2969
|
},
|
|
2906
2970
|
async (params) => {
|
|
2907
2971
|
const start = Date.now();
|
|
2908
2972
|
const db = ensureDb(ctx, params.target_dir);
|
|
2909
2973
|
if (!db) return notInitialized();
|
|
2910
|
-
|
|
2974
|
+
refreshFromDocs6(db, params.target_dir);
|
|
2911
2975
|
let phase;
|
|
2912
2976
|
if (params.phase_id) {
|
|
2913
2977
|
phase = db.prepare("SELECT id, name, phase_number, status, gate_status FROM phases WHERE id = ?").get(params.phase_id);
|
|
@@ -3116,18 +3180,18 @@ function registerCompletePhase(server, ctx) {
|
|
|
3116
3180
|
}
|
|
3117
3181
|
|
|
3118
3182
|
// src/tools/activate-role.ts
|
|
3119
|
-
import { z as
|
|
3183
|
+
import { z as z26 } from "zod";
|
|
3120
3184
|
import { loadRole, loadRoles } from "@arcbridge/core";
|
|
3121
3185
|
function registerActivateRole(server, ctx) {
|
|
3122
3186
|
server.tool(
|
|
3123
3187
|
"arcbridge_activate_role",
|
|
3124
3188
|
"Activate an agent role: loads the role's system prompt, required tools, quality focus, and pre-loaded architectural context.",
|
|
3125
3189
|
{
|
|
3126
|
-
target_dir:
|
|
3127
|
-
role:
|
|
3190
|
+
target_dir: z26.string().describe("Absolute path to the project directory"),
|
|
3191
|
+
role: z26.string().describe(
|
|
3128
3192
|
"Role ID to activate (e.g., 'architect', 'implementer', 'security-reviewer')"
|
|
3129
3193
|
),
|
|
3130
|
-
building_block:
|
|
3194
|
+
building_block: z26.string().optional().describe("Focus on a specific building block (for implementer/code-reviewer roles)")
|
|
3131
3195
|
},
|
|
3132
3196
|
async (params) => {
|
|
3133
3197
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -3429,18 +3493,18 @@ function getRoleDefinition(roleId) {
|
|
|
3429
3493
|
}
|
|
3430
3494
|
|
|
3431
3495
|
// src/tools/verify-scenarios.ts
|
|
3432
|
-
import { z as
|
|
3496
|
+
import { z as z27 } from "zod";
|
|
3433
3497
|
import { verifyScenarios as verifyScenarios2, loadConfig as loadConfig5 } from "@arcbridge/core";
|
|
3434
3498
|
function registerVerifyScenarios(server, ctx) {
|
|
3435
3499
|
server.tool(
|
|
3436
3500
|
"arcbridge_verify_scenarios",
|
|
3437
3501
|
"Run linked tests for quality scenarios and update their pass/fail status. Only runs scenarios with verification='automatic' or 'semi-automatic' and non-empty linked_tests.",
|
|
3438
3502
|
{
|
|
3439
|
-
target_dir:
|
|
3440
|
-
scenario_ids:
|
|
3503
|
+
target_dir: z27.string().describe("Absolute path to the project directory"),
|
|
3504
|
+
scenario_ids: z27.array(z27.string()).optional().describe(
|
|
3441
3505
|
"Specific scenario IDs to verify (e.g., ['SEC-01', 'PERF-01']). If omitted, verifies all automatic scenarios."
|
|
3442
3506
|
),
|
|
3443
|
-
test_command:
|
|
3507
|
+
test_command: z27.string().optional().describe(
|
|
3444
3508
|
"Override the test command from config (e.g., 'npx jest'). File paths are appended as arguments."
|
|
3445
3509
|
)
|
|
3446
3510
|
},
|
|
@@ -3507,7 +3571,7 @@ function registerVerifyScenarios(server, ctx) {
|
|
|
3507
3571
|
}
|
|
3508
3572
|
|
|
3509
3573
|
// src/tools/run-role-check.ts
|
|
3510
|
-
import { z as
|
|
3574
|
+
import { z as z28 } from "zod";
|
|
3511
3575
|
import {
|
|
3512
3576
|
loadRole as loadRole2,
|
|
3513
3577
|
loadRoles as loadRoles2,
|
|
@@ -3522,11 +3586,11 @@ function registerRunRoleCheck(server, ctx) {
|
|
|
3522
3586
|
"arcbridge_run_role_check",
|
|
3523
3587
|
"Run a role-specific architectural analysis: resolves the role and executes relevant checks (drift, quality scenarios, boundaries, changed files) based on the role's focus areas.",
|
|
3524
3588
|
{
|
|
3525
|
-
target_dir:
|
|
3526
|
-
role:
|
|
3589
|
+
target_dir: z28.string().describe("Absolute path to the project directory"),
|
|
3590
|
+
role: z28.string().describe(
|
|
3527
3591
|
"Role ID to run checks for (e.g., 'security-reviewer', 'quality-guardian', 'architect', 'phase-manager', 'code-reviewer')"
|
|
3528
3592
|
),
|
|
3529
|
-
scope:
|
|
3593
|
+
scope: z28.enum(SCOPE_VALUES).default("current-phase").describe(
|
|
3530
3594
|
"Scope of analysis: 'last-commit' (recent changes), 'current-phase' (since phase start), 'full-project' (everything)"
|
|
3531
3595
|
)
|
|
3532
3596
|
},
|
|
@@ -3947,17 +4011,17 @@ function runCustomRoleCheck(db, lines, roleDef) {
|
|
|
3947
4011
|
}
|
|
3948
4012
|
|
|
3949
4013
|
// src/tools/update-scenario-status.ts
|
|
3950
|
-
import { z as
|
|
4014
|
+
import { z as z29 } from "zod";
|
|
3951
4015
|
import { syncScenarioToYaml, transaction as transaction2 } from "@arcbridge/core";
|
|
3952
4016
|
function registerUpdateScenarioStatus(server, ctx) {
|
|
3953
4017
|
server.tool(
|
|
3954
4018
|
"arcbridge_update_scenario_status",
|
|
3955
4019
|
"Update a quality scenario's status and optionally link test files. Use this to mark scenarios as passing/failing after manual verification, or to link test files so `arcbridge_verify_scenarios` can run them automatically.",
|
|
3956
4020
|
{
|
|
3957
|
-
target_dir:
|
|
3958
|
-
scenario_id:
|
|
3959
|
-
status:
|
|
3960
|
-
linked_tests:
|
|
4021
|
+
target_dir: z29.string().describe("Absolute path to the project directory"),
|
|
4022
|
+
scenario_id: z29.string().describe("Quality scenario ID (e.g., 'SEC-01', 'PERF-01')"),
|
|
4023
|
+
status: z29.enum(["passing", "failing", "untested", "partial"]).describe("New status for the scenario"),
|
|
4024
|
+
linked_tests: z29.array(z29.string()).optional().describe(
|
|
3961
4025
|
"Test file paths to link to this scenario (e.g., ['src/__tests__/auth.test.ts']). Once linked, `arcbridge_verify_scenarios` can run them automatically. Also sets verification to 'semi-automatic' if currently 'manual'."
|
|
3962
4026
|
)
|
|
3963
4027
|
},
|
|
@@ -4038,33 +4102,33 @@ ${invalid.map((p) => ` - ${p}`).join("\n")}`
|
|
|
4038
4102
|
}
|
|
4039
4103
|
|
|
4040
4104
|
// src/tools/record-activity.ts
|
|
4041
|
-
import { z as
|
|
4105
|
+
import { z as z30 } from "zod";
|
|
4042
4106
|
import { insertActivity as insertActivity2, getSessionTotals } from "@arcbridge/core";
|
|
4043
4107
|
function registerRecordActivity(server, ctx) {
|
|
4044
4108
|
server.tool(
|
|
4045
4109
|
"arcbridge_record_activity",
|
|
4046
4110
|
"Record agent activity \u2014 model, tokens, cost, duration, and optional quality snapshot. Use this to track what work was done and measure agent performance.",
|
|
4047
4111
|
{
|
|
4048
|
-
target_dir:
|
|
4049
|
-
tool_name:
|
|
4050
|
-
action:
|
|
4051
|
-
model:
|
|
4052
|
-
agent_role:
|
|
4053
|
-
task_id:
|
|
4054
|
-
phase_id:
|
|
4055
|
-
input_tokens:
|
|
4056
|
-
output_tokens:
|
|
4057
|
-
total_tokens:
|
|
4058
|
-
cost_usd:
|
|
4059
|
-
duration_ms:
|
|
4060
|
-
drift_count:
|
|
4061
|
-
drift_errors:
|
|
4062
|
-
test_pass_count:
|
|
4063
|
-
test_fail_count:
|
|
4064
|
-
lint_clean:
|
|
4065
|
-
typecheck_clean:
|
|
4066
|
-
notes:
|
|
4067
|
-
metadata:
|
|
4112
|
+
target_dir: z30.string().describe("Absolute path to the project directory"),
|
|
4113
|
+
tool_name: z30.string().describe("Name of the tool or action performed (e.g., 'arcbridge_update_task', 'code_edit')"),
|
|
4114
|
+
action: z30.string().optional().describe("Human-readable label (e.g., 'implement login form')"),
|
|
4115
|
+
model: z30.string().optional().describe("Model identifier (e.g., 'claude-sonnet-4-20250514')"),
|
|
4116
|
+
agent_role: z30.string().optional().describe("Active ArcBridge role (e.g., 'implementer')"),
|
|
4117
|
+
task_id: z30.string().optional().describe("Associated task ID"),
|
|
4118
|
+
phase_id: z30.string().optional().describe("Associated phase ID"),
|
|
4119
|
+
input_tokens: z30.number().int().nonnegative().optional().describe("Input/prompt tokens"),
|
|
4120
|
+
output_tokens: z30.number().int().nonnegative().optional().describe("Output/completion tokens"),
|
|
4121
|
+
total_tokens: z30.number().int().nonnegative().optional().describe("Total tokens (auto-computed if input+output given)"),
|
|
4122
|
+
cost_usd: z30.number().nonnegative().optional().describe("Estimated cost in USD"),
|
|
4123
|
+
duration_ms: z30.number().int().nonnegative().optional().describe("Wall-clock duration in ms"),
|
|
4124
|
+
drift_count: z30.number().int().nonnegative().optional().describe("Current drift count"),
|
|
4125
|
+
drift_errors: z30.number().int().nonnegative().optional().describe("Current drift errors"),
|
|
4126
|
+
test_pass_count: z30.number().int().nonnegative().optional().describe("Passing tests"),
|
|
4127
|
+
test_fail_count: z30.number().int().nonnegative().optional().describe("Failing tests"),
|
|
4128
|
+
lint_clean: z30.boolean().optional().describe("Whether lint passes cleanly"),
|
|
4129
|
+
typecheck_clean: z30.boolean().optional().describe("Whether typecheck passes cleanly"),
|
|
4130
|
+
notes: z30.string().optional().describe("Free-form notes"),
|
|
4131
|
+
metadata: z30.record(z30.unknown()).optional().describe("Additional key-value metadata")
|
|
4068
4132
|
},
|
|
4069
4133
|
async (params) => {
|
|
4070
4134
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -4119,23 +4183,23 @@ function registerRecordActivity(server, ctx) {
|
|
|
4119
4183
|
}
|
|
4120
4184
|
|
|
4121
4185
|
// src/tools/get-metrics.ts
|
|
4122
|
-
import { z as
|
|
4186
|
+
import { z as z31 } from "zod";
|
|
4123
4187
|
import { queryMetrics } from "@arcbridge/core";
|
|
4124
4188
|
function registerGetMetrics(server, ctx) {
|
|
4125
4189
|
server.tool(
|
|
4126
4190
|
"arcbridge_get_metrics",
|
|
4127
4191
|
"Query agent activity metrics \u2014 filter by model, task, phase, or time range. Group by model/task/phase/tool/day for aggregated views.",
|
|
4128
4192
|
{
|
|
4129
|
-
target_dir:
|
|
4130
|
-
task_id:
|
|
4131
|
-
phase_id:
|
|
4132
|
-
model:
|
|
4133
|
-
agent_role:
|
|
4134
|
-
tool_name:
|
|
4135
|
-
since:
|
|
4136
|
-
until:
|
|
4137
|
-
group_by:
|
|
4138
|
-
limit:
|
|
4193
|
+
target_dir: z31.string().describe("Absolute path to the project directory"),
|
|
4194
|
+
task_id: z31.string().optional().describe("Filter by task ID"),
|
|
4195
|
+
phase_id: z31.string().optional().describe("Filter by phase ID"),
|
|
4196
|
+
model: z31.string().optional().describe("Filter by model name"),
|
|
4197
|
+
agent_role: z31.string().optional().describe("Filter by agent role"),
|
|
4198
|
+
tool_name: z31.string().optional().describe("Filter by tool name"),
|
|
4199
|
+
since: z31.string().optional().describe("ISO 8601 timestamp \u2014 activity after this time"),
|
|
4200
|
+
until: z31.string().optional().describe("ISO 8601 timestamp \u2014 activity before this time"),
|
|
4201
|
+
group_by: z31.enum(["model", "task", "phase", "tool", "day", "none"]).default("none").describe("Group results for aggregation"),
|
|
4202
|
+
limit: z31.number().int().min(1).max(500).default(50).describe("Max rows in detail view (group_by=none)")
|
|
4139
4203
|
},
|
|
4140
4204
|
async (params) => {
|
|
4141
4205
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -4218,23 +4282,23 @@ function mdCell(val) {
|
|
|
4218
4282
|
}
|
|
4219
4283
|
|
|
4220
4284
|
// src/tools/export-metrics.ts
|
|
4221
|
-
import { z as
|
|
4285
|
+
import { z as z32 } from "zod";
|
|
4222
4286
|
import { exportMetrics } from "@arcbridge/core";
|
|
4223
4287
|
function registerExportMetrics(server, ctx) {
|
|
4224
4288
|
server.tool(
|
|
4225
4289
|
"arcbridge_export_metrics",
|
|
4226
4290
|
"Export agent activity metrics to a file (JSON, CSV, or Markdown) in .arcbridge/metrics/ for git commits or reporting.",
|
|
4227
4291
|
{
|
|
4228
|
-
target_dir:
|
|
4229
|
-
format:
|
|
4230
|
-
task_id:
|
|
4231
|
-
phase_id:
|
|
4232
|
-
model:
|
|
4233
|
-
agent_role:
|
|
4234
|
-
tool_name:
|
|
4235
|
-
since:
|
|
4236
|
-
until:
|
|
4237
|
-
max_rows:
|
|
4292
|
+
target_dir: z32.string().describe("Absolute path to the project directory"),
|
|
4293
|
+
format: z32.enum(["json", "csv", "markdown"]).default("json").describe("Export format"),
|
|
4294
|
+
task_id: z32.string().optional().describe("Filter by task ID"),
|
|
4295
|
+
phase_id: z32.string().optional().describe("Filter by phase ID"),
|
|
4296
|
+
model: z32.string().optional().describe("Filter by model name"),
|
|
4297
|
+
agent_role: z32.string().optional().describe("Filter by agent role"),
|
|
4298
|
+
tool_name: z32.string().optional().describe("Filter by tool name"),
|
|
4299
|
+
since: z32.string().optional().describe("ISO 8601 \u2014 activity after this time"),
|
|
4300
|
+
until: z32.string().optional().describe("ISO 8601 \u2014 activity before this time"),
|
|
4301
|
+
max_rows: z32.number().int().min(1).default(1e5).describe("Maximum rows to export (default: 100,000)")
|
|
4238
4302
|
},
|
|
4239
4303
|
async (params) => {
|
|
4240
4304
|
const db = ensureDb(ctx, params.target_dir);
|
|
@@ -4283,6 +4347,7 @@ function createArcBridgeServer() {
|
|
|
4283
4347
|
registerUpdateTask(server, ctx);
|
|
4284
4348
|
registerCreateTask(server, ctx);
|
|
4285
4349
|
registerDeleteTask(server, ctx);
|
|
4350
|
+
registerCreatePhase(server, ctx);
|
|
4286
4351
|
registerReindex(server, ctx);
|
|
4287
4352
|
registerSearchSymbols(server, ctx);
|
|
4288
4353
|
registerGetSymbol(server, ctx);
|