fix(workflow,skills): portable receipt report path; clippy type alias; warm rustfmt in test

- Workflow receipts rendered the report path with Path::display, so Windows
  emitted `.codewhale\reports\<id>.md`. written_run_report now returns a
  `/`-joined workspace-relative string on every platform (fixes the two
  windows-latest workflow receipt tests).
- parse_frontmatter's return type tripped clippy::type_complexity under
  -D warnings; name it with a `Frontmatter<'a>` alias.
- patch_normalizes_rust_in_an_already_clean_file warms the rustfmt proxy
  first: a cold Windows runner exceeded the 5s formatter budget on the first
  launch (5.23s), which skips normalization by design. Pre-existing flake,
  passes on other branches in 1.4-3.1s.

Local: cargo clippy -p codewhale-tui --all-targets --all-features with CI
flags clean; cargo test -p codewhale-tui --lib (workflow, apply_patch,
rust_format, skills filters) 415 passed, 0 failed; cargo fmt --check and
git diff --check clean; check-versions.sh --range-audit-advisory OK.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01R9rJEoMuUSRWznU6QjkE7h
This commit is contained in:
CodeWhale BotandClaude Opus 5.5 committed 2026-09-25 15:16:08 -07:00
1 parent 9225bed083
commit 8bc34f9bf4
4 files changed
+21 -6

No files matched your search

+4 -1
View File
@@ -762,6 +762,9 @@ fn is_valid_skill_name(name: &str) -> bool {
.all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '-')
}
/// Parsed frontmatter: lowercased metadata keys and the body after the fence.
pub(crate) type Frontmatter<'a> = (HashMap<String, String>, &'a str);
/// Split a Markdown file into its `---` frontmatter metadata and body.
///
/// Returns `Ok(None)` when the file does not open with a `---` fence. Keys are
@@ -770,7 +773,7 @@ fn is_valid_skill_name(name: &str) -> bool {
/// one frontmatter reader: skills and Claude Code agent files both use it.
pub(crate) fn parse_frontmatter(
content: &str,
) -> std::result::Result<Option<(HashMap<String, String>, &str)>, String> {
) -> std::result::Result<Option<Frontmatter<'_>>, String> {
if !content.trim_start().starts_with("---") {
return Ok(None);
}
+6
View File
@@ -1677,6 +1677,12 @@ mod tests {
/// text, so the model's next patch context matches the bytes on disk.
#[tokio::test]
async fn patch_normalizes_rust_in_an_already_clean_file() {
// Warm the `rustfmt` proxy first: on a cold CI runner the first rustup
// shim launch alone can exceed the formatter's 5s budget, which skips
// normalization (by design) and fails this test for the wrong reason.
let _ = std::process::Command::new("rustfmt")
.arg("--version")
.output();
let tmp = tempdir().expect("tempdir");
let ctx = ToolContext::new(tmp.path().to_path_buf());
let file = tmp.path().join("clean.rs");
+1 -2
View File
@@ -337,8 +337,7 @@ fn finish_workflow_controller(state: &WorkflowWorkspaceState, record: &WorkflowR
"child_count": record.child_ids.len(),
"detail": { "tool": "workflow", "action": "status", "run_id": truncate_chars(&record.run_id, 64) },
});
let report = written_run_report(&controller.driver.workspace, &record.run_id)
.map(|path| path.display().to_string());
let report = written_run_report(&controller.driver.workspace, &record.run_id);
if let Some(report) = &report {
receipt["report"] = json!(report);
}
+10 -3
View File
@@ -52,10 +52,17 @@ fn run_report_relative_path(run_id: &str) -> Option<PathBuf> {
}
/// The run's report path relative to the workspace, only when the report
/// was actually written.
pub(super) fn written_run_report(workspace: &Path, run_id: &str) -> Option<PathBuf> {
/// was actually written. Always `/`-separated: the path is shown to the model
/// and the user in receipts, and must read the same on every platform.
pub(super) fn written_run_report(workspace: &Path, run_id: &str) -> Option<String> {
let relative = run_report_relative_path(run_id)?;
workspace.join(&relative).is_file().then_some(relative)
workspace.join(&relative).is_file().then(|| {
relative
.components()
.map(|part| part.as_os_str().to_string_lossy())
.collect::<Vec<_>>()
.join("/")
})
}
/// Bounded preview of a raw `responseSchema` reply for run records and