Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .trinity/seals/claw_ClawGates.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:723a598914ee23e57be303db50d42531cc4e060b0dc2f4cb56234e53ef1f545c",
"gen_hash_rust": "sha256:a959e6e61dbce9d00050932baed8e74633a5ce6e4a6dc376f9ee3c5494445473",
"gen_hash_verilog": "sha256:27185ecb4aa7e109f3c9fb7280863ac2fff7f4262bf8b02b9c3177612079580f",
"gen_hash_zig": "sha256:d96163a4182c592c121c7cf497d5770791f41fb7fb382300b2d79dee3ef3c79e",
"gen_hash_c": "sha256:e83faa16fdda54ccb71a5cef820dcbcb0b115a1a964b1b769e8efa3fe4f46de4",
"gen_hash_rust": "sha256:f5a230d83ed3b53022cda5241bcb97a98a6f7d35118813dd896bfd94a408db57",
"gen_hash_verilog": "sha256:e60c97323fe49104fa91dec8d4d70db8c3070acb09e10955bae928b09a0aaeac",
"gen_hash_zig": "sha256:2bb85ab7683c3ce5f9e68d5cdeec753084408e7c0b36e65e68a3aba22a8312e8",
"module": "ClawGates",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T22:24:12Z",
"sealed_at": "2026-10-18T22:41:04Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:1976cf9af48f8799d5d7584648c3cca97ca35d0ccd31b5019b0a1fed909f1e90",
"spec_hash": "sha256:944d2af8d1a9f6ad261a527445f94922e3f299d5bb3657341f6f5cdc5c38f9c1",
"spec_path": "specs/claw/gates.t27",
"tests": {
"failed": 0,
Expand Down
22 changes: 11 additions & 11 deletions .trinity/seals/claw_ClawGatesPins.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
{
"built_by": "t27c-bootstrap@0.5.2+4ab200073",
"built_by": "t27c-bootstrap@0.5.2+9448ab4be",
"closure": [
{
"spec": "specs/claw/gates.t27",
"spec_hash": "sha256:3ae3db764f44ce4e0c45b8c7af6f17db39755e3c23be43c17a75409394a0a32d"
"spec_hash": "sha256:944d2af8d1a9f6ad261a527445f94922e3f299d5bb3657341f6f5cdc5c38f9c1"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:cd501815d2c74fa080136736e0518a67b592c44a853000153812721f8e8ea57d",
"gen_hash_rust": "sha256:af20324af83bbf7f3eba345a64033ca44fca7934a470055624ec381a77ff74e3",
"gen_hash_verilog": "sha256:1e0ce75eba74ad61a29409655a21add1b64eafd9d90a7c12d748d4173f082478",
"gen_hash_zig": "sha256:ca3b9d27acacfadaeea3cedd46f29834c25e2e258819017d71653a3a24df473b",
"gen_hash_c": "sha256:9b019d7001ef279fa03cb313208c21af916bcd0b04a18301b3ba9a11b61c4c7e",
"gen_hash_rust": "sha256:82c7f3aa3cdb72a027efb1f3c66b96052c7dfdb63d0be68a44458ff8d694e240",
"gen_hash_verilog": "sha256:0ae1fdb0af1f915ab3ec0b2926c26061de7ca11cf1d76919464dda405b48b3f5",
"gen_hash_zig": "sha256:7ad136326adee3ce56c546e7d70a4f5d8a7283ffd0f12b9efbdde3a31a5d3036",
"module": "ClawGatesPins",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T09:41:14Z",
"sealed_at": "2026-10-18T22:41:06Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:e18a7800770e75607f68b089aaa38880e490276fbe6706372b0e302bb990238c",
"spec_hash": "sha256:a6ab857762046c32d4b9b1314e8709e2e74a1b6faada15b2d38aeecb7fab5ef8",
"spec_path": "specs/claw/gates_pins.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 5,
"total": 5,
"passed": 6,
"total": 6,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
31 changes: 17 additions & 14 deletions gen/c/claw/gates.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
static const const char* NAMES[67] = { "agent-runner-docker", "auto-merge-ready-prs", "bootstrap-tests", "build-paper", "build-vivado-image", "catalog-count-gate", "cli-tri", "conflict-markers", "conformance-integrity-gate", "coq-kernel", "coq-proofs", "corpus-ratchet", "damage-negatives", "deploy-api", "documented-commands", "dupe-ratchet", "emit-bitexact-gate", "exhaustive-nightly", "fix-carries-source", "fpga-build", "gate-topology", "gf-wide-conformance", "gf16-conformance", "harness-scratch", "issue-gate", "l1-traceability", "lean-proofs", "loop-tools-gate", "needs-boundary", "oracle-nightly", "orphan-modules", "own-language", "pack-index-consistency-gate", "phi-loop-ci", "pr-budget", "pr-dashboard", "pusher", "queen-doctor", "queen-export-push", "queen-feed-empty-bodies", "queen-feed-roadmap", "queen-feed-untested", "queen-publish", "queen-refile", "queen-watchdog", "release", "rings-rust", "sandbox-docker", "sbom", "schema-validation", "scorecard", "seal-coverage", "seal-staleness-warn", "secret-scan", "sign-release", "spec-guards", "spec-parse-ratchet", "t27b-native", "t27o-golden", "t27o-release", "untrusted-input-gate", "verilog-widths", "vivado-synth", "wasm-explorer", "withdrawn-live-gate", "xilinx7-l3-bench", "zenodo-publish" };
static const size_t NAME_LENS[67] = { 19, 20, 15, 11, 18, 18, 7, 16, 26, 10, 10, 14, 16, 10, 19, 12, 18, 18, 18, 10, 13, 19, 16, 15, 10, 15, 11, 15, 14, 14, 14, 12, 27, 11, 9, 12, 6, 12, 17, 23, 18, 19, 13, 12, 14, 7, 10, 14, 4, 17, 9, 13, 19, 11, 12, 11, 18, 11, 11, 12, 20, 14, 12, 13, 19, 16, 14 };
static const uint8_t CLASSES[67] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const size_t EVENT_LENS[67] = { 22, 46, 35, 35, 17, 30, 17, 35, 35, 35, 35, 35, 35, 22, 35, 35, 30, 26, 30, 35, 44, 35, 35, 35, 37, 30, 30, 35, 26, 26, 35, 12, 35, 30, 19, 30, 26, 26, 26, 26, 26, 26, 31, 26, 26, 7, 35, 22, 30, 35, 54, 35, 30, 35, 25, 35, 35, 35, 13, 4, 35, 35, 17, 17, 35, 30, 25 };
static const const char* EVENTS[67] = { "push,workflow_dispatch", "schedule,pull_request_target,workflow_dispatch", "push,pull_request,workflow_dispatch", "push,pull_request,workflow_dispatch", "workflow_dispatch", "pull_request,workflow_dispatch", "pull_request,push", "pull_request,push,workflow_dispatch", "push,pull_request,workflow_dispatch", "push,pull_request,workflow_dispatch", "push,pull_request,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,push,workflow_dispatch", "push,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,workflow_dispatch", "schedule,workflow_dispatch", "pull_request,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,push,workflow_dispatch,schedule", "push,pull_request,workflow_dispatch", "push,pull_request,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request_target,workflow_dispatch", "pull_request,workflow_dispatch", "pull_request,workflow_dispatch", "pull_request,push,workflow_dispatch", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request", "push,pull_request,workflow_dispatch", "pull_request,workflow_dispatch", "pull_request_target", "workflow_dispatch,pull_request", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "push,schedule,workflow_dispatch", "schedule,workflow_dispatch", "schedule,workflow_dispatch", "release", "push,pull_request,workflow_dispatch", "push,workflow_dispatch", "push,release,workflow_dispatch", "pull_request,push,workflow_dispatch", "branch_protection_rule,schedule,push,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,workflow_dispatch", "push,pull_request,workflow_dispatch", "release,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,push,workflow_dispatch", "pull_request,push,workflow_dispatch", "workflow_call", "push", "pull_request,push,workflow_dispatch", "pull_request,push,workflow_dispatch", "workflow_dispatch", "push,pull_request", "pull_request,push,workflow_dispatch", "workflow_dispatch,pull_request", "release,workflow_dispatch" };
#define P_OK 0
#define P_SPEC_ONLY 1
Expand Down Expand Up @@ -53,7 +54,7 @@ uint8_t class_of(const char* name, size_t name_len);
bool is_blocking(const char* name, size_t name_len);
const char* events_of(const char* name, size_t name_len);
uint32_t count_class(uint8_t c);
bool rows_filled(const char* names[static 67], const char* events[static 67]);
bool rows_filled(size_t name_lens[static 67], size_t event_lens[static 67]);
bool every_row_filled(void);
bool names_unique_in(const char* names[static 67], size_t lens[static 67]);
bool all_names_unique(void);
Expand Down Expand Up @@ -107,20 +108,20 @@ uint32_t count_class(uint8_t c) {
return n;
}

bool rows_filled(const char* names[static 67], const char* events[static 67]) {
bool rows_filled(size_t name_lens[static 67], size_t event_lens[static 67]) {
for (size_t i = 0; i < 67; i++) {
if ((names[i] == "")) {
if ((name_lens[i] == 0)) {
return false;
}
if ((events[i] == "")) {
if ((event_lens[i] == 0)) {
return false;
}
}
return true;
}

bool every_row_filled(void) {
return rows_filled(NAMES, EVENTS);
return rows_filled(NAME_LENS, EVENT_LENS);
}

bool names_unique_in(const char* names[static 67], size_t lens[static 67]) {
Expand Down Expand Up @@ -604,19 +605,21 @@ void test_coverage_report_lines_are_exact(void) {
}

void test_a_hole_in_either_column_fails_the_filled_check(void) {
assert((rows_filled(NAMES, EVENTS) == true));
const char* n[67] = {0};
assert((rows_filled(NAME_LENS, EVENT_LENS) == true));
size_t n[67] = {0};
for (size_t i = 0; i < 67; i++) {
n[i] = NAMES[i];
n[i] = NAME_LENS[i];
}
n[66] = "";
assert((rows_filled(n, EVENTS) == false));
const char* e[67] = {0};
n[66] = 0;
assert((rows_filled(n, EVENT_LENS) == false));
size_t e[67] = {0};
for (size_t i = 0; i < 67; i++) {
e[i] = EVENTS[i];
e[i] = EVENT_LENS[i];
}
e[0] = "";
assert((rows_filled(NAMES, e) == false));
e[0] = 0;
assert((rows_filled(NAME_LENS, e) == false));
e[0] = 1;
assert((rows_filled(NAME_LENS, e) == true));
}

void test_a_repeated_name_is_caught_wherever_it_sits(void) {
Expand Down
54 changes: 39 additions & 15 deletions specs/claw/gates.t27
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,25 @@ pub const CLASSES : [67]u8 = [
0, 0,
];

/// Length of EVENTS[i], parallel row, for the same reason as NAME_LENS: gen-c carries no .len.
/// specs/claw/gates_pins.t27 pins each row to EVENTS[i].len.
pub const EVENT_LENS : [67]usize = [
22, 46, 35, 35, 17,
30, 17, 35, 35,
35, 35, 35, 35, 22,
35, 35, 30, 26, 30,
35, 44, 35, 35, 35,
37, 30, 30, 35, 26,
26, 35, 12, 35, 30,
19, 30, 26, 26, 26, 26,
26, 26, 31, 26, 26,
7, 35, 22, 30, 35,
54, 35, 30, 35, 25,
35, 35, 35, 13, 4,
35, 35, 17, 17, 35,
30, 25,
];

/// Trigger keys of row i, comma-joined, as measured 2026-10-12 (see header).
pub const EVENTS : [67]str = [
"push,workflow_dispatch", "schedule,pull_request_target,workflow_dispatch", "push,pull_request,workflow_dispatch", "push,pull_request,workflow_dispatch", "workflow_dispatch",
Expand Down Expand Up @@ -151,18 +170,20 @@ pub fn count_class(c: u8) -> u32 {

/// Every row of a table shaped like this one has a name and a recorded trigger set. The
/// columns are parameters so a test can hand in a copy with one hole: a check that only reads
/// the constant table can never fail, and no mutant of it can die (#10686).
pub fn rows_filled(names: [67]str, events: [67]str) -> bool {
/// the constant table can never fail, and no mutant of it can die (#10686). It reads the length
/// columns, not the strings: gen-c lowers `s == ""` to a C pointer comparison, so in the
/// committed gates.c an empty-string test compared addresses, not contents.
pub fn rows_filled(name_lens: [67]usize, event_lens: [67]usize) -> bool {
for i in 0..67 {
if names[i] == "" { return false; }
if events[i] == "" { return false; }
if name_lens[i] == 0 { return false; }
if event_lens[i] == 0 { return false; }
}
return true;
}

/// Every row of the inventory has a name and a recorded trigger set.
pub fn every_row_filled() -> bool {
return rows_filled(NAMES, EVENTS);
return rows_filled(NAME_LENS, EVENT_LENS);
}

/// No name appears twice in a name column (with its length column).
Expand Down Expand Up @@ -575,7 +596,7 @@ test coverage_report_carries_every_class {
// The length-table pins live in specs/claw/gates_pins.t27: they read .len on
// strings, which the zig runner executes and the gen-c backend cannot lower,
// so they sit in a companion module that is never gen-c'd. A wrong number in
// NAME_LENS/PREFIX_LENS/SUFFIX_LENS/*_LEN fails there, not silently here.
// NAME_LENS/EVENT_LENS/PREFIX_LENS/SUFFIX_LENS/*_LEN fails there, not silently here.

test audit_tail_line_matches_the_count {
// The runner prints the report; the tail must say what the count says.
Expand Down Expand Up @@ -616,15 +637,18 @@ test coverage_report_lines_are_exact {
}

test a_hole_in_either_column_fails_the_filled_check {
assert rows_filled(NAMES, EVENTS) == true;
var n : [67]str = undefined;
for i in 0..67 { n[i] = NAMES[i]; }
n[66] = "";
assert rows_filled(n, EVENTS) == false;
var e : [67]str = undefined;
for i in 0..67 { e[i] = EVENTS[i]; }
e[0] = "";
assert rows_filled(NAMES, e) == false;
assert rows_filled(NAME_LENS, EVENT_LENS) == true;
var n : [67]usize = undefined;
for i in 0..67 { n[i] = NAME_LENS[i]; }
n[66] = 0;
assert rows_filled(n, EVENT_LENS) == false;
var e : [67]usize = undefined;
for i in 0..67 { e[i] = EVENT_LENS[i]; }
e[0] = 0;
assert rows_filled(NAME_LENS, e) == false;
// One byte is enough: the check asks "empty or not", never "how long".
e[0] = 1;
assert rows_filled(NAME_LENS, e) == true;
}

test a_repeated_name_is_caught_wherever_it_sits {
Expand Down
10 changes: 9 additions & 1 deletion specs/claw/gates_pins.t27
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
; specs/claw/gates_pins.t27 -- the length-table pins for specs/claw/gates.t27.
; gates.t27 carries every string length explicitly (NAME_LENS, PREFIX_LENS,
; gates.t27 carries every string length explicitly (NAME_LENS, EVENT_LENS, PREFIX_LENS,
; SUFFIX_LENS, HEAD_LEN, OK_TAIL_LEN, DRIFT_TAIL_LEN) because the gen-c backend
; lowers str to const char* and cannot express .len; those tables are the one
; hand-generated input to that idiom, and a wrong number there would miscompare
Expand All @@ -22,6 +22,14 @@ test name_lens_pin_every_row_to_the_bytes {
}
}

test event_lens_pin_every_row_to_the_bytes {
// every_row_filled reads EVENT_LENS, not EVENTS: a zero here for a filled row, or a
// nonzero length for an emptied one, would make the filled check lie.
for i in 0..67 {
assert gates::EVENT_LENS[i] == gates::EVENTS[i].len;
}
}

test report_lens_pin_their_strings {
for k in 0..3 {
assert gates::PREFIX_LENS[k] == gates::LINE_PREFIX[k].len;
Expand Down
Loading