* fix(state): normalize extended-length mkdir paths
On Windows fs.mkdir(recursive) reports the first created directory as an
extended-length path (\?\C:\...) while the requested directory is a plain
drive path. path.resolve keeps the prefix, so the two never compare equal
and path.relative between them yields an absolute path. The chain walk then
takes "C:" as its next segment and syncs a directory that does not exist,
so ensureDirectory throws ENOENT every time it actually creates something.
That breaks LLM cache writes, state.set, diff snapshots, and approval index
publication on the first Windows run.
Strip the prefix before resolving so both ends of the chain share one root
form. On POSIX the prefixes never occur and the walk is unchanged.
* fix(state): keep device namespaces out of the path normalization
Stripping every \?\ prefix also rewrote namespaces that have no plain
equivalent, so an explicitly configured LOBSTER_STATE_DIR such as
\?\Volume{GUID}\lobster\state became relative and resolved against the
current drive. That regressed a form main handles today.
Map only the drive-letter and UNC namespaces, which do have a plain
equivalent, and return anything else untouched. Cover the mapping directly
so the device-namespace case is pinned.
* fix(state): recognise the UNC namespace whatever its case
Windows compares path namespace components case-insensitively, so
`\?\unc\server\share` names the same share as `\?\UNC\server\share`.
Matching only the uppercase form left the lowercase spelling extended
while the directory it walks toward is plain, so the sync walk could
never reach the requested final path on such a setup.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gD5sJTbh2jn1uvgNCmkLq
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Harden LLM cache files, diff snapshots, and approval ID indexes against truncated or malformed JSON after process termination.
Disposable cache and snapshot corruption now recovers as a miss; authoritative resume state still surfaces malformed JSON. Approval short-ID indexes use atomic no-overwrite publication and degrade to full resume-token approval when the index cannot be published durably.
Closes#111.
Closes#112.
Closes#113.
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Fixes#108 and #109.
- Replace direct state writes with same-directory atomic temp-file writes.
- Preserve existing file modes and create new state files as 0600.
- Clean up temp files on failed replacement paths.
- Add state/SDK regression coverage plus changelog entry.
Proof:
- pnpm run typecheck
- node --test dist/test/state.test.js dist/test/resume.test.js dist/test/multi_approval_resume.test.js dist/test/approve_preview.test.js
- pnpm run lint
- pnpm run test
- built SDK write/read proof preserved 0600 across replacement
- autoreview clean: no accepted/actionable findings
Co-authored-by: Krasimir Kralev <krasi@idrobots.com>