@rigour-labs/mcp 2.22.0 → 3.0.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/README.md +11 -1
- package/dist/index.js +73 -1236
- package/dist/tools/agent-handlers.d.ts +14 -0
- package/dist/tools/agent-handlers.js +176 -0
- package/dist/tools/definitions.d.ts +293 -0
- package/dist/tools/definitions.js +249 -0
- package/dist/tools/execution-handlers.d.ts +11 -0
- package/dist/tools/execution-handlers.js +134 -0
- package/dist/tools/memory-handlers.d.ts +10 -0
- package/dist/tools/memory-handlers.js +52 -0
- package/dist/tools/pattern-handlers.d.ts +9 -0
- package/dist/tools/pattern-handlers.js +72 -0
- package/dist/tools/quality-handlers.d.ts +25 -0
- package/dist/tools/quality-handlers.js +116 -0
- package/dist/tools/review-handler.d.ts +16 -0
- package/dist/tools/review-handler.js +42 -0
- package/dist/utils/config.d.ts +153 -0
- package/dist/utils/config.js +93 -0
- package/package.json +21 -3
- package/.claude-plugin/SKILL.md +0 -51
- package/.claude-plugin/marketplace.json +0 -21
- package/.claude-plugin/plugin.json +0 -17
- package/server.json +0 -21
- package/src/index.test.ts +0 -333
- package/src/index.ts +0 -1432
- package/src/smoke.test.ts +0 -7
- package/src/supervisor.test.ts +0 -158
- package/tsconfig.json +0 -10
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Definitions
|
|
3
|
+
*
|
|
4
|
+
* Schema definitions for all Rigour MCP tools.
|
|
5
|
+
* Each tool has a name, description, and JSON Schema for its input.
|
|
6
|
+
*
|
|
7
|
+
* @since v2.17.0 — extracted from monolithic index.ts
|
|
8
|
+
*/
|
|
9
|
+
function cwdParam() {
|
|
10
|
+
return {
|
|
11
|
+
cwd: {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "Absolute path to the project root.",
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export const TOOL_DEFINITIONS = [
|
|
18
|
+
// ─── Core Quality Gates ───────────────────────────────
|
|
19
|
+
{
|
|
20
|
+
name: "rigour_check",
|
|
21
|
+
description: "Run quality gate checks on the project. Matches the CLI 'check' command.",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: cwdParam(),
|
|
25
|
+
required: ["cwd"],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "rigour_explain",
|
|
30
|
+
description: "Explain the last quality gate failures with actionable bullets. Matches the CLI 'explain' command.",
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: cwdParam(),
|
|
34
|
+
required: ["cwd"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "rigour_status",
|
|
39
|
+
description: "Quick PASS/FAIL check with JSON-friendly output for polling current project state.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: cwdParam(),
|
|
43
|
+
required: ["cwd"],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "rigour_get_fix_packet",
|
|
48
|
+
description: "Retrieves a prioritized 'Fix Packet' (v2 schema) containing detailed machine-readable diagnostic data.",
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: cwdParam(),
|
|
52
|
+
required: ["cwd"],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "rigour_list_gates",
|
|
57
|
+
description: "Lists all configured quality gates and their thresholds for the current project.",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: cwdParam(),
|
|
61
|
+
required: ["cwd"],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "rigour_get_config",
|
|
66
|
+
description: "Returns the current Rigour configuration (rigour.yml) for agent reasoning.",
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: "object",
|
|
69
|
+
properties: cwdParam(),
|
|
70
|
+
required: ["cwd"],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
// ─── Memory Persistence ───────────────────────────────
|
|
74
|
+
{
|
|
75
|
+
name: "rigour_remember",
|
|
76
|
+
description: "Store a persistent instruction or context that the AI should remember across sessions. Use this to persist user preferences, project conventions, or critical instructions.",
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: {
|
|
80
|
+
...cwdParam(),
|
|
81
|
+
key: { type: "string", description: "A unique key for this memory (e.g., 'user_preferences', 'coding_style')." },
|
|
82
|
+
value: { type: "string", description: "The instruction or context to remember." },
|
|
83
|
+
},
|
|
84
|
+
required: ["cwd", "key", "value"],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "rigour_recall",
|
|
89
|
+
description: "Retrieve stored instructions or context. Call this at the start of each session to restore memory. Returns all stored memories if no key specified.",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: "object",
|
|
92
|
+
properties: {
|
|
93
|
+
...cwdParam(),
|
|
94
|
+
key: { type: "string", description: "Optional. Key of specific memory to retrieve." },
|
|
95
|
+
},
|
|
96
|
+
required: ["cwd"],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "rigour_forget",
|
|
101
|
+
description: "Remove a stored memory by key.",
|
|
102
|
+
inputSchema: {
|
|
103
|
+
type: "object",
|
|
104
|
+
properties: {
|
|
105
|
+
...cwdParam(),
|
|
106
|
+
key: { type: "string", description: "Key of the memory to remove." },
|
|
107
|
+
},
|
|
108
|
+
required: ["cwd", "key"],
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
// ─── Pattern Intelligence ─────────────────────────────
|
|
112
|
+
{
|
|
113
|
+
name: "rigour_check_pattern",
|
|
114
|
+
description: "Checks if a proposed code pattern (function, component, etc.) already exists, is stale, or has security vulnerabilities (CVEs). CALL THIS BEFORE CREATING NEW CODE.",
|
|
115
|
+
inputSchema: {
|
|
116
|
+
type: "object",
|
|
117
|
+
properties: {
|
|
118
|
+
...cwdParam(),
|
|
119
|
+
name: { type: "string", description: "The name of the function, class, or component you want to create." },
|
|
120
|
+
type: { type: "string", description: "The type of pattern (e.g., 'function', 'component', 'hook', 'type')." },
|
|
121
|
+
intent: { type: "string", description: "What the code is for (e.g., 'format dates', 'user authentication')." },
|
|
122
|
+
},
|
|
123
|
+
required: ["cwd", "name"],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "rigour_security_audit",
|
|
128
|
+
description: "Runs a live security audit (CVE check) on the project dependencies.",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: "object",
|
|
131
|
+
properties: cwdParam(),
|
|
132
|
+
required: ["cwd"],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
// ─── Execution & Supervision ──────────────────────────
|
|
136
|
+
{
|
|
137
|
+
name: "rigour_run",
|
|
138
|
+
description: "Execute a command under Rigour supervision. This tool can be INTERCEPTED and ARBITRATED by the Governance Studio.",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {
|
|
142
|
+
...cwdParam(),
|
|
143
|
+
command: { type: "string", description: "The command to run (e.g., 'npm test', 'pytest')." },
|
|
144
|
+
silent: { type: "boolean", description: "If true, hides the command output from the agent." },
|
|
145
|
+
},
|
|
146
|
+
required: ["cwd", "command"],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "rigour_run_supervised",
|
|
151
|
+
description: "Run a command under FULL Supervisor Mode. Iteratively executes the command, checks quality gates, and returns fix packets until PASS or max retries reached. Use this for self-healing agent loops.",
|
|
152
|
+
inputSchema: {
|
|
153
|
+
type: "object",
|
|
154
|
+
properties: {
|
|
155
|
+
...cwdParam(),
|
|
156
|
+
command: { type: "string", description: "The agent command to run (e.g., 'claude \"fix the bug\"', 'aider --message \"refactor auth\"')." },
|
|
157
|
+
maxRetries: { type: "number", description: "Maximum retry iterations (default: 3)." },
|
|
158
|
+
dryRun: { type: "boolean", description: "If true, simulates the loop without executing the command. Useful for testing gate checks." },
|
|
159
|
+
},
|
|
160
|
+
required: ["cwd", "command"],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
// ─── Multi-Agent Governance (v2.14+) ──────────────────
|
|
164
|
+
{
|
|
165
|
+
name: "rigour_agent_register",
|
|
166
|
+
description: "Register an agent in a multi-agent session. Use this at the START of agent execution to claim task scope and enable cross-agent conflict detection. Required for Agent Team Governance.",
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: {
|
|
170
|
+
...cwdParam(),
|
|
171
|
+
agentId: { type: "string", description: "Unique identifier for this agent (e.g., 'agent-a', 'opus-frontend')." },
|
|
172
|
+
taskScope: { type: "array", items: { type: "string" }, description: "Glob patterns defining the files/directories this agent will work on (e.g., ['src/api/**', 'tests/api/**'])." },
|
|
173
|
+
},
|
|
174
|
+
required: ["cwd", "agentId", "taskScope"],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "rigour_checkpoint",
|
|
179
|
+
description: "Record a quality checkpoint during long-running agent execution. Use periodically (every 15-30 min) to enable drift detection and quality monitoring. Essential for GPT-5.3 coworking mode.",
|
|
180
|
+
inputSchema: {
|
|
181
|
+
type: "object",
|
|
182
|
+
properties: {
|
|
183
|
+
...cwdParam(),
|
|
184
|
+
progressPct: { type: "number", description: "Estimated progress percentage (0-100)." },
|
|
185
|
+
filesChanged: { type: "array", items: { type: "string" }, description: "List of files modified since last checkpoint." },
|
|
186
|
+
summary: { type: "string", description: "Brief description of work done since last checkpoint." },
|
|
187
|
+
qualityScore: { type: "number", description: "Self-assessed quality score (0-100). Be honest - artificially high scores trigger drift detection." },
|
|
188
|
+
},
|
|
189
|
+
required: ["cwd", "progressPct", "summary", "qualityScore"],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: "rigour_handoff",
|
|
194
|
+
description: "Handoff task to another agent in a multi-agent workflow. Use when delegating a subtask or completing your scope. Enables verified handoff governance.",
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
...cwdParam(),
|
|
199
|
+
fromAgentId: { type: "string", description: "ID of the agent initiating the handoff." },
|
|
200
|
+
toAgentId: { type: "string", description: "ID of the agent receiving the handoff." },
|
|
201
|
+
taskDescription: { type: "string", description: "Description of the task being handed off." },
|
|
202
|
+
filesInScope: { type: "array", items: { type: "string" }, description: "Files relevant to the handoff." },
|
|
203
|
+
context: { type: "string", description: "Additional context for the receiving agent." },
|
|
204
|
+
},
|
|
205
|
+
required: ["cwd", "fromAgentId", "toAgentId", "taskDescription"],
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "rigour_agent_deregister",
|
|
210
|
+
description: "Deregister an agent from the multi-agent session. Use when an agent completes its work or needs to release its scope for another agent.",
|
|
211
|
+
inputSchema: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
...cwdParam(),
|
|
215
|
+
agentId: { type: "string", description: "ID of the agent to deregister." },
|
|
216
|
+
},
|
|
217
|
+
required: ["cwd", "agentId"],
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
name: "rigour_handoff_accept",
|
|
222
|
+
description: "Accept a pending handoff from another agent. Use to formally acknowledge receipt of a task and verify you are the intended recipient.",
|
|
223
|
+
inputSchema: {
|
|
224
|
+
type: "object",
|
|
225
|
+
properties: {
|
|
226
|
+
...cwdParam(),
|
|
227
|
+
handoffId: { type: "string", description: "ID of the handoff to accept." },
|
|
228
|
+
agentId: { type: "string", description: "ID of the accepting agent (must match toAgentId in the handoff)." },
|
|
229
|
+
},
|
|
230
|
+
required: ["cwd", "handoffId", "agentId"],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
// ─── Code Review ──────────────────────────────────────
|
|
234
|
+
{
|
|
235
|
+
name: "rigour_review",
|
|
236
|
+
description: "Perform a high-fidelity code review on a pull request diff. Analyzes changed files using all active quality gates.",
|
|
237
|
+
inputSchema: {
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: {
|
|
240
|
+
...cwdParam(),
|
|
241
|
+
repository: { type: "string", description: "Full repository name (e.g., 'owner/repo')." },
|
|
242
|
+
branch: { type: "string", description: "The branch containing the changes." },
|
|
243
|
+
diff: { type: "string", description: "The git diff content to analyze." },
|
|
244
|
+
files: { type: "array", items: { type: "string" }, description: "List of filenames that were changed." },
|
|
245
|
+
},
|
|
246
|
+
required: ["cwd", "diff"],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GateRunner } from "@rigour-labs/core";
|
|
2
|
+
type ToolResult = {
|
|
3
|
+
content: {
|
|
4
|
+
type: string;
|
|
5
|
+
text: string;
|
|
6
|
+
}[];
|
|
7
|
+
isError?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function handleRun(cwd: string, command: string, requestId: string): Promise<ToolResult>;
|
|
10
|
+
export declare function handleRunSupervised(runner: GateRunner, cwd: string, command: string, maxRetries: number, dryRun: boolean, requestId: string): Promise<ToolResult>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution & Supervision Tool Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handlers for: rigour_run, rigour_run_supervised
|
|
5
|
+
*
|
|
6
|
+
* @since v2.17.0 — extracted from monolithic index.ts
|
|
7
|
+
*/
|
|
8
|
+
import fs from "fs-extra";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { logStudioEvent } from '../utils/config.js';
|
|
11
|
+
export async function handleRun(cwd, command, requestId) {
|
|
12
|
+
// 1. Log Interceptable Event
|
|
13
|
+
await logStudioEvent(cwd, {
|
|
14
|
+
type: "interception_requested",
|
|
15
|
+
requestId,
|
|
16
|
+
tool: "rigour_run",
|
|
17
|
+
command,
|
|
18
|
+
});
|
|
19
|
+
// 2. Poll for Human Arbitration (Max 60s wait)
|
|
20
|
+
console.error(`[RIGOUR] Waiting for human arbitration for command: ${command}`);
|
|
21
|
+
const decision = await pollArbitration(cwd, requestId, 60000);
|
|
22
|
+
if (decision === 'reject') {
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: "text", text: `❌ COMMAND REJECTED BY GOVERNOR: The execution of "${command}" was blocked by a human operator in the Governance Studio.` }],
|
|
25
|
+
isError: true,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// Execute
|
|
29
|
+
const { execa } = await import("execa");
|
|
30
|
+
try {
|
|
31
|
+
const { stdout, stderr } = await execa(command, { shell: true, cwd });
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: `✅ COMMAND EXECUTED (Approved by Governor):\n\nSTDOUT:\n${stdout}\n\nSTDERR:\n${stderr}` }],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
return {
|
|
38
|
+
content: [{ type: "text", text: `❌ COMMAND FAILED:\n\n${e.message}` }],
|
|
39
|
+
isError: true,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function handleRunSupervised(runner, cwd, command, maxRetries, dryRun, requestId) {
|
|
44
|
+
const { execa } = await import("execa");
|
|
45
|
+
let iteration = 0;
|
|
46
|
+
let lastReport = null;
|
|
47
|
+
let result = null;
|
|
48
|
+
const iterations = [];
|
|
49
|
+
await logStudioEvent(cwd, {
|
|
50
|
+
type: "supervisor_started",
|
|
51
|
+
requestId,
|
|
52
|
+
command,
|
|
53
|
+
maxRetries,
|
|
54
|
+
dryRun,
|
|
55
|
+
});
|
|
56
|
+
while (iteration < maxRetries) {
|
|
57
|
+
iteration++;
|
|
58
|
+
if (!dryRun) {
|
|
59
|
+
try {
|
|
60
|
+
await execa(command, { shell: true, cwd });
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
console.error(`[RIGOUR] Iteration ${iteration} command error: ${e.message}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.error(`[RIGOUR] Iteration ${iteration} (DRY RUN - skipping command execution)`);
|
|
68
|
+
}
|
|
69
|
+
lastReport = await runner.run(cwd);
|
|
70
|
+
iterations.push({ iteration, status: lastReport.status, failures: lastReport.failures.length });
|
|
71
|
+
await logStudioEvent(cwd, {
|
|
72
|
+
type: "supervisor_iteration",
|
|
73
|
+
requestId,
|
|
74
|
+
iteration,
|
|
75
|
+
status: lastReport.status,
|
|
76
|
+
failures: lastReport.failures.length,
|
|
77
|
+
});
|
|
78
|
+
if (lastReport.status === "PASS") {
|
|
79
|
+
result = {
|
|
80
|
+
content: [{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: `✅ SUPERVISOR MODE: PASSED on iteration ${iteration}/${maxRetries}\n\nIterations:\n${iterations.map(i => ` ${i.iteration}. ${i.status} (${i.failures} failures)`).join("\n")}\n\nAll quality gates have been satisfied.`,
|
|
83
|
+
}],
|
|
84
|
+
};
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
if (iteration >= maxRetries) {
|
|
88
|
+
const fixPacket = lastReport.failures.map((f, i) => {
|
|
89
|
+
const sevTag = `[${(f.severity || 'medium').toUpperCase()}]`;
|
|
90
|
+
const provTag = f.provenance ? `(${f.provenance})` : '';
|
|
91
|
+
let text = `FIX TASK ${i + 1}: ${sevTag} ${provTag} [${f.id.toUpperCase()}] ${f.title}\n`;
|
|
92
|
+
text += ` - CONTEXT: ${f.details}\n`;
|
|
93
|
+
if (f.files && f.files.length > 0)
|
|
94
|
+
text += ` - TARGET FILES: ${f.files.join(", ")}\n`;
|
|
95
|
+
if (f.hint)
|
|
96
|
+
text += ` - REFACTORING GUIDANCE: ${f.hint}\n`;
|
|
97
|
+
return text;
|
|
98
|
+
}).join("\n---\n");
|
|
99
|
+
result = {
|
|
100
|
+
content: [{
|
|
101
|
+
type: "text",
|
|
102
|
+
text: `❌ SUPERVISOR MODE: FAILED after ${iteration} iterations\n\nIterations:\n${iterations.map(i => ` ${i.iteration}. ${i.status} (${i.failures} failures)`).join("\n")}\n\nFINAL FIX PACKET:\n${fixPacket}`,
|
|
103
|
+
}],
|
|
104
|
+
isError: true,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
await logStudioEvent(cwd, {
|
|
109
|
+
type: "supervisor_completed",
|
|
110
|
+
requestId,
|
|
111
|
+
finalStatus: lastReport?.status || "UNKNOWN",
|
|
112
|
+
totalIterations: iteration,
|
|
113
|
+
});
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
// ─── Private Helpers ──────────────────────────────────────────────
|
|
117
|
+
async function pollArbitration(cwd, rid, timeout) {
|
|
118
|
+
const start = Date.now();
|
|
119
|
+
const eventsPath = path.join(cwd, '.rigour/events.jsonl');
|
|
120
|
+
while (Date.now() - start < timeout) {
|
|
121
|
+
if (await fs.pathExists(eventsPath)) {
|
|
122
|
+
const content = await fs.readFile(eventsPath, 'utf-8');
|
|
123
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
124
|
+
for (const line of lines.reverse()) {
|
|
125
|
+
const event = JSON.parse(line);
|
|
126
|
+
if (event.tool === 'human_arbitration' && event.requestId === rid) {
|
|
127
|
+
return event.decision;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
132
|
+
}
|
|
133
|
+
return "approve"; // Default auto-approve if no human response
|
|
134
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type ToolResult = {
|
|
2
|
+
content: {
|
|
3
|
+
type: string;
|
|
4
|
+
text: string;
|
|
5
|
+
}[];
|
|
6
|
+
};
|
|
7
|
+
export declare function handleRemember(cwd: string, key: string, value: string): Promise<ToolResult>;
|
|
8
|
+
export declare function handleRecall(cwd: string, key?: string): Promise<ToolResult>;
|
|
9
|
+
export declare function handleForget(cwd: string, key: string): Promise<ToolResult>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Persistence Tool Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handlers for: rigour_remember, rigour_recall, rigour_forget
|
|
5
|
+
*
|
|
6
|
+
* @since v2.17.0 — extracted from monolithic index.ts
|
|
7
|
+
*/
|
|
8
|
+
import { loadMemory, saveMemory } from '../utils/config.js';
|
|
9
|
+
export async function handleRemember(cwd, key, value) {
|
|
10
|
+
const store = await loadMemory(cwd);
|
|
11
|
+
store.memories[key] = { value, timestamp: new Date().toISOString() };
|
|
12
|
+
await saveMemory(cwd, store);
|
|
13
|
+
return {
|
|
14
|
+
content: [{
|
|
15
|
+
type: "text",
|
|
16
|
+
text: `MEMORY STORED: "${key}" has been saved. This instruction will persist across sessions.\n\nStored value: ${value}`,
|
|
17
|
+
}],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export async function handleRecall(cwd, key) {
|
|
21
|
+
const store = await loadMemory(cwd);
|
|
22
|
+
if (key) {
|
|
23
|
+
const memory = store.memories[key];
|
|
24
|
+
if (!memory) {
|
|
25
|
+
return { content: [{ type: "text", text: `NO MEMORY FOUND for key "${key}". Use rigour_remember to store instructions.` }] };
|
|
26
|
+
}
|
|
27
|
+
return { content: [{ type: "text", text: `RECALLED MEMORY [${key}]:\n${memory.value}\n\n(Stored: ${memory.timestamp})` }] };
|
|
28
|
+
}
|
|
29
|
+
const keys = Object.keys(store.memories);
|
|
30
|
+
if (keys.length === 0) {
|
|
31
|
+
return { content: [{ type: "text", text: "NO MEMORIES STORED. Use rigour_remember to persist important instructions." }] };
|
|
32
|
+
}
|
|
33
|
+
const allMemories = keys.map(k => {
|
|
34
|
+
const mem = store.memories[k];
|
|
35
|
+
return `## ${k}\n${mem.value}\n(Stored: ${mem.timestamp})`;
|
|
36
|
+
}).join("\n\n---\n\n");
|
|
37
|
+
return {
|
|
38
|
+
content: [{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: `RECALLED ALL MEMORIES (${keys.length} items):\n\n${allMemories}\n\n---\nIMPORTANT: Follow these stored instructions throughout this session.`,
|
|
41
|
+
}],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export async function handleForget(cwd, key) {
|
|
45
|
+
const store = await loadMemory(cwd);
|
|
46
|
+
if (!store.memories[key]) {
|
|
47
|
+
return { content: [{ type: "text", text: `NO MEMORY FOUND for key "${key}". Nothing to forget.` }] };
|
|
48
|
+
}
|
|
49
|
+
delete store.memories[key];
|
|
50
|
+
await saveMemory(cwd, store);
|
|
51
|
+
return { content: [{ type: "text", text: `MEMORY DELETED: "${key}" has been removed.` }] };
|
|
52
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type ToolResult = {
|
|
2
|
+
content: {
|
|
3
|
+
type: string;
|
|
4
|
+
text: string;
|
|
5
|
+
}[];
|
|
6
|
+
};
|
|
7
|
+
export declare function handleCheckPattern(cwd: string, patternName: string, type?: string, intent?: string): Promise<ToolResult>;
|
|
8
|
+
export declare function handleSecurityAudit(cwd: string): Promise<ToolResult>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Intelligence Tool Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handlers for: rigour_check_pattern, rigour_security_audit
|
|
5
|
+
*
|
|
6
|
+
* @since v2.17.0 — extracted from monolithic index.ts
|
|
7
|
+
*/
|
|
8
|
+
import { PatternMatcher, loadPatternIndex, getDefaultIndexPath, StalenessDetector, SecurityDetector, } from "@rigour-labs/core/pattern-index";
|
|
9
|
+
export async function handleCheckPattern(cwd, patternName, type, intent) {
|
|
10
|
+
const indexPath = getDefaultIndexPath(cwd);
|
|
11
|
+
const index = await loadPatternIndex(indexPath);
|
|
12
|
+
let resultText = "";
|
|
13
|
+
// 1. Check for Reinvention
|
|
14
|
+
if (index) {
|
|
15
|
+
const matcher = new PatternMatcher(index);
|
|
16
|
+
const matchResult = await matcher.match({ name: patternName, type, intent });
|
|
17
|
+
if (matchResult.status === "FOUND_SIMILAR") {
|
|
18
|
+
resultText += `🚨 PATTERN REINVENTION DETECTED\n`;
|
|
19
|
+
resultText += `Similar pattern already exists: "${matchResult.matches[0].pattern.name}" in ${matchResult.matches[0].pattern.file}\n`;
|
|
20
|
+
resultText += `SUGGESTION: ${matchResult.suggestion}\n\n`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
resultText += `⚠️ Pattern index not found. Run 'rigour index' to enable reinvention detection.\n\n`;
|
|
25
|
+
}
|
|
26
|
+
// 2. Check for Staleness/Best Practices
|
|
27
|
+
const detector = new StalenessDetector(cwd);
|
|
28
|
+
const staleness = await detector.checkStaleness(`${type || 'function'} ${patternName} {}`);
|
|
29
|
+
if (staleness.status !== "FRESH") {
|
|
30
|
+
resultText += `⚠️ STALENESS/ANTI-PATTERN WARNING\n`;
|
|
31
|
+
for (const issue of staleness.issues) {
|
|
32
|
+
resultText += `- ${issue.reason}\n REPLACEMENT: ${issue.replacement}\n`;
|
|
33
|
+
}
|
|
34
|
+
resultText += `\n`;
|
|
35
|
+
}
|
|
36
|
+
// 3. Check Security for this library (if it's an import)
|
|
37
|
+
if (intent && intent.includes('import')) {
|
|
38
|
+
const security = new SecurityDetector(cwd);
|
|
39
|
+
const audit = await security.runAudit();
|
|
40
|
+
const relatedVulns = audit.vulnerabilities.filter(v => patternName.toLowerCase().includes(v.packageName.toLowerCase()) ||
|
|
41
|
+
intent.toLowerCase().includes(v.packageName.toLowerCase()));
|
|
42
|
+
if (relatedVulns.length > 0) {
|
|
43
|
+
resultText += `🛡️ SECURITY/CVE WARNING\n`;
|
|
44
|
+
for (const v of relatedVulns) {
|
|
45
|
+
resultText += `- [${v.severity.toUpperCase()}] ${v.packageName}: ${v.title} (${v.url})\n`;
|
|
46
|
+
}
|
|
47
|
+
resultText += `\n`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!resultText) {
|
|
51
|
+
resultText = `✅ Pattern "${patternName}" is fresh, secure, and unique to the codebase.\n\nRECOMMENDED ACTION: Proceed with implementation.`;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
let recommendation = "Proceed with caution, addressing the warnings above.";
|
|
55
|
+
if (resultText.includes("🚨 PATTERN REINVENTION")) {
|
|
56
|
+
recommendation = "STOP and REUSE the existing pattern mentioned above. Do not create a duplicate.";
|
|
57
|
+
}
|
|
58
|
+
else if (resultText.includes("🛡️ SECURITY/CVE WARNING")) {
|
|
59
|
+
recommendation = "STOP and update your dependencies or find an alternative library. Do not proceed with vulnerable code.";
|
|
60
|
+
}
|
|
61
|
+
else if (resultText.includes("⚠️ STALENESS")) {
|
|
62
|
+
recommendation = "Follow the replacement suggestion to ensure best practices.";
|
|
63
|
+
}
|
|
64
|
+
resultText += `\nRECOMMENDED ACTION: ${recommendation}`;
|
|
65
|
+
}
|
|
66
|
+
return { content: [{ type: "text", text: resultText }] };
|
|
67
|
+
}
|
|
68
|
+
export async function handleSecurityAudit(cwd) {
|
|
69
|
+
const security = new SecurityDetector(cwd);
|
|
70
|
+
const summary = await security.getSecuritySummary();
|
|
71
|
+
return { content: [{ type: "text", text: summary }] };
|
|
72
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Gate Tool Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handlers for: rigour_check, rigour_explain, rigour_status,
|
|
5
|
+
* rigour_get_fix_packet, rigour_list_gates, rigour_get_config
|
|
6
|
+
*
|
|
7
|
+
* @since v2.17.0 — extracted from monolithic index.ts
|
|
8
|
+
*/
|
|
9
|
+
import { GateRunner, Report } from "@rigour-labs/core";
|
|
10
|
+
import type { Config } from "@rigour-labs/core";
|
|
11
|
+
type ToolResult = {
|
|
12
|
+
content: {
|
|
13
|
+
type: string;
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
isError?: boolean;
|
|
17
|
+
_rigour_report?: Report;
|
|
18
|
+
};
|
|
19
|
+
export declare function handleCheck(runner: GateRunner, cwd: string): Promise<ToolResult>;
|
|
20
|
+
export declare function handleExplain(runner: GateRunner, cwd: string): Promise<ToolResult>;
|
|
21
|
+
export declare function handleStatus(runner: GateRunner, cwd: string): Promise<ToolResult>;
|
|
22
|
+
export declare function handleGetFixPacket(runner: GateRunner, cwd: string, config: Config): Promise<ToolResult>;
|
|
23
|
+
export declare function handleListGates(config: Config): ToolResult;
|
|
24
|
+
export declare function handleGetConfig(config: Config): ToolResult;
|
|
25
|
+
export {};
|