e6da6d4397fc
report a clone's flagged saves with their reasons in text and JSON, closing 3.0.20's codex review; drop the flagged_ids helper this orphaned (3.0.35)
- time
- 2026-09-24 03:52 UTC · 2 weeks ago
- machine
- koh2
- agent
- claude-opus-5-5
- session
- koh 3 reliability campaign
- parent
- 88ecb8e00ef9
↓ koh-e6da6d43.tar.gzatlas at this save
files changed6 files
VERSION+1 −1src/cli/cmd_steal.v+18 −10src/events/events.v+0 −13src/events/events_test.v+0 −2tests/cli_test.v+28 −0v.mod+1 −1src/cli/cmd_steal.v+18 −10
@@ -77,13 +77,7 @@7777 note('kept mine for ${fmt.plural(report.kept_mine, 'file')}')7878 }7979 }80- for flag in report.flagged {81- warn('[${flag.save_id}] came in flagged${if flag.reason != '' {82- ' — ${flag.reason}'83- } else {84- ''85- }}')86- }80+ warn_flagged(report.flagged)8781 if report.clashes.len > 0 {8882 note('${report.clashes.len} changed on both machines: ${report.clashes.join(', ')}')8983 }@@ -175,6 +169,13 @@175169 snapshot.restore_files(store, target, snapshot.Ignore{}, files, []) or {176170 return refuse(args.json(), err.msg())177171 }172+ mut flagged := []events.Flag{}173+ for _, flag in events.latest_flags(store) or { return refuse(args.json(), err.msg()) } {174+ if flag.flagged {175+ flagged << flag176+ }177+ }178+ flagged.sort(a.save_id < b.save_id)178179 if args.json() {179180 emit_json(json.encode(StolenJson{180181 repo: name@@ -183,15 +184,22 @@183184 objects: fetched.repo_objects.len184185 events: fetched.events_out.len185186 head: fetched.head187+ flagged: flagged.map(it.save_id)186188 }))187189 return 0188190 }189191 ok('fetched "${name}" into ${target}')190192 note('${fetched.saves.len} saves at [${fetched.head}]')191- for save_id in events.flagged_ids(store) or { []string{} } {192- warn('[${save_id}] came in flagged')193- }193+ warn_flagged(flagged)194194 return 0195+}196+197+// warn_flagged prints the line the document asks for, per incoming flagged save.198+fn warn_flagged(flags []events.Flag) {199+ for flag in flags {200+ reason := if flag.reason != '' { ' — ${flag.reason}' } else { '' }201+ warn('[${flag.save_id}] came in flagged${reason}')202+ }195203 }196204 197205 struct ReposJson {src/events/events.v+0 −13
@@ -206,19 +206,6 @@206206 }207207 }208208 209-// flagged_ids is what the log and the history view mark.210-pub fn flagged_ids(store &storage.Store) ![]string {211- flags := latest_flags(store)!212- mut ids := []string{}213- for save_id, state in flags {214- if state.flagged {215- ids << save_id216- }217- }218- ids.sort()219- return ids220-}221-222209 pub fn strip_events(store &storage.Store) ![]Event {223210 mut stmt := store.db.prepare('${select_event} WHERE kind = ? ORDER BY created_at, id')!224211 defer {src/events/events_test.v+0 −2
@@ -30,11 +30,9 @@3030 state := flag_state(store, save.id)!3131 assert state.flagged3232 assert state.reason == 'broken build'33- assert flagged_ids(store)! == [save.id]3433 3534 clear_flag(store, save.id)!3635 assert !flag_state(store, save.id)!.flagged37- assert flagged_ids(store)!.len == 03836 3937 // Clearing is itself an event, so flagging stays undoable: the events are4038 // all still there, newest simply wins — even when both land in the sametests/cli_test.v+28 −0
@@ -701,6 +701,34 @@701701 assert run_home(b, home, 'log').out.contains('combine: kept mine for')702702 }703703 704+// A clone brings in the whole history, flags included; both output forms must705+// say which saves came in flagged, and why.706+fn test_a_clone_reports_flagged_saves() {707+ syncroot := temp_repo('clone-flags')708+ home := temp_repo('clone-flags-home')709+ defer {710+ os.rmdir_all(syncroot) or {}711+ os.rmdir_all(home) or {}712+ }713+ a := os.join_path(syncroot, 'A', 'proj')714+ os.mkdir_all(a) or { panic(err) }715+ init_repo(a)716+ assert run_home(a, home, 'remote', 'folder', os.join_path(syncroot, 'remote')).code == 0717+ write(a, 'a.txt', 'one\n')718+ id := run_home(a, home, 'save', 'risky', '--json').out.all_after('"id":"')[..12]719+ assert run_home(a, home, 'flag', id, '--reason', 'broke the build').code == 0720+ assert run_home(a, home, 'offer').code == 0721+ for name in ['B', 'C'] {722+ os.mkdir_all(os.join_path(syncroot, name)) or { panic(err) }723+ }724+ json_clone := run_home(os.join_path(syncroot, 'B'), home, 'steal', 'proj', '--json')725+ assert json_clone.code == 0726+ assert json_clone.out.contains('"flagged":["${id}"]')727+ text_clone := run_home(os.join_path(syncroot, 'C'), home, 'steal', 'proj')728+ assert text_clone.code == 0729+ assert text_clone.out.contains('[${id}] came in flagged — broke the build')730+}731+704732 fn test_man_and_koh2_handoff() {705733 dir := temp_repo('man')706734 home := temp_repo('man-home')v.mod+1 −1
@@ -1,6 +1,6 @@11 Module {22 name: 'koh3'3- version: '3.0.34'3+ version: '3.0.35'44 description: 'One SQLite file per repo, one line of history.'55 license: 'MIT'66 }