slopwatch_claim_and_verify
Register AI implementation claims and verify actual code changes in one step to track promises versus delivered work.
Instructions
Register claim and verify implementation in one call - reduces from 2 tool calls to 1
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| claim | Yes | What you implemented | |
| originalFileContents | Yes | Original content of files before implementation (filename -> content) | |
| updatedFileContents | Yes | Updated content of files after implementation (filename -> content) |
Implementation Reference
- src/mcp-server.js:120-187 (handler)Primary handler for slopwatch_claim_and_verify tool. Registers claim with file snapshots, calls analysis, stores results, and returns verification status with confidence.async handleClaimAndVerify(args) { const { claim, originalFileContents, updatedFileContents } = args; const claimId = Math.random().toString(36).substr(2, 9); // Create file snapshots from provided content const fileSnapshots = {}; const fileList = Object.keys(originalFileContents); for (const [filename, content] of Object.entries(originalFileContents)) { fileSnapshots[filename] = { hash: crypto.createHash('sha256').update(content || '').digest('hex'), content: content || '', exists: true }; } const claimRecord = { id: claimId, claim, files: fileList, timestamp: new Date().toISOString(), status: 'pending', fileSnapshots }; this.claims.set(claimId, claimRecord); // Track claim registration analytics.trackClaim(claimId, fileList.length, fileList.length > 0); try { const result = await this.analyzeImplementation(claimRecord, updatedFileContents); // Store verification result claimRecord.status = result.isVerified ? 'verified' : 'failed'; this.verificationResults.push({ ...result, claimId, timestamp: new Date().toISOString(), claim: claimRecord.claim }); // Track verification analytics.trackVerification(claimId, result.isVerified, result.confidence); const statusEmoji = result.isVerified ? '✅' : '❌'; const statusText = result.isVerified ? 'PASSED' : 'FAILED'; return { content: [ { type: 'text', text: `${statusEmoji} ${statusText} (${result.confidence}%)` } ] }; } catch (error) { return { content: [ { type: 'text', text: `❌ Error: ${error.message}` } ] }; } }
- src/mcp-server.js:45-64 (schema)Input schema defining the parameters for the slopwatch_claim_and_verify tool: claim string and before/after file contents objects.inputSchema: { type: 'object', properties: { claim: { type: 'string', description: 'What you implemented' }, originalFileContents: { type: 'object', description: 'Original content of files before implementation (filename -> content)', additionalProperties: { type: 'string' } }, updatedFileContents: { type: 'object', description: 'Updated content of files after implementation (filename -> content)', additionalProperties: { type: 'string' } } }, required: ['claim', 'originalFileContents', 'updatedFileContents'] }
- src/mcp-server.js:42-65 (registration)Tool registration in the ListTools response, including name, description, and input schema.{ name: 'slopwatch_claim_and_verify', description: 'Register claim and verify implementation in one call - reduces from 2 tool calls to 1', inputSchema: { type: 'object', properties: { claim: { type: 'string', description: 'What you implemented' }, originalFileContents: { type: 'object', description: 'Original content of files before implementation (filename -> content)', additionalProperties: { type: 'string' } }, updatedFileContents: { type: 'object', description: 'Updated content of files after implementation (filename -> content)', additionalProperties: { type: 'string' } } }, required: ['claim', 'originalFileContents', 'updatedFileContents'] } },
- src/mcp-server.js:107-109 (registration)Dispatch registration in the CallToolRequestSchema handler switch statement, routing to the specific handler.switch (name) { case 'slopwatch_claim_and_verify': return await this.handleClaimAndVerify(args);
- src/mcp-server.js:191-276 (helper)Helper function performing the core verification logic: hashes files, detects changes, extracts keywords from claim, computes confidence score based on changes and keyword matches.async analyzeImplementation(claimRecord, updatedFileContents) { const { claim, files, fileSnapshots } = claimRecord; // If no files specified in original claim, but we have updated content, use those files const filesToCheck = files.length > 0 ? files : Object.keys(updatedFileContents); if (filesToCheck.length === 0) { return { isVerified: false, confidence: 0, details: 'No files specified for verification', analysis: 'Cannot verify implementation without file content' }; } let changedFiles = 0; let totalFiles = filesToCheck.length; let analysisDetails = []; let keywordMatches = 0; // Extract keywords from the claim const keywords = this.extractKeywords(claim); for (const filename of filesToCheck) { const updatedContent = updatedFileContents[filename] || ''; const currentHash = crypto.createHash('sha256').update(updatedContent).digest('hex'); const snapshot = fileSnapshots[filename]; if (!snapshot) { // If no snapshot exists, treat empty string as original content const originalHash = crypto.createHash('sha256').update('').digest('hex'); if (originalHash !== currentHash && updatedContent.length > 0) { changedFiles++; // Analyze content for keywords const foundKeywords = keywords.filter(keyword => updatedContent.toLowerCase().includes(keyword.toLowerCase()) ); keywordMatches += foundKeywords.length; analysisDetails.push( `✅ ${filename}: New file created (${foundKeywords.length} keywords found: ${foundKeywords.join(', ')})` ); } else { analysisDetails.push(`❌ ${filename}: No content provided`); } continue; } // Check if file was modified if (snapshot.hash !== currentHash) { changedFiles++; // Analyze content changes for keywords const addedContent = this.getAddedContent(snapshot.content || '', updatedContent); const foundKeywords = keywords.filter(keyword => addedContent.toLowerCase().includes(keyword.toLowerCase()) ); keywordMatches += foundKeywords.length; analysisDetails.push( `✅ ${filename}: Modified (${foundKeywords.length} keywords found: ${foundKeywords.join(', ')})` ); } else { analysisDetails.push(`❌ ${filename}: No changes detected`); } } // Calculate confidence based on multiple factors const fileChangeScore = (changedFiles / totalFiles) * 60; // 60% weight for file changes const keywordScore = Math.min((keywordMatches / keywords.length) * 40, 40); // 40% weight for keyword matches const confidence = Math.round(fileChangeScore + keywordScore); const isVerified = confidence >= 50; // Require at least 50% confidence return { isVerified, confidence, details: isVerified ? `Implementation verified: ${changedFiles}/${totalFiles} files modified, ${keywordMatches}/${keywords.length} keywords found` : `Implementation failed: ${changedFiles}/${totalFiles} files modified, ${keywordMatches}/${keywords.length} keywords found`, analysis: analysisDetails.join('\n') }; }