• Correctness audit result: I found two high-priority defects and several concrete medium- priority bugs. This review is limited to coding, algorithmic, and reliability issues. I made no source changes. ## Findings 1. High — divide can share mutable events between output repositories. surgeon/inner.go:1613 uses c := b, which only copies the pointer. During surgeon/ inner.go:10760, a blob needed by both partitions is therefore the same object in both repositories, with its repo field ultimately pointing at only one. Resets and front passthroughs are also reused rather than independently cloned. Subsequent mutation or export of one partition can affect the other. Fix: implement explicit event copy constructors that allocate new objects and rebuild mutex/map fields; assert that every event belongs to exactly one resulting repository. 2. High — rebuild can report success after commands or filesystem operations fail. surgeon/inner.go:8527 ignores initializer, pipe-close, and importer-exit errors. surgeon/ inner.go:8623 also ignores checkout, directory creation, and every rename result during repository replacement. It announces completion before the replacement is finished. Additionally, preserveMe is constructed but surgeon/inner.go:8724, so an appended author map is not restored. Fix: propagate every error, validate staging before replacement, check every move, provide rollback, and announce completion only after the entire operation succeeds. 3. Medium — embedded CVS/SVN revision-cookie parsing is effectively disabled. All three calls to FindAllStringSubmatch(..., 0) in surgeon/inner.go:1673 request zero matches. There are further defects: $Rev is not actually accepted, $Id parses m[0] rather than the captured contents, and one branch accesses fields[2] only when len(fields) == 2. After those are fixed, surgeon/inner.go:6203 writes to an uninitialized map, and its CVS key uses the pathname twice instead of pathname plus revision. Fix: correct the expressions and captures, initialize the map, centralize key construction, and add end-to-end stampify tests. 4. Medium — cloning a repository erases assignments from the original. surgeon/inner.go:5254 assigns a new map to repo.assignments, not newRepo.assignments, and then iterates the now-empty original. Thus a supposedly non-mutating clone operation changes its source. Fix: deep-copy into the clone and test that assignments in both repositories remain independent. 5. Medium — renumber never removes duplicate done trailers. surgeon/inner.go:7837 builds newEvents, but never assigns it to repo.events. Its length comparison compares repo.events with its own original length, so the condition can never be true. Fix: compare len(newEvents), install the filtered slice, then append exactly one trailer. 6. Medium — SVN timestamp collision adjustment discards its calculation. surgeon/svnread.go:1432 calls time.Time.Add, but ignores the returned value. Since time.Time is immutable, the documented round-up behavior never occurs. Fix: return or assign the adjusted timestamp before truncation, with tests around the half- second boundary. 7. Medium — tar import continues after errors and accepts invalid strip counts. surgeon/reposurgeon.go:7315 accepts negative or excessive --strip values. surgeon/ inner.go:9955 logs open/extraction failures but continues, and surgeon/inner.go:9984 can panic. Earlier events may already have been inserted when a later tarball fails. Fix: return errors immediately, validate each entry’s component count, and stage the complete import before modifying repository state. 8. Medium — compressed blob failures are replaced by a nil-pointer panic. Both surgeon/inner.go:1447 and surgeon/inner.go:1482 test err2 but call err.Error(). At that point err is normally nil. Fix: report err2, and close the underlying file when stream initialization fails. 9. Medium — malformed legacy-map entries can panic. surgeon/inner.go:5931 splits into parts but mistakenly validates fields before indexing parts[1]. Sequence numbers are used without bounds checking, a blank-field error is constructed and discarded, and scanner.Err() is ignored. Fix: validate parts, bounds-check the selected commit, and return all parsing and scanning errors. 10. Medium — fast-import parse errors frequently become runtime panics. Several directive handlers index token slices without checking arity; for example surgeon/ inner.go:4525. The tag parser can warn about a missing tagger and then dereference the nil tagger at surgeon/inner.go:4922. Fix: use shared checked-token helpers and return line-numbered parse errors instead of continuing. ## Validation and recommended improvements - go test -race ./... passed. - go vet -copylocks=false ./... passed; formatting was clean. - The full integration run reached 587 tests. Its 16 reported failures were Fossil tests blocked by a read-only sandbox configuration file, not observed product failures. - Repeated and shuffled unit tests expose an order dependency in surgeon/ reposurgeon_test.go:950, which assumes the global blob counter begins at zero. - Unit coverage is approximately 22.7% for surgeon and 6.5% for cutter; mapper and tool have no Go tests. The best improvement sequence is: fix event ownership and rebuild error handling first, then the disabled cookie logic and clone/renumber defects. Afterward, add repository ownership invariants, shuffled tests, parser fuzz tests, and targeted staticcheck/errcheck enforcement. Existing untracked files were left untouched.