From 269ce7501897872f27c4f9fdeddff069ce9fea10 Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Mon, 19 Oct 2026 08:04:30 +0700 Subject: [PATCH] test(claw): kill the real t27f_gate.t27 mutation survivors (#10740) Eleven tests against the 53 survivors of the t27f_gate sweep. 35 are now caught; the 18 left are equivalent (a loop bound one past an empty range, an equal value reassigned, a field bound that only an empty field reaches). Production code is unchanged. Resealed ClawT27fGate and the four seals that record t27f_gate.t27 as a dependency (ClawT27fGatePins, t27f deps_card, spec_deps, why_card), and regenerated gen/c/claw/t27f_gate.c, which carries the tests. Co-Authored-By: Claude Opus 5.5 --- .trinity/seals/claw_ClawT27fGate.json | 20 ++-- .trinity/seals/claw_ClawT27fGatePins.json | 8 +- .trinity/seals/t27f_t27f_deps_card.json | 4 +- .trinity/seals/t27f_t27f_spec_deps.json | 4 +- .trinity/seals/t27f_t27f_why_card.json | 4 +- gen/c/claw/t27f_gate.c | 132 +++++++++++++++++++++- specs/claw/t27f_gate.t27 | 122 ++++++++++++++++++++ 7 files changed, 273 insertions(+), 21 deletions(-) diff --git a/.trinity/seals/claw_ClawT27fGate.json b/.trinity/seals/claw_ClawT27fGate.json index 712fbb49ea..d37cb00927 100644 --- a/.trinity/seals/claw_ClawT27fGate.json +++ b/.trinity/seals/claw_ClawT27fGate.json @@ -1,5 +1,5 @@ { - "built_by": "t27c-bootstrap@0.5.2+043cdea36", + "built_by": "t27c-bootstrap@0.5.2+9448ab4be", "closure": [ { "spec": "specs/ci/affected.t27", @@ -19,27 +19,27 @@ } ], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:f04634c3086d38301f1099fd9e14e5a10f61abac58441271c080bc1abcab9c9c", - "gen_hash_rust": "sha256:cdafe83e3bfa9e4fae5d727c58ff3ea74be36bff109ae7f643b32770db78e7e5", - "gen_hash_verilog": "sha256:0eff930fe14e25bf33a511ab0015c3040678d2ff0818000f6a80efdc0527278c", - "gen_hash_zig": "sha256:bdbcb346f994bed18e49299cd96c51abb8ac22a128b8ab02a48079a69b490e46", + "gen_hash_c": "sha256:adb37d1db380dad43f9f084b6dd3f3ddb2c4a907df064da67007b0cf470e6fff", + "gen_hash_rust": "sha256:4a2e4f1ba4da95cb8af40a056ac8d189f25c3fca40ef273a039138e42a4d7645", + "gen_hash_verilog": "sha256:ed477594da235d12667966a7a526714964ad24098c0460dc8c80b3ef406ffa60", + "gen_hash_zig": "sha256:420efd4fb4ef6e72b1a30a1369f0cd93f757499c5784819ec97c45fd03de5d44", "module": "ClawT27fGate", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T07:41:52Z", + "sealed_at": "2026-10-19T01:02:57Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:856be049f9ef3de20cce2f7d18ca3b78a5f4a8ad660dddd8f2cf1aa97bc61ee7", + "spec_hash": "sha256:6d43c460d2c289c77ed6096962348af419c1cf328f18d4db3806ab4ed72c0b9e", "spec_path": "specs/claw/t27f_gate.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 28, - "total": 28, + "passed": 39, + "total": 39, "vacuous": 0 }, "toolchain": { - "test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d", + "test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10", "zig": "0.16.0" } } \ No newline at end of file diff --git a/.trinity/seals/claw_ClawT27fGatePins.json b/.trinity/seals/claw_ClawT27fGatePins.json index 8b84ae2bbe..e9a22c3f4a 100644 --- a/.trinity/seals/claw_ClawT27fGatePins.json +++ b/.trinity/seals/claw_ClawT27fGatePins.json @@ -1,9 +1,9 @@ { - "built_by": "t27c-bootstrap@0.5.2+043cdea36", + "built_by": "t27c-bootstrap@0.5.2+9448ab4be", "closure": [ { "spec": "specs/claw/t27f_gate.t27", - "spec_hash": "sha256:856be049f9ef3de20cce2f7d18ca3b78a5f4a8ad660dddd8f2cf1aa97bc61ee7" + "spec_hash": "sha256:6d43c460d2c289c77ed6096962348af419c1cf328f18d4db3806ab4ed72c0b9e" }, { "spec": "specs/t27f/hot.t27", @@ -18,7 +18,7 @@ "module": "ClawT27fGatePins", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T07:41:53Z", + "sealed_at": "2026-10-19T01:03:00Z", "sealed_by": "t27c-bootstrap@0.5.2", "spec_hash": "sha256:1a4fc11a3ee61e990b6226621b4379fe34a727f0d1c830004bfddb5640836666", "spec_path": "specs/claw/t27f_gate_pins.t27", @@ -31,7 +31,7 @@ "vacuous": 0 }, "toolchain": { - "test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d", + "test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10", "zig": "0.16.0" } } \ No newline at end of file diff --git a/.trinity/seals/t27f_t27f_deps_card.json b/.trinity/seals/t27f_t27f_deps_card.json index 65d4dbd6cb..98eb98d323 100644 --- a/.trinity/seals/t27f_t27f_deps_card.json +++ b/.trinity/seals/t27f_t27f_deps_card.json @@ -7,7 +7,7 @@ }, { "spec": "specs/claw/t27f_gate.t27", - "spec_hash": "sha256:856be049f9ef3de20cce2f7d18ca3b78a5f4a8ad660dddd8f2cf1aa97bc61ee7" + "spec_hash": "sha256:6d43c460d2c289c77ed6096962348af419c1cf328f18d4db3806ab4ed72c0b9e" }, { "spec": "specs/policy/text_lines.t27", @@ -34,7 +34,7 @@ "module": "t27f_deps_card", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-19T00:03:40Z", + "sealed_at": "2026-10-19T01:03:00Z", "sealed_by": "t27c-bootstrap@0.5.2", "spec_hash": "sha256:05e744da11ef490c883a7a46c9d5ee7869a1b21f50f1999e6dda0706d68b5f0d", "spec_path": "specs/t27f/deps_card.t27", diff --git a/.trinity/seals/t27f_t27f_spec_deps.json b/.trinity/seals/t27f_t27f_spec_deps.json index e9a0a1a744..68636c5ac7 100644 --- a/.trinity/seals/t27f_t27f_spec_deps.json +++ b/.trinity/seals/t27f_t27f_spec_deps.json @@ -7,7 +7,7 @@ }, { "spec": "specs/claw/t27f_gate.t27", - "spec_hash": "sha256:856be049f9ef3de20cce2f7d18ca3b78a5f4a8ad660dddd8f2cf1aa97bc61ee7" + "spec_hash": "sha256:6d43c460d2c289c77ed6096962348af419c1cf328f18d4db3806ab4ed72c0b9e" }, { "spec": "specs/policy/text_lines.t27", @@ -22,7 +22,7 @@ "module": "t27f_spec_deps", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T23:14:31Z", + "sealed_at": "2026-10-19T01:03:01Z", "sealed_by": "t27c-bootstrap@0.5.2", "spec_hash": "sha256:c6e6c03537dd7238ce7cceb937dfe307294ab59d4946de95f7d96e40333cb070", "spec_path": "specs/t27f/spec_deps.t27", diff --git a/.trinity/seals/t27f_t27f_why_card.json b/.trinity/seals/t27f_t27f_why_card.json index 47ea880754..78822d4827 100644 --- a/.trinity/seals/t27f_t27f_why_card.json +++ b/.trinity/seals/t27f_t27f_why_card.json @@ -7,7 +7,7 @@ }, { "spec": "specs/claw/t27f_gate.t27", - "spec_hash": "sha256:856be049f9ef3de20cce2f7d18ca3b78a5f4a8ad660dddd8f2cf1aa97bc61ee7" + "spec_hash": "sha256:6d43c460d2c289c77ed6096962348af419c1cf328f18d4db3806ab4ed72c0b9e" }, { "spec": "specs/policy/text_lines.t27", @@ -30,7 +30,7 @@ "module": "t27f_why_card", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T23:40:53Z", + "sealed_at": "2026-10-19T01:03:01Z", "sealed_by": "t27c-bootstrap@0.5.2", "spec_hash": "sha256:01381c902fe4b5702dc26505a0d081faa0895bfaf60ef51a529cfef894a8ae68", "spec_path": "specs/t27f/why_card.t27", diff --git a/gen/c/claw/t27f_gate.c b/gen/c/claw/t27f_gate.c index feb31d4306..b8d0968a3e 100644 --- a/gen/c/claw/t27f_gate.c +++ b/gen/c/claw/t27f_gate.c @@ -1280,6 +1280,125 @@ void test_no_annotation_text_can_break_its_line(void) { } } +void test_holds_never_reads_past_its_range(void) { + const char* s = "abc$"; + assert((holds(s, 0, 2, "abc$") == false)); + assert((holds(s, 0, 3, "abc$") == true)); +} + +void test_a_spec_hash_saved_as_missing_is_not_recorded(void) { + const char* out = "spec_hash: MISMATCH (saved=missing, current=sha256:bb)\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + uint8_t fl = seal_flags(out, 0, lit_len(out)); + assert((flag_on(fl, F_READ) == true)); + assert((flag_on(fl, F_RECORDED) == false)); + assert((flags_verdict(fl) == V_UNSEALED)); +} + +void test_negative_control_a_record_with_an_empty_path_or_no_url_is_unreadable(void) { + const char* no_url = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert((t27f_conclusion(no_url, lit_len(no_url)) == CONCL_FAILURE)); + const char* no_path = "repo\tgHashTag/trios\n@\t\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert((t27f_conclusion(no_path, lit_len(no_path)) == CONCL_FAILURE)); + const char* no_path_two = "repo\tgHashTag/trios\n@\t\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert((t27f_conclusion(no_path_two, lit_len(no_path_two)) == CONCL_FAILURE)); + const char* one_char = "repo\tgHashTag/trios\n@\ta\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert((t27f_conclusion(one_char, lit_len(one_char)) == CONCL_SUCCESS)); +} + +void test_a_record_with_no_output_lines_is_its_own_unreadable_row(void) { + uint8_t out[4096] = {0}; + const char* inp = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\n@\tspecs/b.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + size_t n = lit_len(inp); + assert((record_count(inp, n) == 2)); + assert((t27f_conclusion(inp, n) == CONCL_FAILURE)); + size_t w = t27f_report(inp, n, &out, 4096); + assert((holds(&out, 0, w, "T27F seals: 2 spec(s), 1 sealed, 0 neutral, 1 failing\n$") == true)); + assert((holds(&out, 0, w, "| `specs/a.t27` | `0123456789ab` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |\n| `specs/b.t27` | `0123456789ab` | - | - | sealed | reuse |$") == true)); + size_t a = t27f_annotations(inp, n, &out, 4096); + assert((holds(&out, 0, a, "specs/a.t27\t1\tfailure\tT27F seal: unreadable\t$") == true)); +} + +void test_the_repo_line_need_not_be_the_first_line(void) { + const char* late = "# header\nrepo\tgHashTag/ghashtag.github.io\n@\tt27/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MISMATCH (saved=sha256:aa, current=sha256:bb)\n$"; + assert((input_readable(late, lit_len(late)) == true)); + assert((t27f_conclusion(late, lit_len(late)) == CONCL_NEUTRAL)); +} + +void test_ten_and_its_powers_are_written_in_full(void) { + uint8_t out[64] = {0}; + size_t w = put_decimal(&out, 0, 64, 10); + assert((w == 2)); + assert((out[0] == '1')); + assert((out[1] == '0')); + w = put_decimal(&out, 0, 64, 100); + assert((holds(&out, 0, w, "100$") == true)); + assert((w == 3)); +} + +void test_the_query_keeps_every_letter_and_digit_at_its_bounds(void) { + uint8_t out[64] = {0}; + const char* q = "azAZ09-._~/:$"; + size_t w = put_query(&out, 0, 64, q, 0, lit_len(q)); + assert((w == lit_len(q))); + assert((holds(&out, 0, w, "azAZ09-._~/:$") == true)); + const char* edge = "`{@[$"; + w = put_query(&out, 0, 64, edge, 0, lit_len(edge)); + assert((holds(&out, 0, w, "%60%7B%40%5B$") == true)); +} + +void test_the_digest_and_graph_columns_show_exactly_their_fields(void) { + uint8_t out[4096] = {0}; + const char* inp = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\nError: parse error\n@\tspecs/b.t27\t0123456789abc\turl\nError: parse error\n@\tspecs/c.t27\t\turl\nError: parse error\n@\t\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nError: parse error\n$"; + size_t w = t27f_report(inp, lit_len(inp), &out, 4096); + assert((w < 4096)); + assert((holds(&out, 0, w, "| `specs/a.t27` | `0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef` | - | - | unreadable | - | - |$") == true)); + assert((holds(&out, 0, w, "| `specs/b.t27` | `0123456789ab` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |$") == true)); + assert((holds(&out, 0, w, "| `specs/c.t27` | `` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |$") == true)); + assert((holds(&out, 0, w, "| `` | `0123456789ab` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |$") == true)); +} + +void test_a_neutral_row_is_counted_as_neutral(void) { + uint8_t out[4096] = {0}; + const char* inp = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nError: No saved seal found at .trinity/seals/A.json. Run with --save first.\n$"; + size_t w = t27f_report(inp, lit_len(inp), &out, 4096); + assert((holds(&out, 0, w, "claw/t27f\nneutral\nT27F seals: 1 spec(s), 0 sealed, 1 neutral, 0 failing\n$") == true)); +} + +void test_a_report_or_annotations_that_fit_exactly_are_kept(void) { + uint8_t out[4096] = {0}; + const char* inp = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + size_t full = t27f_report(inp, lit_len(inp), &out, 4096); + assert((full < 4096)); + assert((t27f_report(inp, lit_len(inp), &out, full) == full)); + assert((holds(&out, 0, full, "claw/t27f\nsuccess\nT27F seals: 1 spec(s)$") == true)); + const char* empty = "repo\tgHashTag/trios\n$"; + size_t e = t27f_report(empty, lit_len(empty), &out, 4096); + assert((t27f_report(empty, lit_len(empty), &out, e) == e)); + assert((holds(&out, 0, e, "claw/t27f\nneutral\nT27F seals: no spec in scope\n$") == true)); + const char* bad = "@\tx\n$"; + size_t u = t27f_report(bad, lit_len(bad), &out, 4096); + assert((t27f_report(bad, lit_len(bad), &out, u) == u)); + assert((holds(&out, 0, u, "claw/t27f\nfailure\nT27F seals: the input could not be read\n$") == true)); + const char* one = "repo\tgHashTag/trios\n@\ta\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nError: parse error\n$"; + size_t a = t27f_annotations(one, lit_len(one), &out, 4096); + assert((holds(&out, 0, a, "a\t1\tfailure\tT27F seal: unreadable\t$") == true)); + assert((t27f_annotations(one, lit_len(one), &out, a) == a)); +} + +void test_negative_control_the_scope_reads_names_and_room_exactly(void) { + uint8_t set[512] = {0}; + const char* short = "x\n.t27\na\nspecs/.t27\n--graph\nspecs/z.t27\n$"; + assert((t27f_scope(short, lit_len(short), &set, 512) == 0)); + const char* two = "specs/c.t27\nspecs/d.t27\n--graph\n$"; + assert((t27f_scope(two, lit_len(two), &set, 12) == 13)); + const char* edge = "specs/c.t27\n--graph\nspecs/b.t27\tspecs/c.t27\n$"; + assert((t27f_scope(edge, lit_len(edge), &set, 12) == 13)); + const char* order = "specs/c.t27\n--graph\nspecs/z.t27\nspecs/x.t27\tspecs/y.t27\nspecs/b.t27\tspecs/c.t27\n$"; + size_t sn = t27f_scope(order, lit_len(order), &set, 512); + assert((in_set(&set, sn, "specs/b.t27", 0, 11) == true)); + assert((sn == 24)); +} + /* ------------------------------------------------------- Test runner (compile with -DT27_TEST_MAIN to execute) @@ -1316,7 +1435,18 @@ int main(void) { test_the_annotations_are_cut_into_batches_of_fifty(); test_negative_control_unreadable_input_or_no_room_writes_no_annotation(); test_no_annotation_text_can_break_its_line(); - printf("All %d tests passed.\n", 28); + test_holds_never_reads_past_its_range(); + test_a_spec_hash_saved_as_missing_is_not_recorded(); + test_negative_control_a_record_with_an_empty_path_or_no_url_is_unreadable(); + test_a_record_with_no_output_lines_is_its_own_unreadable_row(); + test_the_repo_line_need_not_be_the_first_line(); + test_ten_and_its_powers_are_written_in_full(); + test_the_query_keeps_every_letter_and_digit_at_its_bounds(); + test_the_digest_and_graph_columns_show_exactly_their_fields(); + test_a_neutral_row_is_counted_as_neutral(); + test_a_report_or_annotations_that_fit_exactly_are_kept(); + test_negative_control_the_scope_reads_names_and_room_exactly(); + printf("All %d tests passed.\n", 39); return 0; } #endif /* T27_TEST_MAIN */ diff --git a/specs/claw/t27f_gate.t27 b/specs/claw/t27f_gate.t27 index dfdc058cbb..b2854026a6 100644 --- a/specs/claw/t27f_gate.t27 +++ b/specs/claw/t27f_gate.t27 @@ -987,6 +987,128 @@ test no_annotation_text_can_break_its_line { } } +// The tests below were written against a mutation sweep of this file (#10740): each one fails +// under at least one mutant of the production code above that the earlier tests let through. + +test holds_never_reads_past_its_range { + const s : str = "abc$"; + assert holds(s, 0, 2, "abc$") == false; + assert holds(s, 0, 3, "abc$") == true; +} + +test a_spec_hash_saved_as_missing_is_not_recorded { + const out : str = "spec_hash: MISMATCH (saved=missing, current=sha256:bb)\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + const fl : u8 = seal_flags(out, 0, lit_len(out)); + assert flag_on(fl, F_READ) == true; + assert flag_on(fl, F_RECORDED) == false; + assert flags_verdict(fl) == V_UNSEALED; +} + +test negative_control_a_record_with_an_empty_path_or_no_url_is_unreadable { + const no_url : str = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert t27f_conclusion(no_url, lit_len(no_url)) == CONCL_FAILURE; + const no_path : str = "repo\tgHashTag/trios\n@\t\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert t27f_conclusion(no_path, lit_len(no_path)) == CONCL_FAILURE; + const no_path_two : str = "repo\tgHashTag/trios\n@\t\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert t27f_conclusion(no_path_two, lit_len(no_path_two)) == CONCL_FAILURE; + const one_char : str = "repo\tgHashTag/trios\n@\ta\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + assert t27f_conclusion(one_char, lit_len(one_char)) == CONCL_SUCCESS; +} + +test a_record_with_no_output_lines_is_its_own_unreadable_row { + var out : [4096]u8 = undefined; + const inp : str = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\n@\tspecs/b.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + const n : usize = lit_len(inp); + assert record_count(inp, n) == 2; + assert t27f_conclusion(inp, n) == CONCL_FAILURE; + const w : usize = t27f_report(inp, n, &out, 4096); + assert holds(&out, 0, w, "T27F seals: 2 spec(s), 1 sealed, 0 neutral, 1 failing\n$") == true; + assert holds(&out, 0, w, "| `specs/a.t27` | `0123456789ab` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |\n| `specs/b.t27` | `0123456789ab` | - | - | sealed | reuse |$") == true; + const a : usize = t27f_annotations(inp, n, &out, 4096); + assert holds(&out, 0, a, "specs/a.t27\t1\tfailure\tT27F seal: unreadable\t$") == true; +} + +test the_repo_line_need_not_be_the_first_line { + const late : str = "# header\nrepo\tgHashTag/ghashtag.github.io\n@\tt27/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MISMATCH (saved=sha256:aa, current=sha256:bb)\n$"; + assert input_readable(late, lit_len(late)) == true; + assert t27f_conclusion(late, lit_len(late)) == CONCL_NEUTRAL; +} + +test ten_and_its_powers_are_written_in_full { + var out : [64]u8 = undefined; + var w : usize = put_decimal(&out, 0, 64, 10); + assert w == 2; + assert out[0] == '1'; + assert out[1] == '0'; + w = put_decimal(&out, 0, 64, 100); + assert holds(&out, 0, w, "100$") == true; + assert w == 3; +} + +test the_query_keeps_every_letter_and_digit_at_its_bounds { + var out : [64]u8 = undefined; + const q : str = "azAZ09-._~/:$"; + var w : usize = put_query(&out, 0, 64, q, 0, lit_len(q)); + assert w == lit_len(q); + assert holds(&out, 0, w, "azAZ09-._~/:$") == true; + const edge : str = "`{@[$"; + w = put_query(&out, 0, 64, edge, 0, lit_len(edge)); + assert holds(&out, 0, w, "%60%7B%40%5B$") == true; +} + +test the_digest_and_graph_columns_show_exactly_their_fields { + var out : [4096]u8 = undefined; + const inp : str = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\nError: parse error\n@\tspecs/b.t27\t0123456789abc\turl\nError: parse error\n@\tspecs/c.t27\t\turl\nError: parse error\n@\t\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nError: parse error\n$"; + const w : usize = t27f_report(inp, lit_len(inp), &out, 4096); + assert w < 4096; + assert holds(&out, 0, w, "| `specs/a.t27` | `0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef` | - | - | unreadable | - | - |$") == true; + assert holds(&out, 0, w, "| `specs/b.t27` | `0123456789ab` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |$") == true; + assert holds(&out, 0, w, "| `specs/c.t27` | `` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |$") == true; + assert holds(&out, 0, w, "| `` | `0123456789ab` | - | - | unreadable | - | [view](https://t27.ai/t27f/graph/?src=url) |$") == true; +} + +test a_neutral_row_is_counted_as_neutral { + var out : [4096]u8 = undefined; + const inp : str = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nError: No saved seal found at .trinity/seals/A.json. Run with --save first.\n$"; + const w : usize = t27f_report(inp, lit_len(inp), &out, 4096); + assert holds(&out, 0, w, "claw/t27f\nneutral\nT27F seals: 1 spec(s), 0 sealed, 1 neutral, 0 failing\n$") == true; +} + +test a_report_or_annotations_that_fit_exactly_are_kept { + var out : [4096]u8 = undefined; + const inp : str = "repo\tgHashTag/trios\n@\tspecs/a.t27\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nspec_hash: MATCH\ngen_hash_zig: MATCH\ngen_hash_verilog: MATCH\ngen_hash_c: MATCH\ngen_hash_rust: MATCH\n$"; + const full : usize = t27f_report(inp, lit_len(inp), &out, 4096); + assert full < 4096; + assert t27f_report(inp, lit_len(inp), &out, full) == full; + assert holds(&out, 0, full, "claw/t27f\nsuccess\nT27F seals: 1 spec(s)$") == true; + const empty : str = "repo\tgHashTag/trios\n$"; + const e : usize = t27f_report(empty, lit_len(empty), &out, 4096); + assert t27f_report(empty, lit_len(empty), &out, e) == e; + assert holds(&out, 0, e, "claw/t27f\nneutral\nT27F seals: no spec in scope\n$") == true; + const bad : str = "@\tx\n$"; + const u : usize = t27f_report(bad, lit_len(bad), &out, 4096); + assert t27f_report(bad, lit_len(bad), &out, u) == u; + assert holds(&out, 0, u, "claw/t27f\nfailure\nT27F seals: the input could not be read\n$") == true; + const one : str = "repo\tgHashTag/trios\n@\ta\t0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\turl\nError: parse error\n$"; + const a : usize = t27f_annotations(one, lit_len(one), &out, 4096); + assert holds(&out, 0, a, "a\t1\tfailure\tT27F seal: unreadable\t$") == true; + assert t27f_annotations(one, lit_len(one), &out, a) == a; +} + +test negative_control_the_scope_reads_names_and_room_exactly { + var set : [512]u8 = undefined; + const short : str = "x\n.t27\na\nspecs/.t27\n--graph\nspecs/z.t27\n$"; + assert t27f_scope(short, lit_len(short), &set, 512) == 0; + const two : str = "specs/c.t27\nspecs/d.t27\n--graph\n$"; + assert t27f_scope(two, lit_len(two), &set, 12) == 13; + const edge : str = "specs/c.t27\n--graph\nspecs/b.t27\tspecs/c.t27\n$"; + assert t27f_scope(edge, lit_len(edge), &set, 12) == 13; + const order : str = "specs/c.t27\n--graph\nspecs/z.t27\nspecs/x.t27\tspecs/y.t27\nspecs/b.t27\tspecs/c.t27\n$"; + const sn : usize = t27f_scope(order, lit_len(order), &set, 512); + assert in_set(&set, sn, "specs/b.t27", 0, 11) == true; + assert sn == 24; +} + invariant the_conclusions_order_success_neutral_failure { assert CONCL_SUCCESS < CONCL_NEUTRAL; assert CONCL_NEUTRAL < CONCL_FAILURE;