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
↓ koh-2c62be3a.tar.gzatlas at this save
files changed6 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 −1src/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 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)!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 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() {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 }