@hivehub/rulebook 4.4.1 → 5.0.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/README.md +45 -4
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +86 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/core/agent-template-engine.d.ts +51 -0
- package/dist/core/agent-template-engine.d.ts.map +1 -0
- package/dist/core/agent-template-engine.js +273 -0
- package/dist/core/agent-template-engine.js.map +1 -0
- package/dist/core/complexity-detector.d.ts +36 -0
- package/dist/core/complexity-detector.d.ts.map +1 -0
- package/dist/core/complexity-detector.js +254 -0
- package/dist/core/complexity-detector.js.map +1 -0
- package/dist/core/generator.d.ts +1 -0
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/generator.js +21 -3
- package/dist/core/generator.js.map +1 -1
- package/dist/core/indexer/background-indexer.d.ts +2 -2
- package/dist/core/indexer/background-indexer.d.ts.map +1 -1
- package/dist/core/indexer/background-indexer.js +55 -61
- package/dist/core/indexer/background-indexer.js.map +1 -1
- package/dist/core/rule-engine.d.ts +64 -0
- package/dist/core/rule-engine.d.ts.map +1 -0
- package/dist/core/rule-engine.js +333 -0
- package/dist/core/rule-engine.js.map +1 -0
- package/dist/core/task-manager.d.ts +4 -0
- package/dist/core/task-manager.d.ts.map +1 -1
- package/dist/core/task-manager.js +39 -24
- package/dist/core/task-manager.js.map +1 -1
- package/dist/index.js +182 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/rulebook-server.d.ts.map +1 -1
- package/dist/mcp/rulebook-server.js +278 -26
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/memory/hnsw-index.d.ts +3 -1
- package/dist/memory/hnsw-index.d.ts.map +1 -1
- package/dist/memory/hnsw-index.js +121 -18
- package/dist/memory/hnsw-index.js.map +1 -1
- package/dist/memory/memory-manager.d.ts +2 -0
- package/dist/memory/memory-manager.d.ts.map +1 -1
- package/dist/memory/memory-manager.js +16 -7
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/memory-store.d.ts +15 -3
- package/dist/memory/memory-store.d.ts.map +1 -1
- package/dist/memory/memory-store.js +327 -274
- package/dist/memory/memory-store.js.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -3
- package/templates/agents/compiler/codegen-debugger.md +34 -0
- package/templates/agents/compiler/stdlib-engineer.md +28 -0
- package/templates/agents/compiler/test-coverage-guardian.md +31 -0
- package/templates/agents/game-engine/cpp-core-expert.md +35 -0
- package/templates/agents/game-engine/render-engineer.md +22 -0
- package/templates/agents/game-engine/shader-engineer.md +38 -0
- package/templates/agents/game-engine/systems-integration.md +43 -0
- package/templates/agents/generic/code-reviewer.md +39 -0
- package/templates/agents/generic/docs-writer.md +25 -0
- package/templates/agents/generic/project-manager.md +34 -0
- package/templates/agents/generic/researcher.md +34 -0
- package/templates/agents/generic/test-engineer.md +40 -0
- package/templates/agents/mobile/platform-specialist.md +22 -0
- package/templates/agents/mobile/ui-engineer.md +22 -0
- package/templates/agents/web-app/api-designer.md +22 -0
- package/templates/agents/web-app/backend-engineer.md +30 -0
- package/templates/agents/web-app/database-engineer.md +22 -0
- package/templates/agents/web-app/frontend-engineer.md +29 -0
- package/templates/agents/web-app/security-reviewer.md +32 -0
- package/templates/core/AGENT_AUTOMATION.md +8 -0
- package/templates/core/RULEBOOK.md +12 -0
- package/templates/core/TIER1_PROHIBITIONS.md +154 -0
- package/templates/core/TOKEN_OPTIMIZATION.md +49 -0
- package/templates/git/GIT_WORKFLOW.md +35 -0
- package/templates/rules/follow-task-sequence.md +36 -0
- package/templates/rules/git-safety.md +29 -0
- package/templates/rules/incremental-tests.md +29 -0
- package/templates/rules/no-deferred.md +31 -0
- package/templates/rules/no-shortcuts.md +30 -0
- package/templates/rules/research-first.md +30 -0
- package/templates/rules/sequential-editing.md +21 -0
- package/templates/rules/session-workflow.md +24 -0
- package/templates/rules/task-decomposition.md +32 -0
|
@@ -17,7 +17,13 @@ function withTimeout(promise, ms = MCP_TOOL_TIMEOUT_MS, label = 'tool') {
|
|
|
17
17
|
const timer = setTimeout(() => {
|
|
18
18
|
reject(new Error(`[rulebook-mcp] ${label} timed out after ${ms}ms`));
|
|
19
19
|
}, ms);
|
|
20
|
-
promise.then((val) => {
|
|
20
|
+
promise.then((val) => {
|
|
21
|
+
clearTimeout(timer);
|
|
22
|
+
resolve(val);
|
|
23
|
+
}, (err) => {
|
|
24
|
+
clearTimeout(timer);
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
21
27
|
});
|
|
22
28
|
}
|
|
23
29
|
// Find .rulebook file/directory by walking up directories
|
|
@@ -152,7 +158,7 @@ export async function startRulebookMcpServer() {
|
|
|
152
158
|
}
|
|
153
159
|
const server = new McpServer({
|
|
154
160
|
name: 'rulebook-task-management',
|
|
155
|
-
version: '
|
|
161
|
+
version: '5.0.0',
|
|
156
162
|
});
|
|
157
163
|
// --- Wrap all tool handlers with timeout guard ---
|
|
158
164
|
// Intercept registerTool to automatically add timeout protection to every handler.
|
|
@@ -166,7 +172,9 @@ export async function startRulebookMcpServer() {
|
|
|
166
172
|
const msg = error instanceof Error ? error.message : String(error);
|
|
167
173
|
console.error(`[rulebook-mcp] ${name} error: ${msg}`);
|
|
168
174
|
return {
|
|
169
|
-
content: [
|
|
175
|
+
content: [
|
|
176
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: msg }) },
|
|
177
|
+
],
|
|
170
178
|
};
|
|
171
179
|
}
|
|
172
180
|
};
|
|
@@ -1046,12 +1054,9 @@ export async function startRulebookMcpServer() {
|
|
|
1046
1054
|
],
|
|
1047
1055
|
};
|
|
1048
1056
|
}
|
|
1049
|
-
//
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
};
|
|
1053
|
-
process.on('SIGTERM', cleanupLock);
|
|
1054
|
-
process.on('SIGINT', cleanupLock);
|
|
1057
|
+
// Lock cleanup is handled by the top-level SIGINT handler (line ~858)
|
|
1058
|
+
// which shuts down all managers. Adding per-call SIGINT/SIGTERM listeners
|
|
1059
|
+
// causes accumulation and race conditions with the server shutdown handler.
|
|
1055
1060
|
try {
|
|
1056
1061
|
// Validate tool is available before starting
|
|
1057
1062
|
const toolCmdNames = {
|
|
@@ -1312,8 +1317,6 @@ export async function startRulebookMcpServer() {
|
|
|
1312
1317
|
finally {
|
|
1313
1318
|
// Always release lock, even on error
|
|
1314
1319
|
await ralphManager.releaseLock();
|
|
1315
|
-
process.removeListener('SIGTERM', cleanupLock);
|
|
1316
|
-
process.removeListener('SIGINT', cleanupLock);
|
|
1317
1320
|
}
|
|
1318
1321
|
}
|
|
1319
1322
|
catch (error) {
|
|
@@ -1724,7 +1727,10 @@ export async function startRulebookMcpServer() {
|
|
|
1724
1727
|
content: [
|
|
1725
1728
|
{
|
|
1726
1729
|
type: 'text',
|
|
1727
|
-
text: JSON.stringify({
|
|
1730
|
+
text: JSON.stringify({
|
|
1731
|
+
success: false,
|
|
1732
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1733
|
+
}),
|
|
1728
1734
|
},
|
|
1729
1735
|
],
|
|
1730
1736
|
};
|
|
@@ -1735,7 +1741,10 @@ export async function startRulebookMcpServer() {
|
|
|
1735
1741
|
title: 'List Decision Records',
|
|
1736
1742
|
description: 'List all architectural decision records',
|
|
1737
1743
|
inputSchema: {
|
|
1738
|
-
status: z
|
|
1744
|
+
status: z
|
|
1745
|
+
.string()
|
|
1746
|
+
.optional()
|
|
1747
|
+
.describe('Filter by status (proposed, accepted, rejected, superseded, deprecated)'),
|
|
1739
1748
|
projectId: projectIdSchema,
|
|
1740
1749
|
},
|
|
1741
1750
|
}, async (args) => {
|
|
@@ -1760,7 +1769,10 @@ export async function startRulebookMcpServer() {
|
|
|
1760
1769
|
content: [
|
|
1761
1770
|
{
|
|
1762
1771
|
type: 'text',
|
|
1763
|
-
text: JSON.stringify({
|
|
1772
|
+
text: JSON.stringify({
|
|
1773
|
+
success: false,
|
|
1774
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1775
|
+
}),
|
|
1764
1776
|
},
|
|
1765
1777
|
],
|
|
1766
1778
|
};
|
|
@@ -1796,7 +1808,11 @@ export async function startRulebookMcpServer() {
|
|
|
1796
1808
|
content: [
|
|
1797
1809
|
{
|
|
1798
1810
|
type: 'text',
|
|
1799
|
-
text: JSON.stringify({
|
|
1811
|
+
text: JSON.stringify({
|
|
1812
|
+
success: true,
|
|
1813
|
+
decision: result.decision,
|
|
1814
|
+
content: result.content,
|
|
1815
|
+
}),
|
|
1800
1816
|
},
|
|
1801
1817
|
],
|
|
1802
1818
|
};
|
|
@@ -1806,7 +1822,10 @@ export async function startRulebookMcpServer() {
|
|
|
1806
1822
|
content: [
|
|
1807
1823
|
{
|
|
1808
1824
|
type: 'text',
|
|
1809
|
-
text: JSON.stringify({
|
|
1825
|
+
text: JSON.stringify({
|
|
1826
|
+
success: false,
|
|
1827
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1828
|
+
}),
|
|
1810
1829
|
},
|
|
1811
1830
|
],
|
|
1812
1831
|
};
|
|
@@ -1818,7 +1837,10 @@ export async function startRulebookMcpServer() {
|
|
|
1818
1837
|
description: 'Update an existing architectural decision record',
|
|
1819
1838
|
inputSchema: {
|
|
1820
1839
|
id: z.number().describe('Decision ID to update'),
|
|
1821
|
-
status: z
|
|
1840
|
+
status: z
|
|
1841
|
+
.string()
|
|
1842
|
+
.optional()
|
|
1843
|
+
.describe('New status (proposed, accepted, rejected, superseded, deprecated)'),
|
|
1822
1844
|
context: z.string().optional().describe('Updated context'),
|
|
1823
1845
|
decision: z.string().optional().describe('Updated decision text'),
|
|
1824
1846
|
projectId: projectIdSchema,
|
|
@@ -1859,7 +1881,10 @@ export async function startRulebookMcpServer() {
|
|
|
1859
1881
|
content: [
|
|
1860
1882
|
{
|
|
1861
1883
|
type: 'text',
|
|
1862
|
-
text: JSON.stringify({
|
|
1884
|
+
text: JSON.stringify({
|
|
1885
|
+
success: false,
|
|
1886
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1887
|
+
}),
|
|
1863
1888
|
},
|
|
1864
1889
|
],
|
|
1865
1890
|
};
|
|
@@ -1909,7 +1934,10 @@ export async function startRulebookMcpServer() {
|
|
|
1909
1934
|
content: [
|
|
1910
1935
|
{
|
|
1911
1936
|
type: 'text',
|
|
1912
|
-
text: JSON.stringify({
|
|
1937
|
+
text: JSON.stringify({
|
|
1938
|
+
success: false,
|
|
1939
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1940
|
+
}),
|
|
1913
1941
|
},
|
|
1914
1942
|
],
|
|
1915
1943
|
};
|
|
@@ -1946,7 +1974,10 @@ export async function startRulebookMcpServer() {
|
|
|
1946
1974
|
content: [
|
|
1947
1975
|
{
|
|
1948
1976
|
type: 'text',
|
|
1949
|
-
text: JSON.stringify({
|
|
1977
|
+
text: JSON.stringify({
|
|
1978
|
+
success: false,
|
|
1979
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1980
|
+
}),
|
|
1950
1981
|
},
|
|
1951
1982
|
],
|
|
1952
1983
|
};
|
|
@@ -1973,7 +2004,10 @@ export async function startRulebookMcpServer() {
|
|
|
1973
2004
|
content: [
|
|
1974
2005
|
{
|
|
1975
2006
|
type: 'text',
|
|
1976
|
-
text: JSON.stringify({
|
|
2007
|
+
text: JSON.stringify({
|
|
2008
|
+
success: false,
|
|
2009
|
+
error: `Knowledge entry "${args.id}" not found`,
|
|
2010
|
+
}),
|
|
1977
2011
|
},
|
|
1978
2012
|
],
|
|
1979
2013
|
};
|
|
@@ -1992,7 +2026,10 @@ export async function startRulebookMcpServer() {
|
|
|
1992
2026
|
content: [
|
|
1993
2027
|
{
|
|
1994
2028
|
type: 'text',
|
|
1995
|
-
text: JSON.stringify({
|
|
2029
|
+
text: JSON.stringify({
|
|
2030
|
+
success: false,
|
|
2031
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2032
|
+
}),
|
|
1996
2033
|
},
|
|
1997
2034
|
],
|
|
1998
2035
|
};
|
|
@@ -2034,7 +2071,10 @@ export async function startRulebookMcpServer() {
|
|
|
2034
2071
|
content: [
|
|
2035
2072
|
{
|
|
2036
2073
|
type: 'text',
|
|
2037
|
-
text: JSON.stringify({
|
|
2074
|
+
text: JSON.stringify({
|
|
2075
|
+
success: false,
|
|
2076
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2077
|
+
}),
|
|
2038
2078
|
},
|
|
2039
2079
|
],
|
|
2040
2080
|
};
|
|
@@ -2070,7 +2110,10 @@ export async function startRulebookMcpServer() {
|
|
|
2070
2110
|
content: [
|
|
2071
2111
|
{
|
|
2072
2112
|
type: 'text',
|
|
2073
|
-
text: JSON.stringify({
|
|
2113
|
+
text: JSON.stringify({
|
|
2114
|
+
success: false,
|
|
2115
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2116
|
+
}),
|
|
2074
2117
|
},
|
|
2075
2118
|
],
|
|
2076
2119
|
};
|
|
@@ -2082,7 +2125,9 @@ export async function startRulebookMcpServer() {
|
|
|
2082
2125
|
description: 'Promote a learning to a knowledge entry or decision record',
|
|
2083
2126
|
inputSchema: {
|
|
2084
2127
|
id: z.string().describe('Learning ID to promote'),
|
|
2085
|
-
target: z
|
|
2128
|
+
target: z
|
|
2129
|
+
.enum(['knowledge', 'decision'])
|
|
2130
|
+
.describe('Promote to knowledge base or decision record'),
|
|
2086
2131
|
title: z.string().optional().describe('Override title for the promoted entry'),
|
|
2087
2132
|
projectId: projectIdSchema,
|
|
2088
2133
|
},
|
|
@@ -2118,7 +2163,214 @@ export async function startRulebookMcpServer() {
|
|
|
2118
2163
|
content: [
|
|
2119
2164
|
{
|
|
2120
2165
|
type: 'text',
|
|
2121
|
-
text: JSON.stringify({
|
|
2166
|
+
text: JSON.stringify({
|
|
2167
|
+
success: false,
|
|
2168
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2169
|
+
}),
|
|
2170
|
+
},
|
|
2171
|
+
],
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
});
|
|
2175
|
+
// ── v5.0 Tools: Session Management, Rules, Blockers ──────────────────
|
|
2176
|
+
// Register tool: rulebook_session_start
|
|
2177
|
+
server.registerTool('rulebook_session_start', {
|
|
2178
|
+
title: 'Start Session',
|
|
2179
|
+
description: 'Load session context: reads PLANS.md and searches relevant memories. Call at the start of every session.',
|
|
2180
|
+
inputSchema: {
|
|
2181
|
+
query: z
|
|
2182
|
+
.string()
|
|
2183
|
+
.optional()
|
|
2184
|
+
.describe('Optional search query to find relevant past memories'),
|
|
2185
|
+
projectId: projectIdSchema,
|
|
2186
|
+
},
|
|
2187
|
+
}, async (args) => {
|
|
2188
|
+
try {
|
|
2189
|
+
const root = args.projectId && workspaceManager
|
|
2190
|
+
? (await workspaceManager.getWorker(args.projectId)).projectRoot
|
|
2191
|
+
: projectRoot;
|
|
2192
|
+
const { join } = await import('path');
|
|
2193
|
+
const { existsSync } = await import('fs');
|
|
2194
|
+
const { readFile } = await import('fs/promises');
|
|
2195
|
+
const result = { plans: null, memories: [] };
|
|
2196
|
+
// Read PLANS.md
|
|
2197
|
+
const plansPath = join(root, '.rulebook', 'PLANS.md');
|
|
2198
|
+
if (existsSync(plansPath)) {
|
|
2199
|
+
result.plans = await readFile(plansPath, 'utf-8');
|
|
2200
|
+
}
|
|
2201
|
+
// Search relevant memories
|
|
2202
|
+
if (args.query && memoryManager) {
|
|
2203
|
+
const searchResults = await memoryManager.searchMemories({
|
|
2204
|
+
query: args.query,
|
|
2205
|
+
mode: 'hybrid',
|
|
2206
|
+
limit: 5,
|
|
2207
|
+
});
|
|
2208
|
+
result.memories = searchResults;
|
|
2209
|
+
}
|
|
2210
|
+
return {
|
|
2211
|
+
content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }) }],
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
2214
|
+
catch (error) {
|
|
2215
|
+
return {
|
|
2216
|
+
content: [
|
|
2217
|
+
{
|
|
2218
|
+
type: 'text',
|
|
2219
|
+
text: JSON.stringify({
|
|
2220
|
+
success: false,
|
|
2221
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2222
|
+
}),
|
|
2223
|
+
},
|
|
2224
|
+
],
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
});
|
|
2228
|
+
// Register tool: rulebook_session_end
|
|
2229
|
+
server.registerTool('rulebook_session_end', {
|
|
2230
|
+
title: 'End Session',
|
|
2231
|
+
description: 'Save session summary to PLANS.md history section. Call at the end of every session.',
|
|
2232
|
+
inputSchema: {
|
|
2233
|
+
summary: z.string().describe('Session summary: what was accomplished, key decisions, next steps'),
|
|
2234
|
+
projectId: projectIdSchema,
|
|
2235
|
+
},
|
|
2236
|
+
}, async (args) => {
|
|
2237
|
+
try {
|
|
2238
|
+
const root = args.projectId && workspaceManager
|
|
2239
|
+
? (await workspaceManager.getWorker(args.projectId)).projectRoot
|
|
2240
|
+
: projectRoot;
|
|
2241
|
+
const { join } = await import('path');
|
|
2242
|
+
const { existsSync } = await import('fs');
|
|
2243
|
+
const { readFile, writeFile } = await import('fs/promises');
|
|
2244
|
+
const plansPath = join(root, '.rulebook', 'PLANS.md');
|
|
2245
|
+
const date = new Date().toISOString().split('T')[0];
|
|
2246
|
+
const entry = `### ${date}\n${args.summary}\n`;
|
|
2247
|
+
if (existsSync(plansPath)) {
|
|
2248
|
+
let content = await readFile(plansPath, 'utf-8');
|
|
2249
|
+
// Insert after <!-- PLANS:HISTORY:START -->
|
|
2250
|
+
if (content.includes('<!-- PLANS:HISTORY:START -->')) {
|
|
2251
|
+
content = content.replace('<!-- PLANS:HISTORY:START -->', `<!-- PLANS:HISTORY:START -->\n${entry}`);
|
|
2252
|
+
}
|
|
2253
|
+
else {
|
|
2254
|
+
content += `\n## Session History\n\n<!-- PLANS:HISTORY:START -->\n${entry}<!-- PLANS:HISTORY:END -->\n`;
|
|
2255
|
+
}
|
|
2256
|
+
await writeFile(plansPath, content, 'utf-8');
|
|
2257
|
+
}
|
|
2258
|
+
else {
|
|
2259
|
+
// Create PLANS.md from scratch
|
|
2260
|
+
const newContent = `# Project Plans & Session Context\n\n<!-- PLANS:CONTEXT:START -->\n_No active context._\n<!-- PLANS:CONTEXT:END -->\n\n<!-- PLANS:TASK:START -->\n_No task in progress._\n<!-- PLANS:TASK:END -->\n\n## Session History\n\n<!-- PLANS:HISTORY:START -->\n${entry}<!-- PLANS:HISTORY:END -->\n`;
|
|
2261
|
+
const { mkdirSync } = await import('fs');
|
|
2262
|
+
const dir = join(root, '.rulebook');
|
|
2263
|
+
if (!existsSync(dir))
|
|
2264
|
+
mkdirSync(dir, { recursive: true });
|
|
2265
|
+
await writeFile(plansPath, newContent, 'utf-8');
|
|
2266
|
+
}
|
|
2267
|
+
// Also save to memory if available
|
|
2268
|
+
if (memoryManager) {
|
|
2269
|
+
await memoryManager.saveMemory({
|
|
2270
|
+
type: 'observation',
|
|
2271
|
+
title: `Session summary ${date}`,
|
|
2272
|
+
content: args.summary,
|
|
2273
|
+
tags: ['session', 'summary'],
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
2276
|
+
return {
|
|
2277
|
+
content: [
|
|
2278
|
+
{ type: 'text', text: JSON.stringify({ success: true, message: 'Session summary saved to PLANS.md' }) },
|
|
2279
|
+
],
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2282
|
+
catch (error) {
|
|
2283
|
+
return {
|
|
2284
|
+
content: [
|
|
2285
|
+
{
|
|
2286
|
+
type: 'text',
|
|
2287
|
+
text: JSON.stringify({
|
|
2288
|
+
success: false,
|
|
2289
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2290
|
+
}),
|
|
2291
|
+
},
|
|
2292
|
+
],
|
|
2293
|
+
};
|
|
2294
|
+
}
|
|
2295
|
+
});
|
|
2296
|
+
// Register tool: rulebook_rules_list
|
|
2297
|
+
server.registerTool('rulebook_rules_list', {
|
|
2298
|
+
title: 'List Rules',
|
|
2299
|
+
description: 'List all canonical rules from .rulebook/rules/ with tier and tool targeting info',
|
|
2300
|
+
inputSchema: {
|
|
2301
|
+
projectId: projectIdSchema,
|
|
2302
|
+
},
|
|
2303
|
+
}, async (args) => {
|
|
2304
|
+
try {
|
|
2305
|
+
const root = args.projectId && workspaceManager
|
|
2306
|
+
? (await workspaceManager.getWorker(args.projectId)).projectRoot
|
|
2307
|
+
: projectRoot;
|
|
2308
|
+
const { listRules } = await import('../core/rule-engine.js');
|
|
2309
|
+
const rules = await listRules(root);
|
|
2310
|
+
return {
|
|
2311
|
+
content: [{ type: 'text', text: JSON.stringify({ success: true, rules, count: rules.length }) }],
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
catch (error) {
|
|
2315
|
+
return {
|
|
2316
|
+
content: [
|
|
2317
|
+
{
|
|
2318
|
+
type: 'text',
|
|
2319
|
+
text: JSON.stringify({
|
|
2320
|
+
success: false,
|
|
2321
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2322
|
+
}),
|
|
2323
|
+
},
|
|
2324
|
+
],
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
});
|
|
2328
|
+
// Register tool: rulebook_blockers
|
|
2329
|
+
server.registerTool('rulebook_blockers', {
|
|
2330
|
+
title: 'Show Blockers',
|
|
2331
|
+
description: 'Show task blocker chain with cascade impact analysis',
|
|
2332
|
+
inputSchema: {
|
|
2333
|
+
projectId: projectIdSchema,
|
|
2334
|
+
},
|
|
2335
|
+
}, async (args) => {
|
|
2336
|
+
try {
|
|
2337
|
+
const tm = await getTaskMgr(args.projectId);
|
|
2338
|
+
const tasks = await tm.listTasks();
|
|
2339
|
+
// Build blocker chain from task metadata
|
|
2340
|
+
const blockers = [];
|
|
2341
|
+
for (const task of tasks) {
|
|
2342
|
+
const metadata = await tm.getTaskMetadata(task.id);
|
|
2343
|
+
const blocks = Array.isArray(metadata?.blocks) ? metadata.blocks : [];
|
|
2344
|
+
const blockedBy = Array.isArray(metadata?.blockedBy) ? metadata.blockedBy : [];
|
|
2345
|
+
if (blocks.length > 0 || blockedBy.length > 0) {
|
|
2346
|
+
blockers.push({
|
|
2347
|
+
taskId: task.id,
|
|
2348
|
+
blocks,
|
|
2349
|
+
blockedBy,
|
|
2350
|
+
cascadeImpact: metadata?.cascadeImpact || blocks.length,
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
// Sort by cascade impact (highest first)
|
|
2355
|
+
blockers.sort((a, b) => b.cascadeImpact - a.cascadeImpact);
|
|
2356
|
+
return {
|
|
2357
|
+
content: [
|
|
2358
|
+
{
|
|
2359
|
+
type: 'text',
|
|
2360
|
+
text: JSON.stringify({ success: true, blockers, count: blockers.length }),
|
|
2361
|
+
},
|
|
2362
|
+
],
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
catch (error) {
|
|
2366
|
+
return {
|
|
2367
|
+
content: [
|
|
2368
|
+
{
|
|
2369
|
+
type: 'text',
|
|
2370
|
+
text: JSON.stringify({
|
|
2371
|
+
success: false,
|
|
2372
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2373
|
+
}),
|
|
2122
2374
|
},
|
|
2123
2375
|
],
|
|
2124
2376
|
};
|