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
16 changes: 8 additions & 8 deletions .trinity/seals/claw_ClawGates.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:e83faa16fdda54ccb71a5cef820dcbcb0b115a1a964b1b769e8efa3fe4f46de4",
"gen_hash_rust": "sha256:f5a230d83ed3b53022cda5241bcb97a98a6f7d35118813dd896bfd94a408db57",
"gen_hash_verilog": "sha256:e60c97323fe49104fa91dec8d4d70db8c3070acb09e10955bae928b09a0aaeac",
"gen_hash_zig": "sha256:2bb85ab7683c3ce5f9e68d5cdeec753084408e7c0b36e65e68a3aba22a8312e8",
"gen_hash_c": "sha256:5ea99f4bd997bc13d2fbe28e6c2233288882316921a77b3629cae88dc9c98bb3",
"gen_hash_rust": "sha256:6ffb149e2944c1cbfdea5fc806fdf457ff6134c9dfeec6d516ab25a55f9a6196",
"gen_hash_verilog": "sha256:9a8147bffc70fa6445ab2e5b07adb5d8e9394998701a175e9cf956002a60ede3",
"gen_hash_zig": "sha256:29203b78b4748ecea4123004d55f88435200878599e3d41c511c8b24679fefde",
"module": "ClawGates",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T22:41:04Z",
"sealed_at": "2026-10-18T22:53:22Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:944d2af8d1a9f6ad261a527445f94922e3f299d5bb3657341f6f5cdc5c38f9c1",
"spec_hash": "sha256:020e33b38748419eb5d46d108a64adb0246f5b4c2ef9c83f06735daebcb1e0aa",
"spec_path": "specs/claw/gates.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 23,
"total": 23,
"passed": 24,
"total": 24,
"vacuous": 0
},
"toolchain": {
Expand Down
49 changes: 31 additions & 18 deletions gen/c/claw/gates.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ static const size_t CLASS_LABEL_LENS[3] = { 10, 6, 11 };
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);
size_t events_len_of(const char* name, size_t name_len);
uint32_t count_class(uint8_t c);
bool rows_filled(size_t name_lens[static 67], size_t event_lens[static 67]);
bool every_row_filled(void);
Expand Down Expand Up @@ -98,6 +99,15 @@ const char* events_of(const char* name, size_t name_len) {
return "";
}

size_t events_len_of(const char* name, size_t name_len) {
for (size_t i = 0; i < 67; i++) {
if (str_eq(NAMES[i], NAME_LENS[i], name, name_len)) {
return EVENT_LENS[i];
}
}
return 0;
}

uint32_t count_class(uint8_t c) {
uint32_t n = 0;
for (size_t i = 0; i < 67; i++) {
Expand Down Expand Up @@ -442,20 +452,26 @@ void test_rows_stay_aligned_name_class_events(void) {
const char* ol = "own-language";
const char* ev_qp = "push,schedule,workflow_dispatch";
const char* ev_ol = "pull_request";
assert((NAMES[1] == want1));
assert((str_eq(NAMES[1], NAME_LENS[1], want1, 20) == true));
assert((CLASSES[1] == G_REPORTING));
assert((NAMES[42] == want42));
assert((str_eq(NAMES[42], NAME_LENS[42], want42, 13) == true));
assert((CLASSES[42] == G_REPORTING));
assert((NAMES[29] == want29));
assert((str_eq(NAMES[29], NAME_LENS[29], want29, 14) == true));
assert((CLASSES[29] == G_SOFT));
assert((events_of(qp, 13) == ev_qp));
assert((events_of(ol, 12) == ev_ol));
assert((str_eq(events_of(qp, 13), events_len_of(qp, 13), ev_qp, 31) == true));
assert((str_eq(events_of(ol, 12), events_len_of(ol, 12), ev_ol, 12) == true));
}

void test_unknown_name_is_unknown_and_not_blocking(void) {
assert((class_of("no-such-gate", 12) == G_UNKNOWN));
assert((is_blocking("no-such-gate", 12) == false));
assert((events_of("no-such-gate", 12) == ""));
assert((events_len_of("no-such-gate", 12) == 0));
}

void test_events_len_of_answers_every_row(void) {
for (size_t i = 0; i < 67; i++) {
assert((events_len_of(NAMES[i], NAME_LENS[i]) == EVENT_LENS[i]));
}
}

void test_nightly_pair_contrast(void) {
Expand Down Expand Up @@ -523,14 +539,10 @@ void test_audit_ignores_blank_lines_in_the_directory(void) {
}

void test_audit_prefixes_name_the_problem_kind(void) {
const char* spec_only = LINE_PREFIX[P_SPEC_ONLY];
assert((spec_only == "SPEC-ONLY "));
const char* dir_only = LINE_PREFIX[P_DIR_ONLY];
assert((dir_only == "DIR-ONLY "));
const char* ok = LINE_PREFIX[P_OK];
assert((ok == ""));
const char* tail = DRIFT_TAIL;
assert((tail == "claw: DRIFT -- regenerate specs/claw/gates.t27 (docs/claw/README.md)"));
assert((str_eq(LINE_PREFIX[P_SPEC_ONLY], PREFIX_LENS[P_SPEC_ONLY], "SPEC-ONLY ", 11) == true));
assert((str_eq(LINE_PREFIX[P_DIR_ONLY], PREFIX_LENS[P_DIR_ONLY], "DIR-ONLY ", 11) == true));
assert((PREFIX_LENS[P_OK] == 0));
assert((str_eq(DRIFT_TAIL, DRIFT_TAIL_LEN, "claw: DRIFT -- regenerate specs/claw/gates.t27 (docs/claw/README.md)", 68) == true));
}

void test_every_row_round_trips_through_the_name_lookup(void) {
Expand All @@ -547,9 +559,9 @@ void test_every_row_round_trips_through_the_name_lookup(void) {
}

void test_soft_gates_report_their_events(void) {
assert((events_of("oracle-nightly", 14) == "schedule,workflow_dispatch"));
assert((events_of("queen-doctor", 12) == "schedule,workflow_dispatch"));
assert((events_of("rings-rust", 10) == "push,pull_request,workflow_dispatch"));
assert((str_eq(events_of("oracle-nightly", 14), events_len_of("oracle-nightly", 14), "schedule,workflow_dispatch", 26) == true));
assert((str_eq(events_of("queen-doctor", 12), events_len_of("queen-doctor", 12), "schedule,workflow_dispatch", 26) == true));
assert((str_eq(events_of("rings-rust", 10), events_len_of("rings-rust", 10), "push,pull_request,workflow_dispatch", 35) == true));
}

void test_coverage_report_carries_every_class(void) {
Expand Down Expand Up @@ -679,6 +691,7 @@ int main(void) {
test_class_census_62_3_2();
test_rows_stay_aligned_name_class_events();
test_unknown_name_is_unknown_and_not_blocking();
test_events_len_of_answers_every_row();
test_nightly_pair_contrast();
test_reporting_gates_never_block_a_merge();
test_audit_clean_when_directory_matches_inventory();
Expand All @@ -694,7 +707,7 @@ int main(void) {
test_a_hole_in_either_column_fails_the_filled_check();
test_a_repeated_name_is_caught_wherever_it_sits();
test_a_class_outside_the_three_is_unknown();
printf("All %d tests passed.\n", 23);
printf("All %d tests passed.\n", 24);
return 0;
}
#endif /* T27_TEST_MAIN */
Expand Down
50 changes: 33 additions & 17 deletions specs/claw/gates.t27
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ pub fn events_of(name: str, name_len: usize) -> str {
return "";
}

/// Length of events_of(name); 0 when the name is not in the inventory. A caller that lowers
/// through gen-c compares the result with str_eq and this length: `events_of(x) == "..."` would
/// lower to a C pointer comparison (#8013).
pub fn events_len_of(name: str, name_len: usize) -> usize {
for i in 0..67 {
if str_eq(NAMES[i], NAME_LENS[i], name, name_len) { return EVENT_LENS[i]; }
}
return 0;
}

/// How many workflows carry a given class.
pub fn count_class(c: u8) -> u32 {
let mut n : u32 = 0;
Expand Down Expand Up @@ -448,20 +458,30 @@ test rows_stay_aligned_name_class_events {
var ol : str = "own-language";
var ev_qp : str = "push,schedule,workflow_dispatch";
var ev_ol : str = "pull_request";
assert NAMES[1] == want1;
// Every string compare carries its lengths through str_eq: `==` on str lowers to a C
// pointer comparison under gen-c (#8013, #10698).
assert str_eq(NAMES[1], NAME_LENS[1], want1, 20) == true;
assert CLASSES[1] == G_REPORTING;
assert NAMES[42] == want42;
assert str_eq(NAMES[42], NAME_LENS[42], want42, 13) == true;
assert CLASSES[42] == G_REPORTING;
assert NAMES[29] == want29;
assert str_eq(NAMES[29], NAME_LENS[29], want29, 14) == true;
assert CLASSES[29] == G_SOFT;
assert events_of(qp, 13) == ev_qp;
assert events_of(ol, 12) == ev_ol;
assert str_eq(events_of(qp, 13), events_len_of(qp, 13), ev_qp, 31) == true;
assert str_eq(events_of(ol, 12), events_len_of(ol, 12), ev_ol, 12) == true;
}

test unknown_name_is_unknown_and_not_blocking {
assert class_of("no-such-gate", 12) == G_UNKNOWN;
assert is_blocking("no-such-gate", 12) == false;
assert events_of("no-such-gate", 12) == "";
assert events_len_of("no-such-gate", 12) == 0;
}

test events_len_of_answers_every_row {
// Every row through the length lookup, so a lookup that returned the wrong row's length, or
// the sentinel for a known name, fails here and not only on the five rows named above.
for i in 0..67 {
assert events_len_of(NAMES[i], NAME_LENS[i]) == EVENT_LENS[i];
}
}

test nightly_pair_contrast {
Expand Down Expand Up @@ -536,14 +556,10 @@ test audit_ignores_blank_lines_in_the_directory {
}

test audit_prefixes_name_the_problem_kind {
var spec_only : str = LINE_PREFIX[P_SPEC_ONLY];
assert spec_only == "SPEC-ONLY ";
var dir_only : str = LINE_PREFIX[P_DIR_ONLY];
assert dir_only == "DIR-ONLY ";
var ok : str = LINE_PREFIX[P_OK];
assert ok == "";
var tail : str = DRIFT_TAIL;
assert tail == "claw: DRIFT -- regenerate specs/claw/gates.t27 (docs/claw/README.md)";
assert str_eq(LINE_PREFIX[P_SPEC_ONLY], PREFIX_LENS[P_SPEC_ONLY], "SPEC-ONLY ", 11) == true;
assert str_eq(LINE_PREFIX[P_DIR_ONLY], PREFIX_LENS[P_DIR_ONLY], "DIR-ONLY ", 11) == true;
assert PREFIX_LENS[P_OK] == 0;
assert str_eq(DRIFT_TAIL, DRIFT_TAIL_LEN, "claw: DRIFT -- regenerate specs/claw/gates.t27 (docs/claw/README.md)", 68) == true;
}
test every_row_round_trips_through_the_name_lookup {
// Before T8, 8 of 66 names ever went through class_of -- a class swap
Expand All @@ -566,9 +582,9 @@ test soft_gates_report_their_events {
// events_of answered for blocking and reporting rows before T8; the
// three soft rows were assumed. Lengths are hand-counted literals
// (gen-c carries no .len); the tables are pinned in gates_pins.t27.
assert events_of("oracle-nightly", 14) == "schedule,workflow_dispatch";
assert events_of("queen-doctor", 12) == "schedule,workflow_dispatch";
assert events_of("rings-rust", 10) == "push,pull_request,workflow_dispatch";
assert str_eq(events_of("oracle-nightly", 14), events_len_of("oracle-nightly", 14), "schedule,workflow_dispatch", 26) == true;
assert str_eq(events_of("queen-doctor", 12), events_len_of("queen-doctor", 12), "schedule,workflow_dispatch", 26) == true;
assert str_eq(events_of("rings-rust", 10), events_len_of("rings-rust", 10), "push,pull_request,workflow_dispatch", 35) == true;
}

test coverage_report_carries_every_class {
Expand Down
Loading