memoryd: sync begins when Honcho is turned on, and conclusions are matched by peer

Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
2026-09-28 13:40:48 -07:00
co-authored by ornith-1.5-35b-a3b
parent fb2afa1979
commit 5f4e0d9997
25 changed files with 720 additions and 80 deletions
+26 -15
View File
@@ -1,6 +1,7 @@
//! The Honcho ledger's file (M5c spec, section 5): read through at start, a line cut off by a
//! crash dropped and cut from the file, a damaged line refused with its number and the runbook
//! pointer, the file's mode, and a failed write that changes nothing. Do not edit.
//! pointer, the file's mode, and a failed write that changes nothing. From M5c-1 task 15 every
//! ledger that is read back starts with when sync began. Do not edit.
#[path = "support/ledger.rs"]
mod ledger;
@@ -10,7 +11,8 @@ mod tmp;
use std::os::unix::fs::PermissionsExt;
use ledger::{
Home, conclude, decided, edit, failed, line, sent, skip, to_trusted, turn, unconclude,
Home, began_line, conclude, decided, edit, failed, line, sent, skip, to_trusted, turn,
unconclude,
};
use memoryd::honcho::ledger::{Counts, Item, Ledger, LedgerError, Workspace};
@@ -56,7 +58,7 @@ fn an_empty_file_is_an_empty_ledger() {
#[test]
fn reopening_reads_the_ledger_through() {
let home = Home::new("ledger-reopen");
let mut ledger = home.open();
let mut ledger = home.begun();
let (a, b, c, d, e) = (
turn("chat-1", 1),
turn("chat-1", 2),
@@ -81,7 +83,7 @@ fn reopening_reads_the_ledger_through() {
assert_eq!(again.counts(), ledger.counts());
assert_eq!(again.sent_ids(&c), Some(&["c-1".to_string()][..]));
assert_eq!(
again.conclusion(Workspace::Trusted, "x"),
again.conclusion(Workspace::Trusted, "kyle", "x"),
Some((c.clone(), "c-1".to_string()))
);
for item in [&a, &b, &c, &d, &e] {
@@ -111,7 +113,8 @@ fn reopening_reads_the_ledger_through() {
fn a_cut_off_last_line_is_dropped_and_cut_from_the_file() {
let (a, b, c) = (turn("chat-1", 1), turn("chat-1", 2), turn("chat-1", 3));
let whole = format!(
"{}{}",
"{}{}{}",
began_line(),
line(&decided(&a, to_trusted("kyle"))),
line(&decided(&b, to_trusted("kyle")))
);
@@ -150,7 +153,11 @@ fn a_cut_off_first_line_leaves_an_empty_file() {
fn a_line_cut_inside_a_character_is_dropped_too() {
let home = Home::new("ledger-torn-utf8");
let a = edit("2026-09-28-0001", 0);
let first = line(&decided(&turn("chat-1", 1), to_trusted("kyle")));
let first = format!(
"{}{}",
began_line(),
line(&decided(&turn("chat-1", 1), to_trusted("kyle")))
);
let second = line(&decided(&a, conclude(Workspace::Trusted, "Kyle's café")));
let at = second.find('é').unwrap() + 1;
let mut bytes = first.clone().into_bytes();
@@ -175,11 +182,11 @@ fn a_damaged_line_stops_the_ledger_with_its_number_and_the_pointer() {
] {
for tail in ["", "{\"type\":\"se"] {
let home = Home::new("ledger-damaged");
let text = format!("{first}{second}{third}{tail}");
let text = format!("{}{first}{second}{third}{tail}", began_line());
home.write(&text);
let (number, shown) = damaged(&home);
assert_eq!(number, 2, "{second}");
let start = format!("{}:2: ", home.path.display());
assert_eq!(number, 3, "{second}");
let start = format!("{}:3: ", home.path.display());
assert!(shown.starts_with(&start), "{shown}");
assert!(shown.contains(why), "{shown}");
assert!(shown.ends_with(POINTER), "{shown}");
@@ -194,17 +201,17 @@ fn a_line_that_breaks_the_rules_is_damage() {
let cases = [
(
vec![sent(&a, &["m"])],
1,
2,
"turn 1 of session chat-1: not waiting to be sent",
),
(
vec![decided(&a, to_trusted("kyle")), decided(&a, skip("again"))],
2,
3,
"turn 1 of session chat-1: decided already",
),
(
vec![decided(&b, skip("flagged")), failed(&b, Some(400))],
2,
3,
"part 2 of edit 2026-09-28-0001: not waiting to be sent",
),
(
@@ -214,13 +221,17 @@ fn a_line_that_breaks_the_rules_is_damage() {
decided(&b, to_trusted("kyle")),
failed(&a, None),
],
4,
5,
"turn 1 of session chat-1: not waiting to be sent",
),
];
for (records, number, why) in cases {
let home = Home::new("ledger-rules");
let text: String = records.iter().map(line).collect();
let text = format!(
"{}{}",
began_line(),
records.iter().map(line).collect::<String>()
);
home.write(&text);
let (got, shown) = damaged(&home);
assert_eq!(got, number, "{text}");
@@ -266,7 +277,7 @@ fn a_missing_directory_is_an_io_error_and_changes_nothing() {
#[test]
fn a_failed_write_changes_nothing_in_memory() {
let home = Home::new("ledger-failed-write");
let mut ledger = home.open();
let mut ledger = home.begun();
let (a, b) = (turn("chat-1", 1), turn("chat-1", 2));
ledger.append(decided(&a, to_trusted("kyle"))).unwrap();
let kept = home.text();