openSync with read-only mode fails fsync on Windows because FlushFileBuffers requires write-permission FD. This caused atomic writes to fail silently, leaving migrated config unwritten and triggering repeated migration + .bak.<timestamp> generation on every startup.
Same root cause as PR #3644 (#3643). Hyperplan disappear is a secondary symptom of plugin load instability.
Fixes#3877
Replaces fsyncSync(tempFileDescriptor) with tolerantFsyncSync, allowing
EPERM/EACCES/ENOTSUP/EINVAL during fsync while still propagating real
errors. Adds an optional deps.fsyncSync injection point used solely by
the new EPERM tolerance regression tests.
Without this fix, plugin startup itself can fail on synced folders
because writeFileAtomically is used by config migrations and posthog
activity state — the same EPERM-on-fsync failure pattern reported for
team_create.
On Windows, renameSync fails with EPERM/EACCES when the target file
already exists. Fall back to unlink + rename on Windows permission
errors while preserving atomic semantics on other platforms.
🤖 Generated with OhMyOpenCode assistance
https://github.com/code-yeongyu/oh-my-opencode