Skip to content

Commit 2197f54

Browse files
committed
v2.2.9: Remove verify_work_recorded tool and enhance built-in memory reminder system
1 parent 356be56 commit 2197f54

File tree

3 files changed

+60
-144
lines changed

3 files changed

+60
-144
lines changed

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [2.2.9] - 2025-12-02
9+
10+
### Removed
11+
12+
- **verify_work_recorded Tool**: Removed as standalone MCP tool (functionality now built-in)
13+
- Issue: Redundant with v2.2.7's automatic memory reminder system
14+
- Confusion: AI didn't know whether to call this tool or rely on automatic reminders
15+
- Solution: Rely entirely on `wrapWithReminder()` automatic system
16+
- All tools (except `record_context`) now automatically show memory reminders
17+
- No action needed: Memory tracking still works automatically
18+
- Location: `src/mcp-server.ts`
19+
20+
### Improved
21+
22+
- **Enhanced Memory Reminder System**: Upgraded `wrapWithReminder()` with more detailed information
23+
- Increased file display limit: 5 → 10 files
24+
- Shows change type for each file: (add), (modify), or (delete)
25+
- Provides context type suggestions: bug_fix, feature_add, code_modify, etc.
26+
- Better formatted output with warning emoji (⚠️) for visibility
27+
- Uses `getPendingDetails()` for richer file information
28+
- Location: `src/mcp-server.ts`
29+
30+
### Technical Details
31+
32+
- **Built-in Memory Reminder**: `wrapWithReminder()` automatically appends reminders to all tool responses
33+
- **PendingMemoryTracker**: Tracks unrecorded file changes with change types across all tools
34+
- **Automatic Detection**: Shows up to 10 pending files with change types and total count
35+
- **Smart Filtering**: Skips reminder for `record_context` to avoid loops
36+
- **Rich Context**: Displays file paths with change types for better decision making
37+
38+
---
39+
840
## [2.2.8] - 2025-12-02
941

1042
### Added

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "devmind-mcp",
3-
"version": "2.2.8",
3+
"version": "2.2.9",
44
"description": "DevMind MCP - AI Assistant Memory System - Pure MCP Tool",
55
"main": "dist/index.js",
66
"type": "module",

src/mcp-server.ts

Lines changed: 27 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,7 @@ export class AiMemoryMcpServer {
7373
private pendingMemoryTracker: PendingMemoryTracker;
7474

7575
// Tools that should NOT trigger memory reminder (to avoid infinite loops)
76-
private readonly NO_REMINDER_TOOLS = new Set([
77-
"record_context",
78-
"verify_work_recorded",
79-
]);
76+
private readonly NO_REMINDER_TOOLS = new Set(["record_context"]);
8077

8178
// 真实日期记录函数
8279
private getCurrentRealDate(): string {
@@ -207,20 +204,26 @@ export class AiMemoryMcpServer {
207204
*/
208205
private generateMemoryReminder(): {
209206
pending_count: number;
210-
pending_files: string[];
207+
pending_details: Array<{ file: string; type: string }>;
211208
action: string;
212209
} | null {
213-
const unrecordedFiles = this.pendingMemoryTracker.getUnrecorded();
210+
const pendingDetails = this.pendingMemoryTracker.getPendingDetails();
214211

215-
if (unrecordedFiles.length === 0) {
212+
if (pendingDetails.length === 0) {
216213
return null;
217214
}
218215

216+
// Format file details with change type
217+
const fileDetails = pendingDetails.slice(0, 10).map((detail) => ({
218+
file: detail.filePath,
219+
type: detail.changeType,
220+
}));
221+
219222
return {
220-
pending_count: unrecordedFiles.length,
221-
pending_files: unrecordedFiles.slice(0, 5), // Show max 5 files
223+
pending_count: pendingDetails.length,
224+
pending_details: fileDetails,
222225
action:
223-
"Call record_context NOW to save your work before responding to user.",
226+
"Call record_context NOW with appropriate type (bug_fix, feature_add, code_modify, etc.) before responding to user.",
224227
};
225228
}
226229

@@ -241,12 +244,21 @@ export class AiMemoryMcpServer {
241244
return result;
242245
}
243246

247+
// Format file list with change types
248+
const fileList = reminder.pending_details
249+
.map((detail) => `${detail.file} (${detail.type})`)
250+
.join(", ");
251+
252+
const moreFilesText =
253+
reminder.pending_count > 10
254+
? ` (+${reminder.pending_count - 10} more)`
255+
: "";
256+
244257
// Add reminder to the result
245-
const reminderText = `\n\n---\n[MEMORY REMINDER] ${
246-
reminder.pending_count
247-
} file(s) edited but not recorded: ${reminder.pending_files.join(", ")}${
248-
reminder.pending_count > 5 ? ` (+${reminder.pending_count - 5} more)` : ""
249-
}. ${reminder.action}`;
258+
const reminderText = `\n\n---\n⚠️ [MEMORY REMINDER] ${reminder.pending_count} file(s) edited but not recorded:
259+
${fileList}${moreFilesText}
260+
261+
${reminder.action}`;
250262

251263
// Append reminder to the last text content
252264
const newContent = [...result.content];
@@ -546,22 +558,6 @@ export class AiMemoryMcpServer {
546558
required: ["content"], // type is optional for AI auto-classification
547559
},
548560
},
549-
{
550-
name: "verify_work_recorded",
551-
description:
552-
"Call before responding to user. Checks if edited files have been recorded. Returns warning if record_context was not called.",
553-
inputSchema: {
554-
type: "object",
555-
properties: {
556-
work_summary: {
557-
type: "string",
558-
description: "Brief summary of work done",
559-
},
560-
project_path: { type: "string", description: "Project path" },
561-
},
562-
required: ["work_summary"],
563-
},
564-
},
565561
{
566562
name: "end_session",
567563
description: "End a development session",
@@ -885,10 +881,6 @@ export class AiMemoryMcpServer {
885881
return this.handleRecordContext(
886882
safeArgs as unknown as RecordContextParams
887883
);
888-
case "verify_work_recorded":
889-
return this.handleVerifyWorkRecorded(
890-
safeArgs as { work_summary: string; project_path?: string }
891-
);
892884
case "end_session":
893885
return executeAndWrap(() =>
894886
this.handleEndSession(safeArgs as { session_id: string })
@@ -1760,114 +1752,6 @@ export class AiMemoryMcpServer {
17601752
}
17611753
}
17621754

1763-
/**
1764-
* Handle verify_work_recorded tool call
1765-
* Checks if there are unrecorded file changes and provides guidance
1766-
*/
1767-
private async handleVerifyWorkRecorded(args: {
1768-
work_summary: string;
1769-
project_path?: string;
1770-
}) {
1771-
try {
1772-
// Get current session
1773-
let sessionId: string | null = null;
1774-
let projectPath = args.project_path;
1775-
1776-
// If no project_path provided, try to infer from current working directory
1777-
if (!projectPath) {
1778-
const potentialDirs = [
1779-
process.env.INIT_CWD,
1780-
process.env.PWD,
1781-
process.env.CD,
1782-
process.cwd(),
1783-
].filter(Boolean) as string[];
1784-
1785-
for (const dir of potentialDirs) {
1786-
if (existsSync(dir)) {
1787-
projectPath = dir;
1788-
break;
1789-
}
1790-
}
1791-
}
1792-
1793-
if (projectPath) {
1794-
sessionId = await this.sessionManager.getCurrentSession(projectPath);
1795-
}
1796-
1797-
// Check for unrecorded files
1798-
const unrecordedFiles = this.pendingMemoryTracker.getUnrecorded(
1799-
sessionId || undefined
1800-
);
1801-
1802-
if (unrecordedFiles.length > 0) {
1803-
// There are unrecorded files - return warning
1804-
const fileList = unrecordedFiles
1805-
.slice(0, 10)
1806-
.map((f, i) => ` ${i + 1}. ${f}`)
1807-
.join("\n");
1808-
const moreFiles =
1809-
unrecordedFiles.length > 10
1810-
? `\n ... and ${unrecordedFiles.length - 10} more files`
1811-
: "";
1812-
1813-
// Suggest context type based on work summary
1814-
const suggestedType = this.suggestContextType(args.work_summary);
1815-
1816-
const warningText = `WARNING: Work not fully recorded
1817-
1818-
Unrecorded files (${unrecordedFiles.length}):
1819-
${fileList}${moreFiles}
1820-
1821-
ACTION REQUIRED:
1822-
Call record_context with:
1823-
- type: ${suggestedType}
1824-
- content: "${args.work_summary}"
1825-
- files_changed: [${unrecordedFiles
1826-
.slice(0, 5)
1827-
.map((f) => `"${f}"`)
1828-
.join(", ")}${unrecordedFiles.length > 5 ? ", ..." : ""}]
1829-
1830-
Then call verify_work_recorded again to confirm.`;
1831-
1832-
return {
1833-
content: [{ type: "text", text: warningText }],
1834-
isError: true,
1835-
_meta: {
1836-
verification_status: "failed",
1837-
unrecorded_count: unrecordedFiles.length,
1838-
suggested_type: suggestedType,
1839-
},
1840-
};
1841-
}
1842-
1843-
// All work is recorded
1844-
const successText = `VERIFICATION PASSED: All work has been recorded.
1845-
1846-
You may now respond to the user.`;
1847-
1848-
return {
1849-
content: [{ type: "text", text: successText }],
1850-
isError: false,
1851-
_meta: {
1852-
verification_status: "passed",
1853-
unrecorded_count: 0,
1854-
},
1855-
};
1856-
} catch (error) {
1857-
return {
1858-
content: [
1859-
{
1860-
type: "text",
1861-
text: `Failed to verify work: ${
1862-
error instanceof Error ? error.message : "Unknown error"
1863-
}`,
1864-
},
1865-
],
1866-
isError: true,
1867-
};
1868-
}
1869-
}
1870-
18711755
/**
18721756
* Suggest context type based on work summary
18731757
*/

0 commit comments

Comments
 (0)