9d0727d49b
Follow-up to the salvaged #93200 commit. Factors the portable _cross_process_repair_lock ownership pattern (msvcrt on Windows, flock on POSIX, bounded 120s wait) into a cycle-safe shared primitive, fts_rebuild_admission() in hermes_state_common, and routes EVERY full structural FTS rebuild entry point through it: - SessionSearchMixin.rebuild_fts() (replaces the POSIX-only, fail-open 30s flock from the original commit) - _init_schema's trigger-repair rebuilds (_rebuild_fts_indexes / _rebuild_legacy_fts_indexes) via _run_admitted_startup_rebuild - _recover_stale_fts() Fail closed: a caller that cannot acquire the authority DEFERS the rebuild (FTS detached + durable stale breadcrumb, retried at next startup) instead of proceeding into the exact concurrent-rebuild interleaving that structurally corrupted state.db in production. Chunked deferred backfill (fts_rebuild_step) intentionally stays outside the authority. Adds spawned-process regression tests (real child process holding the real lock file): holder blocks contender, deferral fails closed on both the runtime and schema paths, release/holder-death permits the next owner, and stale recovery completes after contention clears. Sabotage-verified: 4/6 tests fail with the admission forced open.