@hivehub/rulebook 4.0.0 → 4.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/.claude/commands/continue.md +33 -33
- package/.claude/commands/ralph-config.md +112 -112
- package/.claude/commands/ralph-history.md +110 -110
- package/.claude/commands/ralph-init.md +72 -72
- package/.claude/commands/ralph-pause-resume.md +105 -105
- package/.claude/commands/ralph-run.md +101 -101
- package/.claude/commands/ralph-status.md +76 -76
- package/.claude/commands/rulebook-memory-save.md +48 -48
- package/.claude/commands/rulebook-memory-search.md +47 -47
- package/.claude/commands/rulebook-task-apply.md +67 -67
- package/.claude/commands/rulebook-task-archive.md +70 -70
- package/.claude/commands/rulebook-task-create.md +93 -93
- package/.claude/commands/rulebook-task-list.md +42 -42
- package/.claude/commands/rulebook-task-show.md +52 -52
- package/.claude/commands/rulebook-task-validate.md +53 -53
- package/.claude-plugin/marketplace.json +28 -28
- package/.claude-plugin/plugin.json +8 -8
- package/README.md +34 -0
- package/dist/cli/commands.d.ts +18 -6
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +717 -406
- package/dist/cli/commands.js.map +1 -1
- package/dist/core/claude-mcp.d.ts +4 -2
- package/dist/core/claude-mcp.d.ts.map +1 -1
- package/dist/core/claude-mcp.js +14 -9
- package/dist/core/claude-mcp.js.map +1 -1
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/generator.js +13 -0
- package/dist/core/generator.js.map +1 -1
- package/dist/core/indexer/background-indexer.d.ts +27 -0
- package/dist/core/indexer/background-indexer.d.ts.map +1 -0
- package/dist/core/indexer/background-indexer.js +156 -0
- package/dist/core/indexer/background-indexer.js.map +1 -0
- package/dist/core/indexer/file-parser.d.ts +28 -0
- package/dist/core/indexer/file-parser.d.ts.map +1 -0
- package/dist/core/indexer/file-parser.js +171 -0
- package/dist/core/indexer/file-parser.js.map +1 -0
- package/dist/core/indexer/indexer-types.d.ts +35 -0
- package/dist/core/indexer/indexer-types.d.ts.map +1 -0
- package/dist/core/indexer/indexer-types.js +8 -0
- package/dist/core/indexer/indexer-types.js.map +1 -0
- package/dist/core/workspace/legacy-migrator.d.ts +29 -0
- package/dist/core/workspace/legacy-migrator.d.ts.map +1 -0
- package/dist/core/workspace/legacy-migrator.js +142 -0
- package/dist/core/workspace/legacy-migrator.js.map +1 -0
- package/dist/core/workspace/project-worker.d.ts +49 -0
- package/dist/core/workspace/project-worker.d.ts.map +1 -0
- package/dist/core/workspace/project-worker.js +108 -0
- package/dist/core/workspace/project-worker.js.map +1 -0
- package/dist/core/workspace/workspace-manager.d.ts +90 -0
- package/dist/core/workspace/workspace-manager.d.ts.map +1 -0
- package/dist/core/workspace/workspace-manager.js +337 -0
- package/dist/core/workspace/workspace-manager.js.map +1 -0
- package/dist/core/workspace/workspace-types.d.ts +37 -0
- package/dist/core/workspace/workspace-types.d.ts.map +1 -0
- package/dist/core/workspace/workspace-types.js +8 -0
- package/dist/core/workspace/workspace-types.js.map +1 -0
- package/dist/index.js +43 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp/rulebook-server.d.ts.map +1 -1
- package/dist/mcp/rulebook-server.js +450 -81
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/memory/memory-manager.d.ts +4 -1
- package/dist/memory/memory-manager.d.ts.map +1 -1
- package/dist/memory/memory-manager.js +33 -4
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/memory-search.d.ts +2 -2
- package/dist/memory/memory-search.d.ts.map +1 -1
- package/dist/memory/memory-search.js +19 -0
- package/dist/memory/memory-search.js.map +1 -1
- package/dist/memory/memory-store.d.ts +13 -0
- package/dist/memory/memory-store.d.ts.map +1 -1
- package/dist/memory/memory-store.js +88 -1
- package/dist/memory/memory-store.js.map +1 -1
- package/dist/memory/memory-types.d.ts +15 -0
- package/dist/memory/memory-types.d.ts.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +22 -21
- package/templates/agents/implementer.md +35 -35
- package/templates/agents/researcher.md +34 -34
- package/templates/agents/team-lead.md +34 -34
- package/templates/agents/tester.md +42 -42
- package/templates/ci/rulebook-review.yml +26 -26
- package/templates/cli/AIDER.md +49 -49
- package/templates/cli/AMAZON_Q.md +25 -25
- package/templates/cli/AUGGIE.md +32 -32
- package/templates/cli/CLAUDE.md +117 -117
- package/templates/cli/CLINE.md +99 -99
- package/templates/cli/CODEBUDDY.md +20 -20
- package/templates/cli/CODEIUM.md +20 -20
- package/templates/cli/CODEX.md +21 -21
- package/templates/cli/CONTINUE.md +34 -34
- package/templates/cli/CURSOR_CLI.md +62 -62
- package/templates/cli/FACTORY.md +18 -18
- package/templates/cli/GEMINI.md +35 -35
- package/templates/cli/KILOCODE.md +18 -18
- package/templates/cli/OPENCODE.md +18 -18
- package/templates/cli/_GENERIC_TEMPLATE.md +29 -29
- package/templates/commands/rulebook-memory-save.md +48 -48
- package/templates/commands/rulebook-memory-search.md +47 -47
- package/templates/commands/rulebook-task-apply.md +67 -67
- package/templates/commands/rulebook-task-archive.md +94 -70
- package/templates/commands/rulebook-task-create.md +93 -93
- package/templates/commands/rulebook-task-list.md +42 -42
- package/templates/commands/rulebook-task-show.md +52 -52
- package/templates/commands/rulebook-task-validate.md +53 -53
- package/templates/core/AGENTS_LEAN.md +25 -25
- package/templates/core/AGENTS_OVERRIDE.md +16 -16
- package/templates/core/AGENT_AUTOMATION.md +288 -288
- package/templates/core/DAG.md +304 -304
- package/templates/core/DOCUMENTATION_RULES.md +36 -36
- package/templates/core/MULTI_AGENT.md +74 -74
- package/templates/core/PLANS.md +28 -28
- package/templates/core/QUALITY_ENFORCEMENT.md +68 -68
- package/templates/core/RALPH.md +471 -471
- package/templates/core/RULEBOOK.md +1935 -1893
- package/templates/core/WORKSPACE.md +69 -0
- package/templates/frameworks/ANGULAR.md +36 -36
- package/templates/frameworks/DJANGO.md +83 -83
- package/templates/frameworks/ELECTRON.md +147 -147
- package/templates/frameworks/FLASK.md +38 -38
- package/templates/frameworks/FLUTTER.md +55 -55
- package/templates/frameworks/JQUERY.md +32 -32
- package/templates/frameworks/LARAVEL.md +38 -38
- package/templates/frameworks/NESTJS.md +43 -43
- package/templates/frameworks/NEXTJS.md +127 -127
- package/templates/frameworks/NUXT.md +40 -40
- package/templates/frameworks/RAILS.md +66 -66
- package/templates/frameworks/REACT.md +38 -38
- package/templates/frameworks/REACT_NATIVE.md +47 -47
- package/templates/frameworks/SPRING.md +39 -39
- package/templates/frameworks/SYMFONY.md +36 -36
- package/templates/frameworks/VUE.md +36 -36
- package/templates/frameworks/ZEND.md +35 -35
- package/templates/git/CI_CD_PATTERNS.md +661 -661
- package/templates/git/GITHUB_ACTIONS.md +728 -728
- package/templates/git/GITLAB_CI.md +730 -730
- package/templates/git/GIT_WORKFLOW.md +1157 -1157
- package/templates/git/SECRETS_MANAGEMENT.md +585 -585
- package/templates/hooks/COMMIT_MSG.md +530 -530
- package/templates/hooks/POST_CHECKOUT.md +546 -546
- package/templates/hooks/PREPARE_COMMIT_MSG.md +619 -619
- package/templates/hooks/PRE_COMMIT.md +414 -414
- package/templates/hooks/PRE_PUSH.md +601 -601
- package/templates/ides/CONTINUE_RULES.md +16 -16
- package/templates/ides/COPILOT.md +37 -37
- package/templates/ides/COPILOT_INSTRUCTIONS.md +23 -23
- package/templates/ides/CURSOR.md +43 -43
- package/templates/ides/GEMINI_RULES.md +17 -17
- package/templates/ides/JETBRAINS_AI.md +35 -35
- package/templates/ides/REPLIT.md +36 -36
- package/templates/ides/TABNINE.md +29 -29
- package/templates/ides/VSCODE.md +40 -40
- package/templates/ides/WINDSURF.md +36 -36
- package/templates/ides/WINDSURF_RULES.md +14 -14
- package/templates/ides/ZED.md +32 -32
- package/templates/ides/cursor-mdc/go.mdc +24 -24
- package/templates/ides/cursor-mdc/python.mdc +24 -24
- package/templates/ides/cursor-mdc/quality.mdc +25 -25
- package/templates/ides/cursor-mdc/ralph.mdc +39 -39
- package/templates/ides/cursor-mdc/rulebook.mdc +38 -38
- package/templates/ides/cursor-mdc/rust.mdc +24 -24
- package/templates/ides/cursor-mdc/typescript.mdc +25 -25
- package/templates/languages/C.md +333 -333
- package/templates/languages/CPP.md +743 -743
- package/templates/languages/CSHARP.md +417 -417
- package/templates/languages/ELIXIR.md +454 -454
- package/templates/languages/ERLANG.md +361 -361
- package/templates/languages/GO.md +645 -645
- package/templates/languages/HASKELL.md +177 -177
- package/templates/languages/JAVA.md +607 -607
- package/templates/languages/JAVASCRIPT.md +631 -631
- package/templates/languages/JULIA.md +97 -97
- package/templates/languages/KOTLIN.md +511 -511
- package/templates/languages/LISP.md +100 -100
- package/templates/languages/LUA.md +74 -74
- package/templates/languages/OBJECTIVEC.md +90 -90
- package/templates/languages/PHP.md +416 -416
- package/templates/languages/PYTHON.md +682 -682
- package/templates/languages/RUBY.md +421 -421
- package/templates/languages/RUST.md +477 -477
- package/templates/languages/SAS.md +73 -73
- package/templates/languages/SCALA.md +348 -348
- package/templates/languages/SOLIDITY.md +580 -580
- package/templates/languages/SQL.md +137 -137
- package/templates/languages/SWIFT.md +466 -466
- package/templates/languages/TYPESCRIPT.md +591 -591
- package/templates/languages/ZIG.md +265 -265
- package/templates/modules/ATLASSIAN.md +255 -255
- package/templates/modules/CONTEXT7.md +54 -54
- package/templates/modules/FIGMA.md +267 -267
- package/templates/modules/GITHUB_MCP.md +64 -64
- package/templates/modules/GRAFANA.md +328 -328
- package/templates/modules/MEMORY.md +126 -126
- package/templates/modules/NOTION.md +247 -247
- package/templates/modules/PLAYWRIGHT.md +90 -90
- package/templates/modules/RULEBOOK_MCP.md +156 -156
- package/templates/modules/SERENA.md +337 -337
- package/templates/modules/SUPABASE.md +223 -223
- package/templates/modules/SYNAP.md +69 -69
- package/templates/modules/VECTORIZER.md +63 -63
- package/templates/modules/sequential-thinking.md +42 -42
- package/templates/ralph/ralph-history.bat +4 -4
- package/templates/ralph/ralph-history.sh +5 -5
- package/templates/ralph/ralph-init.bat +5 -5
- package/templates/ralph/ralph-init.sh +5 -5
- package/templates/ralph/ralph-pause.bat +5 -5
- package/templates/ralph/ralph-pause.sh +5 -5
- package/templates/ralph/ralph-run.bat +5 -5
- package/templates/ralph/ralph-run.sh +5 -5
- package/templates/ralph/ralph-status.bat +4 -4
- package/templates/ralph/ralph-status.sh +5 -5
- package/templates/services/AZURE_BLOB.md +184 -184
- package/templates/services/CASSANDRA.md +239 -239
- package/templates/services/DATADOG.md +26 -26
- package/templates/services/DOCKER.md +124 -124
- package/templates/services/DOCKER_COMPOSE.md +168 -168
- package/templates/services/DYNAMODB.md +308 -308
- package/templates/services/ELASTICSEARCH.md +347 -347
- package/templates/services/GCS.md +178 -178
- package/templates/services/HELM.md +194 -194
- package/templates/services/INFLUXDB.md +265 -265
- package/templates/services/KAFKA.md +341 -341
- package/templates/services/KUBERNETES.md +208 -208
- package/templates/services/MARIADB.md +183 -183
- package/templates/services/MEMCACHED.md +242 -242
- package/templates/services/MINIO.md +201 -201
- package/templates/services/MONGODB.md +268 -268
- package/templates/services/MYSQL.md +358 -358
- package/templates/services/NEO4J.md +247 -247
- package/templates/services/OPENTELEMETRY.md +25 -25
- package/templates/services/ORACLE.md +290 -290
- package/templates/services/PINO.md +24 -24
- package/templates/services/POSTGRESQL.md +326 -326
- package/templates/services/PROMETHEUS.md +33 -33
- package/templates/services/RABBITMQ.md +286 -286
- package/templates/services/REDIS.md +292 -292
- package/templates/services/S3.md +298 -298
- package/templates/services/SENTRY.md +23 -23
- package/templates/services/SQLITE.md +294 -294
- package/templates/services/SQLSERVER.md +294 -294
- package/templates/services/WINSTON.md +30 -30
- package/templates/skills/cli/aider/SKILL.md +59 -59
- package/templates/skills/cli/amazon-q/SKILL.md +35 -35
- package/templates/skills/cli/auggie/SKILL.md +42 -42
- package/templates/skills/cli/claude/SKILL.md +42 -42
- package/templates/skills/cli/cline/SKILL.md +42 -42
- package/templates/skills/cli/codebuddy/SKILL.md +30 -30
- package/templates/skills/cli/codeium/SKILL.md +30 -30
- package/templates/skills/cli/codex/SKILL.md +31 -31
- package/templates/skills/cli/continue/SKILL.md +44 -44
- package/templates/skills/cli/cursor-cli/SKILL.md +38 -38
- package/templates/skills/cli/factory/SKILL.md +28 -28
- package/templates/skills/cli/gemini/SKILL.md +45 -45
- package/templates/skills/cli/kilocode/SKILL.md +28 -28
- package/templates/skills/cli/opencode/SKILL.md +28 -28
- package/templates/skills/core/agent-automation/SKILL.md +194 -194
- package/templates/skills/core/dag/SKILL.md +314 -314
- package/templates/skills/core/documentation-rules/SKILL.md +46 -46
- package/templates/skills/core/quality-enforcement/SKILL.md +78 -78
- package/templates/skills/core/rulebook/SKILL.md +176 -176
- package/templates/skills/frameworks/angular/SKILL.md +46 -46
- package/templates/skills/frameworks/django/SKILL.md +93 -93
- package/templates/skills/frameworks/electron/SKILL.md +157 -157
- package/templates/skills/frameworks/flask/SKILL.md +48 -48
- package/templates/skills/frameworks/flutter/SKILL.md +65 -65
- package/templates/skills/frameworks/jquery/SKILL.md +42 -42
- package/templates/skills/frameworks/laravel/SKILL.md +48 -48
- package/templates/skills/frameworks/nestjs/SKILL.md +53 -53
- package/templates/skills/frameworks/nextjs/SKILL.md +137 -137
- package/templates/skills/frameworks/nuxt/SKILL.md +50 -50
- package/templates/skills/frameworks/rails/SKILL.md +76 -76
- package/templates/skills/frameworks/react/SKILL.md +48 -48
- package/templates/skills/frameworks/react-native/SKILL.md +57 -57
- package/templates/skills/frameworks/spring/SKILL.md +49 -49
- package/templates/skills/frameworks/symfony/SKILL.md +46 -46
- package/templates/skills/frameworks/vue/SKILL.md +46 -46
- package/templates/skills/frameworks/zend/SKILL.md +45 -45
- package/templates/skills/ides/copilot/SKILL.md +47 -47
- package/templates/skills/ides/cursor/SKILL.md +53 -53
- package/templates/skills/ides/jetbrains-ai/SKILL.md +45 -45
- package/templates/skills/ides/replit/SKILL.md +46 -46
- package/templates/skills/ides/tabnine/SKILL.md +39 -39
- package/templates/skills/ides/vscode/SKILL.md +50 -50
- package/templates/skills/ides/windsurf/SKILL.md +46 -46
- package/templates/skills/ides/zed/SKILL.md +42 -42
- package/templates/skills/languages/c/SKILL.md +343 -343
- package/templates/skills/languages/cpp/SKILL.md +753 -753
- package/templates/skills/languages/csharp/SKILL.md +427 -427
- package/templates/skills/languages/elixir/SKILL.md +464 -464
- package/templates/skills/languages/erlang/SKILL.md +371 -371
- package/templates/skills/languages/go/SKILL.md +655 -655
- package/templates/skills/languages/haskell/SKILL.md +187 -187
- package/templates/skills/languages/java/SKILL.md +617 -617
- package/templates/skills/languages/javascript/SKILL.md +641 -641
- package/templates/skills/languages/julia/SKILL.md +107 -107
- package/templates/skills/languages/kotlin/SKILL.md +521 -521
- package/templates/skills/languages/lisp/SKILL.md +110 -110
- package/templates/skills/languages/lua/SKILL.md +84 -84
- package/templates/skills/languages/objectivec/SKILL.md +100 -100
- package/templates/skills/languages/php/SKILL.md +426 -426
- package/templates/skills/languages/python/SKILL.md +692 -692
- package/templates/skills/languages/ruby/SKILL.md +431 -431
- package/templates/skills/languages/rust/SKILL.md +487 -487
- package/templates/skills/languages/sas/SKILL.md +83 -83
- package/templates/skills/languages/scala/SKILL.md +358 -358
- package/templates/skills/languages/solidity/SKILL.md +590 -590
- package/templates/skills/languages/sql/SKILL.md +147 -147
- package/templates/skills/languages/swift/SKILL.md +476 -476
- package/templates/skills/languages/typescript/SKILL.md +302 -302
- package/templates/skills/languages/zig/SKILL.md +275 -275
- package/templates/skills/modules/atlassian/SKILL.md +265 -265
- package/templates/skills/modules/context7/SKILL.md +64 -64
- package/templates/skills/modules/figma/SKILL.md +277 -277
- package/templates/skills/modules/github-mcp/SKILL.md +74 -74
- package/templates/skills/modules/grafana/SKILL.md +338 -338
- package/templates/skills/modules/memory/SKILL.md +73 -73
- package/templates/skills/modules/notion/SKILL.md +257 -257
- package/templates/skills/modules/playwright/SKILL.md +100 -100
- package/templates/skills/modules/rulebook-mcp/SKILL.md +166 -166
- package/templates/skills/modules/serena/SKILL.md +347 -347
- package/templates/skills/modules/supabase/SKILL.md +233 -233
- package/templates/skills/modules/synap/SKILL.md +79 -79
- package/templates/skills/modules/vectorizer/SKILL.md +73 -73
- package/templates/skills/services/azure-blob/SKILL.md +194 -194
- package/templates/skills/services/cassandra/SKILL.md +249 -249
- package/templates/skills/services/dynamodb/SKILL.md +318 -318
- package/templates/skills/services/elasticsearch/SKILL.md +357 -357
- package/templates/skills/services/gcs/SKILL.md +188 -188
- package/templates/skills/services/influxdb/SKILL.md +275 -275
- package/templates/skills/services/kafka/SKILL.md +351 -351
- package/templates/skills/services/mariadb/SKILL.md +193 -193
- package/templates/skills/services/memcached/SKILL.md +252 -252
- package/templates/skills/services/minio/SKILL.md +211 -211
- package/templates/skills/services/mongodb/SKILL.md +278 -278
- package/templates/skills/services/mysql/SKILL.md +368 -368
- package/templates/skills/services/neo4j/SKILL.md +257 -257
- package/templates/skills/services/oracle/SKILL.md +300 -300
- package/templates/skills/services/postgresql/SKILL.md +336 -336
- package/templates/skills/services/rabbitmq/SKILL.md +296 -296
- package/templates/skills/services/redis/SKILL.md +302 -302
- package/templates/skills/services/s3/SKILL.md +308 -308
- package/templates/skills/services/sqlite/SKILL.md +304 -304
- package/templates/skills/services/sqlserver/SKILL.md +304 -304
- package/templates/skills/workflows/ralph/SKILL.md +309 -309
- package/templates/skills/workflows/ralph/install.sh +87 -87
- package/templates/skills/workflows/ralph/manifest.json +158 -158
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { existsSync, readFileSync, statSync } from 'fs';
|
|
5
|
+
import { basename, dirname, join, resolve } from 'path';
|
|
4
6
|
import { z } from 'zod';
|
|
5
|
-
import { TaskManager } from '../core/task-manager.js';
|
|
6
|
-
import { SkillsManager, getDefaultTemplatesPath } from '../core/skills-manager.js';
|
|
7
7
|
import { ConfigManager } from '../core/config-manager.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { BackgroundIndexer } from '../core/indexer/background-indexer.js';
|
|
9
|
+
import { SkillsManager, getDefaultTemplatesPath } from '../core/skills-manager.js';
|
|
10
|
+
import { TaskManager } from '../core/task-manager.js';
|
|
11
|
+
import { WorkspaceManager } from '../core/workspace/workspace-manager.js';
|
|
10
12
|
// Find .rulebook file/directory by walking up directories
|
|
11
13
|
export function findRulebookConfig(startDir) {
|
|
12
14
|
let current = resolve(startDir);
|
|
@@ -54,23 +56,94 @@ function loadConfig() {
|
|
|
54
56
|
return { projectRoot, tasksDir, archiveDir };
|
|
55
57
|
}
|
|
56
58
|
export async function startRulebookMcpServer() {
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
// --- Workspace vs Single-Project Mode ---
|
|
60
|
+
const isWorkspaceMode = process.argv.includes('--workspace');
|
|
61
|
+
let workspaceManager = null;
|
|
62
|
+
// Default managers (single-project mode OR default workspace project)
|
|
63
|
+
let taskManager;
|
|
64
|
+
let skillsManager;
|
|
65
|
+
let configManager;
|
|
66
|
+
let projectRoot;
|
|
67
|
+
if (isWorkspaceMode) {
|
|
68
|
+
const projectRootFlagIndex = process.argv.indexOf('--project-root');
|
|
69
|
+
const startDir = projectRootFlagIndex !== -1 && process.argv[projectRootFlagIndex + 1]
|
|
70
|
+
? process.argv[projectRootFlagIndex + 1]
|
|
71
|
+
: process.cwd();
|
|
72
|
+
const wsConfig = WorkspaceManager.findWorkspaceConfig(startDir);
|
|
73
|
+
if (!wsConfig) {
|
|
74
|
+
console.error('[rulebook-mcp] No workspace config found. Create .rulebook-workspace.json or use a *.code-workspace file.');
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
workspaceManager = new WorkspaceManager(wsConfig, startDir);
|
|
78
|
+
workspaceManager.startIdleChecker();
|
|
79
|
+
projectRoot = startDir;
|
|
80
|
+
// Initialize default project so existing tools work without projectId
|
|
81
|
+
const defaultId = workspaceManager.getDefaultProjectId();
|
|
82
|
+
if (defaultId) {
|
|
83
|
+
try {
|
|
84
|
+
const defaultWorker = await workspaceManager.getWorker(defaultId);
|
|
85
|
+
taskManager = defaultWorker.getTaskManager();
|
|
86
|
+
skillsManager = defaultWorker.getSkillsManager();
|
|
87
|
+
configManager = defaultWorker.getConfigManager();
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
console.error(`[rulebook-mcp] Failed to init default project "${defaultId}":`, e);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
console.error(`[rulebook-mcp] Workspace mode: ${wsConfig.name} (${wsConfig.projects.length} projects, default: ${defaultId})`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const singleConfig = loadConfig();
|
|
98
|
+
projectRoot = singleConfig.projectRoot;
|
|
99
|
+
taskManager = new TaskManager(projectRoot, '.rulebook');
|
|
100
|
+
skillsManager = new SkillsManager(getDefaultTemplatesPath(), projectRoot);
|
|
101
|
+
configManager = new ConfigManager(projectRoot);
|
|
102
|
+
}
|
|
103
|
+
// --- Manager Resolution Helpers (workspace-aware) ---
|
|
104
|
+
async function getTaskMgr(projectId) {
|
|
105
|
+
if (!projectId || !workspaceManager)
|
|
106
|
+
return taskManager;
|
|
107
|
+
const w = await workspaceManager.getWorker(projectId);
|
|
108
|
+
return w.getTaskManager();
|
|
109
|
+
}
|
|
110
|
+
async function getConfigMgr(projectId) {
|
|
111
|
+
if (!projectId || !workspaceManager)
|
|
112
|
+
return configManager;
|
|
113
|
+
const w = await workspaceManager.getWorker(projectId);
|
|
114
|
+
return w.getConfigManager();
|
|
115
|
+
}
|
|
116
|
+
async function getSkillsMgr(projectId) {
|
|
117
|
+
if (!projectId || !workspaceManager)
|
|
118
|
+
return skillsManager;
|
|
119
|
+
const w = await workspaceManager.getWorker(projectId);
|
|
120
|
+
return w.getSkillsManager();
|
|
121
|
+
}
|
|
122
|
+
async function getMemMgr(projectId) {
|
|
123
|
+
if (workspaceManager) {
|
|
124
|
+
const pid = projectId ?? workspaceManager.getDefaultProjectId();
|
|
125
|
+
const w = await workspaceManager.getWorker(pid);
|
|
126
|
+
return w.getMemoryManager();
|
|
127
|
+
}
|
|
128
|
+
return memoryManager;
|
|
129
|
+
}
|
|
61
130
|
const server = new McpServer({
|
|
62
131
|
name: 'rulebook-task-management',
|
|
63
|
-
version: '4.
|
|
132
|
+
version: '4.2.0',
|
|
64
133
|
});
|
|
134
|
+
// Zod schema reused across tools for workspace project targeting
|
|
135
|
+
const projectIdSchema = z.string().optional().describe('Project ID (workspace mode only, defaults to default project)');
|
|
65
136
|
// Register tool: rulebook_task_create
|
|
66
137
|
server.registerTool('rulebook_task_create', {
|
|
67
138
|
title: 'Create Rulebook Task',
|
|
68
139
|
description: 'Create a new Rulebook task',
|
|
69
140
|
inputSchema: {
|
|
70
141
|
taskId: z.string().describe('Task ID in kebab-case'),
|
|
142
|
+
projectId: projectIdSchema,
|
|
71
143
|
},
|
|
72
144
|
}, async (args) => {
|
|
73
|
-
await
|
|
145
|
+
const tm = await getTaskMgr(args.projectId);
|
|
146
|
+
await tm.createTask(args.taskId);
|
|
74
147
|
const resultText = JSON.stringify({
|
|
75
148
|
success: true,
|
|
76
149
|
taskId: args.taskId,
|
|
@@ -89,9 +162,11 @@ export async function startRulebookMcpServer() {
|
|
|
89
162
|
.enum(['pending', 'in-progress', 'completed', 'blocked'])
|
|
90
163
|
.optional()
|
|
91
164
|
.describe('Filter by status'),
|
|
165
|
+
projectId: projectIdSchema,
|
|
92
166
|
},
|
|
93
167
|
}, async (args) => {
|
|
94
|
-
const
|
|
168
|
+
const tm = await getTaskMgr(args.projectId);
|
|
169
|
+
const tasks = await tm.listTasks(args.includeArchived || false);
|
|
95
170
|
let filtered = tasks;
|
|
96
171
|
if (args.status) {
|
|
97
172
|
filtered = tasks.filter((t) => t.status === args.status);
|
|
@@ -120,9 +195,11 @@ export async function startRulebookMcpServer() {
|
|
|
120
195
|
description: 'Show task details',
|
|
121
196
|
inputSchema: {
|
|
122
197
|
taskId: z.string().describe('Task ID to show'),
|
|
198
|
+
projectId: projectIdSchema,
|
|
123
199
|
},
|
|
124
200
|
}, async (args) => {
|
|
125
|
-
const
|
|
201
|
+
const tm = await getTaskMgr(args.projectId);
|
|
202
|
+
const task = await tm.showTask(args.taskId);
|
|
126
203
|
return {
|
|
127
204
|
content: [
|
|
128
205
|
{
|
|
@@ -157,10 +234,12 @@ export async function startRulebookMcpServer() {
|
|
|
157
234
|
.enum(['pending', 'in-progress', 'completed', 'blocked'])
|
|
158
235
|
.optional()
|
|
159
236
|
.describe('New status'),
|
|
237
|
+
projectId: projectIdSchema,
|
|
160
238
|
},
|
|
161
239
|
}, async (args) => {
|
|
240
|
+
const tm = await getTaskMgr(args.projectId);
|
|
162
241
|
if (args.status) {
|
|
163
|
-
await
|
|
242
|
+
await tm.updateTaskStatus(args.taskId, args.status);
|
|
164
243
|
}
|
|
165
244
|
const resultText = JSON.stringify({
|
|
166
245
|
success: true,
|
|
@@ -176,9 +255,11 @@ export async function startRulebookMcpServer() {
|
|
|
176
255
|
description: 'Validate task format',
|
|
177
256
|
inputSchema: {
|
|
178
257
|
taskId: z.string().describe('Task ID to validate'),
|
|
258
|
+
projectId: projectIdSchema,
|
|
179
259
|
},
|
|
180
260
|
}, async (args) => {
|
|
181
|
-
const
|
|
261
|
+
const tm = await getTaskMgr(args.projectId);
|
|
262
|
+
const validation = await tm.validateTask(args.taskId);
|
|
182
263
|
return {
|
|
183
264
|
content: [
|
|
184
265
|
{
|
|
@@ -199,9 +280,11 @@ export async function startRulebookMcpServer() {
|
|
|
199
280
|
inputSchema: {
|
|
200
281
|
taskId: z.string().describe('Task ID to archive'),
|
|
201
282
|
skipValidation: z.boolean().optional().describe('Skip validation before archiving'),
|
|
283
|
+
projectId: projectIdSchema,
|
|
202
284
|
},
|
|
203
285
|
}, async (args) => {
|
|
204
|
-
await
|
|
286
|
+
const tm = await getTaskMgr(args.projectId);
|
|
287
|
+
await tm.archiveTask(args.taskId, args.skipValidation || false);
|
|
205
288
|
const resultText = JSON.stringify({
|
|
206
289
|
success: true,
|
|
207
290
|
taskId: args.taskId,
|
|
@@ -216,9 +299,11 @@ export async function startRulebookMcpServer() {
|
|
|
216
299
|
description: 'Delete a task permanently',
|
|
217
300
|
inputSchema: {
|
|
218
301
|
taskId: z.string().describe('Task ID to delete'),
|
|
302
|
+
projectId: projectIdSchema,
|
|
219
303
|
},
|
|
220
304
|
}, async (args) => {
|
|
221
|
-
await
|
|
305
|
+
const tm = await getTaskMgr(args.projectId);
|
|
306
|
+
await tm.deleteTask(args.taskId);
|
|
222
307
|
const resultText = JSON.stringify({
|
|
223
308
|
success: true,
|
|
224
309
|
taskId: args.taskId,
|
|
@@ -251,19 +336,21 @@ export async function startRulebookMcpServer() {
|
|
|
251
336
|
.optional()
|
|
252
337
|
.describe('Filter by category'),
|
|
253
338
|
enabledOnly: z.boolean().optional().describe('Show only enabled skills'),
|
|
339
|
+
projectId: projectIdSchema,
|
|
254
340
|
},
|
|
255
341
|
}, async (args) => {
|
|
256
342
|
try {
|
|
343
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
344
|
+
const cm = await getConfigMgr(args.projectId);
|
|
257
345
|
let skills;
|
|
258
346
|
if (args.category) {
|
|
259
|
-
skills = await
|
|
347
|
+
skills = await sm.getSkillsByCategory(args.category);
|
|
260
348
|
}
|
|
261
349
|
else {
|
|
262
|
-
skills = await
|
|
350
|
+
skills = await sm.getSkills();
|
|
263
351
|
}
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
const enabledIds = new Set(rulebookConfig.skills?.enabled || []);
|
|
352
|
+
const rbConfig = await cm.loadConfig();
|
|
353
|
+
const enabledIds = new Set(rbConfig.skills?.enabled || []);
|
|
267
354
|
let filteredSkills = skills.map((s) => ({
|
|
268
355
|
id: s.id,
|
|
269
356
|
name: s.metadata.name,
|
|
@@ -310,10 +397,13 @@ export async function startRulebookMcpServer() {
|
|
|
310
397
|
description: 'Show detailed information about a specific skill',
|
|
311
398
|
inputSchema: {
|
|
312
399
|
skillId: z.string().describe('Skill ID (e.g., languages/typescript)'),
|
|
400
|
+
projectId: projectIdSchema,
|
|
313
401
|
},
|
|
314
402
|
}, async (args) => {
|
|
315
403
|
try {
|
|
316
|
-
const
|
|
404
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
405
|
+
const cm = await getConfigMgr(args.projectId);
|
|
406
|
+
const skill = await sm.getSkillById(args.skillId);
|
|
317
407
|
if (!skill) {
|
|
318
408
|
return {
|
|
319
409
|
content: [
|
|
@@ -328,8 +418,8 @@ export async function startRulebookMcpServer() {
|
|
|
328
418
|
],
|
|
329
419
|
};
|
|
330
420
|
}
|
|
331
|
-
const
|
|
332
|
-
const enabled =
|
|
421
|
+
const rbConfig = await cm.loadConfig();
|
|
422
|
+
const enabled = rbConfig.skills?.enabled?.includes(args.skillId) || false;
|
|
333
423
|
return {
|
|
334
424
|
content: [
|
|
335
425
|
{
|
|
@@ -374,14 +464,16 @@ export async function startRulebookMcpServer() {
|
|
|
374
464
|
description: 'Enable a skill in the project configuration',
|
|
375
465
|
inputSchema: {
|
|
376
466
|
skillId: z.string().describe('Skill ID to enable (e.g., languages/typescript)'),
|
|
467
|
+
projectId: projectIdSchema,
|
|
377
468
|
},
|
|
378
469
|
}, async (args) => {
|
|
379
470
|
try {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
await
|
|
383
|
-
|
|
384
|
-
|
|
471
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
472
|
+
const cm = await getConfigMgr(args.projectId);
|
|
473
|
+
let rbConfig = await cm.loadConfig();
|
|
474
|
+
rbConfig = await sm.enableSkill(args.skillId, rbConfig);
|
|
475
|
+
await cm.saveConfig(rbConfig);
|
|
476
|
+
const validation = await sm.validateSkills(rbConfig);
|
|
385
477
|
const resultText = JSON.stringify({
|
|
386
478
|
success: true,
|
|
387
479
|
skillId: args.skillId,
|
|
@@ -412,12 +504,14 @@ export async function startRulebookMcpServer() {
|
|
|
412
504
|
description: 'Disable a skill in the project configuration',
|
|
413
505
|
inputSchema: {
|
|
414
506
|
skillId: z.string().describe('Skill ID to disable (e.g., languages/typescript)'),
|
|
507
|
+
projectId: projectIdSchema,
|
|
415
508
|
},
|
|
416
509
|
}, async (args) => {
|
|
417
510
|
try {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
511
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
512
|
+
const cm = await getConfigMgr(args.projectId);
|
|
513
|
+
let rbConfig = await cm.loadConfig();
|
|
514
|
+
if (!rbConfig.skills?.enabled?.includes(args.skillId)) {
|
|
421
515
|
return {
|
|
422
516
|
content: [
|
|
423
517
|
{
|
|
@@ -430,8 +524,8 @@ export async function startRulebookMcpServer() {
|
|
|
430
524
|
],
|
|
431
525
|
};
|
|
432
526
|
}
|
|
433
|
-
|
|
434
|
-
await
|
|
527
|
+
rbConfig = await sm.disableSkill(args.skillId, rbConfig);
|
|
528
|
+
await cm.saveConfig(rbConfig);
|
|
435
529
|
const resultText = JSON.stringify({
|
|
436
530
|
success: true,
|
|
437
531
|
skillId: args.skillId,
|
|
@@ -460,12 +554,15 @@ export async function startRulebookMcpServer() {
|
|
|
460
554
|
description: 'Search for skills by name, description, or tags',
|
|
461
555
|
inputSchema: {
|
|
462
556
|
query: z.string().describe('Search query'),
|
|
557
|
+
projectId: projectIdSchema,
|
|
463
558
|
},
|
|
464
559
|
}, async (args) => {
|
|
465
560
|
try {
|
|
466
|
-
const
|
|
467
|
-
const
|
|
468
|
-
const
|
|
561
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
562
|
+
const cm = await getConfigMgr(args.projectId);
|
|
563
|
+
const skills = await sm.searchSkills(args.query);
|
|
564
|
+
const rbConfig = await cm.loadConfig();
|
|
565
|
+
const enabledIds = new Set(rbConfig.skills?.enabled || []);
|
|
469
566
|
return {
|
|
470
567
|
content: [
|
|
471
568
|
{
|
|
@@ -504,11 +601,15 @@ export async function startRulebookMcpServer() {
|
|
|
504
601
|
server.registerTool('rulebook_skill_validate', {
|
|
505
602
|
title: 'Validate Skills Configuration',
|
|
506
603
|
description: 'Validate the current skills configuration for conflicts and dependencies',
|
|
507
|
-
inputSchema: {
|
|
508
|
-
|
|
604
|
+
inputSchema: {
|
|
605
|
+
projectId: projectIdSchema,
|
|
606
|
+
},
|
|
607
|
+
}, async (args) => {
|
|
509
608
|
try {
|
|
510
|
-
const
|
|
511
|
-
const
|
|
609
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
610
|
+
const cm = await getConfigMgr(args.projectId);
|
|
611
|
+
const rbConfig = await cm.loadConfig();
|
|
612
|
+
const validation = await sm.validateSkills(rbConfig);
|
|
512
613
|
return {
|
|
513
614
|
content: [
|
|
514
615
|
{
|
|
@@ -519,7 +620,7 @@ export async function startRulebookMcpServer() {
|
|
|
519
620
|
errors: validation.errors,
|
|
520
621
|
warnings: validation.warnings,
|
|
521
622
|
conflicts: validation.conflicts,
|
|
522
|
-
enabledCount:
|
|
623
|
+
enabledCount: rbConfig.skills?.enabled?.length || 0,
|
|
523
624
|
}),
|
|
524
625
|
},
|
|
525
626
|
],
|
|
@@ -542,22 +643,42 @@ export async function startRulebookMcpServer() {
|
|
|
542
643
|
// ============================================
|
|
543
644
|
// Memory System Functions (v3.0)
|
|
544
645
|
// ============================================
|
|
545
|
-
// Conditionally initialize MemoryManager
|
|
646
|
+
// Conditionally initialize MemoryManager (single-project mode only;
|
|
647
|
+
// in workspace mode each worker manages its own memory)
|
|
546
648
|
let memoryManager = null;
|
|
649
|
+
let bgIndexer = null;
|
|
547
650
|
let autoCaptureEnabled = false;
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
651
|
+
if (!isWorkspaceMode) {
|
|
652
|
+
const rulebookConfig = await configManager.loadConfig();
|
|
653
|
+
if (rulebookConfig.memory?.enabled) {
|
|
654
|
+
try {
|
|
655
|
+
const { createMemoryManager } = await import('../memory/memory-manager.js');
|
|
656
|
+
const memoryDbPath = join(projectRoot, rulebookConfig.memory.dbPath ?? '.rulebook/memory/memory.db');
|
|
657
|
+
console.error(`[rulebook-mcp] Memory DB: ${memoryDbPath}`);
|
|
658
|
+
memoryManager = createMemoryManager(projectRoot, rulebookConfig.memory);
|
|
659
|
+
autoCaptureEnabled = rulebookConfig.memory.autoCapture !== false;
|
|
660
|
+
// Boot Background Indexer
|
|
661
|
+
bgIndexer = new BackgroundIndexer(memoryManager, projectRoot, { enabled: true });
|
|
662
|
+
bgIndexer.start();
|
|
663
|
+
global.__indexerStatus = () => bgIndexer?.getStatus();
|
|
664
|
+
}
|
|
665
|
+
catch (e) {
|
|
666
|
+
console.warn('[rulebook-mcp] Failed to boot Memory/Indexer:', e);
|
|
667
|
+
}
|
|
559
668
|
}
|
|
560
669
|
}
|
|
670
|
+
// Graceful shutdown for both modes
|
|
671
|
+
process.on('SIGINT', async () => {
|
|
672
|
+
console.error('[rulebook-mcp] Shutting down...');
|
|
673
|
+
if (workspaceManager) {
|
|
674
|
+
await workspaceManager.shutdownAll();
|
|
675
|
+
}
|
|
676
|
+
if (bgIndexer)
|
|
677
|
+
bgIndexer.stop();
|
|
678
|
+
if (memoryManager)
|
|
679
|
+
await memoryManager.close();
|
|
680
|
+
process.exit(0);
|
|
681
|
+
});
|
|
561
682
|
/**
|
|
562
683
|
* Auto-capture: save tool interactions to memory in the background.
|
|
563
684
|
* Fire-and-forget — never blocks or fails the original tool call.
|
|
@@ -603,12 +724,14 @@ export async function startRulebookMcpServer() {
|
|
|
603
724
|
limit: z.number().optional().describe('Max results (default 20)'),
|
|
604
725
|
mode: z.enum(['bm25', 'vector', 'hybrid']).optional().describe('Search mode'),
|
|
605
726
|
type: z.string().optional().describe('Filter by memory type'),
|
|
727
|
+
projectId: projectIdSchema,
|
|
606
728
|
},
|
|
607
729
|
}, async (args) => {
|
|
608
|
-
|
|
730
|
+
const mm = await getMemMgr(args.projectId);
|
|
731
|
+
if (!mm)
|
|
609
732
|
return memoryNotEnabled();
|
|
610
733
|
try {
|
|
611
|
-
const results = await
|
|
734
|
+
const results = await mm.searchMemories({
|
|
612
735
|
query: args.query,
|
|
613
736
|
limit: args.limit,
|
|
614
737
|
mode: args.mode,
|
|
@@ -638,12 +761,14 @@ export async function startRulebookMcpServer() {
|
|
|
638
761
|
inputSchema: {
|
|
639
762
|
memoryId: z.string().describe('Memory ID to anchor timeline'),
|
|
640
763
|
window: z.number().optional().describe('Number of memories before/after (default 5)'),
|
|
764
|
+
projectId: projectIdSchema,
|
|
641
765
|
},
|
|
642
766
|
}, async (args) => {
|
|
643
|
-
|
|
767
|
+
const mm = await getMemMgr(args.projectId);
|
|
768
|
+
if (!mm)
|
|
644
769
|
return memoryNotEnabled();
|
|
645
770
|
try {
|
|
646
|
-
const timeline = await
|
|
771
|
+
const timeline = await mm.getTimeline(args.memoryId, args.window);
|
|
647
772
|
return {
|
|
648
773
|
content: [{ type: 'text', text: JSON.stringify({ success: true, timeline }) }],
|
|
649
774
|
};
|
|
@@ -662,12 +787,14 @@ export async function startRulebookMcpServer() {
|
|
|
662
787
|
description: 'Get full details for specific memory IDs',
|
|
663
788
|
inputSchema: {
|
|
664
789
|
ids: z.array(z.string()).describe('Memory IDs to fetch'),
|
|
790
|
+
projectId: projectIdSchema,
|
|
665
791
|
},
|
|
666
792
|
}, async (args) => {
|
|
667
|
-
|
|
793
|
+
const mm = await getMemMgr(args.projectId);
|
|
794
|
+
if (!mm)
|
|
668
795
|
return memoryNotEnabled();
|
|
669
796
|
try {
|
|
670
|
-
const memories = await
|
|
797
|
+
const memories = await mm.getFullDetails(args.ids);
|
|
671
798
|
return {
|
|
672
799
|
content: [{ type: 'text', text: JSON.stringify({ success: true, memories }) }],
|
|
673
800
|
};
|
|
@@ -691,12 +818,14 @@ export async function startRulebookMcpServer() {
|
|
|
691
818
|
title: z.string().describe('Memory title'),
|
|
692
819
|
content: z.string().describe('Memory content'),
|
|
693
820
|
tags: z.array(z.string()).optional().describe('Tags'),
|
|
821
|
+
projectId: projectIdSchema,
|
|
694
822
|
},
|
|
695
823
|
}, async (args) => {
|
|
696
|
-
|
|
824
|
+
const mm = await getMemMgr(args.projectId);
|
|
825
|
+
if (!mm)
|
|
697
826
|
return memoryNotEnabled();
|
|
698
827
|
try {
|
|
699
|
-
const memory = await
|
|
828
|
+
const memory = await mm.saveMemory({
|
|
700
829
|
type: args.type,
|
|
701
830
|
title: args.title,
|
|
702
831
|
content: args.content,
|
|
@@ -726,12 +855,15 @@ export async function startRulebookMcpServer() {
|
|
|
726
855
|
server.registerTool('rulebook_memory_stats', {
|
|
727
856
|
title: 'Memory Statistics',
|
|
728
857
|
description: 'Get memory database statistics',
|
|
729
|
-
inputSchema: {
|
|
730
|
-
|
|
731
|
-
|
|
858
|
+
inputSchema: {
|
|
859
|
+
projectId: projectIdSchema,
|
|
860
|
+
},
|
|
861
|
+
}, async (args) => {
|
|
862
|
+
const mm = await getMemMgr(args.projectId);
|
|
863
|
+
if (!mm)
|
|
732
864
|
return memoryNotEnabled();
|
|
733
865
|
try {
|
|
734
|
-
const stats = await
|
|
866
|
+
const stats = await mm.getStats();
|
|
735
867
|
return {
|
|
736
868
|
content: [{ type: 'text', text: JSON.stringify({ success: true, stats }) }],
|
|
737
869
|
};
|
|
@@ -750,12 +882,14 @@ export async function startRulebookMcpServer() {
|
|
|
750
882
|
description: 'Force memory eviction and cleanup',
|
|
751
883
|
inputSchema: {
|
|
752
884
|
force: z.boolean().optional().describe('Force cleanup regardless of size'),
|
|
885
|
+
projectId: projectIdSchema,
|
|
753
886
|
},
|
|
754
887
|
}, async (args) => {
|
|
755
|
-
|
|
888
|
+
const mm = await getMemMgr(args.projectId);
|
|
889
|
+
if (!mm)
|
|
756
890
|
return memoryNotEnabled();
|
|
757
891
|
try {
|
|
758
|
-
const result = await
|
|
892
|
+
const result = await mm.cleanup(args.force ?? false);
|
|
759
893
|
return {
|
|
760
894
|
content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }) }],
|
|
761
895
|
};
|
|
@@ -782,16 +916,16 @@ export async function startRulebookMcpServer() {
|
|
|
782
916
|
const { Logger } = await import('../core/logger.js');
|
|
783
917
|
const { RalphManager } = await import('../core/ralph-manager.js');
|
|
784
918
|
const { PRDGenerator } = await import('../core/prd-generator.js');
|
|
785
|
-
const logger = new Logger(
|
|
786
|
-
const ralphManager = new RalphManager(
|
|
787
|
-
const prdGenerator = new PRDGenerator(
|
|
919
|
+
const logger = new Logger(projectRoot);
|
|
920
|
+
const ralphManager = new RalphManager(projectRoot, logger);
|
|
921
|
+
const prdGenerator = new PRDGenerator(projectRoot, logger);
|
|
788
922
|
const configData = await configManager.loadConfig();
|
|
789
923
|
const maxIterations = configData.ralph?.maxIterations || 10;
|
|
790
924
|
const tool = (configData.ralph?.tool || 'claude');
|
|
791
925
|
// Generate PRD first, then initialize with correct task count
|
|
792
|
-
const prd = await prdGenerator.generatePRD(basename(
|
|
926
|
+
const prd = await prdGenerator.generatePRD(basename(projectRoot) || 'project');
|
|
793
927
|
const { writeFile } = await import('../utils/file-system.js');
|
|
794
|
-
const prdPath = join(
|
|
928
|
+
const prdPath = join(projectRoot, '.rulebook', 'ralph', 'prd.json');
|
|
795
929
|
await writeFile(prdPath, JSON.stringify(prd, null, 2));
|
|
796
930
|
// Initialize after PRD is written so task count is correct
|
|
797
931
|
await ralphManager.initialize(maxIterations, tool);
|
|
@@ -836,8 +970,8 @@ export async function startRulebookMcpServer() {
|
|
|
836
970
|
const { RalphParser } = await import('../agents/ralph-parser.js');
|
|
837
971
|
const { spawn } = await import('child_process');
|
|
838
972
|
const { execSync } = await import('child_process');
|
|
839
|
-
const logger = new Logger(
|
|
840
|
-
const ralphManager = new RalphManager(
|
|
973
|
+
const logger = new Logger(projectRoot);
|
|
974
|
+
const ralphManager = new RalphManager(projectRoot, logger);
|
|
841
975
|
const configData = await configManager.loadConfig();
|
|
842
976
|
const maxIterations = args.maxIterations || configData.ralph?.maxIterations || 10;
|
|
843
977
|
const tool = (args.tool || configData.ralph?.tool || 'claude');
|
|
@@ -897,7 +1031,7 @@ export async function startRulebookMcpServer() {
|
|
|
897
1031
|
let stdout = '';
|
|
898
1032
|
let stderr = '';
|
|
899
1033
|
const proc = spawn(cmd, cmdArgs, {
|
|
900
|
-
cwd:
|
|
1034
|
+
cwd: projectRoot,
|
|
901
1035
|
shell: true,
|
|
902
1036
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
903
1037
|
});
|
|
@@ -960,7 +1094,7 @@ export async function startRulebookMcpServer() {
|
|
|
960
1094
|
}
|
|
961
1095
|
};
|
|
962
1096
|
const proc = spawn(cfg.cmd, cfg.args, {
|
|
963
|
-
cwd:
|
|
1097
|
+
cwd: projectRoot,
|
|
964
1098
|
shell: true,
|
|
965
1099
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
966
1100
|
});
|
|
@@ -1147,8 +1281,8 @@ export async function startRulebookMcpServer() {
|
|
|
1147
1281
|
try {
|
|
1148
1282
|
const { Logger } = await import('../core/logger.js');
|
|
1149
1283
|
const { RalphManager } = await import('../core/ralph-manager.js');
|
|
1150
|
-
const logger = new Logger(
|
|
1151
|
-
const ralphManager = new RalphManager(
|
|
1284
|
+
const logger = new Logger(projectRoot);
|
|
1285
|
+
const ralphManager = new RalphManager(projectRoot, logger);
|
|
1152
1286
|
const status = await ralphManager.getStatus();
|
|
1153
1287
|
if (!status) {
|
|
1154
1288
|
return {
|
|
@@ -1214,8 +1348,8 @@ export async function startRulebookMcpServer() {
|
|
|
1214
1348
|
try {
|
|
1215
1349
|
const { Logger } = await import('../core/logger.js');
|
|
1216
1350
|
const { IterationTracker } = await import('../core/iteration-tracker.js');
|
|
1217
|
-
const logger = new Logger(
|
|
1218
|
-
const tracker = new IterationTracker(
|
|
1351
|
+
const logger = new Logger(projectRoot);
|
|
1352
|
+
const tracker = new IterationTracker(projectRoot, logger);
|
|
1219
1353
|
const history = await tracker.getHistory(args.limit || 10, args.taskId);
|
|
1220
1354
|
const stats = await tracker.getStatistics();
|
|
1221
1355
|
return {
|
|
@@ -1258,6 +1392,241 @@ export async function startRulebookMcpServer() {
|
|
|
1258
1392
|
}
|
|
1259
1393
|
});
|
|
1260
1394
|
}
|
|
1395
|
+
// --- Background Indexer Tools ---
|
|
1396
|
+
// Register tool: rulebook_codebase_search
|
|
1397
|
+
server.registerTool('rulebook_codebase_search', {
|
|
1398
|
+
title: 'Codebase Semantic Search',
|
|
1399
|
+
description: 'Search the entire project semantically (via AST chunks and paragraphs)',
|
|
1400
|
+
inputSchema: {
|
|
1401
|
+
query: z.string().describe('The code or concept you are looking for'),
|
|
1402
|
+
limit: z.number().optional().describe('Result limit (default 10)'),
|
|
1403
|
+
},
|
|
1404
|
+
}, async (args) => {
|
|
1405
|
+
if (!memoryManager)
|
|
1406
|
+
return memoryNotEnabled();
|
|
1407
|
+
try {
|
|
1408
|
+
const results = await memoryManager.searchMemories({
|
|
1409
|
+
query: args.query,
|
|
1410
|
+
limit: args.limit ?? 10,
|
|
1411
|
+
mode: 'hybrid', // Force hybrid search for best code-chunk matching
|
|
1412
|
+
});
|
|
1413
|
+
// Filter out normal memories, keep only code nodes
|
|
1414
|
+
const codeResults = results.filter((r) => r.id.startsWith('__code__'));
|
|
1415
|
+
return {
|
|
1416
|
+
content: [
|
|
1417
|
+
{ type: 'text', text: JSON.stringify({ success: true, results: codeResults }) },
|
|
1418
|
+
],
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
catch (error) {
|
|
1422
|
+
return {
|
|
1423
|
+
content: [
|
|
1424
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
|
|
1425
|
+
],
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
// Register tool: rulebook_codebase_graph
|
|
1430
|
+
server.registerTool('rulebook_codebase_graph', {
|
|
1431
|
+
title: 'Codebase Graph Explorer',
|
|
1432
|
+
description: 'Find relationships (imports, exports) of a specific code node or file',
|
|
1433
|
+
inputSchema: {
|
|
1434
|
+
filePath: z.string().describe('The strict file path to query (e.g. src/core/app.ts)'),
|
|
1435
|
+
},
|
|
1436
|
+
}, async (args) => {
|
|
1437
|
+
if (!memoryManager)
|
|
1438
|
+
return memoryNotEnabled();
|
|
1439
|
+
try {
|
|
1440
|
+
// Since V1 has limited Graph search implementation in memory-search,
|
|
1441
|
+
// we'll return a placeholder indicating the edge relations.
|
|
1442
|
+
// In a real implementation we would call a memoryManager.getGraphAdjacent(args.filePath)
|
|
1443
|
+
return {
|
|
1444
|
+
content: [
|
|
1445
|
+
{
|
|
1446
|
+
type: 'text',
|
|
1447
|
+
text: JSON.stringify({
|
|
1448
|
+
success: true,
|
|
1449
|
+
message: `Graph query for ${args.filePath} accepted. (Note: Graph deep-search pending V2 implementation, use codebase_search for now.)`,
|
|
1450
|
+
filePath: args.filePath,
|
|
1451
|
+
}),
|
|
1452
|
+
},
|
|
1453
|
+
],
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
catch (error) {
|
|
1457
|
+
return {
|
|
1458
|
+
content: [
|
|
1459
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
|
|
1460
|
+
],
|
|
1461
|
+
};
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1464
|
+
// Register tool: rulebook_indexer_status
|
|
1465
|
+
server.registerTool('rulebook_indexer_status', {
|
|
1466
|
+
title: 'Background Indexer Status',
|
|
1467
|
+
description: 'Get the status of the local autonomous filesystem indexer',
|
|
1468
|
+
inputSchema: {},
|
|
1469
|
+
}, async () => {
|
|
1470
|
+
try {
|
|
1471
|
+
// Because the BackgroundIndexer runs asynchronously, we fetch its global state
|
|
1472
|
+
// assuming it was attached to the server context during boot.
|
|
1473
|
+
const status = global.__indexerStatus
|
|
1474
|
+
? global.__indexerStatus()
|
|
1475
|
+
: { running: false, error: 'Indexer not attached to global context' };
|
|
1476
|
+
return {
|
|
1477
|
+
content: [{ type: 'text', text: JSON.stringify({ success: true, status }) }],
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
catch (error) {
|
|
1481
|
+
return {
|
|
1482
|
+
content: [
|
|
1483
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
|
|
1484
|
+
],
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
});
|
|
1488
|
+
// ============================================
|
|
1489
|
+
// Workspace Tools (v4.2 — workspace mode only)
|
|
1490
|
+
// ============================================
|
|
1491
|
+
if (workspaceManager) {
|
|
1492
|
+
// Register tool: rulebook_workspace_list
|
|
1493
|
+
server.registerTool('rulebook_workspace_list', {
|
|
1494
|
+
title: 'List Workspace Projects',
|
|
1495
|
+
description: 'List all projects in the current workspace',
|
|
1496
|
+
inputSchema: {},
|
|
1497
|
+
}, async () => {
|
|
1498
|
+
const projects = workspaceManager.getProjects();
|
|
1499
|
+
const activeIds = workspaceManager.getActiveWorkerIds();
|
|
1500
|
+
return {
|
|
1501
|
+
content: [
|
|
1502
|
+
{
|
|
1503
|
+
type: 'text',
|
|
1504
|
+
text: JSON.stringify({
|
|
1505
|
+
success: true,
|
|
1506
|
+
workspace: workspaceManager.getConfig().name,
|
|
1507
|
+
defaultProject: workspaceManager.getDefaultProjectId(),
|
|
1508
|
+
projects: projects.map((p) => ({
|
|
1509
|
+
name: p.name,
|
|
1510
|
+
path: p.path,
|
|
1511
|
+
workerActive: activeIds.includes(p.name),
|
|
1512
|
+
})),
|
|
1513
|
+
count: projects.length,
|
|
1514
|
+
}),
|
|
1515
|
+
},
|
|
1516
|
+
],
|
|
1517
|
+
};
|
|
1518
|
+
});
|
|
1519
|
+
// Register tool: rulebook_workspace_status
|
|
1520
|
+
server.registerTool('rulebook_workspace_status', {
|
|
1521
|
+
title: 'Workspace Status',
|
|
1522
|
+
description: 'Get detailed status of all workspace projects (workers, tasks, memory)',
|
|
1523
|
+
inputSchema: {},
|
|
1524
|
+
}, async () => {
|
|
1525
|
+
try {
|
|
1526
|
+
const status = await workspaceManager.getStatus();
|
|
1527
|
+
return {
|
|
1528
|
+
content: [{ type: 'text', text: JSON.stringify({ success: true, ...status }) }],
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
catch (error) {
|
|
1532
|
+
return {
|
|
1533
|
+
content: [
|
|
1534
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
|
|
1535
|
+
],
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
// Register tool: rulebook_workspace_search
|
|
1540
|
+
server.registerTool('rulebook_workspace_search', {
|
|
1541
|
+
title: 'Cross-Project Memory Search',
|
|
1542
|
+
description: 'Search memories across all projects in the workspace',
|
|
1543
|
+
inputSchema: {
|
|
1544
|
+
query: z.string().describe('Search query'),
|
|
1545
|
+
limit: z.number().optional().describe('Max results per project (default 10)'),
|
|
1546
|
+
},
|
|
1547
|
+
}, async (args) => {
|
|
1548
|
+
try {
|
|
1549
|
+
const results = await workspaceManager.searchMemoryAcrossProjects(args.query, {
|
|
1550
|
+
limit: args.limit,
|
|
1551
|
+
});
|
|
1552
|
+
return {
|
|
1553
|
+
content: [
|
|
1554
|
+
{
|
|
1555
|
+
type: 'text',
|
|
1556
|
+
text: JSON.stringify({
|
|
1557
|
+
success: true,
|
|
1558
|
+
results,
|
|
1559
|
+
projectsSearched: results.length,
|
|
1560
|
+
}),
|
|
1561
|
+
},
|
|
1562
|
+
],
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
catch (error) {
|
|
1566
|
+
return {
|
|
1567
|
+
content: [
|
|
1568
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
|
|
1569
|
+
],
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
});
|
|
1573
|
+
// Register tool: rulebook_workspace_tasks
|
|
1574
|
+
server.registerTool('rulebook_workspace_tasks', {
|
|
1575
|
+
title: 'List Tasks Across Projects',
|
|
1576
|
+
description: 'List tasks from all workspace projects',
|
|
1577
|
+
inputSchema: {
|
|
1578
|
+
status: z
|
|
1579
|
+
.enum(['pending', 'in-progress', 'completed', 'blocked'])
|
|
1580
|
+
.optional()
|
|
1581
|
+
.describe('Filter by status'),
|
|
1582
|
+
},
|
|
1583
|
+
}, async (args) => {
|
|
1584
|
+
try {
|
|
1585
|
+
const allTasks = [];
|
|
1586
|
+
for (const project of workspaceManager.getProjects()) {
|
|
1587
|
+
try {
|
|
1588
|
+
const tm = await getTaskMgr(project.name);
|
|
1589
|
+
const tasks = await tm.listTasks(false);
|
|
1590
|
+
const filtered = args.status
|
|
1591
|
+
? tasks.filter((t) => t.status === args.status)
|
|
1592
|
+
: tasks;
|
|
1593
|
+
if (filtered.length > 0) {
|
|
1594
|
+
allTasks.push({
|
|
1595
|
+
project: project.name,
|
|
1596
|
+
tasks: filtered.map((t) => ({
|
|
1597
|
+
id: t.id,
|
|
1598
|
+
title: t.title,
|
|
1599
|
+
status: t.status,
|
|
1600
|
+
})),
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
catch {
|
|
1605
|
+
// Skip projects that fail
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
return {
|
|
1609
|
+
content: [
|
|
1610
|
+
{
|
|
1611
|
+
type: 'text',
|
|
1612
|
+
text: JSON.stringify({
|
|
1613
|
+
success: true,
|
|
1614
|
+
projects: allTasks,
|
|
1615
|
+
totalTasks: allTasks.reduce((sum, p) => sum + p.tasks.length, 0),
|
|
1616
|
+
}),
|
|
1617
|
+
},
|
|
1618
|
+
],
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
catch (error) {
|
|
1622
|
+
return {
|
|
1623
|
+
content: [
|
|
1624
|
+
{ type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
|
|
1625
|
+
],
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
});
|
|
1629
|
+
}
|
|
1261
1630
|
const transport = new StdioServerTransport();
|
|
1262
1631
|
await server.connect(transport);
|
|
1263
1632
|
}
|