Skip to content
Draft
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
6 changes: 4 additions & 2 deletions .github/workflows/t27b-native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,13 @@ jobs:

- name: tri t27b ratchet against the ledger
id: ratchet
env:
PR_FLAG: ${{ github.event_name == 'pull_request' && '--pr' || '' }}
run: |
set +e
./scripts/tri t27b ratchet --run run.json --json > ratchet.json 2> ratchet.err
./scripts/tri t27b ratchet --run run.json $PR_FLAG --json > ratchet.json 2> ratchet.err
code=$?
./scripts/tri t27b ratchet --run run.json > ratchet.txt 2>&1
./scripts/tri t27b ratchet --run run.json $PR_FLAG > ratchet.txt 2>&1
cat ratchet.txt
cat ratchet.err
echo "exit=$code" >> "$GITHUB_OUTPUT"
Expand Down
28 changes: 28 additions & 0 deletions .trinity/seals/src_port::trios_mesh_node_crypto.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"built_by": "t27c-bootstrap@0.5.2+cd8a65666",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:1e74b996ade22e83796910c9b4e244b1cc04f6253a35505054198be62254e853",
"gen_hash_rust": "sha256:ea7c338992c88064b5375c0b5462bb4868f244384f01a344780f025452123335",
"gen_hash_verilog": "sha256:fc2816200338199bc3a3553bfd5fa97ddc9ec7e707af61b23ec096758d38e309",
"gen_hash_zig": "sha256:11c4e273387ec011bd4e7c6a27d1a0217fc821c5c58f1abb7e225a95d9eee469",
"module": "port::trios_mesh_node_crypto",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-15T19:35:12Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:d1d3ed152196c59afbafb1b1c08af5ef6e270fd7e354dc4f101e5bc9dcf212d7",
"spec_path": "specs/port/trios/crates/trios-mesh-node/src/crypto.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 23,
"total": 23,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"zig": "0.16.0"
}
}
19 changes: 10 additions & 9 deletions .trinity/seals/t27b_T27bSteward.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
{
"built_by": "t27c-bootstrap@0.5.2+0d573722c",
"built_by": "t27c-bootstrap@0.5.2+cd8a65666",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:c699bc3ab8e8e01af1729ea96725a3abc2a8e6a85c88d5644fe30978e2fa57ee",
"gen_hash_rust": "sha256:0c6fe0756c745a0ff553e141c197f6535107ce71d8f8f556d70b31a6b04a11db",
"gen_hash_verilog": "sha256:eb7f9f6aecff876331ea1ad8fbdf9d32d55af1bef22d379eff01216d98adef76",
"gen_hash_zig": "sha256:db0e1e6532a57d2ba0c6559f001812827cfc8fc677876747c84848068af60b7e",
"gen_hash_c": "sha256:042f0a9f08534cdde91942cc7c3c0e8ce94134e6e9f6ceacf1aaadcb29f91de9",
"gen_hash_rust": "sha256:5d4af985fc5c471ad4e3bba71643067ccd7cb93de1372cdc9a2c3cca73dd13f6",
"gen_hash_verilog": "sha256:a9ba4ed46258687262c9e17669107da71c184e27f71ef73e65f1679da4b10d63",
"gen_hash_zig": "sha256:4eb8cadfd3dfc70296f06b8ca4f34c4a9ef9600fc262354fdb1fe5c5a0426fe7",
"module": "T27bSteward",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-09T21:34:31Z",
"sealed_at": "2026-10-15T19:29:16Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:70867c8cd8a8155d82f352b6833168f04c846a736413d6b2420d54774994123e",
"spec_hash": "sha256:e302b1c3cb8c988982f01fb092a62758ca68996a61bb64f6b437b336b486e23f",
"spec_path": "specs/tri/t27b/steward.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 128,
"total": 128
"passed": 137,
"total": 137,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
Expand Down
14 changes: 7 additions & 7 deletions .trinity/seals/t27o_T27oRust.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"built_by": "t27c-bootstrap@0.5.2+e7fbc2639",
"built_by": "t27c-bootstrap@0.5.2+cd8a65666",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:5ced192099954e788bc953c0973428c9f278751b7610f050e07758a9a6611a14",
"gen_hash_rust": "sha256:ae84f2ed194de288b42f9dfeb10b6a965c65f99ca992ef82aaf971082aaca512",
"gen_hash_verilog": "sha256:130434cc65aee3c2c38a14354c010aedbfd11c6e2e565a2da72448ca8a471d17",
"gen_hash_zig": "sha256:a3aee0b8ec566bb21157cb64c6330e87ffcb44ce765a2bf150beb95dd0c9b2ab",
"gen_hash_c": "sha256:93076da93a404ea49f455526fa1d25dfc8b6040dda6f2972dcb747074eb755a3",
"gen_hash_rust": "sha256:d912c313830e2ec4ba390adcf66baabba71cecd6f720246e1a619a95b0964334",
"gen_hash_verilog": "sha256:2b7550a7c7d5e0f989df3e4a00597c788e5abc0671043978bef8bd4cfd40aa9c",
"gen_hash_zig": "sha256:a47e14e956324ccd1ff1d9f521f2761b659ee6e61623c53365af62043c731264",
"module": "T27oRust",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-12T10:09:28Z",
"sealed_at": "2026-10-15T19:29:34Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:f4ee9bcc7818621bf5d591d8d74f6cb41ef6fcac3e558e550af6dc45d549aec5",
"spec_hash": "sha256:690282a6a0c834606de0def8b4b05499c1a0e415bc270ffac2d908bc3ca5abbf",
"spec_path": "specs/tools/t27o/rust_convert.t27",
"tests": {
"failed": 0,
Expand Down
102 changes: 101 additions & 1 deletion gen/c/tri/t27b/steward.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bool unlisted(uint8_t reference, bool listed);
bool over_cap(uint32_t not_pass, uint32_t cap, bool has_cap);
bool ratchet_is_red(uint8_t code);
bool is_unimplemented(uint8_t v);
bool ratchet_red(uint8_t code, uint8_t got, bool pr);
uint8_t bless_reason(uint8_t got, uint8_t kept);
bool cap_rises(uint32_t not_pass, uint32_t old_cap, bool has_old);
bool lab_stale(uint32_t age_min, uint32_t limit_min);
Expand Down Expand Up @@ -222,6 +223,34 @@ bool is_unimplemented(uint8_t v) {
return false;
}

bool ratchet_red(uint8_t code, uint8_t got, bool pr) {
if ((pr == false)) {
return ratchet_is_red(code);
}
if ((code == 2)) {
return true;
}
if ((code == 8)) {
return true;
}
if ((code == 9)) {
return true;
}
if ((code > 9)) {
return true;
}
if ((code == 7)) {
if (is_pass(got)) {
return false;
}
if (is_unimplemented(got)) {
return false;
}
return true;
}
return false;
}

uint8_t bless_reason(uint8_t got, uint8_t kept) {
if ((kept != 0)) {
return kept;
Expand Down Expand Up @@ -469,6 +498,14 @@ uint32_t with_tests(uint32_t reference, uint32_t vacuous) {
/* invariant: no_total_in_the_ledger_header */
/* invariant no_total_in_the_ledger_header is not a C constant expression: (header_stored(5) == false) */

/* invariant: strict_ratchet_red_is_ratchet_is_red */
/* invariant strict_ratchet_red_is_ratchet_is_red is not a C constant expression: (ratchet_red(0, 6, false) == ratchet_is_red(0)) */
/* invariant strict_ratchet_red_is_ratchet_is_red is not a C constant expression: (ratchet_red(2, 0, false) == ratchet_is_red(2)) */
/* invariant strict_ratchet_red_is_ratchet_is_red is not a C constant expression: (ratchet_red(3, 0, false) == ratchet_is_red(3)) */
/* invariant strict_ratchet_red_is_ratchet_is_red is not a C constant expression: (ratchet_red(5, 0, false) == ratchet_is_red(5)) */
/* invariant strict_ratchet_red_is_ratchet_is_red is not a C constant expression: (ratchet_red(7, 0, false) == ratchet_is_red(7)) */
/* invariant strict_ratchet_red_is_ratchet_is_red is not a C constant expression: (ratchet_red(8, 0, false) == ratchet_is_red(8)) */

/* invariant: gained_never_red */
/* invariant gained_never_red is not a C constant expression: (delta_is_red(delta_code(0, 0, 2, 0, 0, 1)) == false) */

Expand Down Expand Up @@ -613,6 +650,60 @@ void test_ratchet_red_codes(void) {
assert((ratchet_is_red(6) == false));
}

void test_pr_lag_is_pending(void) {
assert((ratchet_red(7, 0, true) == false));
assert((ratchet_red(7, 1, true) == false));
assert((ratchet_red(7, 2, true) == false));
assert((ratchet_red(7, 3, true) == false));
assert((ratchet_red(7, 4, true) == false));
assert((ratchet_red(3, 0, true) == false));
assert((ratchet_red(4, 2, true) == false));
assert((ratchet_red(5, 0, true) == false));
assert((ratchet_red(1, 1, true) == false));
assert((ratchet_red(6, 0, true) == false));
assert((ratchet_red(0, 0, true) == false));
}

void test_negative_pr_unlisted_mismatch_is_red(void) {
assert(ratchet_red(7, 6, true));
}

void test_negative_pr_unlisted_crash_is_red(void) {
assert(ratchet_red(7, 7, true));
}

void test_negative_pr_unlisted_fail_is_red(void) {
assert(ratchet_red(7, 5, true));
}

void test_negative_pr_unlisted_timeout_is_red(void) {
assert(ratchet_red(7, 8, true));
}

void test_negative_pr_unlisted_not_run_is_red(void) {
assert(ratchet_red(7, 9, true));
}

void test_negative_pr_unlisted_missing_is_red(void) {
assert(ratchet_red(7, 10, true));
}

void test_negative_pr_regression_is_red(void) {
assert(ratchet_red(2, 2, true));
assert(ratchet_red(2, 0, true));
assert(ratchet_red(8, 0, true));
assert(ratchet_red(9, 0, true));
assert(ratchet_red(10, 0, true));
}

void test_master_and_the_lab_stay_strict(void) {
assert(ratchet_red(7, 0, false));
assert(ratchet_red(7, 6, false));
assert(ratchet_red(3, 0, false));
assert(ratchet_red(5, 0, false));
assert((ratchet_red(4, 2, false) == false));
}

void test_bless_keeps_a_written_reason(void) {
assert_eq(bless_reason(5, 2), 2);
}
Expand Down Expand Up @@ -1048,6 +1139,15 @@ int main(void) {
test_ratchet_unlisted();
test_ratchet_cap();
test_ratchet_red_codes();
test_pr_lag_is_pending();
test_negative_pr_unlisted_mismatch_is_red();
test_negative_pr_unlisted_crash_is_red();
test_negative_pr_unlisted_fail_is_red();
test_negative_pr_unlisted_timeout_is_red();
test_negative_pr_unlisted_not_run_is_red();
test_negative_pr_unlisted_missing_is_red();
test_negative_pr_regression_is_red();
test_master_and_the_lab_stay_strict();
test_bless_keeps_a_written_reason();
test_bless_unimplemented();
test_bless_refuses_a_defect();
Expand Down Expand Up @@ -1145,7 +1245,7 @@ int main(void) {
test_ledger_stores_where_it_came_from();
test_ledger_derives_its_counts();
test_ledger_stores_no_unknown_field();
printf("All %d tests passed.\n", 128);
printf("All %d tests passed.\n", 137);
return 0;
}
#endif /* T27_TEST_MAIN */
Expand Down
7 changes: 4 additions & 3 deletions gen/rust/tools/t27o/rust_convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7262,7 +7262,7 @@ pub fn out_format(src: &[u8], st: &mut [usize], out: &mut [u8], a: usize, ret: b
}
let fq: usize = quoted_end(src, f);
let mut p: usize = (f + 1);
let mut piece: usize = (f + 1);
let mut piece: usize = p;
let mut arg: usize = skip_ws(src, fq);
if tok_is(src, arg, b",") {
arg = skip_ws(src, tok_end(src, arg));
Expand Down Expand Up @@ -7310,8 +7310,9 @@ pub fn out_format(src: &[u8], st: &mut [usize], out: &mut [u8], a: usize, ret: b
refuse(st, R_STRUSE, a, a, fe);
return ();
}
if ((fq - 1) > piece) {
put_out_piece(src, st, out, piece, (fq - 1));
let tail_end: usize = (fq - 1);
if (tail_end > piece) {
put_out_piece(src, st, out, piece, tail_end);
newline(st, out);
}
st[(P) as usize] = skip_ws(src, rp);
Expand Down
26 changes: 12 additions & 14 deletions scripts/tri_loop/t27b.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,30 +190,27 @@
(`unimplemented` | `reference-bug` | `n/a`). `ratchet` diffs one lab run
(latest.json shape) against it:

UNEXPECTED FAILURE a ledger pass that is not a pass now (a pass that turned
vacuous included); a ledger pass_vacuous that no longer
passes at all
UNEXPECTED FAILURE a ledger pass that is not a pass now (vacuous included);
a ledger pass_vacuous that no longer passes at all
UNEXPECTED PASS a ledger non-pass that passes now; a pass_vacuous that
is a real pass now. Red too: an improvement nobody
blesses leaves slack for the next regression
is a real pass now. Red: an unblessed gain leaves slack
UNLISTED the reference passes a spec the ledger does not name
STALE a ledger spec the reference now fails, or that is gone
OVER CAP more non-pass entries than `max_not_pass`, which only
moves down (raising it is a hand edit in the PR)
BAD REASON a non-pass entry whose reason is not one of the three
-- not red --
MOVED still not a pass, but the first blocker changed
UNJUDGED the reference could not judge the spec in this run
(lab_error, timeout, skip): no verdict either way
VACUITY MEASURED a ledger pass blessed from a run that did not count
asserts (source.asserts_counted false) is pass_vacuous
in a run that does: a first measurement, not a
regression. Bless to record it
UNJUDGED the reference gave no verdict (lab_error, timeout, skip)
VACUITY MEASURED a ledger pass blessed before asserts were counted is
pass_vacuous in a run that counts: a first measurement,
not a regression. Bless to record it

tri t27b ratchet # latest lab run vs the ledger
tri t27b ratchet --run runs/<sha>.json # a saved run (path or URL)
tri t27b ratchet --bless # rewrite the ledger from the run
tri t27b ratchet --json # the verdict, machine-readable
tri t27b ratchet --pr # a PR: lag pending, a defect red

Exit 0 green, 1 red (or a refused bless), 2 usage or an unreadable input.
"""
Expand Down Expand Up @@ -876,7 +873,7 @@ def ratchet(run, ledger):
"""
r = rules()
found = []
add = lambda kind, path, what: found.append({"kind": kind, "path": path, "what": what}) # noqa: E731
add = lambda kind, path, what, t27b=None: found.append({"kind": kind, "path": path, "what": what, "t27b": t27b}) # noqa: E731
by_path = {x.get("file"): x for x in run["results"]}
entries = {e["path"]: e for e in ledger.get("entries", [])}
# A ledger blessed from a run without assert counts cannot tell pass from
Expand Down Expand Up @@ -916,7 +913,7 @@ def ratchet(run, ledger):
if r.unlisted(rec.get("reference") or "missing", path in entries):
got, blocker = observed(rec)
add("UNLISTED", path, f"the reference passes it and the ledger does not name it (t27b {got}"
+ (f": {blocker})" if blocker else ")"))
+ (f": {blocker})" if blocker else ")"), got)
not_pass = sum(1 for e in entries.values() if not r.is_pass(e.get("t27b") or "missing"))
cap = ledger.get("max_not_pass")
if r.over_cap(not_pass, cap):
Expand Down Expand Up @@ -1020,6 +1017,7 @@ def ratchet_main(argv):
ap.add_argument("--bless", action="store_true", help="rewrite the ledger from the run")
ap.add_argument("--accept-new", action="store_true",
help="bless: let the cap rise by exactly the non-pass specs new to the ledger")
ap.add_argument("--pr", action="store_true", help="a pull request: lag is pending, a runtime defect stays red")
ap.add_argument("--json", action="store_true")
try:
args = ap.parse_args(argv)
Expand Down Expand Up @@ -1059,7 +1057,7 @@ def ratchet_main(argv):
try:
found = ratchet(run, old)
counts = {k: sum(1 for f in found if f["kind"] == k) for k in KINDS}
red = sum(v for k, v in counts.items() if rules().ratchet_is_red(k))
red = sum(1 for f in found if rules().ratchet_is_red(f["kind"], f["t27b"] or "pass", args.pr))
except Exception as e: # noqa: BLE001 -- RulesUnavailable lives in a lazily imported module
if type(e).__name__ != "RulesUnavailable":
raise
Expand Down
8 changes: 4 additions & 4 deletions scripts/tri_loop/t27b_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def _build():
so.unlisted.restype = ctypes.c_bool
so.over_cap.argtypes = [ctypes.c_uint32, ctypes.c_uint32, ctypes.c_bool]
so.over_cap.restype = ctypes.c_bool
so.ratchet_is_red.argtypes = [ctypes.c_uint8]
so.ratchet_is_red.restype = ctypes.c_bool
so.ratchet_red.argtypes = [ctypes.c_uint8, ctypes.c_uint8, ctypes.c_bool]
so.ratchet_red.restype = ctypes.c_bool
so.bless_reason.argtypes = [ctypes.c_uint8, ctypes.c_uint8]
so.bless_reason.restype = ctypes.c_uint8
so.cap_rises.argtypes = [ctypes.c_uint32, ctypes.c_uint32, ctypes.c_bool]
Expand Down Expand Up @@ -189,8 +189,8 @@ def over_cap(not_pass, cap):
return bool(lib().over_cap(not_pass, cap if has else 0, has))


def ratchet_is_red(kind):
return bool(lib().ratchet_is_red(RATCHETS.index(kind)))
def ratchet_is_red(kind, t27b="pass", pr=False):
return bool(lib().ratchet_red(RATCHETS.index(kind), verdict(t27b), bool(pr)))


def bless_reason(got, kept):
Expand Down
Loading
Loading