@hivehub/rulebook 4.1.0 → 4.2.1
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 +137 -1
- package/dist/cli/commands.d.ts +18 -6
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +727 -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.map +1 -1
- package/dist/core/indexer/background-indexer.js +26 -5
- package/dist/core/indexer/background-indexer.js.map +1 -1
- package/dist/core/indexer/file-parser.d.ts.map +1 -1
- package/dist/core/indexer/file-parser.js +1 -1
- package/dist/core/indexer/file-parser.js.map +1 -1
- package/dist/core/indexer/indexer-types.d.ts.map +1 -1
- 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 +347 -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 +367 -100
- package/dist/mcp/rulebook-server.js.map +1 -1
- package/dist/memory/memory-manager.js +2 -2
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/memory-search.js.map +1 -1
- package/dist/memory/memory-store.d.ts.map +1 -1
- package/dist/memory/memory-store.js +1 -1
- package/dist/memory/memory-store.js.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 -94
- 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 -1935
- 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
|
@@ -8,6 +8,7 @@ import { ConfigManager } from '../core/config-manager.js';
|
|
|
8
8
|
import { BackgroundIndexer } from '../core/indexer/background-indexer.js';
|
|
9
9
|
import { SkillsManager, getDefaultTemplatesPath } from '../core/skills-manager.js';
|
|
10
10
|
import { TaskManager } from '../core/task-manager.js';
|
|
11
|
+
import { WorkspaceManager } from '../core/workspace/workspace-manager.js';
|
|
11
12
|
// Find .rulebook file/directory by walking up directories
|
|
12
13
|
export function findRulebookConfig(startDir) {
|
|
13
14
|
let current = resolve(startDir);
|
|
@@ -55,23 +56,94 @@ function loadConfig() {
|
|
|
55
56
|
return { projectRoot, tasksDir, archiveDir };
|
|
56
57
|
}
|
|
57
58
|
export async function startRulebookMcpServer() {
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
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. Run `rulebook workspace init` to create .rulebook/workspace.json.');
|
|
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
|
+
}
|
|
62
130
|
const server = new McpServer({
|
|
63
131
|
name: 'rulebook-task-management',
|
|
64
|
-
version: '4.1
|
|
132
|
+
version: '4.2.1',
|
|
65
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)');
|
|
66
136
|
// Register tool: rulebook_task_create
|
|
67
137
|
server.registerTool('rulebook_task_create', {
|
|
68
138
|
title: 'Create Rulebook Task',
|
|
69
139
|
description: 'Create a new Rulebook task',
|
|
70
140
|
inputSchema: {
|
|
71
141
|
taskId: z.string().describe('Task ID in kebab-case'),
|
|
142
|
+
projectId: projectIdSchema,
|
|
72
143
|
},
|
|
73
144
|
}, async (args) => {
|
|
74
|
-
await
|
|
145
|
+
const tm = await getTaskMgr(args.projectId);
|
|
146
|
+
await tm.createTask(args.taskId);
|
|
75
147
|
const resultText = JSON.stringify({
|
|
76
148
|
success: true,
|
|
77
149
|
taskId: args.taskId,
|
|
@@ -90,9 +162,11 @@ export async function startRulebookMcpServer() {
|
|
|
90
162
|
.enum(['pending', 'in-progress', 'completed', 'blocked'])
|
|
91
163
|
.optional()
|
|
92
164
|
.describe('Filter by status'),
|
|
165
|
+
projectId: projectIdSchema,
|
|
93
166
|
},
|
|
94
167
|
}, async (args) => {
|
|
95
|
-
const
|
|
168
|
+
const tm = await getTaskMgr(args.projectId);
|
|
169
|
+
const tasks = await tm.listTasks(args.includeArchived || false);
|
|
96
170
|
let filtered = tasks;
|
|
97
171
|
if (args.status) {
|
|
98
172
|
filtered = tasks.filter((t) => t.status === args.status);
|
|
@@ -121,9 +195,11 @@ export async function startRulebookMcpServer() {
|
|
|
121
195
|
description: 'Show task details',
|
|
122
196
|
inputSchema: {
|
|
123
197
|
taskId: z.string().describe('Task ID to show'),
|
|
198
|
+
projectId: projectIdSchema,
|
|
124
199
|
},
|
|
125
200
|
}, async (args) => {
|
|
126
|
-
const
|
|
201
|
+
const tm = await getTaskMgr(args.projectId);
|
|
202
|
+
const task = await tm.showTask(args.taskId);
|
|
127
203
|
return {
|
|
128
204
|
content: [
|
|
129
205
|
{
|
|
@@ -158,10 +234,12 @@ export async function startRulebookMcpServer() {
|
|
|
158
234
|
.enum(['pending', 'in-progress', 'completed', 'blocked'])
|
|
159
235
|
.optional()
|
|
160
236
|
.describe('New status'),
|
|
237
|
+
projectId: projectIdSchema,
|
|
161
238
|
},
|
|
162
239
|
}, async (args) => {
|
|
240
|
+
const tm = await getTaskMgr(args.projectId);
|
|
163
241
|
if (args.status) {
|
|
164
|
-
await
|
|
242
|
+
await tm.updateTaskStatus(args.taskId, args.status);
|
|
165
243
|
}
|
|
166
244
|
const resultText = JSON.stringify({
|
|
167
245
|
success: true,
|
|
@@ -177,9 +255,11 @@ export async function startRulebookMcpServer() {
|
|
|
177
255
|
description: 'Validate task format',
|
|
178
256
|
inputSchema: {
|
|
179
257
|
taskId: z.string().describe('Task ID to validate'),
|
|
258
|
+
projectId: projectIdSchema,
|
|
180
259
|
},
|
|
181
260
|
}, async (args) => {
|
|
182
|
-
const
|
|
261
|
+
const tm = await getTaskMgr(args.projectId);
|
|
262
|
+
const validation = await tm.validateTask(args.taskId);
|
|
183
263
|
return {
|
|
184
264
|
content: [
|
|
185
265
|
{
|
|
@@ -200,9 +280,11 @@ export async function startRulebookMcpServer() {
|
|
|
200
280
|
inputSchema: {
|
|
201
281
|
taskId: z.string().describe('Task ID to archive'),
|
|
202
282
|
skipValidation: z.boolean().optional().describe('Skip validation before archiving'),
|
|
283
|
+
projectId: projectIdSchema,
|
|
203
284
|
},
|
|
204
285
|
}, async (args) => {
|
|
205
|
-
await
|
|
286
|
+
const tm = await getTaskMgr(args.projectId);
|
|
287
|
+
await tm.archiveTask(args.taskId, args.skipValidation || false);
|
|
206
288
|
const resultText = JSON.stringify({
|
|
207
289
|
success: true,
|
|
208
290
|
taskId: args.taskId,
|
|
@@ -217,9 +299,11 @@ export async function startRulebookMcpServer() {
|
|
|
217
299
|
description: 'Delete a task permanently',
|
|
218
300
|
inputSchema: {
|
|
219
301
|
taskId: z.string().describe('Task ID to delete'),
|
|
302
|
+
projectId: projectIdSchema,
|
|
220
303
|
},
|
|
221
304
|
}, async (args) => {
|
|
222
|
-
await
|
|
305
|
+
const tm = await getTaskMgr(args.projectId);
|
|
306
|
+
await tm.deleteTask(args.taskId);
|
|
223
307
|
const resultText = JSON.stringify({
|
|
224
308
|
success: true,
|
|
225
309
|
taskId: args.taskId,
|
|
@@ -252,19 +336,21 @@ export async function startRulebookMcpServer() {
|
|
|
252
336
|
.optional()
|
|
253
337
|
.describe('Filter by category'),
|
|
254
338
|
enabledOnly: z.boolean().optional().describe('Show only enabled skills'),
|
|
339
|
+
projectId: projectIdSchema,
|
|
255
340
|
},
|
|
256
341
|
}, async (args) => {
|
|
257
342
|
try {
|
|
343
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
344
|
+
const cm = await getConfigMgr(args.projectId);
|
|
258
345
|
let skills;
|
|
259
346
|
if (args.category) {
|
|
260
|
-
skills = await
|
|
347
|
+
skills = await sm.getSkillsByCategory(args.category);
|
|
261
348
|
}
|
|
262
349
|
else {
|
|
263
|
-
skills = await
|
|
350
|
+
skills = await sm.getSkills();
|
|
264
351
|
}
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
const enabledIds = new Set(rulebookConfig.skills?.enabled || []);
|
|
352
|
+
const rbConfig = await cm.loadConfig();
|
|
353
|
+
const enabledIds = new Set(rbConfig.skills?.enabled || []);
|
|
268
354
|
let filteredSkills = skills.map((s) => ({
|
|
269
355
|
id: s.id,
|
|
270
356
|
name: s.metadata.name,
|
|
@@ -311,10 +397,13 @@ export async function startRulebookMcpServer() {
|
|
|
311
397
|
description: 'Show detailed information about a specific skill',
|
|
312
398
|
inputSchema: {
|
|
313
399
|
skillId: z.string().describe('Skill ID (e.g., languages/typescript)'),
|
|
400
|
+
projectId: projectIdSchema,
|
|
314
401
|
},
|
|
315
402
|
}, async (args) => {
|
|
316
403
|
try {
|
|
317
|
-
const
|
|
404
|
+
const sm = await getSkillsMgr(args.projectId);
|
|
405
|
+
const cm = await getConfigMgr(args.projectId);
|
|
406
|
+
const skill = await sm.getSkillById(args.skillId);
|
|
318
407
|
if (!skill) {
|
|
319
408
|
return {
|
|
320
409
|
content: [
|
|
@@ -329,8 +418,8 @@ export async function startRulebookMcpServer() {
|
|
|
329
418
|
],
|
|
330
419
|
};
|
|
331
420
|
}
|
|
332
|
-
const
|
|
333
|
-
const enabled =
|
|
421
|
+
const rbConfig = await cm.loadConfig();
|
|
422
|
+
const enabled = rbConfig.skills?.enabled?.includes(args.skillId) || false;
|
|
334
423
|
return {
|
|
335
424
|
content: [
|
|
336
425
|
{
|
|
@@ -375,14 +464,16 @@ export async function startRulebookMcpServer() {
|
|
|
375
464
|
description: 'Enable a skill in the project configuration',
|
|
376
465
|
inputSchema: {
|
|
377
466
|
skillId: z.string().describe('Skill ID to enable (e.g., languages/typescript)'),
|
|
467
|
+
projectId: projectIdSchema,
|
|
378
468
|
},
|
|
379
469
|
}, async (args) => {
|
|
380
470
|
try {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
await
|
|
384
|
-
|
|
385
|
-
|
|
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);
|
|
386
477
|
const resultText = JSON.stringify({
|
|
387
478
|
success: true,
|
|
388
479
|
skillId: args.skillId,
|
|
@@ -413,12 +504,14 @@ export async function startRulebookMcpServer() {
|
|
|
413
504
|
description: 'Disable a skill in the project configuration',
|
|
414
505
|
inputSchema: {
|
|
415
506
|
skillId: z.string().describe('Skill ID to disable (e.g., languages/typescript)'),
|
|
507
|
+
projectId: projectIdSchema,
|
|
416
508
|
},
|
|
417
509
|
}, async (args) => {
|
|
418
510
|
try {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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)) {
|
|
422
515
|
return {
|
|
423
516
|
content: [
|
|
424
517
|
{
|
|
@@ -431,8 +524,8 @@ export async function startRulebookMcpServer() {
|
|
|
431
524
|
],
|
|
432
525
|
};
|
|
433
526
|
}
|
|
434
|
-
|
|
435
|
-
await
|
|
527
|
+
rbConfig = await sm.disableSkill(args.skillId, rbConfig);
|
|
528
|
+
await cm.saveConfig(rbConfig);
|
|
436
529
|
const resultText = JSON.stringify({
|
|
437
530
|
success: true,
|
|
438
531
|
skillId: args.skillId,
|
|
@@ -461,12 +554,15 @@ export async function startRulebookMcpServer() {
|
|
|
461
554
|
description: 'Search for skills by name, description, or tags',
|
|
462
555
|
inputSchema: {
|
|
463
556
|
query: z.string().describe('Search query'),
|
|
557
|
+
projectId: projectIdSchema,
|
|
464
558
|
},
|
|
465
559
|
}, async (args) => {
|
|
466
560
|
try {
|
|
467
|
-
const
|
|
468
|
-
const
|
|
469
|
-
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 || []);
|
|
470
566
|
return {
|
|
471
567
|
content: [
|
|
472
568
|
{
|
|
@@ -505,11 +601,15 @@ export async function startRulebookMcpServer() {
|
|
|
505
601
|
server.registerTool('rulebook_skill_validate', {
|
|
506
602
|
title: 'Validate Skills Configuration',
|
|
507
603
|
description: 'Validate the current skills configuration for conflicts and dependencies',
|
|
508
|
-
inputSchema: {
|
|
509
|
-
|
|
604
|
+
inputSchema: {
|
|
605
|
+
projectId: projectIdSchema,
|
|
606
|
+
},
|
|
607
|
+
}, async (args) => {
|
|
510
608
|
try {
|
|
511
|
-
const
|
|
512
|
-
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);
|
|
513
613
|
return {
|
|
514
614
|
content: [
|
|
515
615
|
{
|
|
@@ -520,7 +620,7 @@ export async function startRulebookMcpServer() {
|
|
|
520
620
|
errors: validation.errors,
|
|
521
621
|
warnings: validation.warnings,
|
|
522
622
|
conflicts: validation.conflicts,
|
|
523
|
-
enabledCount:
|
|
623
|
+
enabledCount: rbConfig.skills?.enabled?.length || 0,
|
|
524
624
|
}),
|
|
525
625
|
},
|
|
526
626
|
],
|
|
@@ -543,37 +643,42 @@ export async function startRulebookMcpServer() {
|
|
|
543
643
|
// ============================================
|
|
544
644
|
// Memory System Functions (v3.0)
|
|
545
645
|
// ============================================
|
|
546
|
-
// Conditionally initialize MemoryManager
|
|
646
|
+
// Conditionally initialize MemoryManager (single-project mode only;
|
|
647
|
+
// in workspace mode each worker manages its own memory)
|
|
547
648
|
let memoryManager = null;
|
|
548
649
|
let bgIndexer = null;
|
|
549
650
|
let autoCaptureEnabled = false;
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
console.
|
|
566
|
-
|
|
567
|
-
bgIndexer.stop();
|
|
568
|
-
if (memoryManager)
|
|
569
|
-
await memoryManager.close();
|
|
570
|
-
process.exit(0);
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
catch (e) {
|
|
574
|
-
console.warn('[rulebook-mcp] Failed to boot Memory/Indexer:', e);
|
|
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
|
+
}
|
|
575
668
|
}
|
|
576
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
|
+
});
|
|
577
682
|
/**
|
|
578
683
|
* Auto-capture: save tool interactions to memory in the background.
|
|
579
684
|
* Fire-and-forget — never blocks or fails the original tool call.
|
|
@@ -619,12 +724,14 @@ export async function startRulebookMcpServer() {
|
|
|
619
724
|
limit: z.number().optional().describe('Max results (default 20)'),
|
|
620
725
|
mode: z.enum(['bm25', 'vector', 'hybrid']).optional().describe('Search mode'),
|
|
621
726
|
type: z.string().optional().describe('Filter by memory type'),
|
|
727
|
+
projectId: projectIdSchema,
|
|
622
728
|
},
|
|
623
729
|
}, async (args) => {
|
|
624
|
-
|
|
730
|
+
const mm = await getMemMgr(args.projectId);
|
|
731
|
+
if (!mm)
|
|
625
732
|
return memoryNotEnabled();
|
|
626
733
|
try {
|
|
627
|
-
const results = await
|
|
734
|
+
const results = await mm.searchMemories({
|
|
628
735
|
query: args.query,
|
|
629
736
|
limit: args.limit,
|
|
630
737
|
mode: args.mode,
|
|
@@ -654,12 +761,14 @@ export async function startRulebookMcpServer() {
|
|
|
654
761
|
inputSchema: {
|
|
655
762
|
memoryId: z.string().describe('Memory ID to anchor timeline'),
|
|
656
763
|
window: z.number().optional().describe('Number of memories before/after (default 5)'),
|
|
764
|
+
projectId: projectIdSchema,
|
|
657
765
|
},
|
|
658
766
|
}, async (args) => {
|
|
659
|
-
|
|
767
|
+
const mm = await getMemMgr(args.projectId);
|
|
768
|
+
if (!mm)
|
|
660
769
|
return memoryNotEnabled();
|
|
661
770
|
try {
|
|
662
|
-
const timeline = await
|
|
771
|
+
const timeline = await mm.getTimeline(args.memoryId, args.window);
|
|
663
772
|
return {
|
|
664
773
|
content: [{ type: 'text', text: JSON.stringify({ success: true, timeline }) }],
|
|
665
774
|
};
|
|
@@ -678,12 +787,14 @@ export async function startRulebookMcpServer() {
|
|
|
678
787
|
description: 'Get full details for specific memory IDs',
|
|
679
788
|
inputSchema: {
|
|
680
789
|
ids: z.array(z.string()).describe('Memory IDs to fetch'),
|
|
790
|
+
projectId: projectIdSchema,
|
|
681
791
|
},
|
|
682
792
|
}, async (args) => {
|
|
683
|
-
|
|
793
|
+
const mm = await getMemMgr(args.projectId);
|
|
794
|
+
if (!mm)
|
|
684
795
|
return memoryNotEnabled();
|
|
685
796
|
try {
|
|
686
|
-
const memories = await
|
|
797
|
+
const memories = await mm.getFullDetails(args.ids);
|
|
687
798
|
return {
|
|
688
799
|
content: [{ type: 'text', text: JSON.stringify({ success: true, memories }) }],
|
|
689
800
|
};
|
|
@@ -707,12 +818,14 @@ export async function startRulebookMcpServer() {
|
|
|
707
818
|
title: z.string().describe('Memory title'),
|
|
708
819
|
content: z.string().describe('Memory content'),
|
|
709
820
|
tags: z.array(z.string()).optional().describe('Tags'),
|
|
821
|
+
projectId: projectIdSchema,
|
|
710
822
|
},
|
|
711
823
|
}, async (args) => {
|
|
712
|
-
|
|
824
|
+
const mm = await getMemMgr(args.projectId);
|
|
825
|
+
if (!mm)
|
|
713
826
|
return memoryNotEnabled();
|
|
714
827
|
try {
|
|
715
|
-
const memory = await
|
|
828
|
+
const memory = await mm.saveMemory({
|
|
716
829
|
type: args.type,
|
|
717
830
|
title: args.title,
|
|
718
831
|
content: args.content,
|
|
@@ -742,12 +855,15 @@ export async function startRulebookMcpServer() {
|
|
|
742
855
|
server.registerTool('rulebook_memory_stats', {
|
|
743
856
|
title: 'Memory Statistics',
|
|
744
857
|
description: 'Get memory database statistics',
|
|
745
|
-
inputSchema: {
|
|
746
|
-
|
|
747
|
-
|
|
858
|
+
inputSchema: {
|
|
859
|
+
projectId: projectIdSchema,
|
|
860
|
+
},
|
|
861
|
+
}, async (args) => {
|
|
862
|
+
const mm = await getMemMgr(args.projectId);
|
|
863
|
+
if (!mm)
|
|
748
864
|
return memoryNotEnabled();
|
|
749
865
|
try {
|
|
750
|
-
const stats = await
|
|
866
|
+
const stats = await mm.getStats();
|
|
751
867
|
return {
|
|
752
868
|
content: [{ type: 'text', text: JSON.stringify({ success: true, stats }) }],
|
|
753
869
|
};
|
|
@@ -766,12 +882,14 @@ export async function startRulebookMcpServer() {
|
|
|
766
882
|
description: 'Force memory eviction and cleanup',
|
|
767
883
|
inputSchema: {
|
|
768
884
|
force: z.boolean().optional().describe('Force cleanup regardless of size'),
|
|
885
|
+
projectId: projectIdSchema,
|
|
769
886
|
},
|
|
770
887
|
}, async (args) => {
|
|
771
|
-
|
|
888
|
+
const mm = await getMemMgr(args.projectId);
|
|
889
|
+
if (!mm)
|
|
772
890
|
return memoryNotEnabled();
|
|
773
891
|
try {
|
|
774
|
-
const result = await
|
|
892
|
+
const result = await mm.cleanup(args.force ?? false);
|
|
775
893
|
return {
|
|
776
894
|
content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }) }],
|
|
777
895
|
};
|
|
@@ -798,16 +916,16 @@ export async function startRulebookMcpServer() {
|
|
|
798
916
|
const { Logger } = await import('../core/logger.js');
|
|
799
917
|
const { RalphManager } = await import('../core/ralph-manager.js');
|
|
800
918
|
const { PRDGenerator } = await import('../core/prd-generator.js');
|
|
801
|
-
const logger = new Logger(
|
|
802
|
-
const ralphManager = new RalphManager(
|
|
803
|
-
const prdGenerator = new PRDGenerator(
|
|
919
|
+
const logger = new Logger(projectRoot);
|
|
920
|
+
const ralphManager = new RalphManager(projectRoot, logger);
|
|
921
|
+
const prdGenerator = new PRDGenerator(projectRoot, logger);
|
|
804
922
|
const configData = await configManager.loadConfig();
|
|
805
923
|
const maxIterations = configData.ralph?.maxIterations || 10;
|
|
806
924
|
const tool = (configData.ralph?.tool || 'claude');
|
|
807
925
|
// Generate PRD first, then initialize with correct task count
|
|
808
|
-
const prd = await prdGenerator.generatePRD(basename(
|
|
926
|
+
const prd = await prdGenerator.generatePRD(basename(projectRoot) || 'project');
|
|
809
927
|
const { writeFile } = await import('../utils/file-system.js');
|
|
810
|
-
const prdPath = join(
|
|
928
|
+
const prdPath = join(projectRoot, '.rulebook', 'ralph', 'prd.json');
|
|
811
929
|
await writeFile(prdPath, JSON.stringify(prd, null, 2));
|
|
812
930
|
// Initialize after PRD is written so task count is correct
|
|
813
931
|
await ralphManager.initialize(maxIterations, tool);
|
|
@@ -852,8 +970,8 @@ export async function startRulebookMcpServer() {
|
|
|
852
970
|
const { RalphParser } = await import('../agents/ralph-parser.js');
|
|
853
971
|
const { spawn } = await import('child_process');
|
|
854
972
|
const { execSync } = await import('child_process');
|
|
855
|
-
const logger = new Logger(
|
|
856
|
-
const ralphManager = new RalphManager(
|
|
973
|
+
const logger = new Logger(projectRoot);
|
|
974
|
+
const ralphManager = new RalphManager(projectRoot, logger);
|
|
857
975
|
const configData = await configManager.loadConfig();
|
|
858
976
|
const maxIterations = args.maxIterations || configData.ralph?.maxIterations || 10;
|
|
859
977
|
const tool = (args.tool || configData.ralph?.tool || 'claude');
|
|
@@ -913,7 +1031,7 @@ export async function startRulebookMcpServer() {
|
|
|
913
1031
|
let stdout = '';
|
|
914
1032
|
let stderr = '';
|
|
915
1033
|
const proc = spawn(cmd, cmdArgs, {
|
|
916
|
-
cwd:
|
|
1034
|
+
cwd: projectRoot,
|
|
917
1035
|
shell: true,
|
|
918
1036
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
919
1037
|
});
|
|
@@ -976,7 +1094,7 @@ export async function startRulebookMcpServer() {
|
|
|
976
1094
|
}
|
|
977
1095
|
};
|
|
978
1096
|
const proc = spawn(cfg.cmd, cfg.args, {
|
|
979
|
-
cwd:
|
|
1097
|
+
cwd: projectRoot,
|
|
980
1098
|
shell: true,
|
|
981
1099
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
982
1100
|
});
|
|
@@ -1163,8 +1281,8 @@ export async function startRulebookMcpServer() {
|
|
|
1163
1281
|
try {
|
|
1164
1282
|
const { Logger } = await import('../core/logger.js');
|
|
1165
1283
|
const { RalphManager } = await import('../core/ralph-manager.js');
|
|
1166
|
-
const logger = new Logger(
|
|
1167
|
-
const ralphManager = new RalphManager(
|
|
1284
|
+
const logger = new Logger(projectRoot);
|
|
1285
|
+
const ralphManager = new RalphManager(projectRoot, logger);
|
|
1168
1286
|
const status = await ralphManager.getStatus();
|
|
1169
1287
|
if (!status) {
|
|
1170
1288
|
return {
|
|
@@ -1230,8 +1348,8 @@ export async function startRulebookMcpServer() {
|
|
|
1230
1348
|
try {
|
|
1231
1349
|
const { Logger } = await import('../core/logger.js');
|
|
1232
1350
|
const { IterationTracker } = await import('../core/iteration-tracker.js');
|
|
1233
|
-
const logger = new Logger(
|
|
1234
|
-
const tracker = new IterationTracker(
|
|
1351
|
+
const logger = new Logger(projectRoot);
|
|
1352
|
+
const tracker = new IterationTracker(projectRoot, logger);
|
|
1235
1353
|
const history = await tracker.getHistory(args.limit || 10, args.taskId);
|
|
1236
1354
|
const stats = await tracker.getStatistics();
|
|
1237
1355
|
return {
|
|
@@ -1290,12 +1408,14 @@ export async function startRulebookMcpServer() {
|
|
|
1290
1408
|
const results = await memoryManager.searchMemories({
|
|
1291
1409
|
query: args.query,
|
|
1292
1410
|
limit: args.limit ?? 10,
|
|
1293
|
-
mode: 'hybrid' // Force hybrid search for best code-chunk matching
|
|
1411
|
+
mode: 'hybrid', // Force hybrid search for best code-chunk matching
|
|
1294
1412
|
});
|
|
1295
1413
|
// Filter out normal memories, keep only code nodes
|
|
1296
1414
|
const codeResults = results.filter((r) => r.id.startsWith('__code__'));
|
|
1297
1415
|
return {
|
|
1298
|
-
content: [
|
|
1416
|
+
content: [
|
|
1417
|
+
{ type: 'text', text: JSON.stringify({ success: true, results: codeResults }) },
|
|
1418
|
+
],
|
|
1299
1419
|
};
|
|
1300
1420
|
}
|
|
1301
1421
|
catch (error) {
|
|
@@ -1317,17 +1437,20 @@ export async function startRulebookMcpServer() {
|
|
|
1317
1437
|
if (!memoryManager)
|
|
1318
1438
|
return memoryNotEnabled();
|
|
1319
1439
|
try {
|
|
1320
|
-
// Since V1 has limited Graph search implementation in memory-search,
|
|
1440
|
+
// Since V1 has limited Graph search implementation in memory-search,
|
|
1321
1441
|
// we'll return a placeholder indicating the edge relations.
|
|
1322
1442
|
// In a real implementation we would call a memoryManager.getGraphAdjacent(args.filePath)
|
|
1323
1443
|
return {
|
|
1324
|
-
content: [
|
|
1325
|
-
|
|
1444
|
+
content: [
|
|
1445
|
+
{
|
|
1446
|
+
type: 'text',
|
|
1447
|
+
text: JSON.stringify({
|
|
1326
1448
|
success: true,
|
|
1327
1449
|
message: `Graph query for ${args.filePath} accepted. (Note: Graph deep-search pending V2 implementation, use codebase_search for now.)`,
|
|
1328
|
-
filePath: args.filePath
|
|
1329
|
-
})
|
|
1330
|
-
}
|
|
1450
|
+
filePath: args.filePath,
|
|
1451
|
+
}),
|
|
1452
|
+
},
|
|
1453
|
+
],
|
|
1331
1454
|
};
|
|
1332
1455
|
}
|
|
1333
1456
|
catch (error) {
|
|
@@ -1347,7 +1470,9 @@ export async function startRulebookMcpServer() {
|
|
|
1347
1470
|
try {
|
|
1348
1471
|
// Because the BackgroundIndexer runs asynchronously, we fetch its global state
|
|
1349
1472
|
// assuming it was attached to the server context during boot.
|
|
1350
|
-
const status = global.__indexerStatus
|
|
1473
|
+
const status = global.__indexerStatus
|
|
1474
|
+
? global.__indexerStatus()
|
|
1475
|
+
: { running: false, error: 'Indexer not attached to global context' };
|
|
1351
1476
|
return {
|
|
1352
1477
|
content: [{ type: 'text', text: JSON.stringify({ success: true, status }) }],
|
|
1353
1478
|
};
|
|
@@ -1360,6 +1485,148 @@ export async function startRulebookMcpServer() {
|
|
|
1360
1485
|
};
|
|
1361
1486
|
}
|
|
1362
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
|
+
}
|
|
1363
1630
|
const transport = new StdioServerTransport();
|
|
1364
1631
|
await server.connect(transport);
|
|
1365
1632
|
}
|