pmat 3.15.0

PMAT - Zero-config AI context generation and code quality toolkit (CLI, MCP, HTTP)
// Core ToolHandler implementation for PdmtTool
// Included from pdmt_handler.rs — no `use` imports or `#!` inner attributes allowed

#[async_trait]
impl ToolHandler for PdmtTool {
    fn metadata(&self) -> Option<ToolInfo> {
        let schema = json!({
            "type": "object",
            "properties": {
                "requirements": {
                    "type": "array",
                    "items": { "type": "string" },
                    "description": "Requirements to convert into deterministic actionable todos"
                },
                "project_name": { "type": "string", "description": "Project or component name" },
                "granularity":  { "type": "string", "enum": ["low", "medium", "high"], "description": "Task detail level (default: high)" },
                "quality_config": {
                    "type": "object",
                    "description": "Quality enforcement config",
                    "properties": {
                        "enforcement_mode":       { "type": "string", "enum": ["strict", "advisory", "auto_fix"] },
                        "coverage_threshold":     { "type": "number"  },
                        "max_complexity":         { "type": "integer" },
                        "require_doctests":       { "type": "boolean" },
                        "require_property_tests": { "type": "boolean" },
                        "require_examples":       { "type": "boolean" },
                        "zero_satd_tolerance":    { "type": "boolean" }
                    }
                }
            },
            "required": ["requirements"]
        });
        Some(build_tool_info(
            "pdmt_deterministic_todos",
            "Generate deterministic, quality-enforced todo lists from a list of requirements.",
            schema,
        ))
    }

    async fn handle(&self, args: Value, _extra: RequestHandlerExtra) -> Result<Value> {
        debug!("Handling pdmt_deterministic_todos with args: {}", args);

        let input: PdmtInput = serde_json::from_value(args)
            .map_err(|e| Error::validation(format!("Invalid arguments: {e}")))?;

        if input.requirements.is_empty() {
            return Err(Error::validation("Requirements list cannot be empty"));
        }

        info!(
            "Generating deterministic todos for {} requirements",
            input.requirements.len()
        );

        // Convert input quality config to internal format
        let enforcement_mode = match input.quality_config.enforcement_mode.as_str() {
            "strict" => EnforcementMode::Strict,
            "advisory" => EnforcementMode::Advisory,
            "auto_fix" | "autofix" => EnforcementMode::AutoFix,
            _ => {
                return Err(Error::validation(format!(
                    "Invalid enforcement mode: {}. Must be 'strict', 'advisory', or 'auto_fix'",
                    input.quality_config.enforcement_mode
                )))
            }
        };

        let quality_config = PdmtQualityConfig {
            enforcement_mode,
            coverage_threshold: input.quality_config.coverage_threshold,
            max_complexity: input.quality_config.max_complexity,
            require_doctests: input.quality_config.require_doctests,
            require_property_tests: input.quality_config.require_property_tests,
            require_examples: input.quality_config.require_examples,
            zero_satd_tolerance: input.quality_config.zero_satd_tolerance,
        };

        // Generate deterministic todos
        let todo_list = self
            .service
            .generate_todos(
                input.requirements,
                input.project_name,
                &input.granularity,
                quality_config,
            )
            .map_err(|e| Error::internal(format!("Failed to generate todos: {e}")))?;

        // Run quality enforcement validation
        let quality_validation = self
            .quality_enforcer
            .enforce_quality_standards(&todo_list)
            .await
            .map_err(|e| Error::internal(format!("Quality validation failed: {e}")))?;

        // Calculate summary statistics
        let total_todos = todo_list.todos.len();
        let estimated_total_hours: f32 = todo_list.todos.iter().map(|t| t.estimated_hours).sum();

        // Prepare output
        let output = PdmtOutput {
            success: quality_validation.overall_passed,
            message: if quality_validation.overall_passed {
                format!(
                        "Successfully generated {total_todos} deterministic todos with quality enforcement"
                    )
            } else {
                format!(
                        "Generated {total_todos} todos but quality validation failed. Review violations."
                    )
            },
            todo_list: Some(
                serde_json::to_value(&todo_list)
                    .map_err(|e| Error::internal(format!("Failed to serialize todo list: {e}")))?,
            ),
            quality_validation: Some(serde_json::to_value(&quality_validation).map_err(|e| {
                Error::internal(format!("Failed to serialize validation results: {e}"))
            })?),
            total_todos,
            estimated_total_hours,
        };

        if quality_validation.overall_passed {
            info!(
                "Successfully generated {} todos totaling {} hours",
                total_todos, estimated_total_hours
            );
        } else {
            error!(
                "Quality validation failed with {} recommendations",
                quality_validation.recommendations.len()
            );
        }

        serde_json::to_value(output)
            .map_err(|e| Error::internal(format!("Serialization error: {e}")))
    }
}