2c62be3a9131

warn instead of failing when LOG.md cannot be written after a committed change (3.0.15)

time
2026-09-23 22:10 UTC · 2 weeks ago
machine
koh2
agent
claude-opus-5-5
session
koh 3 review fixes
parent
f7de384191a7
6 files VERSION+1 −1src/history/commit.v+1 −1src/history/log_md.v+9 −1src/sync/steal.v+1 −1tests/cli_test.v+16 −0v.mod+1 −1
VERSION+1 −1
@@ -1 +1 @@1-3.0.141+3.0.15

view file

src/history/commit.v+1 −1
@@ -51,7 +51,7 @@5151 		return err5252 	}5353 	store.commit()!54-	write_log_md(store)!54+	refresh_log_md(store)5555 	return save5656 }5757 

view file

src/history/log_md.v+9 −1
@@ -10,9 +10,17 @@1010 const log_marker = '<!-- Koh maintains this file. Do not edit. Read before starting work. -->'1111 const log_shown = 201212 13+// refresh_log_md rewrites LOG.md after a change to history has committed.14+// The history is what matters, so a LOG.md that cannot be written is a warning15+// on stderr, never a failed command: a save that exits 1 after landing would16+// send an agent to save again.17+pub fn refresh_log_md(store &storage.Store) {18+	write_log_md(store) or { eprintln('  ! LOG.md was not updated: ${err.msg()}') }19+}20+1321 // write_log_md refreshes LOG.md from the line. It runs after every save,1422 // whatever made it — save, checkpoint, undo, load, revert, pluck or a steal.15-pub fn write_log_md(store &storage.Store) ! {23+fn write_log_md(store &storage.Store) ! {1624 	path := os.join_path(store.root, 'LOG.md')1725 	if os.is_file(path) {1826 		existing := os.read_file(path)!

view file

src/sync/steal.v+1 −1
@@ -144,7 +144,7 @@144144 		files := history.files_of(store, final.id)!145145 		snapshot.restore_files(store, store.root, snapshot.load(store.root), files, [])!146146 	}147-	history.write_log_md(store)!147+	history.refresh_log_md(store)148148 	return report149149 }150150 

view file

tests/cli_test.v+16 −0
@@ -155,6 +155,22 @@155155 	assert !run(dir, 'status').out.contains('LOG.md')156156 }157157 158+// LOG.md is a convenience written after the save commits. If it cannot be159+// written, the save still happened, and an agent that retried on a failure160+// would only be told nothing had changed.161+fn test_a_save_succeeds_when_log_md_cannot_be_written() {162+	dir := temp_repo('logmd')163+	defer { os.rmdir_all(dir) or {} }164+	init_repo(dir)165+	os.mkdir_all(os.join_path(dir, 'LOG.md')) or { panic(err) }166+	write(dir, 'a.txt', 'one\n')167+	r := run(dir, 'save', 'first', '--json')168+	assert r.code == 0169+	assert r.out.starts_with('{')170+	assert r.err.contains('LOG.md')171+	assert run(dir, 'log', '--json').out.contains('"message":"first"')172+}173+158174 // `save` records the executable bit, so `status` has to see it too, or a159175 // chmod would be invisible until it turned up in a save.160176 fn test_status_sees_an_executable_bit_change() {

view file

v.mod+1 −1
@@ -1,6 +1,6 @@11 Module {22 	name: 'koh3'3-	version: '3.0.14'3+	version: '3.0.15'44 	description: 'One SQLite file per repo, one line of history.'55 	license: 'MIT'66 }

view file