From f1175d33db05cae911f978d15f5e659a36e43168 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 13:38:51 +0000 Subject: [PATCH 1/4] chore(ci): cargo fmt, gitleaks SHA exemption, playground template owner Three small fixes for reds that main shows since its workflows run again. - src/rust/proof_search.rs: `cargo fmt` with the pinned 1.99.0 toolchain. Rust CI on main (run 42351375993) failed only at the fmt step; this is the only file the workspace-wide `cargo fmt --all` changes. - .gitleaks.toml: an anchored exemption for one value, d3e4b485a2af90c92a8e18af0888cd19cb132cd9, the metadatastician/standards commit that workflow-linter.yml's lock refresh checks out as `authority_sha=`. It is a public git object id. Since #455 it trips generic-api-key on every PR's history scan. Measured with the CI-pinned gitleaks 8.18.4 and the estate baseline at the caller's pin: old config 2 findings with a planted look-alike (the SHA and the plant), new config 1 (the plant only), clean tree 0. - echidna-playground/ci-templates/governance.yml: the never-run template now names metadatastician/standards at the same pin as root's live governance.yml (a797d30), not the old owner at 861b5e9. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JHfuPCv1pEiqkQGG5DQASb --- .gitleaks.toml | 10 ++++++++ .../ci-templates/governance.yml | 4 +-- src/rust/proof_search.rs | 25 ++++++++----------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/.gitleaks.toml b/.gitleaks.toml index cd3ab63c..edf2fd5d 100644 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -41,3 +41,13 @@ paths = [ '''(^|/)models/premise_vocab\.txt$''', ] + +# One exact value each, anchored, never a path: a credential planted in the +# same file is still caught (estate baseline, "prefer a value entry"). +regexes = [ + # Commit SHA of metadatastician/standards that workflow-linter.yml's lock + # refresh checks out as `authority_sha=` and re-verifies with rev-parse. A + # public git object id, not a credential; generic-api-key reports it from + # #455 on (scanned 2026-11-09 with gitleaks 8.18.4: 1 finding, this one). + '''^d3e4b485a2af90c92a8e18af0888cd19cb132cd9$''', +] diff --git a/echidna-playground/ci-templates/governance.yml b/echidna-playground/ci-templates/governance.yml index a8135d52..88a975f0 100644 --- a/echidna-playground/ci-templates/governance.yml +++ b/echidna-playground/ci-templates/governance.yml @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MPL-2.0 # governance.yml — single wrapper calling the shared estate governance bundle -# in hyperpolymath/standards instead of carrying per-repo copies. +# in metadatastician/standards instead of carrying per-repo copies. # # Replaces the per-repo governance scaffolding removed in the same commit: # quality.yml, guix-guix-policy.yml, npm-bun-blocker.yml, ts-blocker.yml, @@ -23,4 +23,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@861b5e911d9e5dcfb3c0ab3dd2a9a3c8fd0a1613 + uses: metadatastician/standards/.github/workflows/governance-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12 # same pin as root .github/workflows/governance.yml diff --git a/src/rust/proof_search.rs b/src/rust/proof_search.rs index 3c90d3bf..949b63c9 100644 --- a/src/rust/proof_search.rs +++ b/src/rust/proof_search.rs @@ -384,7 +384,8 @@ mod chapel_ffi { let start = start.clone(); std::thread::spawn(move || { start.wait(); - let strategy = ChapelParallelSearch::new().expect("real Chapel runtime"); + let strategy = + ChapelParallelSearch::new().expect("real Chapel runtime"); assert_eq!(ChapelParallelSearch::available_prover_count(), 0); for _ in 0..2 { assert!(strategy.available()); @@ -414,10 +415,8 @@ mod chapel_ffi { // No global environment mutation races with other Rust tests, and // no external prover can be dispatched by this allocation/free probe. let empty_path = tempfile::tempdir().expect("empty prover search directory"); - let mut command = real_probe_command( - "real_search_without_provers_fails_and_frees_result", - CHILD, - ); + let mut command = + real_probe_command("real_search_without_provers_fails_and_frees_result", CHILD); command.env("PATH", empty_path.path()); run_real_probe( &mut command, @@ -478,7 +477,10 @@ mod chapel_ffi { matches!(stopped_before_cleanup, Ok(true)), "deadline returned with a live or unobservable prover: {stopped_before_cleanup:?}" ); - assert!(elapsed < Duration::from_secs(3), "deadline took {elapsed:?}"); + assert!( + elapsed < Duration::from_secs(3), + "deadline took {elapsed:?}" + ); let result = result.expect("native timeout returns a failed search result"); assert!(!result.success); assert_eq!( @@ -500,17 +502,12 @@ mod chapel_ffi { .expect("write finite prover"); std::fs::set_permissions(&prover, std::fs::Permissions::from_mode(0o700)) .expect("make finite prover executable"); - let mut command = real_probe_command( - "real_search_deadline_stops_the_owned_prover", - CHILD, - ); + let mut command = + real_probe_command("real_search_deadline_stops_the_owned_prover", CHILD); command .env("PATH", fixture.path()) .env(PID_FILE, fixture.path().join("prover.pid")); - run_real_probe( - &mut command, - "ECHIDNA_REAL_CHAPEL_DEADLINE_PROBE_COMPLETED", - ); + run_real_probe(&mut command, "ECHIDNA_REAL_CHAPEL_DEADLINE_PROBE_COMPLETED"); } } } From 08d74c8c4bb4ef98b1cd10f959ff6b7b026e7ca1 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 14:17:36 +0000 Subject: [PATCH 2/4] fix(ci): rename authority_sha so gitleaks stops reading a commit id as a key generic-api-key matched `authority_sha=<40 hex>` in workflow-linter.yml only because the variable name contains "auth". The previous commit suppressed it with a value entry in .gitleaks.toml, which the governance exemption ratchet correctly rejected (.gitleaks.toml: 2 -> 3). Fix it at the source instead: the variable is now standards_rev, and the .gitleaks.toml entry is removed, so the ledger is back to 2 entries. gitleaks 8.18.4 with the estate baseline staged: - old name, no entry: 1 finding (generic-api-key workflow-linter.yml:80) - new name, no entry: 0 findings - new name plus a planted ghp_ token beside it: 1 finding (still caught) actionlint: clean. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JHfuPCv1pEiqkQGG5DQASb --- .github/workflows/workflow-linter.yml | 6 +++--- .gitleaks.toml | 10 ---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml index 12080ac9..77441bea 100644 --- a/.github/workflows/workflow-linter.yml +++ b/.github/workflows/workflow-linter.yml @@ -77,12 +77,12 @@ jobs: gh extension install github/gh-actions-lock --pin v0.2.0 authority="$RUNNER_TEMP/lock-authority" subject="$RUNNER_TEMP/lock-subject" - authority_sha=d3e4b485a2af90c92a8e18af0888cd19cb132cd9 + standards_rev=d3e4b485a2af90c92a8e18af0888cd19cb132cd9 git init -q "$authority" git -C "$authority" remote add origin https://github.com/metadatastician/standards.git - git -C "$authority" fetch -q --depth 1 origin "$authority_sha" + git -C "$authority" fetch -q --depth 1 origin "$standards_rev" git -C "$authority" checkout -q --detach FETCH_HEAD - test "$(git -C "$authority" rev-parse HEAD)" = "$authority_sha" + test "$(git -C "$authority" rev-parse HEAD)" = "$standards_rev" source_sha=$(git rev-parse HEAD) git clone -q --no-hardlinks "$GITHUB_WORKSPACE" "$subject" git -C "$subject" checkout -q --detach "$source_sha" diff --git a/.gitleaks.toml b/.gitleaks.toml index edf2fd5d..cd3ab63c 100644 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -41,13 +41,3 @@ paths = [ '''(^|/)models/premise_vocab\.txt$''', ] - -# One exact value each, anchored, never a path: a credential planted in the -# same file is still caught (estate baseline, "prefer a value entry"). -regexes = [ - # Commit SHA of metadatastician/standards that workflow-linter.yml's lock - # refresh checks out as `authority_sha=` and re-verifies with rev-parse. A - # public git object id, not a credential; generic-api-key reports it from - # #455 on (scanned 2026-11-09 with gitleaks 8.18.4: 1 finding, this one). - '''^d3e4b485a2af90c92a8e18af0888cd19cb132cd9$''', -] From 198622c24c78d3e121af478c54aec3684e7a43c2 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 14:21:13 +0000 Subject: [PATCH 3/4] fix(deps): rmcp 3.5.0 -> 3.9.0 for RUSTSEC-2026-0457/-0461/-0462 Dependency audit fails on every PR, this one included, because rmcp 3.5.0 (crates/echidna-mcp) has three advisories, the newest published 2026-11-05, after main last passed. Ported from hyperpolymath/echidna#465 so this PR does not wait on it: `cargo update -p rmcp --precise 3.9.0` with the pinned 1.99.0 toolchain, inside the existing "3" requirement. The other lock lines are the resolver re-unifying around rmcp 3.9.0's new sha2/libc dependencies. The resulting Cargo.lock is byte-identical to #465's, so whichever merges first leaves the other a no-op. scripts/ci/audit-dependencies.sh with cargo-audit 0.22.2: Cargo.lock and fuzz/Cargo.lock both PASSED. cargo check -p echidna-mcp --locked: passes. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JHfuPCv1pEiqkQGG5DQASb --- Cargo.lock | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bf91e23..0592b0e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,7 +133,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -144,7 +144,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -640,7 +640,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1246,7 +1246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2093,7 +2093,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2837,20 +2837,22 @@ dependencies = [ [[package]] name = "rmcp" -version = "3.5.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fae7019994ae0fe4ada40b732f798f3ff26f0f04facb1477f1bf37eb4f18a2d3" +checksum = "d24a7e92f4bcaa36b97fa93c4fa7ca8f3e669eced949345b3462dba333c7f909" dependencies = [ "base64 0.23.1", "chrono", "futures", "indexmap", + "libc", "pastey", "pin-project-lite", "rmcp-macros", "schemars", "serde", "serde_json", + "sha2 0.11.0", "thiserror", "tokio", "tokio-util", @@ -2860,9 +2862,9 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "3.5.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e66877136e969d5a2d561ee5841b17717a0619aebd64abb47a2a2f46e34683" +checksum = "b3140f24a766f80f9ec1607bde85680959a69b83d46fa9ce87dadab7e67ab029" dependencies = [ "darling 0.24.0", "proc-macro2", @@ -2910,7 +2912,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3251,7 +3253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3391,10 +3393,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4198,7 +4200,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] From 5276657f533c9cede676f553a0f27801619eb372 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 9 Nov 2026 14:34:30 +0000 Subject: [PATCH 4/4] fix(ci): reasoned inline hypatia allows on the nine Zig callback casts (port of #465) governance / Validate Hypatia Baseline fails on main and so here: Hypatia reports code_safety/zig_ptr_cast and zig_align_cast (high) on the nine `@ptrCast(@alignCast(raw))` lines in src/zig_ffi/. Each cast recovers a callback's own *@This() from the type-erased *anyopaque it was registered with (runtime_owner.Work.context or a std.mem.Allocator vtable ptr), so type and alignment are the original ones. Ported from hyperpolymath/echidna#465 (f48fe0a) so this PR does not wait on it: one reasoned `hypatia: allow -- ` per rule per line, no baseline entry, no code change. Both files are byte-identical to #465's. Inline directives are not an exemption-ratchet ledger. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JHfuPCv1pEiqkQGG5DQASb --- src/zig_ffi/chapel_bridge.zig | 15 ++++++++++----- src/zig_ffi/runtime_owner.zig | 12 ++++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/zig_ffi/chapel_bridge.zig b/src/zig_ffi/chapel_bridge.zig index 807c23fe..f8d12591 100644 --- a/src/zig_ffi/chapel_bridge.zig +++ b/src/zig_ffi/chapel_bridge.zig @@ -70,7 +70,8 @@ fn callOnOwner(owner: anytype, comptime function: anytype, args: anytype, result result: @TypeOf(result), fn run(raw: *anyopaque) void { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds self.result.* = @call(.auto, function, self.arguments); } }; @@ -650,7 +651,8 @@ const CallerAllocator = struct { } fn alloc(raw: *anyopaque, len: usize, alignment: std.mem.Alignment, ret_addr: usize) ?[*]u8 { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds if (!self.record() or self.allocations >= self.fail_after) return null; const pointer = std.heap.c_allocator.rawAlloc(len, alignment, ret_addr) orelse return null; self.allocations += 1; @@ -659,7 +661,8 @@ const CallerAllocator = struct { } fn resize(raw: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) bool { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds _ = self.record(); _ = memory; _ = alignment; @@ -669,7 +672,8 @@ const CallerAllocator = struct { } fn remap(raw: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds _ = self.record(); _ = memory; _ = alignment; @@ -679,7 +683,8 @@ const CallerAllocator = struct { } fn free(raw: *anyopaque, memory: []u8, alignment: std.mem.Alignment, ret_addr: usize) void { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds _ = self.record(); // The backing allocator is cross-thread safe so a failed assertion // never requires corrupting memory or leaking the test allocation. diff --git a/src/zig_ffi/runtime_owner.zig b/src/zig_ffi/runtime_owner.zig index 79d9d543..da2f1b8a 100644 --- a/src/zig_ffi/runtime_owner.zig +++ b/src/zig_ffi/runtime_owner.zig @@ -169,7 +169,8 @@ const Probe = struct { } fn work(raw: *anyopaque) void { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds self.wrong_thread = self.wrong_thread or self.init_id != std.Thread.getCurrentId(); self.calls += 1; } @@ -239,7 +240,8 @@ test "shutdown drains accepted work and refuses new work before joining" { shutdown_failed: bool = false, fn work(raw: *anyopaque) void { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds self.mutex.lock(); self.entered = true; self.changed.broadcast(); @@ -311,7 +313,8 @@ test "owner callbacks cannot re-enter or finalize themselves" { stop_refused: bool = false, fn work(raw: *anyopaque) void { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds var nested = Work{ .context = self.probe, .run = Probe.work }; self.call_refused = if (self.owner.call(&nested)) |_| false else |err| err == error.ReentrantCall; self.stop_refused = if (self.owner.shutdown()) |_| false else |err| err == error.ReentrantCall; @@ -358,7 +361,8 @@ test "a nonowner process-exit request refuses active work without a join cycle" exit_refused: bool = false, fn work(raw: *anyopaque) void { - const self: *@This() = @ptrCast(@alignCast(raw)); + // hypatia: allow code_safety/zig_ptr_cast -- raw is the type-erased *@This() this callback was registered with + const self: *@This() = @ptrCast(@alignCast(raw)); // hypatia: allow code_safety/zig_align_cast -- same pointer, so @This() alignment holds self.mutex.lock(); self.entered = true; self.changed.broadcast();