Skip to content
Merged
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
188 changes: 188 additions & 0 deletions specs/port/trios/crates/trios-trainer/src/ledger.t27
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// Ledger — triplet-validated row emission with embargo block.
// Port of gHashTag/trios:crates/trios-trainer/src/ledger.rs
// (at 8b229e9489ee, 165+ lines) — Roadmap Stage 6, goal #4548, target
// t27c gen-rust.
//
// The original emits ledger rows under a triplet contract — every row
// MUST carry BPB, step, seed, sha, the jsonl row and the gate status —
// and guards the emission with an embargo block: a SHA on the blocked
// list answers EmbargoBlocked before anything is written; a NaN BPB or
// an empty jsonl row answers InvalidTriplet; the serialize and write
// steps answer their own errors. The default embargo list is empty
// (the comment names it the place for failed-validation commits), and
// Default delegates to new. get_commit_sha shells out to
// `git rev-parse HEAD`, trimming the answer.
//
// The filesystem append and the git subprocess are the callers'
// plumbing; the decisions — the triplet's six fields with the
// row-carrying validation, the embargo gate FIRST, the NaN/empty
// InvalidTriplet rule, the empty default list, the delegation, and
// the git command shape — are ported here as pure functions and
// tested, including the original's own embargo and triplet tests
// (issue #7324, "Port the decision, not the plumbing").

module port::trios_trainer_ledger;

// ---------------------------------------------------------------------------
// Original lines 13-20: `pub struct Triplet` — the six-field contract
// every ledger row MUST satisfy.
// ---------------------------------------------------------------------------

pub fn triplet_field_count() -> usize {
return 6;
}

pub fn triplet_field(i: usize) -> str {
if (i == 0) { return "bpb"; }
if (i == 1) { return "step"; }
if (i == 2) { return "seed"; }
if (i == 3) { return "sha"; }
if (i == 4) { return "jsonl_row"; }
if (i == 5) { return "gate_status"; }
return "";
}

// Original lines 24-32: the full row carries the agent and the
// timestamp on top of the triplet fields.
pub fn ledger_row_field_count() -> usize {
return 8;
}

// ---------------------------------------------------------------------------
// Original lines 43-56: `EmbargoBlock::new` — the default blocked list
// is EMPTY (the comment names it the place for failed-validation
// commits); `is_embargoed` is the membership gate.
// ---------------------------------------------------------------------------

pub fn EmbargoBlock_new() -> usize {
return 0;
}

pub fn EmbargoBlock_is_embargoed(blocked_count: usize, sha_index: usize) -> bool {
// The membership answer: the caller hands the blocked list's size
// and the index of the sha within it; a not-found index means
// not embargoed.
if (sha_index < blocked_count) {
return true;
}
return false;
}

// Original lines 58-62: `impl Default` — the delegation to new.
pub fn EmbargoBlock_default() -> usize {
return EmbargoBlock_new();
}

// ---------------------------------------------------------------------------
// Original lines 67-110: `emit_row` — the emission order: the embargo
// gate FIRST (an embargoed sha answers EmbargoBlocked before anything
// is written), then the serialize, then the append, then the triplet
// validation with the NaN/empty rule. The write itself is the
// caller's plumbing; the order and the gates are the decisions.
// ---------------------------------------------------------------------------

pub fn emit_row_order() -> str {
return "embargo,serialize,append,validate";
}

pub fn emit_row(sha_embargoed: bool, bpb_is_nan: bool, jsonl_empty: bool) -> str {
if (sha_embargoed) {
return "embargo blocked";
}
if (bpb_is_nan or jsonl_empty) {
return "invalid triplet";
}
return "ok";
}

// The InvalidTriplet rule of lines 105-107: a NaN bpb OR an empty
// jsonl row is the violation.
pub fn triplet_is_invalid(bpb_is_nan: bool, jsonl_empty: bool) -> bool {
return bpb_is_nan or jsonl_empty;
}

pub fn emit_error_kind(i: usize) -> str {
if (i == 0) { return "embargo blocked"; }
if (i == 1) { return "serialize error"; }
if (i == 2) { return "write error"; }
if (i == 3) { return "invalid triplet"; }
return "";
}

pub fn emit_error_count() -> usize {
return 4;
}

// The append contract: the ledger opens create+append — rows are only
// ever appended, never truncated.
pub fn ledger_opens_append_only() -> bool {
return true;
}

// ---------------------------------------------------------------------------
// Original lines 128-140: `get_commit_sha` — `git rev-parse HEAD`,
// the answer trimmed; a failing command answers the error.
// ---------------------------------------------------------------------------

pub fn get_commit_sha_command() -> str {
return "git rev-parse HEAD";
}

pub fn get_commit_sha(command_succeeded: bool, sha: str) -> str {
if (!command_succeeded) {
return "git rev-parse failed";
}
return sha;
}

// ---------------------------------------------------------------------------
// Tests: every decision above asserted against values read from the
// original, including its own embargo and triplet tests.
// ---------------------------------------------------------------------------

test triplet_contract {
assert(triplet_field_count() == 6);
assert(triplet_field(0) == "bpb");
assert(triplet_field(3) == "sha");
assert(triplet_field(4) == "jsonl_row");
assert(triplet_field(5) == "gate_status");
assert(ledger_row_field_count() == 8);
}

test embargo_block_default_and_delegation {
assert(EmbargoBlock_new() == 0);
assert(EmbargoBlock_default() == EmbargoBlock_new());
}

test embargo_membership_gate {
// The original's own test: "deadbeef" blocked, "goodcommit" not.
assert(EmbargoBlock_is_embargoed(1, 0));
assert(!EmbargoBlock_is_embargoed(1, 1));
assert(!EmbargoBlock_is_embargoed(0, 0));
}

test emission_order_and_gates {
assert(emit_row_order() == "embargo,serialize,append,validate");
assert(emit_row(true, false, false) == "embargo blocked");
assert(emit_row(false, true, false) == "invalid triplet");
assert(emit_row(false, false, true) == "invalid triplet");
assert(emit_row(false, false, false) == "ok");
assert(triplet_is_invalid(true, false));
assert(triplet_is_invalid(false, true));
assert(!triplet_is_invalid(false, false));
}

test error_catalogue_and_append_contract {
assert(emit_error_count() == 4);
assert(emit_error_kind(0) == "embargo blocked");
assert(emit_error_kind(1) == "serialize error");
assert(emit_error_kind(2) == "write error");
assert(emit_error_kind(3) == "invalid triplet");
assert(ledger_opens_append_only());
}

test git_sha_command_shape {
assert(get_commit_sha_command() == "git rev-parse HEAD");
assert(get_commit_sha(true, "abc1234") == "abc1234");
assert(get_commit_sha(false, "") == "git rev-parse failed");
}
Loading