get_tree_validation_report
Validate tree structure to identify antipatterns and calculate quality score for research organization hierarchies.
Instructions
Get validation report for all splits in a tree. Identifies antipatterns and provides an overall quality score. Use this after building a tree to check for common failure modes.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| treeId | Yes | ID of the tree to validate |
Implementation Reference
- src/research-tree.ts:927-970 (handler)Core handler function that executes the tool logic: generates a comprehensive validation report for all splits in a given tree by calling validateSplitQuality on each split tile and aggregating scores and issues.getTreeValidationReport(treeId: string): { treeId: string; splitReports: SplitQualityReport[]; overallScore: number; summary: string; } { const tree = this.trees.get(treeId); if (!tree) { throw new Error(`Tree ${treeId} not found`); } const allTiles = this.getTilesInTree(tree.rootTileId); const tilesWithSplits = allTiles.filter((t) => t.childrenIds.length > 0); const splitReports = tilesWithSplits.map((tile) => this.validateSplitQuality(tile.id)); const overallScore = splitReports.length > 0 ? Math.round(splitReports.reduce((sum, r) => sum + r.score, 0) / splitReports.length) : 100; const totalIssues = splitReports.reduce((sum, r) => sum + r.issues.length, 0); const totalErrors = splitReports.reduce( (sum, r) => sum + r.issues.filter((i) => i.severity === "error").length, 0 ); let summary = `Tree has ${splitReports.length} splits with ${totalIssues} total issues (${totalErrors} errors). Overall score: ${overallScore}/100.`; if (overallScore >= 80) { summary += " Tree structure is good quality."; } else if (overallScore >= 60) { summary += " Some improvements recommended."; } else { summary += " Significant issues detected - review recommendations."; } return { treeId, splitReports, overallScore, summary, }; }
- src/index.ts:377-389 (schema)Input schema definition for the tool, specifying the required 'treeId' parameter.name: "get_tree_validation_report", description: "Get validation report for all splits in a tree. Identifies antipatterns and provides an overall quality score. Use this after building a tree to check for common failure modes.", inputSchema: { type: "object", properties: { treeId: { type: "string", description: "ID of the tree to validate", }, }, required: ["treeId"], }, },
- src/index.ts:654-664 (registration)Tool handler registration in the MCP CallToolRequestSchema switch statement, delegating execution to treeManager.getTreeValidationReport.case "get_tree_validation_report": { const result = treeManager.getTreeValidationReport(args.treeId as string); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; }
- src/research-tree.ts:616-709 (helper)Key helper method called by the handler to validate individual split quality, detecting antipatterns such as vague language, catch-all buckets, mixed dimensions, retroactive splitting, and incomplete coverage.validateSplitQuality(tileId: string): SplitQualityReport { const tile = this.tiles.get(tileId); if (!tile) { throw new Error(`Tile ${tileId} not found`); } const issues: ValidationIssue[] = []; const recommendations: string[] = []; // Get children for analysis const children = tile.childrenIds.map((id) => this.tiles.get(id)).filter((t) => t !== undefined) as Tile[]; if (children.length === 0) { return { tileId: tile.id, tileTitle: tile.title, issues: [], score: 100, recommendations: ["Tile has no children - nothing to validate"], }; } // 1. Check for vague language const vagueIssues = this.detectVagueLanguage(tile, children); issues.push(...vagueIssues); // 2. Check for catch-all buckets const catchAllIssues = this.detectCatchAllBuckets(tile, children); issues.push(...catchAllIssues); // 3. Check for mixed dimensions const mixedDimIssues = this.detectMixedDimensions(tile, children); issues.push(...mixedDimIssues); // 4. Check for retroactive splitting const retroactiveIssues = this.detectRetroactiveSplitting(tile, children); issues.push(...retroactiveIssues); // 5. Check for incomplete coverage if (!tile.isMECE) { issues.push({ type: "incomplete_coverage", severity: "warning", message: "Split has not been validated for MECE completeness", tileId: tile.id, suggestion: "Use mark_mece to validate that the split is Mutually Exclusive and Collectively Exhaustive", }); } // Generate recommendations if (issues.length === 0) { recommendations.push("Split appears well-structured"); if (tile.isMECE) { recommendations.push("MECE validation completed"); } } else { const errorCount = issues.filter((i) => i.severity === "error").length; const warningCount = issues.filter((i) => i.severity === "warning").length; if (errorCount > 0) { recommendations.push(`Address ${errorCount} critical issue(s) before proceeding`); } if (warningCount > 0) { recommendations.push(`Review ${warningCount} warning(s) to improve split quality`); } // Specific recommendations if (issues.some((i) => i.type === "vague_language")) { recommendations.push("Replace vague terms with measurable physical properties or precise definitions"); } if (issues.some((i) => i.type === "catch_all_bucket")) { recommendations.push("Replace catch-all categories with specific, splittable subsets"); } if (issues.some((i) => i.type === "mixed_dimensions")) { recommendations.push("Use a single consistent dimension/attribute for this split level"); } if (issues.some((i) => i.type === "retroactive_splitting")) { recommendations.push("Consider physics/math-based splits instead of known solution types"); } } // Calculate score (100 - 20 per error - 10 per warning) const errorPenalty = issues.filter((i) => i.severity === "error").length * 20; const warningPenalty = issues.filter((i) => i.severity === "warning").length * 10; const score = Math.max(0, 100 - errorPenalty - warningPenalty); return { tileId: tile.id, tileTitle: tile.title, issues, score, recommendations, }; }