knowledge_sync_rules
Automatically syncs high-importance insights into IDE rules files, converting dynamic agent learnings into persistent project rules.
Instructions
Auto-sync graduated insights (importance >= 7) into your project's IDE rules file (.cursorrules or .clauderules). This bridges behavioral memory with static IDE context — turning dynamic agent learnings into always-on rules.
How it works:
Fetches graduated insights from the ledger
Formats them as markdown rules inside sentinel markers
Idempotently writes them into the target file at the project's configured repo_path
Requirements: The project must have a repo_path configured in the dashboard.
Idempotency: Uses <!-- PRISM:AUTO-RULES:START --> / <!-- PRISM:AUTO-RULES:END --> sentinel markers. Running this tool multiple times produces the same file. User-maintained content outside the sentinels is never touched.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes | Project identifier. Must have a repo_path configured in the dashboard. | |
| target_file | No | Target rules filename (default: '.cursorrules'). Common values: '.cursorrules', '.clauderules'. | |
| dry_run | No | If true, returns a preview of the rules block without writing to disk. Default: false. |
Implementation Reference
- Implementation of the knowledge_sync_rules tool handler, which syncs graduated insights into IDE rules files (e.g., .cursorrules) using sentinel markers for idempotency.
export async function knowledgeSyncRulesHandler(args: unknown) { if (!isKnowledgeSyncRulesArgs(args)) { throw new Error("Invalid arguments for knowledge_sync_rules"); } const { project, target_file = ".cursorrules", dry_run = false } = args; const storage = await getStorage(); // 1. Resolve repo path const repoPath = await getSetting(`repo_path:${project}`, ""); if (!repoPath || !repoPath.trim()) { return { content: [{ type: "text", text: `❌ No repo_path configured for project "${project}".\n` + `Set it in the Mind Palace dashboard (Settings → Project Repo Paths) before syncing rules.`, }], isError: true, }; } const normalizedRepoPath = repoPath.trim().replace(/\/+$/, ""); // 2. Fetch graduated insights const insights = await storage.getGraduatedInsights(project, PRISM_USER_ID, 7); if (insights.length === 0) { return { content: [{ type: "text", text: `ℹ️ No graduated insights found for project "${project}".\n` + `Insights graduate when their importance score reaches 7 or higher.\n` + `Use \`knowledge_upvote\` to increase importance of valuable entries.`, }], isError: false, }; } // 3. Format rules block const rulesBlock = formatRulesBlock( insights.map(i => ({ ...i, importance: i.importance ?? 0 })), project ); // 4. Dry-run: return preview without writing if (dry_run) { return { content: [{ type: "text", text: `🔍 **Dry Run Preview** — ${insights.length} graduated insight(s) for "${project}":\n\n` + `Target: ${normalizedRepoPath}/${target_file}\n\n` + `\`\`\`markdown\n${rulesBlock}\n\`\`\`\n\n` + `Run again without \`dry_run\` to write this to disk.`, }], isError: false, }; } // 5. Idempotent file write — with path traversal protection // Reject absolute paths (e.g. "/etc/hosts") if (isAbsolute(target_file)) { return { content: [{ type: "text", text: `❌ Security Error: target_file cannot be an absolute path. Got: "${target_file}"`, }], isError: true, }; } // Resolve both paths to their canonical forms, then assert containment const resolvedRepo = resolve(normalizedRepoPath); const targetPath = resolve(resolvedRepo, target_file); // Ensure the resolved target is strictly inside the repo root // (handles "../../../etc/hosts" style traversal) if (!targetPath.startsWith(resolvedRepo + sep)) { return { content: [{ type: "text", text: `❌ Security Error: Path traversal blocked.\n` + `"${target_file}" resolves outside the repo root "${resolvedRepo}".`, }], isError: true, }; } // Ensure directory exists (handles nested target_file like ".config/rules.md") const targetDir = dirname(targetPath); if (!existsSync(targetDir)) { await mkdir(targetDir, { recursive: true }); } let existingContent = ""; try { existingContent = await readFile(targetPath, "utf-8"); } catch { // File doesn't exist yet — will be created debugLog(`[knowledge_sync_rules] File ${targetPath} doesn't exist, creating new`); } const newContent = applySentinelBlock(existingContent, rulesBlock); await writeFile(targetPath, newContent, "utf-8"); debugLog(`[knowledge_sync_rules] Synced ${insights.length} insights to ${targetPath}`); return { content: [{ type: "text", text: `✅ Synced ${insights.length} graduated insight(s) to \`${targetPath}\`\n\n` + `Top insights synced:\n` + insights.slice(0, 5).map(i => ` • [${i.importance}] ${i.summary.substring(0, 80)}${i.summary.length > 80 ? "..." : ""}` ).join("\n") + (insights.length > 5 ? `\n ... and ${insights.length - 5} more` : ""), }], isError: false, }; } - MCP tool schema definition for knowledge_sync_rules.
export const KNOWLEDGE_SYNC_RULES_TOOL: Tool = { name: "knowledge_sync_rules", description: "Auto-sync graduated insights (importance >= 7) into your project's IDE rules file " + "(.cursorrules or .clauderules). This bridges behavioral memory with static IDE context — " + "turning dynamic agent learnings into always-on rules.\n\n" + "**How it works:**\n" + "1. Fetches graduated insights from the ledger\n" + "2. Formats them as markdown rules inside sentinel markers\n" + "3. Idempotently writes them into the target file at the project's configured repo_path\n\n" + "**Requirements:** The project must have a repo_path configured in the dashboard.\n\n" + "**Idempotency:** Uses `<!-- PRISM:AUTO-RULES:START -->` / `<!-- PRISM:AUTO-RULES:END -->` " + "sentinel markers. Running this tool multiple times produces the same file. " + "User-maintained content outside the sentinels is never touched.", inputSchema: { type: "object", properties: { project: { type: "string", description: "Project identifier. Must have a repo_path configured in the dashboard.", }, target_file: { type: "string", description: "Target rules filename (default: '.cursorrules'). " + "Common values: '.cursorrules', '.clauderules'.", }, dry_run: { type: "boolean", description: "If true, returns a preview of the rules block without writing to disk. Default: false.", }, }, required: ["project"], }, }; - src/server.ts:163-165 (registration)Registration of the knowledge_sync_rules tool and its handler in the main server file.
// v4.2: Knowledge Sync Rules KNOWLEDGE_SYNC_RULES_TOOL, knowledgeSyncRulesHandler,