Originally created by: sosidudku1
On Windows the startup read of <stateDir>/.env can fail with EPERM while the file exists (#59). The loader printed a single stderr line and continued; that line scrolls away before the TUI takes over the alt screen and is easy to miss, so stored API keys silently vanished and setup asked for them again.
load-dotenv: the read of an existing .env is retried up to 3 attempts with 50/150 ms backoff on EPERM/EACCES/EBUSY/EAGAIN, the codes transient antivirus and sync locks surface as on Windows (on POSIX an EACCES is usually a permanent denial and costs one ~200 ms loop before the warning). ENOENT stays a silent no-op, all other codes fail fast.load-dotenv: a failure that survives the retries lands in the new DotenvLoadResult.error (errno code plus attempt count) and prints an actionable warning naming the path and platform-specific fixes: read-only attribute, antivirus exclusion, icacls /reset on Windows; owner and chmod on POSIX. Variable names only, never values. Malformed lines are now reported by line number and length without echoing content, since a torn line from an external non-atomic writer can be a fragment of a secret value.load-config / config-schema: the load outcome travels as config.dotenv so frontends can surface it.tui-command: when config.dotenv.error is set, the TUI repeats the warning as a warn-variant system chat message, because the stderr line is easy to miss under the alt screen.windows-acl (extracted from dotenv-writer): after tightening the .env ACL with icacls /inheritance:r /grant:r, verify the file is still readable by this very process and roll back with icacls /reset when it is not. A grant that resolves to the wrong principal would leave a file nobody can read; that is one plausible cause of the symptom in [#59], and the probe closes it off either way.setDotenvKey) has no retry loop; this PR covers the startup read only..env exists and stays unreadable; the common paths (no file, readable file) are unchanged.Retry-then-success loads keys; persistent EPERM warns with path and guidance without throwing; non-retryable codes fail fast; a missing file stays silent; the warning and parse diagnostics carry no values or file content; loadConfig propagates the outcome into config.dotenv (happy path and the unreadable-file case); ACL tighten/probe/rollback paths are covered with injected deps. The loader contract is pinned in AGENTS.md.
Closes [#59]
Ticket changed by: Ooooze