smart-claude-memory-mcp 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +38 -0
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/README.md +790 -0
- package/dist/chunker.js +33 -0
- package/dist/chunker.js.map +1 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/curriculum/daemon.js +190 -0
- package/dist/curriculum/daemon.js.map +1 -0
- package/dist/curriculum/scanner.js +237 -0
- package/dist/curriculum/scanner.js.map +1 -0
- package/dist/index.js +429 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/migrations.js +128 -0
- package/dist/lib/migrations.js.map +1 -0
- package/dist/ollama.js +59 -0
- package/dist/ollama.js.map +1 -0
- package/dist/project-detect.js +102 -0
- package/dist/project-detect.js.map +1 -0
- package/dist/project.js +26 -0
- package/dist/project.js.map +1 -0
- package/dist/sleep/daemon.js +215 -0
- package/dist/sleep/daemon.js.map +1 -0
- package/dist/sleep/miner.js +285 -0
- package/dist/sleep/miner.js.map +1 -0
- package/dist/supabase.js +405 -0
- package/dist/supabase.js.map +1 -0
- package/dist/telemetry/emit.js +19 -0
- package/dist/telemetry/emit.js.map +1 -0
- package/dist/telemetry/pruner.js +141 -0
- package/dist/telemetry/pruner.js.map +1 -0
- package/dist/telemetry/types.js +2 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/tools/backlog.js +599 -0
- package/dist/tools/backlog.js.map +1 -0
- package/dist/tools/batch-freeze-patterns.js +243 -0
- package/dist/tools/batch-freeze-patterns.js.map +1 -0
- package/dist/tools/bloat-audit.js +101 -0
- package/dist/tools/bloat-audit.js.map +1 -0
- package/dist/tools/checkpoint.js +259 -0
- package/dist/tools/checkpoint.js.map +1 -0
- package/dist/tools/compact.js +60 -0
- package/dist/tools/compact.js.map +1 -0
- package/dist/tools/conflict.js +102 -0
- package/dist/tools/conflict.js.map +1 -0
- package/dist/tools/curriculum.js +225 -0
- package/dist/tools/curriculum.js.map +1 -0
- package/dist/tools/frozen-cache.js +106 -0
- package/dist/tools/frozen-cache.js.map +1 -0
- package/dist/tools/health.js +368 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/hygiene.js +309 -0
- package/dist/tools/hygiene.js.map +1 -0
- package/dist/tools/image.js +107 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/list-global-patterns.js +101 -0
- package/dist/tools/list-global-patterns.js.map +1 -0
- package/dist/tools/orchestrator.js +113 -0
- package/dist/tools/orchestrator.js.map +1 -0
- package/dist/tools/policy.js +90 -0
- package/dist/tools/policy.js.map +1 -0
- package/dist/tools/refactor.js +220 -0
- package/dist/tools/refactor.js.map +1 -0
- package/dist/tools/save.js +42 -0
- package/dist/tools/save.js.map +1 -0
- package/dist/tools/search.js +189 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/setup.js +868 -0
- package/dist/tools/setup.js.map +1 -0
- package/dist/tools/shared-schemas.js +24 -0
- package/dist/tools/shared-schemas.js.map +1 -0
- package/dist/tools/skills.js +174 -0
- package/dist/tools/skills.js.map +1 -0
- package/dist/tools/sleep.js +239 -0
- package/dist/tools/sleep.js.map +1 -0
- package/dist/tools/sovereign-constitution.js +319 -0
- package/dist/tools/sovereign-constitution.js.map +1 -0
- package/dist/tools/summarize.js +55 -0
- package/dist/tools/summarize.js.map +1 -0
- package/dist/tools/sync.js +255 -0
- package/dist/tools/sync.js.map +1 -0
- package/dist/tools/system_dashboard.js +181 -0
- package/dist/tools/system_dashboard.js.map +1 -0
- package/dist/tools/update-rule.js +15 -0
- package/dist/tools/update-rule.js.map +1 -0
- package/dist/tools/verification.js +333 -0
- package/dist/tools/verification.js.map +1 -0
- package/dist/trajectory/daemon.js +270 -0
- package/dist/trajectory/daemon.js.map +1 -0
- package/dist/trajectory/stripper.js +124 -0
- package/dist/trajectory/stripper.js.map +1 -0
- package/dist/trajectory/summarizer.js +77 -0
- package/dist/trajectory/summarizer.js.map +1 -0
- package/dist/transactions/checkpoint.js +272 -0
- package/dist/transactions/checkpoint.js.map +1 -0
- package/dist/verification-gate.js +43 -0
- package/dist/verification-gate.js.map +1 -0
- package/dist/version.js +16 -0
- package/dist/version.js.map +1 -0
- package/hooks/README.md +54 -0
- package/hooks/md-policy.py +497 -0
- package/marketplace.json +13 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { syncLocalMemory } from "./tools/sync.js";
|
|
6
|
+
import { searchMemory } from "./tools/search.js";
|
|
7
|
+
import { listGlobalPatterns, listGlobalPatternsInputShape, } from "./tools/list-global-patterns.js";
|
|
8
|
+
import { saveMemory } from "./tools/save.js";
|
|
9
|
+
import { manageBacklog } from "./tools/backlog.js";
|
|
10
|
+
import { checkCodeHygiene } from "./tools/hygiene.js";
|
|
11
|
+
import { confirmVerification, raisePendingVerification } from "./tools/verification.js";
|
|
12
|
+
import { checkRuleConflicts } from "./tools/conflict.js";
|
|
13
|
+
import { summarizeMemoryFile } from "./tools/summarize.js";
|
|
14
|
+
import { indexImage } from "./tools/image.js";
|
|
15
|
+
import { checkSystemHealth } from "./tools/health.js";
|
|
16
|
+
import { systemDashboardHandler, renderDashboardMarkdown } from "./tools/system_dashboard.js";
|
|
17
|
+
import { initProject, sweepLegacyBackups, legacyBackupSummary } from "./tools/setup.js";
|
|
18
|
+
import { listFrozen, freezeFile, unfreezeFile } from "./tools/policy.js";
|
|
19
|
+
import { batchFreezePatterns } from "./tools/batch-freeze-patterns.js";
|
|
20
|
+
import { refactorGuard } from "./tools/refactor.js";
|
|
21
|
+
import { analyzeRegression } from "./tools/verification.js";
|
|
22
|
+
import { delegateTask, syncArtefacts } from "./tools/orchestrator.js";
|
|
23
|
+
import { upgradeConstitutionBlock } from "./tools/sovereign-constitution.js";
|
|
24
|
+
import { metadataFilterSchema } from "./tools/shared-schemas.js";
|
|
25
|
+
import { packageSkill, packageSkillInputShape, requestSkill, requestSkillInputShape, } from "./tools/skills.js";
|
|
26
|
+
import { compactTrajectoryHandler, compactTrajectoryInputShape, getTrajectorySummaryHandler, getTrajectorySummaryInputShape, } from "./tools/compact.js";
|
|
27
|
+
import { listSkillCandidates, listSkillCandidatesInputShape, composeSkillCandidate, composeSkillCandidateInputShape, promoteSkillCandidate, promoteSkillCandidateInputShape, rejectSkillCandidate, rejectSkillCandidateInputShape, } from "./tools/sleep.js";
|
|
28
|
+
import { checkpointCreateHandler, checkpointCreateInputShape, checkpointCommitHandler, checkpointCommitInputShape, checkpointRollbackHandler, checkpointRollbackInputShape, checkpointListHandler, checkpointListInputShape, } from "./tools/checkpoint.js";
|
|
29
|
+
import { listCurriculumTasks, listCurriculumTasksInputShape, pullCurriculumTask, pullCurriculumTaskInputShape, applyCurriculumTask, applyCurriculumTaskInputShape, rejectCurriculumTask, rejectCurriculumTaskInputShape, } from "./tools/curriculum.js";
|
|
30
|
+
import { startCompactor } from "./trajectory/daemon.js";
|
|
31
|
+
import { startSleepLearner } from "./sleep/daemon.js";
|
|
32
|
+
import { startCurriculumDaemon } from "./curriculum/daemon.js";
|
|
33
|
+
import { startTelemetryPruner } from "./telemetry/pruner.js";
|
|
34
|
+
import { ensureSchema, startKeepAlive, writeFrozenPatternsCache } from "./supabase.js";
|
|
35
|
+
import { currentProjectId } from "./project.js";
|
|
36
|
+
import { VERSION } from "./version.js";
|
|
37
|
+
const server = new McpServer({
|
|
38
|
+
name: "smart-claude-memory-mcp",
|
|
39
|
+
version: VERSION,
|
|
40
|
+
});
|
|
41
|
+
// Startup diagnostics (stderr — never stdout, which is reserved for JSON-RPC).
|
|
42
|
+
// Missing schema is reported loudly with the exact fix command but does not
|
|
43
|
+
// block the server from starting: tools that don't touch the missing tables
|
|
44
|
+
// (e.g. check_system_health, init_project) still work.
|
|
45
|
+
try {
|
|
46
|
+
const report = await ensureSchema();
|
|
47
|
+
if (!report.ok) {
|
|
48
|
+
console.error(`[smart-claude-memory] ${report.message}`);
|
|
49
|
+
console.error(`[smart-claude-memory] Fix: ${report.fix_command}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
console.error(`[smart-claude-memory] ensureSchema failed: ${e.message}`);
|
|
54
|
+
}
|
|
55
|
+
// Keep the Supabase HTTPS pool warm so the first call after idle doesn't
|
|
56
|
+
// pay 1-2s of cold-start.
|
|
57
|
+
startKeepAlive();
|
|
58
|
+
// Start the trajectory compaction daemon (Agentic OS 2026 / AgentDiet).
|
|
59
|
+
// Idle compactor: every TRAJECTORY_COMPACTOR_INTERVAL_MS, pulls the next
|
|
60
|
+
// batch of bloated memory_chunks rows and compresses them into
|
|
61
|
+
// trajectory_summaries. .unref()'d so it never blocks process exit.
|
|
62
|
+
startCompactor();
|
|
63
|
+
// Start the sleep learning daemon (Agentic OS 2026 / Mission 3).
|
|
64
|
+
// Idle miner: every SLEEP_LEARNER_INTERVAL_MS, mines clusters from
|
|
65
|
+
// trajectory_summaries ⋈ archive_backlog and emits skill_candidates.
|
|
66
|
+
// .unref()'d so it never blocks process exit.
|
|
67
|
+
startSleepLearner();
|
|
68
|
+
// Start the curriculum daemon (Agentic OS 2026 / Mission 5 / SCM-S21-D1).
|
|
69
|
+
// Deterministic queuer: every CURRICULUM_INTERVAL_MS, scans coverage,
|
|
70
|
+
// rollback hotspots, and stale skill_candidates and enqueues
|
|
71
|
+
// curriculum_tasks rows. Contains ZERO generative AI — Boundary Invariant #1
|
|
72
|
+
// (ARCHITECTURE.md §4.7). .unref()'d so it never blocks process exit.
|
|
73
|
+
startCurriculumDaemon();
|
|
74
|
+
// Start the telemetry retention pruner (Backlog #124 / ARCHITECTURE.md §4.8).
|
|
75
|
+
// Rolling DELETE: every TELEMETRY_PRUNER_INTERVAL_MS, prunes daemon_telemetry
|
|
76
|
+
// rows older than TELEMETRY_PRUNER_RETENTION_DAYS. .unref()'d so it never
|
|
77
|
+
// blocks process exit.
|
|
78
|
+
startTelemetryPruner();
|
|
79
|
+
// Export the current frozen_features snapshot to the shared cache file so
|
|
80
|
+
// hooks/md-policy.py can read it without hitting Supabase per tool call.
|
|
81
|
+
try {
|
|
82
|
+
const c = await writeFrozenPatternsCache();
|
|
83
|
+
if (!c.ok && c.warning)
|
|
84
|
+
console.error(`[smart-claude-memory] ${c.warning}`);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.error(`[smart-claude-memory] frozen-pattern cache init failed: ${e.message}`);
|
|
88
|
+
}
|
|
89
|
+
// Read-only legacy-backup summary — runs asynchronously so it never blocks
|
|
90
|
+
// startup. Logs count + examples on stderr; actual moves require the
|
|
91
|
+
// sweep_legacy_backups tool with confirm:true.
|
|
92
|
+
void (async () => {
|
|
93
|
+
try {
|
|
94
|
+
const summary = await legacyBackupSummary(process.cwd());
|
|
95
|
+
if (summary.total > 0) {
|
|
96
|
+
console.error(`[smart-claude-memory] Legacy backup scan: ${summary.total} candidate(s) — ` +
|
|
97
|
+
`${summary.high} high-confidence, ${summary.medium} medium. ` +
|
|
98
|
+
`Run sweep_legacy_backups to preview; pass confirm:true to move.`);
|
|
99
|
+
for (const ex of summary.top_examples)
|
|
100
|
+
console.error(` ${ex}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
console.error(`[smart-claude-memory] legacy backup scan failed: ${e.message}`);
|
|
105
|
+
}
|
|
106
|
+
})();
|
|
107
|
+
// High-precision vision default — OCR-first, zero-guessing, explicit symbol inventory.
|
|
108
|
+
// Callers can override per-call via the caption_prompt arg.
|
|
109
|
+
const DEFAULT_VISION_PROMPT = [
|
|
110
|
+
"Analyze this image under STRICT rules:",
|
|
111
|
+
"",
|
|
112
|
+
"1. OCR — Transcribe ALL text verbatim. Prioritize Arabic calligraphy, Arabic handwriting, and English labels. Quote each transcription in double quotes and preserve the original script (do not translate).",
|
|
113
|
+
"2. Zero-Guessing — If a symbol, glyph, or object is ambiguous, describe its shape, color, and position INSTEAD of naming it. Examples: say 'bright orb with radiating rays' not 'crystal ball'; say 'eight-pointed star' not 'compass rose'. Never invent content. Never infer intent.",
|
|
114
|
+
"3. Symbol Inventory — List every mystical or technical symbol as an individual bullet (moon, star, zodiac sign, eye, triangle, hand, etc.). Mark uncertain items as 'unknown: <shape/color description>'.",
|
|
115
|
+
"",
|
|
116
|
+
"Return exactly this structure (Markdown):",
|
|
117
|
+
"",
|
|
118
|
+
"TEXT (OCR):",
|
|
119
|
+
"- \"<verbatim transcription>\" (script: arabic|english|mixed|other)",
|
|
120
|
+
"",
|
|
121
|
+
"SYMBOLS:",
|
|
122
|
+
"- <symbol name or 'unknown: <shape>'>: <location> / <color>",
|
|
123
|
+
"",
|
|
124
|
+
"SCENE:",
|
|
125
|
+
"- <≤ 2 sentences, factual only>",
|
|
126
|
+
].join("\n");
|
|
127
|
+
const projectIdSchema = z
|
|
128
|
+
.string()
|
|
129
|
+
.optional()
|
|
130
|
+
.describe(`Project namespace override. Defaults to the slugified current working directory ('${currentProjectId}'). ` +
|
|
131
|
+
`Memory is strictly isolated per project_id.`);
|
|
132
|
+
// ─── existing tools ───────────────────────────────────────────────────────
|
|
133
|
+
server.tool("sync_local_memory", "Scan MEMORY_ROOTS for .md files, hash-gate, chunk, embed via Ollama, bulk-upsert to Supabase (100/batch). Supports incremental sync, force re-embed, and auto_purge with a mandatory dry-run preview and all-or-nothing verify-before-delete. Protected: CLAUDE.md, MEMORY.md, README.md, LICENSE*, CHANGELOG*.", {
|
|
134
|
+
roots: z.array(z.string()).optional(),
|
|
135
|
+
project_id: projectIdSchema,
|
|
136
|
+
force: z.boolean().optional(),
|
|
137
|
+
auto_purge: z.boolean().optional(),
|
|
138
|
+
confirm: z.boolean().optional(),
|
|
139
|
+
}, async (args) => ({ content: [{ type: "text", text: JSON.stringify(await syncLocalMemory(args), null, 2) }] }));
|
|
140
|
+
server.tool("search_memory", "Dual-scope semantic search over the current project's chunks AND the reserved 'GLOBAL' Knowledge Vault. Intent routing: 'archive'/'completed tasks'/'done tasks' → archive_backlog rows (mode:'archive'); 'Active Backlog'/'pending tasks'/'what's next' → active cloud_backlog rows (mode:'backlog'); everything else → vector search over memory_chunks (mode:'semantic'). Default behavior dual-scopes the search across the current project_id and the reserved 'GLOBAL' scope; pass `include_global: false` to restrict to the current project only. Archived tasks are NEVER mixed into semantic results unless 'archive' is in the query. Optional metadata_filter (JSONB containment, e.g. {\"type\":\"DECISION\"}) is applied via the GIN(jsonb_path_ops) index BEFORE vector ranking; project_id (plus the opt-in 'GLOBAL' fan-out) remains the structural tenancy guard.", {
|
|
141
|
+
query: z.string(),
|
|
142
|
+
limit: z.number().int().positive().max(20).optional(),
|
|
143
|
+
min_similarity: z.number().min(0).max(1).optional(),
|
|
144
|
+
project_id: projectIdSchema,
|
|
145
|
+
metadata_filter: metadataFilterSchema,
|
|
146
|
+
include_global: z
|
|
147
|
+
.boolean()
|
|
148
|
+
.optional()
|
|
149
|
+
.describe("Default true. When true, the search dual-scopes across the current project_id AND the reserved 'GLOBAL' bucket (universal patterns / lessons-learned visible to every project). Pass false to restrict to project_id only."),
|
|
150
|
+
}, async (args) => ({ content: [{ type: "text", text: JSON.stringify(await searchMemory(args), null, 2) }] }));
|
|
151
|
+
server.tool("list_global_patterns", "Browse-only enumeration of the reserved 'GLOBAL' Knowledge Vault — universal patterns / decisions / errors / logs visible to every project. Deterministic SQL read (no embedding cost). Filter via metadata_filter (same JSONB-containment shape as search_memory). Pagination: offset + limit (default 10, max 50), sorted by created_at DESC. Tiered output: default returns a content_preview (≤120 chars); pass include_content:true for the full content field. Distinct from search_memory({ include_global: true }) — that's 'find by meaning' (semantic), this is 'enumerate by attribute' (deterministic).", listGlobalPatternsInputShape, async (args) => ({
|
|
152
|
+
content: [
|
|
153
|
+
{
|
|
154
|
+
type: "text",
|
|
155
|
+
text: JSON.stringify(await listGlobalPatterns(args), null, 2),
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
}));
|
|
159
|
+
server.tool("save_memory", "Persist a single typed memory into the current project's namespace. Categorize the memory via metadata.type: DECISION (architectural choices + rationale), PATTERN (code standards / Rule 5–8 enforcement), ERROR (bug post-mortems + fixes), LOG (general session progress). Always provide metadata.type unless the memory is genuinely uncategorizable. Optional metadata.status / metadata.context_id and any additional pass-through keys are stored verbatim and become filterable via search_memory's metadata_filter (GIN-indexed JSONB containment). Set metadata.is_global=true ONLY for universal Arch-Patterns that apply to ALL projects (e.g., universal architectural decisions, multi-project bug fixes); NEVER for project-specific logic. When is_global=true, you MUST also set metadata.global_rationale (one- or two-sentence justification of the universal truth) — this is the Sovereign Vetting gate. Apply the Cross-Project Test: if the current project were deleted tomorrow, would this memory still be a gold-standard reference for others? If no, keep it local. Global rows are stored under project_id='GLOBAL' (override regardless of explicit project_id arg) and surface in dual-scope search across all projects. The is_global flag and global_rationale are preserved inside the persisted metadata jsonb for audit/traceability.", {
|
|
160
|
+
content: z.string().min(1),
|
|
161
|
+
project_id: projectIdSchema,
|
|
162
|
+
file_origin: z
|
|
163
|
+
.string()
|
|
164
|
+
.optional()
|
|
165
|
+
.describe("Source key for upsert dedup. Defaults to 'inline:<sha256(content).slice(0,12)>' so callers can omit it for one-off saves."),
|
|
166
|
+
chunk_index: z.number().int().nonnegative().optional(),
|
|
167
|
+
metadata: z
|
|
168
|
+
.object({
|
|
169
|
+
type: z.enum(["DECISION", "PATTERN", "ERROR", "LOG"]).optional(),
|
|
170
|
+
status: z.string().optional(),
|
|
171
|
+
context_id: z.string().optional(),
|
|
172
|
+
is_global: z
|
|
173
|
+
.boolean()
|
|
174
|
+
.optional()
|
|
175
|
+
.describe("If true, the memory is saved to the GLOBAL vault. STRICT RULE: Only use this for Arch-Patterns that apply to ALL projects (e.g., universal architectural decisions, multi-project bug fixes). NEVER use for project-specific logic. When true, you MUST include a 'global_rationale' field in the metadata explaining why this is a universal truth. Cross-Project Test: if the current project were deleted tomorrow, would this memory still be a gold-standard reference for others? If no, keep it local."),
|
|
176
|
+
global_rationale: z
|
|
177
|
+
.string()
|
|
178
|
+
.optional()
|
|
179
|
+
.describe("REQUIRED when is_global=true. One- or two-sentence justification of why this memory is a universal truth — not project-specific. Persisted in metadata jsonb for audit."),
|
|
180
|
+
})
|
|
181
|
+
.catchall(z.unknown())
|
|
182
|
+
.optional()
|
|
183
|
+
.describe("Sovereign Taxonomy: type ∈ {DECISION, PATTERN, ERROR, LOG}. Set is_global:true ONLY for universal Arch-Patterns that apply to ALL projects, and you MUST also supply metadata.global_rationale explaining the universal truth (Sovereign Vetting). Pass-through keys are preserved."),
|
|
184
|
+
}, async (args) => ({ content: [{ type: "text", text: JSON.stringify(await saveMemory(args), null, 2) }] }));
|
|
185
|
+
server.tool("upgrade_constitution", "Deterministically upgrade the workspace CLAUDE.md to the canonical Sovereign Memory Protocol template via regex-anchored block replacement. Pre/post project-specific content is preserved byte-for-byte. dry_run:true returns the analysis without writing. force:true overwrites even when the existing block has local customizations (block hash differs from the registered canonical hash). Returns a discriminated union with `action`: already_synced | synced | drift_detected | block_not_found | not_found | error.", {
|
|
186
|
+
workspace: z
|
|
187
|
+
.string()
|
|
188
|
+
.optional()
|
|
189
|
+
.describe("Absolute path to the workspace whose CLAUDE.md should be upgraded. Defaults to process.cwd()."),
|
|
190
|
+
dry_run: z
|
|
191
|
+
.boolean()
|
|
192
|
+
.optional()
|
|
193
|
+
.describe("When true, return what the upgrade would do without modifying any files."),
|
|
194
|
+
force: z
|
|
195
|
+
.boolean()
|
|
196
|
+
.optional()
|
|
197
|
+
.describe("When true, overwrite the constitution block even if its hash does not match a registered canonical hash. Use only when you have reviewed the local customizations and intend to discard them."),
|
|
198
|
+
}, async (args) => {
|
|
199
|
+
const ws = args.workspace ?? process.cwd();
|
|
200
|
+
const result = await upgradeConstitutionBlock(ws, {
|
|
201
|
+
dry_run: args.dry_run,
|
|
202
|
+
force: args.force,
|
|
203
|
+
});
|
|
204
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
205
|
+
});
|
|
206
|
+
// ─── Agentic OS 2026 — JIT Skill Retrieval (SCM-S17-D1) ────────────────────
|
|
207
|
+
server.tool("package_skill", "Persist an executable Skill — an ordered list of steps the agent can follow when a matching task arrives — into the dedicated agent_skills relation (NOT memory_chunks; skills are executable artefacts, not retrieval notes). Identity key is (project_id, name); re-packaging the same name bumps the version while preserving telemetry (frequency_used, success_rate, last_invoked_at). The description is embedded for semantic retrieval by request_skill; the steps array is stored verbatim and returned as-is at request time. Set is_global=true ONLY for procedures that apply to ALL projects (e.g., 'create a git commit', 'open a PR'); the row routes to project_id='GLOBAL' regardless of any explicit project_id. Cross-Project Test: if the current project were deleted tomorrow, would this skill still be a gold-standard reference for others? If no, keep it local. Skills are NEVER preloaded into the LLM context — they are injected on demand by request_skill.", packageSkillInputShape, async (args) => ({
|
|
208
|
+
content: [{ type: "text", text: JSON.stringify(await packageSkill(args), null, 2) }],
|
|
209
|
+
}));
|
|
210
|
+
server.tool("request_skill", "Just-In-Time Skill Retrieval. Semantic search over the agent_skills relation, dual-scoped across the current project_id AND the reserved 'GLOBAL' skill vault by default. Returns up to k skills ranked by a weighted blend of cosine similarity (0.85) and recency decay (0.15) over last_invoked_at — a stale-but-relevant skill still beats a recent-but-irrelevant one. Returning the full `steps` payload is INTENTIONAL: this is the JIT injection. Skills are NEVER preloaded into the system prompt; the agent calls request_skill exactly when it needs the procedure for the current task, gets the executable steps verbatim, and follows them. Pass include_global=false to restrict to the current project. record_telemetry=true (default) fire-and-forget bumps frequency_used / last_invoked_at / success_rate for every hit so the ranking surface adapts to actual usage; pass false for read-only probes.", requestSkillInputShape, async (args) => ({
|
|
211
|
+
content: [{ type: "text", text: JSON.stringify(await requestSkill(args), null, 2) }],
|
|
212
|
+
}));
|
|
213
|
+
// ─── Agentic OS 2026 — Trajectory Compaction (SCM-S18-D1) ──────────────────
|
|
214
|
+
server.tool("compact_trajectory", "Compact a bloated memory_chunks row into a ~50-token semantic summary via the heuristic+LLM pipeline. With chunk_id: targets one row. Without chunk_id: runs one daemon tick over the next batch. dry_run skips persistence.", compactTrajectoryInputShape, async (args) => ({
|
|
215
|
+
content: [
|
|
216
|
+
{ type: "text", text: JSON.stringify(await compactTrajectoryHandler(args), null, 2) },
|
|
217
|
+
],
|
|
218
|
+
}));
|
|
219
|
+
server.tool("get_trajectory_summary", "Read back the compressed summary for a given memory_chunks row id, with original/compressed token counts and compression ratio. Returns {found:false} if no summary exists.", getTrajectorySummaryInputShape, async (args) => ({
|
|
220
|
+
content: [
|
|
221
|
+
{ type: "text", text: JSON.stringify(await getTrajectorySummaryHandler(args), null, 2) },
|
|
222
|
+
],
|
|
223
|
+
}));
|
|
224
|
+
// ─── Agentic OS 2026 — Sleep Learning (SCM-S19-D1) ─────────────────────────
|
|
225
|
+
server.tool("list_skill_candidates", "Review queue for the Sleep Learning miner. SELECT from skill_candidates filtered by project_id and optional lifecycle state ('mined' = pending review, 'promoted' = already minted into agent_skills, 'rejected' = vetoed). Ordered by frequency DESC so the highest-signal patterns surface first. Pass state='mined' to inspect what the idle daemon proposed; pass no state to audit the full history.", listSkillCandidatesInputShape, async (args) => ({
|
|
226
|
+
content: [{ type: "text", text: JSON.stringify(await listSkillCandidates(args), null, 2) }],
|
|
227
|
+
}));
|
|
228
|
+
server.tool("compose_skill_candidate", "SINGLE BRAIN entry point. SCM-S22-D1 (M3 Proposer Remediation): the sleep daemon now stubs candidates with NULL proposed_name / proposed_steps / model — generative naming and step extraction are exclusively Orchestrator (Claude) work. UPDATEs skill_candidates SET proposed_name, proposed_steps WHERE id=? AND state='mined' (promoted/rejected rows are immutable). model is stamped 'orchestrator:claude' for audit. MUST be called before promote_skill_candidate — promote_candidate_to_skill RPC enforces NOT-NULL and will raise otherwise. ⚠ M5 CRASH-CATCH: when a curriculum_tasks row has linked_candidate_id set, the Orchestrator MUST call compose_skill_candidate BEFORE apply_curriculum_task — the atomic apply RPC fires promote_candidate_to_skill in the same transaction, so a null name/steps aborts the whole flow.", composeSkillCandidateInputShape, async (args) => ({
|
|
229
|
+
content: [{ type: "text", text: JSON.stringify(await composeSkillCandidate(args), null, 2) }],
|
|
230
|
+
}));
|
|
231
|
+
server.tool("promote_skill_candidate", "Mint a composed skill_candidate into agent_skills via the promote_candidate_to_skill RPC. Identity (project_id, proposed_name) reuses package_skill's upsert path: re-promoting the same name bumps the version while preserving telemetry. Description defaults to proposed_name + a digest of proposed_steps; pass description to override. trigger_keywords mirrors package_skill for the M1 detector. PRECONDITION: candidate must have non-null proposed_name AND proposed_steps — call compose_skill_candidate first (the daemon stubs with NULLs under the Single Brain mandate).", promoteSkillCandidateInputShape, async (args) => ({
|
|
232
|
+
content: [{ type: "text", text: JSON.stringify(await promoteSkillCandidate(args), null, 2) }],
|
|
233
|
+
}));
|
|
234
|
+
server.tool("reject_skill_candidate", "Veto a mined skill_candidate. Sets state='rejected' and persists rejection_reason for audit. The (project_id, pattern_hash) pair stays rejected across future mining runs — re-mining the same cluster will not resurrect it.", rejectSkillCandidateInputShape, async (args) => ({
|
|
235
|
+
content: [{ type: "text", text: JSON.stringify(await rejectSkillCandidate(args), null, 2) }],
|
|
236
|
+
}));
|
|
237
|
+
// ─── Agentic OS 2026 — Transactional Workflow Checkpoints (M4 / Phase B) ───
|
|
238
|
+
server.tool("checkpoint_create", "Open a workflow_checkpoints row (status='open') anchoring one step of a (possibly skill-mediated) multi-step task. parent_id null = root step; pass parent_id to chain steps into an ordered tree whose terminal-committed source_chunk_id is the replay anchor. When parent_id is null AND backlog_task_id is supplied, the new checkpoint's id is stamped into cloud_backlog.metadata.checkpoint_root_id so archive_done_backlog can populate archive_backlog.chunk_id at archive time — completing the M2→M3 provenance link.", checkpointCreateInputShape, async (args) => ({
|
|
239
|
+
content: [
|
|
240
|
+
{ type: "text", text: JSON.stringify(await checkpointCreateHandler(args), null, 2) },
|
|
241
|
+
],
|
|
242
|
+
}));
|
|
243
|
+
server.tool("checkpoint_commit", "Mark a checkpoint committed and pin source_chunk_id (the memory_chunks row whose trajectory_summaries entry is the replay anchor). Only rows currently in status='open' transition — re-committing is a no-op error so concurrent paths fail fast. The pinned chunk powers restoreFrom() / get_trajectory_summary replay surfaces and feeds archive_backlog.chunk_id at archive time.", checkpointCommitInputShape, async (args) => ({
|
|
244
|
+
content: [
|
|
245
|
+
{ type: "text", text: JSON.stringify(await checkpointCommitHandler(args), null, 2) },
|
|
246
|
+
],
|
|
247
|
+
}));
|
|
248
|
+
server.tool("checkpoint_rollback", "Mark a checkpoint rolledback with a non-empty reason. Walks the parent_id chain via terminal_committed_checkpoint to surface the deepest committed ancestor's source_chunk_id (the replay anchor) so the caller can drive restoreFrom() at the application layer. Rolledback rows are read directly by the M3 Sleep Learner miner as negative signals — no separate signals table is needed.", checkpointRollbackInputShape, async (args) => ({
|
|
249
|
+
content: [
|
|
250
|
+
{ type: "text", text: JSON.stringify(await checkpointRollbackHandler(args), null, 2) },
|
|
251
|
+
],
|
|
252
|
+
}));
|
|
253
|
+
server.tool("checkpoint_list", "List workflow_checkpoints rows scoped to the current project_id (or an explicit override). Optional filters: status ∈ {open, committed, rolledback}, skill_id (agent_skills.id). Ordered by id DESC (newest first). Default limit 20, max 100. Use to inspect mid-flight workflows, audit rollback churn, or surface terminal-committed anchors for ad-hoc replay.", checkpointListInputShape, async (args) => ({
|
|
254
|
+
content: [
|
|
255
|
+
{ type: "text", text: JSON.stringify(await checkpointListHandler(args), null, 2) },
|
|
256
|
+
],
|
|
257
|
+
}));
|
|
258
|
+
// ─── Agentic OS 2026 — M5 Autonomous Curriculum (SCM-S21-D1) ──────────────
|
|
259
|
+
server.tool("list_curriculum_tasks", "Inspect the M5 curriculum queue. SELECT from curriculum_tasks scoped to project_id (default: current). Optional filters: status ∈ {queued, pulled, attempted, verified, rejected, expired}, kind ∈ {test_gap, refactor, rollback_repro}. Ordered by created_at DESC. Default limit 20, max 100. Read-only — never mutates the queue.", listCurriculumTasksInputShape, async (args) => ({
|
|
260
|
+
content: [{ type: "text", text: JSON.stringify(await listCurriculumTasks(args), null, 2) }],
|
|
261
|
+
}));
|
|
262
|
+
server.tool("pull_curriculum_task", "Atomic claim of the next queued curriculum task. Wraps pull_next_curriculum_task RPC (FOR UPDATE SKIP LOCKED) — multi-session safe; two orchestrators never receive the same row. Prioritizes auto-promote-eligible tasks (linked_candidate_id IS NOT NULL) FIFO. Stamps pulled_by_session_id + pulled_at and flips status='pulled'. Returns {claimed:false, task:null} when the queue is empty. ORCHESTRATOR-ONLY entry point — the daemon never calls this.", pullCurriculumTaskInputShape, async (args) => ({
|
|
263
|
+
content: [{ type: "text", text: JSON.stringify(await pullCurriculumTask(args), null, 2) }],
|
|
264
|
+
}));
|
|
265
|
+
server.tool("apply_curriculum_task", "Verification-gated finalize. On success=true: asserts (1) ~/.claude-memory/verification-pending.json is CLEAR (override with bypass_verification_gate:true for tooling); (2) checkpoint_id references a workflow_checkpoints row with status='committed' in the same project. Atomic SQL transaction flips the task to 'verified' AND — if linked_candidate_id was set by the scanner (stale-candidate signal) — fires promote_candidate_to_skill in the same transaction. This is the ONLY M5-permitted auto-promote call site. On success=false: flips status='rejected'; no checkpoint or gate validation required. ⚠ M5 CRASH-CATCH (SCM-S22-D1): if linked_candidate_id is set on the task, the Orchestrator MUST call compose_skill_candidate(candidate_id, proposed_name, proposed_steps) BEFORE invoking this tool. The sleep daemon now stubs candidates with NULL proposed_name/proposed_steps (Single Brain mandate); promote_candidate_to_skill enforces NOT-NULL inside the same SQL transaction and will abort the entire apply otherwise.", applyCurriculumTaskInputShape, async (args) => ({
|
|
266
|
+
content: [{ type: "text", text: JSON.stringify(await applyCurriculumTask(args), null, 2) }],
|
|
267
|
+
}));
|
|
268
|
+
server.tool("reject_curriculum_task", "Manual veto. Update curriculum_tasks SET status='rejected', rejection_reason=<reason>. Use when the orchestrator decides the queued stub is not worth executing (e.g. heuristic false-positive, scope changed, file deprecated). Soft-delete: the row stays for audit.", rejectCurriculumTaskInputShape, async (args) => ({
|
|
269
|
+
content: [{ type: "text", text: JSON.stringify(await rejectCurriculumTask(args), null, 2) }],
|
|
270
|
+
}));
|
|
271
|
+
// ─── v0.5.0 tools ─────────────────────────────────────────────────────────
|
|
272
|
+
server.tool("manage_backlog", "Atomic task backlog in Supabase. Natural-language triggers: 'add to backlog' / 'add task' → add; 'what's on my backlog' / 'list tasks' → list; 'mark done' / 'mark complete' → update with status:done; 'clean up done' → prune_done (archives, not deletes); 'show archive' / 'what did I finish' → archive_list; 'end session' / 'wrap up' / 'handover' → session_end (writes Progress Report to README.md, writes file-tree to project_file_architecture.md, and returns a 1-line resume prompt); 'backfill chunks' / 'backfill archive' → backfill_archive_chunks (M4 Phase B: populate archive_backlog.chunk_id for legacy rows via terminal_committed_checkpoint or a title+timestamp heuristic; dry_run=true is a pure read). Done tasks are ARCHIVED (moved to archive_backlog), never deleted.", {
|
|
273
|
+
action: z.enum([
|
|
274
|
+
"add",
|
|
275
|
+
"list",
|
|
276
|
+
"update",
|
|
277
|
+
"prune_done",
|
|
278
|
+
"archive_list",
|
|
279
|
+
"session_end",
|
|
280
|
+
"backfill_archive_chunks",
|
|
281
|
+
]),
|
|
282
|
+
title: z.string().optional(),
|
|
283
|
+
id: z.number().int().positive().optional(),
|
|
284
|
+
status: z.enum(["todo", "in_progress", "blocked", "done"]).optional(),
|
|
285
|
+
priority: z.number().int().min(1).max(5).optional(),
|
|
286
|
+
notes: z.string().optional(),
|
|
287
|
+
limit: z.number().int().positive().max(200).optional(),
|
|
288
|
+
dry_run: z.boolean().optional(),
|
|
289
|
+
project_id: projectIdSchema,
|
|
290
|
+
}, async (args) => ({
|
|
291
|
+
content: [{ type: "text", text: JSON.stringify(await manageBacklog(args), null, 2) }],
|
|
292
|
+
}));
|
|
293
|
+
server.tool("check_code_hygiene", "Report line counts against the 750-line hard limit. Files already over the limit are flagged 'grandfathered' (edits allowed with warning); the md-policy.py hook blocks brand-new writes that push a file past the limit.", {
|
|
294
|
+
paths: z.array(z.string()).min(1),
|
|
295
|
+
}, async (args) => ({
|
|
296
|
+
content: [{ type: "text", text: JSON.stringify(await checkCodeHygiene(args), null, 2) }],
|
|
297
|
+
}));
|
|
298
|
+
server.tool("confirm_verification", "Close the Hard Stop / Manual Test Gate after a manual check. Natural-language triggers the user might say and that should route to this tool: 'verified', 'test passed', 'it works', 'confirmed', 'all good', 'done testing' → call with success:true; 'broken', 'still failing', 'test failed', 'reverting' → call with success:false. On success:true the file that was under the gate is auto-added to frozen_features (Write blocked going forward, Edit still allowed). On success:false the response surfaces the most recent backup path so the AI can restore the prior state from it.", {
|
|
299
|
+
success: z.boolean(),
|
|
300
|
+
notes: z.string().optional(),
|
|
301
|
+
}, async (args) => ({
|
|
302
|
+
content: [{ type: "text", text: JSON.stringify(await confirmVerification(args), null, 2) }],
|
|
303
|
+
}));
|
|
304
|
+
server.tool("raise_verification_gate", "Arm the Hard Stop gate after a risky or exploratory edit. Natural-language triggers: 'wait for me to test', 'let me verify', 'stop before committing', 'hold up until I check'. While the gate is raised, the hook blocks every further Write/Edit/Bash until confirm_verification clears it. A backup of the edited file is already on disk thanks to the md-policy.py hook; the path is surfaced in confirm_verification's response for recovery on failure.", {
|
|
305
|
+
tool: z.string(),
|
|
306
|
+
file: z.string(),
|
|
307
|
+
reason: z.string().optional(),
|
|
308
|
+
project_id: projectIdSchema,
|
|
309
|
+
}, async (args) => {
|
|
310
|
+
await raisePendingVerification({
|
|
311
|
+
tool: args.tool,
|
|
312
|
+
file: args.file,
|
|
313
|
+
reason: args.reason,
|
|
314
|
+
project_id: args.project_id,
|
|
315
|
+
created_at: new Date().toISOString(),
|
|
316
|
+
});
|
|
317
|
+
return {
|
|
318
|
+
content: [{ type: "text", text: JSON.stringify({ raised: true, ...args }, null, 2) }],
|
|
319
|
+
};
|
|
320
|
+
});
|
|
321
|
+
server.tool("check_rule_conflicts", "Intent-based rule conflict detection. Retrieves top-K chunks for a proposed change, re-ranks with an LLM, then runs pairwise (change vs rule) conflict analysis on the top 3. Opt-in; latency is 1–3s per call.", {
|
|
322
|
+
proposed_change: z.string().min(1),
|
|
323
|
+
project_id: projectIdSchema,
|
|
324
|
+
top_k: z.number().int().positive().max(10).optional(),
|
|
325
|
+
rerank: z.boolean().optional(),
|
|
326
|
+
llm_model: z.string().optional(),
|
|
327
|
+
}, async (args) => ({
|
|
328
|
+
content: [{ type: "text", text: JSON.stringify(await checkRuleConflicts(args), null, 2) }],
|
|
329
|
+
}));
|
|
330
|
+
server.tool("summarize_memory_file", "LLM-driven compression of CLAUDE.md or MEMORY.md toward a token target (default 3000). Preserves every actionable rule; drops verbosity. Supports dry_run to preview.", {
|
|
331
|
+
file_path: z.string(),
|
|
332
|
+
target_tokens: z.number().int().positive().optional(),
|
|
333
|
+
dry_run: z.boolean().optional(),
|
|
334
|
+
llm_model: z.string().optional(),
|
|
335
|
+
}, async (args) => ({
|
|
336
|
+
content: [{ type: "text", text: JSON.stringify(await summarizeMemoryFile(args), null, 2) }],
|
|
337
|
+
}));
|
|
338
|
+
server.tool("index_image", "Caption an image with a local vision model (default: moondream) then embed the caption via nomic-embed-text and upsert into cloud memory. Non-PNG/JPEG inputs (WebP, GIF, BMP) are auto-converted to PNG via ffmpeg. Default prompt enforces OCR-first transcription, zero-guessing for ambiguous symbols, and an explicit symbol inventory.", {
|
|
339
|
+
image_path: z.string(),
|
|
340
|
+
caption_prompt: z.string().optional().default(DEFAULT_VISION_PROMPT),
|
|
341
|
+
project_id: projectIdSchema,
|
|
342
|
+
vision_model: z.string().optional(),
|
|
343
|
+
}, async (args) => ({
|
|
344
|
+
content: [{ type: "text", text: JSON.stringify(await indexImage(args), null, 2) }],
|
|
345
|
+
}));
|
|
346
|
+
server.tool("check_system_health", "System diagnostics: Supabase reachability (memory_chunks count), Ollama reachability, required-model presence (moondream + nomic-embed-text), and keep-alive status (interval, last ping latency, last ping result). Returns overall='healthy'|'degraded'|'down'.", {}, async () => ({
|
|
347
|
+
content: [{ type: "text", text: JSON.stringify(await checkSystemHealth(), null, 2) }],
|
|
348
|
+
}));
|
|
349
|
+
server.tool("system_dashboard", "Unified read API for daemon telemetry. Returns per-daemon live status (get*Status snapshot), 1h and 24h rollups (runs, errors, items_processed, outcomes={verified,rejected,auto_promoted}), 24h error_rate, last error event, and the last 20 recent run events. Backed by the append-only daemon_telemetry table (migration 016). Inputs: optional window_hours (default 24, max 168), optional daemon filter ('sleep_learner' | 'curriculum_scanner' | 'trajectory_compactor').", {
|
|
350
|
+
window_hours: z.number().int().positive().max(168).optional(),
|
|
351
|
+
daemon: z.enum(["sleep_learner", "curriculum_scanner", "trajectory_compactor"]).optional(),
|
|
352
|
+
}, async (args) => ({
|
|
353
|
+
content: [{ type: "text", text: renderDashboardMarkdown(await systemDashboardHandler(args)) }],
|
|
354
|
+
}));
|
|
355
|
+
server.tool("list_frozen", "List the frozen_features patterns for a project. Patterns here are files that the md-policy.py hook will block Writes on (Edits still allowed).", { project_id: projectIdSchema }, async (args) => ({
|
|
356
|
+
content: [{ type: "text", text: JSON.stringify(await listFrozen(args), null, 2) }],
|
|
357
|
+
}));
|
|
358
|
+
server.tool("freeze_file", "Manually mark a file or pattern as frozen. Natural-language triggers: 'freeze this file', 'lock this file', 'protect X from rewrites', 'make this surgical-only'. Once frozen, the md-policy.py hook blocks Write calls on any path containing the pattern; Edit (surgical line-level changes) remains allowed. Every Edit on a frozen file also produces a timestamped backup.", {
|
|
359
|
+
pattern: z.string().min(1),
|
|
360
|
+
project_id: projectIdSchema,
|
|
361
|
+
reason: z.string().optional(),
|
|
362
|
+
}, async (args) => ({
|
|
363
|
+
content: [{ type: "text", text: JSON.stringify(await freezeFile(args), null, 2) }],
|
|
364
|
+
}));
|
|
365
|
+
server.tool("unfreeze_file", "Request to lift the frozen-file guardrail for a pattern. Natural-language triggers: 'unfreeze X', 'I give permission to refactor X', 'you can rewrite X', 'remove the lock on X'. REQUIRES an explicit 'justification' (≥ 4 chars) — this is the Request for Unfreeze dialog: the agent must present a justification to the user, and the user's acknowledgement is what unlocks the tool call. Without the string the call is refused with a warning.", {
|
|
366
|
+
pattern: z.string().min(1),
|
|
367
|
+
project_id: projectIdSchema,
|
|
368
|
+
justification: z.string().describe("Explain why the full-rewrite guardrail can be lifted. Surfaced in tool logs."),
|
|
369
|
+
}, async (args) => ({
|
|
370
|
+
content: [{ type: "text", text: JSON.stringify(await unfreezeFile(args), null, 2) }],
|
|
371
|
+
}));
|
|
372
|
+
server.tool("batch_freeze_patterns", "Hydrate frozen-patterns.json from explicit globs and/or a markdown rule-file in a single call. Natural-language triggers: 'batch freeze', 'hydrate frozen patterns', 'freeze from rules file', 'onboard policies', 'bulk freeze patterns'. Pass `paths` for inline globs/paths, `from_rule_file` to extract patterns from a markdown section (default '## Frozen Patterns'), or both. Each cache entry stores { pattern, source, added_at } — patterns are not eagerly expanded; the same dedup key (trimmed pattern string) is used as freeze_file. First writer wins. Set `dry_run:true` to preview the new patterns without touching disk.", {
|
|
373
|
+
paths: z.array(z.string().min(1)).optional().describe("Explicit globs or paths to freeze. Stored as-given (no eager expansion)."),
|
|
374
|
+
from_rule_file: z.string().optional().describe("Markdown file to extract patterns from. Reads under the `section` heading until the next markdown heading."),
|
|
375
|
+
section: z.string().optional().describe("Markdown heading that begins the pattern list. Default: '## Frozen Patterns'. Comparison is exact-string after rstrip."),
|
|
376
|
+
dry_run: z.boolean().optional().describe("Default false. When true, returns prospective patterns + counts without writing to disk or Supabase."),
|
|
377
|
+
source_tag: z.string().optional().describe("Override the `source` field stored on each new entry. Defaults to the rule-file path or 'inline' for `paths`."),
|
|
378
|
+
project_id: projectIdSchema,
|
|
379
|
+
}, async (args) => ({
|
|
380
|
+
content: [{ type: "text", text: JSON.stringify(await batchFreezePatterns(args), null, 2) }],
|
|
381
|
+
}));
|
|
382
|
+
server.tool("sweep_legacy_backups", "One-time migration/cleanup that consolidates scattered 'backup' files into the project's backups/ folder. Natural-language triggers: 'organize backups', 'consolidate backup files', 'clean up backup clutter', 'migrate legacy backups'. Dry-run by default; set confirm:true to move. Only HIGH-confidence matches are moved unless aggressive:true (MEDIUM matches like backup-service.ts may be production code — opt-in required). Recognizes: *.bak / *.backup / *.old extensions, _backup or -backup suffixes, backup- or old_backup_ prefixes, and backup_<timestamp> filenames.", {
|
|
383
|
+
workspace: z.string().optional().describe("Absolute path. Defaults to the MCP server's cwd."),
|
|
384
|
+
confirm: z.boolean().optional().describe("Required to actually move files. Default false → dry-run preview."),
|
|
385
|
+
aggressive: z.boolean().optional().describe("Also move MEDIUM-confidence matches (filenames containing 'backup' without strict pattern). Default false."),
|
|
386
|
+
dest: z.string().optional().describe("Destination directory. Defaults to <workspace>/backups/legacy-sweep-<timestamp>."),
|
|
387
|
+
}, async (args) => ({
|
|
388
|
+
content: [{ type: "text", text: JSON.stringify(await sweepLegacyBackups(args), null, 2) }],
|
|
389
|
+
}));
|
|
390
|
+
server.tool("init_project", "Readiness report for a workspace: validates required .env vars, locates the md-policy.py hook, checks if the Smart Claude Memory MCP server is registered in Claude Code settings, and confirms dist/ is built. Returns overall='ready'|'partial'|'not_ready' with per-check fix instructions. On boot, init_project may return a recommendation with id 'sovereign_purge'. When present, the Agent MUST ask the user for explicit YES/NO permission before acting. On YES, execute the steps in order: create docs/scm-memory/, move bloated CLAUDE.md to docs/scm-memory/legacy_claude.md, copy the hidden MEMORY.md to docs/scm-memory/legacy_memory.md if found, call sync_local_memory({ force: true }) to vectorize, then call ensureSovereignConstitution({ force: true }) to regenerate a clean v2.1 CLAUDE.md. Never act without user consent.", {
|
|
391
|
+
workspace: z.string().optional().describe("Absolute path. Defaults to the MCP server's cwd (typically the current Claude Code project)."),
|
|
392
|
+
}, async (args) => ({
|
|
393
|
+
content: [{ type: "text", text: JSON.stringify(await initProject(args), null, 2) }],
|
|
394
|
+
}));
|
|
395
|
+
server.tool("refactor_guard", "Multi-stack refactor safety net. Actions: plan (scan imports/exports/parts for TS/JS/Dart/Py via language-specific regex — heuristic, not a full parser); gate (run the project's compiler check — flutter analyze / tsc --noEmit / cargo check / go vet / py_compile — auto-selected from project type markers); rollback (restore a file from the hook-managed backup-index). Natural-language triggers: 'run the build check', 'does it still compile?', 'check for regressions', 'rollback that edit', 'restore from backup'. After any destructive refactor, run action:gate; if it fails, run action:rollback to restore.", {
|
|
396
|
+
action: z.enum(["plan", "gate", "rollback"]),
|
|
397
|
+
paths: z.array(z.string()).optional(),
|
|
398
|
+
workspace: z.string().optional(),
|
|
399
|
+
file: z.string().optional(),
|
|
400
|
+
}, async (args) => ({
|
|
401
|
+
content: [{ type: "text", text: JSON.stringify(await refactorGuard(args), null, 2) }],
|
|
402
|
+
}));
|
|
403
|
+
server.tool("analyze_regression", "Compare a broken file against its most recent N backups and surface the closest-matching prior snapshot. Natural-language triggers: 'what did I break?', 'diff against the last good version', 'find the regression', 'which backup should I restore?'. Returns an edit-distance summary per backup and identifies the smallest-delta candidate as 'closest_prior' — usually the right restore target.", {
|
|
404
|
+
file: z.string(),
|
|
405
|
+
backups_to_compare: z.number().int().positive().max(10).optional(),
|
|
406
|
+
}, async (args) => ({
|
|
407
|
+
content: [{ type: "text", text: JSON.stringify(await analyzeRegression(args), null, 2) }],
|
|
408
|
+
}));
|
|
409
|
+
server.tool("delegate_task", "Orchestrator pattern (v1.1.0 — Autonomous Self-Healing): emit a canonical worker sub-agent prompt for a task. Natural-language triggers: 'delegate this', 'spawn a worker', 'send to sub-agent', 'offload this task'. The returned 'prompt' field plugs into the Agent tool — every delegation carries the contract: do the work → refactor_guard({action:'gate'}) → if red, diagnose via analyze_regression against backups and fix locally (up to max_healing_attempts), re-gate → rollback only if healing exhausts → return a 2-paragraph synthesis with strict no-raw-content caps. Keeps the Orchestrator's context clean of failed-compile churn.", {
|
|
410
|
+
title: z.string().min(1),
|
|
411
|
+
instructions: z.string().min(1),
|
|
412
|
+
target_files: z.array(z.string()).optional(),
|
|
413
|
+
workspace: z.string().optional(),
|
|
414
|
+
run_gate: z.boolean().optional(),
|
|
415
|
+
allow_rollback: z.boolean().optional(),
|
|
416
|
+
self_heal: z.boolean().optional(),
|
|
417
|
+
max_healing_attempts: z.number().int().positive().max(5).optional(),
|
|
418
|
+
synthesis_word_limit: z.number().int().positive().max(1000).optional(),
|
|
419
|
+
}, async (args) => ({
|
|
420
|
+
content: [{ type: "text", text: JSON.stringify(await delegateTask(args), null, 2) }],
|
|
421
|
+
}));
|
|
422
|
+
server.tool("sync_artefacts", "Refresh the project's README 'Recent Progress' + '🗺️ File Architecture' sections AND project_file_architecture.md — without the archive / resume-prompt side effects of session_end. Natural-language triggers: 'sync docs', 'refresh architecture', 'update the readme tree', 'after-worker sync'. Orchestrator calls this after a worker sub-agent reports success so the Mermaid diagram stays the source of truth for planning. Use manage_backlog({action:'session_end'}) instead at the actual end of a working session.", {
|
|
423
|
+
project_id: projectIdSchema,
|
|
424
|
+
}, async (args) => ({
|
|
425
|
+
content: [{ type: "text", text: JSON.stringify(await syncArtefacts(args), null, 2) }],
|
|
426
|
+
}));
|
|
427
|
+
const transport = new StdioServerTransport();
|
|
428
|
+
await server.connect(transport);
|
|
429
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/lib/migrations.ts — schema_migrations ledger helpers (Task 2, Marketplace
|
|
2
|
+
// Packaging epic). Shared module imported by:
|
|
3
|
+
// - scripts/apply-schema.ts (CLI: `npm run schema`)
|
|
4
|
+
// - src/tools/init_project.ts (Task 3 — auto-applies pending migrations on
|
|
5
|
+
// first MCP call so BYO-Supabase users don't have to run the CLI manually)
|
|
6
|
+
//
|
|
7
|
+
// Contract (per spec §4.2):
|
|
8
|
+
// schema_migrations(filename text PRIMARY KEY, sha256 text NOT NULL,
|
|
9
|
+
// applied_at timestamptz NOT NULL DEFAULT now())
|
|
10
|
+
//
|
|
11
|
+
// apply algorithm:
|
|
12
|
+
// 1. ensureLedger() — CREATE TABLE IF NOT EXISTS
|
|
13
|
+
// 2. listPendingMigrations() — diff fs vs ledger
|
|
14
|
+
// 3. for each pending: BEGIN → exec body → INSERT ledger → COMMIT
|
|
15
|
+
// (ROLLBACK + throw on any error; abort the rest of the batch)
|
|
16
|
+
//
|
|
17
|
+
// Idempotency: re-running applyPendingMigrations against a fully-applied DB
|
|
18
|
+
// returns { applied: 0, skipped: N, total: N }.
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
21
|
+
import { dirname, resolve } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname = dirname(__filename);
|
|
25
|
+
/**
|
|
26
|
+
* Absolute path to the directory containing the SQL migration files.
|
|
27
|
+
* Resolves to `<repo>/scripts` from both `src/lib/migrations.ts` (dev,
|
|
28
|
+
* via tsx) and `dist/lib/migrations.js` (built). Both layouts sit two
|
|
29
|
+
* levels deep under the repo root.
|
|
30
|
+
*/
|
|
31
|
+
export const MIGRATIONS_DIR = resolve(__dirname, "..", "..", "scripts");
|
|
32
|
+
/** Regex anchoring a real, numbered migration: 001_schema.sql, 017_foo.sql, etc. */
|
|
33
|
+
const MIGRATION_RE = /^0\d{2}_.+\.sql$/;
|
|
34
|
+
/**
|
|
35
|
+
* Scan MIGRATIONS_DIR for files matching /^0\d{2}_.+\.sql$/, lex-sorted.
|
|
36
|
+
* Reads each file body and computes its sha256 (hex). Pure FS — no DB.
|
|
37
|
+
*
|
|
38
|
+
* Companion test fixtures (smoke/verify scripts) live under
|
|
39
|
+
* `tests/sql_fixtures/`, not in scripts/, so this loader sees only real
|
|
40
|
+
* numbered migrations without an explicit denylist.
|
|
41
|
+
*/
|
|
42
|
+
export function loadMigrationFiles() {
|
|
43
|
+
const files = readdirSync(MIGRATIONS_DIR)
|
|
44
|
+
.filter((name) => MIGRATION_RE.test(name))
|
|
45
|
+
.sort();
|
|
46
|
+
return files.map((filename) => {
|
|
47
|
+
const body = readFileSync(resolve(MIGRATIONS_DIR, filename), "utf8");
|
|
48
|
+
const sha256 = createHash("sha256").update(body).digest("hex");
|
|
49
|
+
return { filename, sha256, body };
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Ensure the schema_migrations ledger table exists. Idempotent —
|
|
54
|
+
* uses CREATE TABLE IF NOT EXISTS so repeated calls are no-ops.
|
|
55
|
+
*
|
|
56
|
+
* Note: this respects the caller's current `search_path`. Tests pin
|
|
57
|
+
* search_path to a temporary schema; production callers leave it at
|
|
58
|
+
* the default (`public`), which is where the ledger lives.
|
|
59
|
+
*/
|
|
60
|
+
export async function ensureLedger(client) {
|
|
61
|
+
await client.query(`
|
|
62
|
+
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
63
|
+
filename text PRIMARY KEY,
|
|
64
|
+
sha256 text NOT NULL,
|
|
65
|
+
applied_at timestamptz NOT NULL DEFAULT now()
|
|
66
|
+
)
|
|
67
|
+
`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Return the subset of MigrationFiles whose filename is NOT yet in the
|
|
71
|
+
* schema_migrations ledger. Ordering matches loadMigrationFiles().
|
|
72
|
+
*
|
|
73
|
+
* Calls ensureLedger() first so an empty/fresh DB returns the full list
|
|
74
|
+
* rather than throwing on a missing table.
|
|
75
|
+
*/
|
|
76
|
+
export async function listPendingMigrations(client) {
|
|
77
|
+
await ensureLedger(client);
|
|
78
|
+
const { rows } = await client.query("SELECT filename FROM schema_migrations");
|
|
79
|
+
const applied = new Set(rows.map((r) => r.filename));
|
|
80
|
+
return loadMigrationFiles().filter((f) => !applied.has(f.filename));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Apply every pending migration, one transaction per file. On any error:
|
|
84
|
+
* ROLLBACK that file and throw — subsequent files are NOT attempted, so
|
|
85
|
+
* the ledger always reflects DB reality.
|
|
86
|
+
*
|
|
87
|
+
* Re-runnable: when nothing is pending, returns `{ applied: 0, skipped:
|
|
88
|
+
* N, total: N }` and does no DB writes beyond the idempotent ensureLedger.
|
|
89
|
+
*/
|
|
90
|
+
export async function applyPendingMigrations(client) {
|
|
91
|
+
await ensureLedger(client);
|
|
92
|
+
const all = loadMigrationFiles();
|
|
93
|
+
const { rows } = await client.query("SELECT filename FROM schema_migrations");
|
|
94
|
+
const alreadyApplied = new Set(rows.map((r) => r.filename));
|
|
95
|
+
const skippedFiles = all
|
|
96
|
+
.filter((f) => alreadyApplied.has(f.filename))
|
|
97
|
+
.map((f) => f.filename);
|
|
98
|
+
const pending = all.filter((f) => !alreadyApplied.has(f.filename));
|
|
99
|
+
const appliedFiles = [];
|
|
100
|
+
for (const file of pending) {
|
|
101
|
+
try {
|
|
102
|
+
await client.query("BEGIN");
|
|
103
|
+
await client.query(file.body);
|
|
104
|
+
await client.query("INSERT INTO schema_migrations (filename, sha256) VALUES ($1, $2)", [file.filename, file.sha256]);
|
|
105
|
+
await client.query("COMMIT");
|
|
106
|
+
appliedFiles.push(file.filename);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
try {
|
|
110
|
+
await client.query("ROLLBACK");
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// ROLLBACK can fail if the connection itself died; surface the
|
|
114
|
+
// ORIGINAL error rather than masking it with the rollback fault.
|
|
115
|
+
}
|
|
116
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
117
|
+
throw new Error(`Migration ${file.filename} failed: ${msg}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
applied: appliedFiles.length,
|
|
122
|
+
skipped: skippedFiles.length,
|
|
123
|
+
total: all.length,
|
|
124
|
+
appliedFiles,
|
|
125
|
+
skippedFiles,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=migrations.js.map
|