delete_extras_fd + list_extras_fd unified behind one delete_walk_fd (DELETE vs LIST) so dry-run and real deletion cannot drift.
The delete skip-prefix set is built once (delete_skips_build) and used by all four former call sites.
Config + minor deferred
Config CLI-parse bookkeeping grouped into Config.cli; dead Config.old_args field removed (--old-args stays an accepted no-op). CONFIG_WIRE_* tables untouched; test_config_wire_golden unchanged (len=886, hash pinned).
protocol_throttle_bytes now resolves the same session as the send path (fixes first-call double-burst).
Added EXDEV cross-filesystem --temp-dir coverage (via batch apply; CI container lacks mount caps — documented).
Const-corrected the delete-manifest API.
Not done (still deferred)
Protocol/transport vtable: AGENTS.md flags the SSL WANT_READ/WANT_WRITE retry as load-bearing; moving SSL behind a vtable needs dedicated TLS/MT regression scaffolding first. Left as-is.
Verification
Strict -Werror build clean; clang-format 18 clean; cppcheck clean; unit 45/45 under ASan/UBSan/valgrind; full integration 884 passed; differential parity 62 passed; config-wire golden unchanged. Two independent reviews (comprehensive + C memory/thread-safety) did per-function equivalence analysis and found no behavior/ownership defects (only cosmetic notes).
## Structural refactor cycle (behavior-preserving, no wire change)
Executes the large structural work deferred from the audit cycle. Every change is a pure refactor: **no behavior change**, `PROTOCOL_VERSION` stays 2.28.0.
### TU splits
- `src/client/scanner.c` (2,560) → `scanner_filter.c` + `scanner.c` + `scanner_parallel.c` (`scanner.h` façade, new `scanner_internal.h`).
- `src/client/client_send.c` (3,874) → `client_report.c` + `client_scan.c` + `client_manifest.c` (new `client_send_internal.h`).
- `src/shared/file_receive.c` (3,827) → `file_save.c` + `incremental_check.c` + `delete_commit.c` (`file_receive.h` façade, new internal headers).
- New `src/shared/delete.c`/`delete.h` owning the whole delete domain (walker primitives, skip-set builder, budget), moved out of `utils.c`.
### God-function decomposition
- `directory_scanner_next` (278) → per-entry/relative-path/mount/finish helpers.
- `send_files` (430) → prepare / prepare-delete / run / finalize / cleanup phases.
- `file_save_to_disk_full_ex` (404) → validate / dispatch / prewrite-policies / install, with a single `out:` cleanup epilogue.
- `server.c handler` (341) → `server_accept_config` / `server_apply_security_gates` / `server_prepare_session` / `server_run_transfer` (security-gate ordering preserved verbatim).
- `receiver_process_pending` (276) → per-status handlers + shared `receiver_drop_pending` teardown.
### De-duplication / consolidation
- `delete_extras_fd` + `list_extras_fd` unified behind one `delete_walk_fd` (DELETE vs LIST) so dry-run and real deletion cannot drift.
- The delete skip-prefix set is built once (`delete_skips_build`) and used by all four former call sites.
### Config + minor deferred
- `Config` CLI-parse bookkeeping grouped into `Config.cli`; dead `Config.old_args` field removed (`--old-args` stays an accepted no-op). `CONFIG_WIRE_*` tables untouched; `test_config_wire_golden` unchanged (len=886, hash pinned).
- `protocol_throttle_bytes` now resolves the same session as the send path (fixes first-call double-burst).
- Added EXDEV cross-filesystem `--temp-dir` coverage (via batch apply; CI container lacks mount caps — documented).
- Const-corrected the delete-manifest API.
### Not done (still deferred)
- **Protocol/transport vtable**: `AGENTS.md` flags the SSL `WANT_READ`/`WANT_WRITE` retry as load-bearing; moving SSL behind a vtable needs dedicated TLS/MT regression scaffolding first. Left as-is.
### Verification
Strict `-Werror` build clean; clang-format 18 clean; cppcheck clean; unit 45/45 under ASan/UBSan/valgrind; full integration 884 passed; differential parity 62 passed; config-wire golden unchanged. Two independent reviews (comprehensive + C memory/thread-safety) did per-function equivalence analysis and found **no behavior/ownership defects** (only cosmetic notes).
Move the stats/progress reporting, scanner-preparation/scan helpers and
manifest/list/dry-run senders out of the ~3.9k-line client_send.c into
client_report.c, client_scan.c and client_manifest.c, sharing declarations
through the new internal client_send_internal.h. client_send.c keeps the
transfer orchestration and is now ~2.1k lines.
Decompose the monolithic send_files into static phase helpers
(send_files_prepare/_prepare_delete/_run/_finalize/_cleanup) driven by a
single SendFilesState; ownership, ordering and exit codes are unchanged.
No behavior change.
Move the filter rule-tree/context helpers and entry inspection into
scanner_filter.c, the parallel scanner into scanner_parallel.c, and keep
the sequential scanner in scanner.c. Shared internal declarations live in
the new scanner_internal.h; scanner.h stays the public façade.
Decompose directory_scanner_next into static helpers (skipped-entry,
selection-protection, mount/-x, directory-finish and per-entry handlers)
with no semantic change.
Pure structural split of src/shared/file_receive.c into focused translation
units behind the unchanged file_receive.h facade:
- file_save.c : save-to-disk, special nodes, --delay-updates staging
- incremental_check.c : xattr/delta/basis/fuzzy receive + check state machine
- delete_commit.c : manifest receive + delete budget walkers
- file_receive.c : wire receive dispatch + deferred dir metadata
The shared receive_file_xattrs helper and MAX_FILE_DATA_SIZE are declared in
incremental_check.h. file_save_to_disk_full_ex is decomposed into static
helpers (validation, special dispatch, dir/symlink creation, path resolution,
pre-write policies, data install) routed through one cleanup epilogue.
No behavior change.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Structural refactor cycle (behavior-preserving, no wire change)
Executes the large structural work deferred from the audit cycle. Every change is a pure refactor: no behavior change,
PROTOCOL_VERSIONstays 2.28.0.TU splits
src/client/scanner.c(2,560) →scanner_filter.c+scanner.c+scanner_parallel.c(scanner.hfaçade, newscanner_internal.h).src/client/client_send.c(3,874) →client_report.c+client_scan.c+client_manifest.c(newclient_send_internal.h).src/shared/file_receive.c(3,827) →file_save.c+incremental_check.c+delete_commit.c(file_receive.hfaçade, new internal headers).src/shared/delete.c/delete.howning the whole delete domain (walker primitives, skip-set builder, budget), moved out ofutils.c.God-function decomposition
directory_scanner_next(278) → per-entry/relative-path/mount/finish helpers.send_files(430) → prepare / prepare-delete / run / finalize / cleanup phases.file_save_to_disk_full_ex(404) → validate / dispatch / prewrite-policies / install, with a singleout:cleanup epilogue.server.c handler(341) →server_accept_config/server_apply_security_gates/server_prepare_session/server_run_transfer(security-gate ordering preserved verbatim).receiver_process_pending(276) → per-status handlers + sharedreceiver_drop_pendingteardown.De-duplication / consolidation
delete_extras_fd+list_extras_fdunified behind onedelete_walk_fd(DELETE vs LIST) so dry-run and real deletion cannot drift.delete_skips_build) and used by all four former call sites.Config + minor deferred
ConfigCLI-parse bookkeeping grouped intoConfig.cli; deadConfig.old_argsfield removed (--old-argsstays an accepted no-op).CONFIG_WIRE_*tables untouched;test_config_wire_goldenunchanged (len=886, hash pinned).protocol_throttle_bytesnow resolves the same session as the send path (fixes first-call double-burst).--temp-dircoverage (via batch apply; CI container lacks mount caps — documented).Not done (still deferred)
AGENTS.mdflags the SSLWANT_READ/WANT_WRITEretry as load-bearing; moving SSL behind a vtable needs dedicated TLS/MT regression scaffolding first. Left as-is.Verification
Strict
-Werrorbuild clean; clang-format 18 clean; cppcheck clean; unit 45/45 under ASan/UBSan/valgrind; full integration 884 passed; differential parity 62 passed; config-wire golden unchanged. Two independent reviews (comprehensive + C memory/thread-safety) did per-function equivalence analysis and found no behavior/ownership defects (only cosmetic notes).