#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn handle_bug_report(
title: Option<&str>,
dry_run: bool,
interactive: bool,
clear: bool,
) -> Result<()> {
use crate::cli::colors as c;
if clear {
clear_error()?;
println!("{}", c::pass("Cleared captured error"));
return Ok(());
}
let error = load_error()?.context(
"No captured error found. Run a pmat command that fails first, \
or the error capture may not be enabled.",
)?;
println!("{} Captured error from: {}", c::label(""), c::path(&error.command));
println!(" {}: {}", c::dim("PMAT Version"), error.version);
println!(" {}: {}", c::dim("OS"), error.os);
println!(" {}: {}", c::dim("Timestamp"), error.timestamp);
println!();
let mut redacted_error = error.clone();
redacted_error.redact_paths();
let issue_content = generate_issue_markdown(&redacted_error, title);
let parts: Vec<&str> = issue_content.splitn(2, "\n---\n").collect();
let issue_title = parts
.first()
.unwrap_or(&"Bug report")
.strip_prefix("TITLE: ")
.unwrap_or("Bug report");
let issue_body = parts.get(1).unwrap_or(&"");
if dry_run {
println!("{} Generated Issue (dry-run):\n", c::label(""));
println!("{}: {}", c::dim("Title"), issue_title);
println!("{}", c::separator());
println!("{}", issue_body);
return Ok(());
}
if interactive {
println!("{} Generated Issue:\n", c::label(""));
println!("{}: {}", c::dim("Title"), issue_title);
println!("{}", c::separator());
println!("{}", issue_body);
println!();
print!("Create this issue? [Y/n] ");
use std::io::Write;
std::io::stdout().flush()?;
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
let input = input.trim().to_lowercase();
if input == "n" || input == "no" {
println!("{}", c::fail("Cancelled"));
return Ok(());
}
}
create_github_issue(issue_title, issue_body)?;
clear_error()?;
Ok(())
}
fn create_github_issue(title: &str, body: &str) -> Result<()> {
use crate::cli::colors as c;
let gh_check = Command::new("gh").arg("--version").output();
if gh_check.is_err() {
return Err(anyhow::anyhow!(
"GitHub CLI (gh) not found. Install it from: https://cli.github.com/"
));
}
println!("{}", c::label("Creating GitHub issue..."));
let output = Command::new("gh")
.args([
"issue",
"create",
"--repo",
"paiml/paiml-mcp-agent-toolkit",
"--title",
title,
"--body",
body,
"--label",
"bug",
])
.output()
.context("Failed to run gh issue create")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("Failed to create issue: {}", stderr));
}
let stdout = String::from_utf8_lossy(&output.stdout);
println!("{} Created: {}", c::pass(""), c::path(stdout.trim()));
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn capture_command_error(command: &str, args: &[String], error: &str) {
let captured = CapturedError::new(command, args, error);
if let Err(e) = crate::services::error_capture::save_error(&captured) {
eprintln!("Warning: Failed to capture error for bug reporting: {}", e);
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn capture_command_error_with_code(command: &str, args: &[String], error: &str, code: i32) {
let captured = CapturedError::new(command, args, error).with_exit_code(code);
if let Err(e) = crate::services::error_capture::save_error(&captured) {
eprintln!("Warning: Failed to capture error for bug reporting: {}", e);
}
}