From 36418a54abec00809173eea3fd75fe4c9c493d53 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 29 Oct 2026 22:58:24 +0000 Subject: [PATCH 1/2] style(rust): reconcile repository with CI rustfmt --- crates/squabble-cli/src/chains.rs | 24 +++++++---- crates/squabble-cli/src/fetch.rs | 32 +++++++------- crates/squabble-cli/src/zero_job.rs | 24 ++++++++--- crates/squabble-core/src/moves.rs | 5 ++- crates/squabble-core/src/startup.rs | 39 +++++++++-------- crates/squabble-fight/src/startup.rs | 62 +++++++++++++++------------- crates/squabble-forge/src/rest.rs | 16 +++++-- 7 files changed, 116 insertions(+), 86 deletions(-) diff --git a/crates/squabble-cli/src/chains.rs b/crates/squabble-cli/src/chains.rs index 545f587..6c532ba 100644 --- a/crates/squabble-cli/src/chains.rs +++ b/crates/squabble-cli/src/chains.rs @@ -239,9 +239,9 @@ fn collect( } squabble_core::startup::CanonicalResolution::Canonical => {} squabble_core::startup::CanonicalResolution::Unverified { reason } => { - graph - .notes - .push(format!("canonical name for `{written}` unverified: {reason}")); + graph.notes.push(format!( + "canonical name for `{written}` unverified: {reason}" + )); } } } @@ -283,7 +283,9 @@ fn narrate(r: &ChainsReport) -> String { o.push_str(&format!(" {repo}: {line}\n")); } if !r.canonical.is_empty() { - o.push_str("\ncanonical names (REST, redirects followed — names compared, pins untouched):\n"); + o.push_str( + "\ncanonical names (REST, redirects followed — names compared, pins untouched):\n", + ); for (written, canonical) in &r.canonical { o.push_str(&format!( " {written} → {canonical} (MOVED — repoint, same pin)\n" @@ -473,8 +475,10 @@ mod tests { const APP: &str = "jobs:\n gov:\n uses: me/standards/.github/workflows/gov.yml@1111111111111111111111111111111111111111\n b:\n steps:\n - uses: me/dead-action@v1\n - uses: actions/checkout@v4\n"; const GOV: &str = "jobs:\n x:\n steps:\n - uses: actions/checkout@v5\n"; const MOVED_APP: &str = "jobs:\n gov:\n uses: old/stds/.github/workflows/gov.yml@2222222222222222222222222222222222222222\n"; - const SKEW_A: &str = "jobs:\n a:\n steps:\n - uses: old/lib@1111111111111111111111111111111111111111\n"; - const SKEW_B: &str = "jobs:\n b:\n steps:\n - uses: new/lib@2222222222222222222222222222222222222222\n"; + const SKEW_A: &str = + "jobs:\n a:\n steps:\n - uses: old/lib@1111111111111111111111111111111111111111\n"; + const SKEW_B: &str = + "jobs:\n b:\n steps:\n - uses: new/lib@2222222222222222222222222222222222222222\n"; /// A REST fake: resolves every requested name as canonical unless the test /// declares a move or a 404 for it. @@ -733,9 +737,11 @@ mod tests { assert_eq!(a.follow, 2); assert!(a.json); assert!(!a.no_canonical); - assert!(parse_args(&["--no-canonical".into(), "gh:me/y".into()]) - .unwrap() - .no_canonical); + assert!( + parse_args(&["--no-canonical".into(), "gh:me/y".into()]) + .unwrap() + .no_canonical + ); assert!(parse_args(&[]).is_err()); assert!(parse_args(&["--batch".into(), "0".into(), "x".into()]).is_err()); assert!(parse_args(&["--nope".into()]).is_err()); diff --git a/crates/squabble-cli/src/fetch.rs b/crates/squabble-cli/src/fetch.rs index c802869..42a8378 100644 --- a/crates/squabble-cli/src/fetch.rs +++ b/crates/squabble-cli/src/fetch.rs @@ -424,22 +424,22 @@ fn parse_policy(perms_json: &str, selected_json: Option<&str>) -> Result ExitCode { }, } } else { - collect(&slug, &snapshot.files, runs, &GhRest, allow_list.as_ref(), notes) + collect( + &slug, + &snapshot.files, + runs, + &GhRest, + allow_list.as_ref(), + notes, + ) }; if args.json { @@ -279,9 +286,16 @@ fn narrate(r: &ZeroJobReport) -> String { Some(n) => format!("{n} job(s)"), None => "job count unreadable".to_string(), }; - o.push_str(&format!("\nrun {} · {} ({jobs})\n", run.run_id, run.workflow)); + o.push_str(&format!( + "\nrun {} · {} ({jobs})\n", + run.run_id, run.workflow + )); for a in &run.attributions { - o.push_str(&format!(" [{}] {}\n", a.class.label().to_uppercase(), a.describe())); + o.push_str(&format!( + " [{}] {}\n", + a.class.label().to_uppercase(), + a.describe() + )); if let Some(m) = a.proposed_move() { o.push_str(&format!(" move: {}\n", m.describe())); } @@ -330,9 +344,7 @@ impl GhRuns { the token's Actions read scope" )) } - s if !(200..300).contains(&s) => { - return Err(format!("`{path}` returned HTTP {s}")) - } + s if !(200..300).contains(&s) => return Err(format!("`{path}` returned HTTP {s}")), _ => {} } let mut runs = parse_startup_runs(&resp.body)?; diff --git a/crates/squabble-core/src/moves.rs b/crates/squabble-core/src/moves.rs index 4f8c095..7ea4421 100644 --- a/crates/squabble-core/src/moves.rs +++ b/crates/squabble-core/src/moves.rs @@ -604,8 +604,9 @@ mod tests { // the pin; admission only lets the check start. Neither drops a // required context nor weakens a check. Move::RepointToCanonical { - written: "old/stds/.github/workflows/gov.yml@8f2ee50841e216cd8c192eeb68953118190f105c" - .into(), + written: + "old/stds/.github/workflows/gov.yml@8f2ee50841e216cd8c192eeb68953118190f105c" + .into(), canonical: "hyperpolymath/standards".into(), pin: "8f2ee50841e216cd8c192eeb68953118190f105c".into(), }, diff --git a/crates/squabble-core/src/startup.rs b/crates/squabble-core/src/startup.rs index 3824b93..705611a 100644 --- a/crates/squabble-core/src/startup.rs +++ b/crates/squabble-core/src/startup.rs @@ -398,8 +398,8 @@ pub fn attribute_zero_job( // verified Marketplace creator. Creator status is not resolvable from here, // so the admission is unknown: leave it unattributed rather than instructing // the owner to change a policy that may already admit it. - let admission_unknown = allow_list - .is_some_and(|a| a.admission_unknown(&effective, kind == EdgeKind::Action)); + let admission_unknown = + allow_list.is_some_and(|a| a.admission_unknown(&effective, kind == EdgeKind::Action)); // A dead coordinate has no canonical target to repoint to. That is a dead // upstream (chains' blocking finding), not an admission fix — say so and @@ -649,9 +649,8 @@ mod tests { #[test] fn a_moved_reusable_is_a_first_class_class_with_a_same_pin_repoint() { - let written = format!( - "hyperpolymath/standards-old/.github/workflows/governance-reusable.yml@{SHA}" - ); + let written = + format!("hyperpolymath/standards-old/.github/workflows/governance-reusable.yml@{SHA}"); let a = attribute_zero_job( CALLER, WF, @@ -688,17 +687,17 @@ mod tests { let raw = format!("old/stds/.github/workflows/gov.yml@{SHA}"); let c = Coordinate::parse(&raw).expect("parse"); assert_eq!(c.owner_repo, "old/stds"); - assert_eq!( - c.path.as_deref(), - Some(".github/workflows/gov.yml") - ); + assert_eq!(c.path.as_deref(), Some(".github/workflows/gov.yml")); assert_eq!( c.rewritten("new/stds"), format!("new/stds/.github/workflows/gov.yml@{SHA}") ); // A tag pin is carried just as literally — never resolved on the way. let tag = Coordinate::parse("old/stds/.github/workflows/gov.yml@v2").unwrap(); - assert_eq!(tag.rewritten("new/stds"), "new/stds/.github/workflows/gov.yml@v2"); + assert_eq!( + tag.rewritten("new/stds"), + "new/stds/.github/workflows/gov.yml@v2" + ); } #[test] @@ -750,10 +749,7 @@ mod tests { Some(&allow(&[])), ); assert_eq!(a.class, StartupFailureClass::AllowListAdmissionRequired); - assert!(a - .sequencing - .first() - .is_some_and(|s| s.contains("EMPTY"))); + assert!(a.sequencing.first().is_some_and(|s| s.contains("EMPTY"))); assert!(a.required_allow_list_pattern.is_some()); } @@ -770,10 +766,7 @@ mod tests { ); // Repoint first: the workflow cannot even be found under the old name. assert_eq!(a.class, StartupFailureClass::MovedCoordinate); - assert_eq!( - a.required_allow_list_pattern.as_deref(), - Some("new/stds@*") - ); + assert_eq!(a.required_allow_list_pattern.as_deref(), Some("new/stds@*")); assert!(a.sequencing[0].contains("repoint")); assert!(a.sequencing[1].contains("new/stds@*")); assert!(matches!( @@ -810,7 +803,10 @@ mod tests { Some(&allow(&["actions/*"])), ); assert_eq!(a.class, StartupFailureClass::AllowListAdmissionRequired); - assert_eq!(a.required_allow_list_pattern.as_deref(), Some("new/action@*")); + assert_eq!( + a.required_allow_list_pattern.as_deref(), + Some("new/action@*") + ); } #[test] @@ -888,7 +884,10 @@ mod tests { }; assert!(!no_gh.covers("actions/checkout")); assert!(a.covers("actions/checkout")); - assert_eq!(no_gh.missing_pattern("actions/checkout").as_deref(), Some("actions/checkout@*")); + assert_eq!( + no_gh.missing_pattern("actions/checkout").as_deref(), + Some("actions/checkout@*") + ); } #[test] diff --git a/crates/squabble-fight/src/startup.rs b/crates/squabble-fight/src/startup.rs index 9e0f419..91d899b 100644 --- a/crates/squabble-fight/src/startup.rs +++ b/crates/squabble-fight/src/startup.rs @@ -61,20 +61,15 @@ pub fn attribute_workflow( let mut out: Vec = Vec::new(); for edge in crate::chains::extract_edges(&RepoId::new(repo), &wf) { let written = coordinate_of(&edge); - let resolution = canonical - .get(&edge.to) - .cloned() - .unwrap_or(CanonicalResolution::Unverified { - reason: "canonical name was not resolved".to_string(), - }); - let attribution = attribute_zero_job( - repo, - workflow, - &written, - edge.kind, - &resolution, - allow_list, - ); + let resolution = + canonical + .get(&edge.to) + .cloned() + .unwrap_or(CanonicalResolution::Unverified { + reason: "canonical name was not resolved".to_string(), + }); + let attribution = + attribute_zero_job(repo, workflow, &written, edge.kind, &resolution, allow_list); if !out.contains(&attribution) { out.push(attribution); } @@ -292,7 +287,13 @@ jobs: canonical: "hyperpolymath/standards".into(), }, )]); - let out = attribute_run(CALLER, &run(40_451_601_571, "hypatia-scan.yml"), &files, &names, None); + let out = attribute_run( + CALLER, + &run(40_451_601_571, "hypatia-scan.yml"), + &files, + &names, + None, + ); assert_eq!(out.len(), 1, "{out:#?}"); let a = &out[0]; assert_eq!(a.repo, CALLER); @@ -304,9 +305,7 @@ jobs: assert_eq!(a.canonical.as_deref(), Some("hyperpolymath/standards")); assert_eq!(a.class, StartupFailureClass::MovedCoordinate); match a.proposed_move() { - Some(Move::RepointToCanonical { - canonical, pin, .. - }) => { + Some(Move::RepointToCanonical { canonical, pin, .. }) => { assert_eq!(canonical, "hyperpolymath/standards"); assert_eq!(pin, SHA); } @@ -364,7 +363,10 @@ jobs: Some(&allow), ); assert_eq!(out.len(), 1); - assert_eq!(out[0].class, StartupFailureClass::AllowListAdmissionRequired); + assert_eq!( + out[0].class, + StartupFailureClass::AllowListAdmissionRequired + ); assert_eq!( out[0].required_allow_list_pattern.as_deref(), Some("old/standards@*") @@ -395,13 +397,7 @@ jobs: #[test] fn a_missing_workflow_file_is_unattributed_not_clean() { - let out = attribute_run( - CALLER, - &run(3, "deleted.yml"), - &[], - &BTreeMap::new(), - None, - ); + let out = attribute_run(CALLER, &run(3, "deleted.yml"), &[], &BTreeMap::new(), None); assert_eq!(out.len(), 1); assert_eq!(out[0].class, StartupFailureClass::Unattributed); assert!(out[0].evidence.contains("not in the local checkout")); @@ -479,7 +475,10 @@ jobs: .to_string(); let err = parse_startup_runs(&body).expect_err("must refuse"); assert!(err.contains("no unsigned integer `id`"), "{err}"); - assert!(err.contains("gov.yml"), "the error must name the run: {err}"); + assert!( + err.contains("gov.yml"), + "the error must name the run: {err}" + ); // A non-integer id is refused the same way, and a healthy run without an // id is still ignored: it is not a startup failure. @@ -499,13 +498,18 @@ jobs: fn malformed_run_payloads_are_errors_not_empty_successes() { assert!(parse_startup_runs("not json").is_err()); assert!(parse_startup_runs("{}").is_err()); - assert!(parse_startup_runs("{\"workflow_runs\":[]}").unwrap().is_empty()); + assert!(parse_startup_runs("{\"workflow_runs\":[]}") + .unwrap() + .is_empty()); } #[test] fn job_counts_are_read_strictly() { assert_eq!(parse_job_count("{\"total_count\":0}").unwrap(), 0); - assert_eq!(parse_job_count("{\"total_count\":0,\"jobs\":[]}").unwrap(), 0); + assert_eq!( + parse_job_count("{\"total_count\":0,\"jobs\":[]}").unwrap(), + 0 + ); assert!(parse_job_count("{}").is_err()); assert!(parse_job_count("[]").is_err()); } diff --git a/crates/squabble-forge/src/rest.rs b/crates/squabble-forge/src/rest.rs index c1a600f..b2d9fa6 100644 --- a/crates/squabble-forge/src/rest.rs +++ b/crates/squabble-forge/src/rest.rs @@ -337,7 +337,8 @@ mod tests { #[test] fn headers_and_body_are_separated_at_the_blank_line() { - let raw = "HTTP/2.0 200 OK\r\nContent-Type: application/json\r\n\r\n{\"full_name\":\"a/b\"}\n"; + let raw = + "HTTP/2.0 200 OK\r\nContent-Type: application/json\r\n\r\n{\"full_name\":\"a/b\"}\n"; let resp = parse_included(raw); assert_eq!(resp.status, 200); assert_eq!(resp.body.trim(), "{\"full_name\":\"a/b\"}"); @@ -346,7 +347,8 @@ mod tests { #[test] fn a_location_header_is_kept_even_when_gh_exits_non_zero() { - let raw = "HTTP/2.0 301 Moved Permanently\nLocation: https://api.github.com/repos/new/name\n\n"; + let raw = + "HTTP/2.0 301 Moved Permanently\nLocation: https://api.github.com/repos/new/name\n\n"; let resp = parse_included(raw); assert_eq!(resp.status, 301); assert_eq!( @@ -462,7 +464,10 @@ mod tests { ), ]); let (out, _) = resolve_canonical(&rest, &[r("ghost/repo")]); - assert_eq!(out.get(&r("ghost/repo")), Some(&CanonicalResolution::NotFound)); + assert_eq!( + out.get(&r("ghost/repo")), + Some(&CanonicalResolution::NotFound) + ); } #[test] @@ -573,7 +578,10 @@ mod tests { canonical: "new/lib".into() }) ); - assert_eq!(out.get(&r("gone/repo")), Some(&CanonicalResolution::NotFound)); + assert_eq!( + out.get(&r("gone/repo")), + Some(&CanonicalResolution::NotFound) + ); assert!(matches!( out.get(&r("rate/limited")), Some(CanonicalResolution::Unverified { .. }) From 5702549ad3e0322ba3a30219ff2ffcb84db5ab56 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 29 Oct 2026 23:01:03 +0000 Subject: [PATCH 2/2] fix(clippy): simplify canonical RepoId mapping --- crates/squabble-core/src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/squabble-core/src/chains.rs b/crates/squabble-core/src/chains.rs index 5bf93a6..29741bf 100644 --- a/crates/squabble-core/src/chains.rs +++ b/crates/squabble-core/src/chains.rs @@ -262,7 +262,7 @@ impl RepoSnapshot { pub fn canonical_id(&self) -> RepoId { self.canonical .as_deref() - .map(|c| RepoId::new(c)) + .map(RepoId::new) .unwrap_or_else(|| self.repo.clone()) } }