Skip to content

[stack 3/8] fix(coding-agent): make persisted state crash-safe - #1160

Open
sethkarten wants to merge 7 commits into
stack/external-02-securityfrom
stack/external-03-persistence
Open

[stack 3/8] fix(coding-agent): make persisted state crash-safe#1160
sethkarten wants to merge 7 commits into
stack/external-02-securityfrom
stack/external-03-persistence

Conversation

@sethkarten

@sethkarten sethkarten commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Stack 3/8 — fix(coding-agent): make persisted state crash-safe

Active review snapshot — do not merge yet. The complete stack is open for architecture/design review, while final cumulative audit, CI, Cursor Bug Bot, and Macroscope findings are being remediated. Branches will be force-updated after validation.

Base: stack/external-02-security
Review order: merge only after the preceding stack layer is accepted. This PR is not intended to merge independently out of order.

Stack navigation

  1. #1158 — ci: harden verification and release compatibility
  2. #1159 — fix(security): harden session and autonomous execution boundaries
  3. #1160 — fix(coding-agent): make persisted state crash-safe
  4. #1161 — fix(daemon): fence worker and supervisor lifecycle state
  5. #1162 — fix(coding-agent): repair queued and archived session lifecycle
  6. #1163 — fix(coding-agent): complete Windows kernel and daemon startup
  7. #1164 — fix(providers): harden MCP OAuth and Codex transports
  8. #1165 — fix(runtime): bound transcript and autonomous recovery

Summary

  • Repair torn JSONL tails without losing concurrent appends, with bounded manual recovery for oversized tails.
  • Serialize session mutations across processes and recover safely from dead lock owners.
  • Make settings, auth, and migration writes private, atomic, durable on POSIX, and restart-idempotent.

Validation

  • npm run check; persistence/session/config focused suites; final crash-lock duration suite pending remediation recheck.
  • Residual/non-blocking: Windows crash-injection not run; POSIX directory fsync skipped on Windows

Provenance

  • Authored independently from upstream/main using issue reports and PR descriptions/comments only.
  • No external contributor branch, diff, commit, implementation code, or test code was fetched, inspected, copied, or reused.
  • The implementation and regression tests in this stack are maintainer-owned.

Linked-item disposition

Fixed on merge

Independently superseded pull requests

Partial/distinct overlap — remains open

Reviewer notes

  • Please review this layer against its immediate stack base, not against main, to avoid cumulative duplicate diffs.
  • No merge is requested; the complete stack is being left for human review.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1c74fdd. Configure here.

data: string | NodeJS.ArrayBufferView,
options: AtomicReplaceOptions = {},
): void {
replaceFileAtomicallySync(path, (fd) => writeFileSync(fd, data), options);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Atomic writes follow planted symlinks

High Severity

writeFileAtomicallySync always re-resolves through resolveFileTargetSync, which follows a final-component symlink via realpathSync. Auth and settings call resolveManagedFilePathSync first to reject symlinks, then write with this helper, so a symlink planted after that check is followed and the symlink target is overwritten. The previous writePrivateFileAtomic renamed onto the lexical path and replaced the symlink itself.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1c74fdd. Configure here.

function ensurePrivateDirectory(path: string): void {
if (!existsSync(path)) mkdirSync(path, { recursive: true, mode: 0o700 });
chmodSync(path, 0o700);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weaker duplicate directory helper

Medium Severity

FileSettingsStorage defines a local ensurePrivateDirectory that only mkdir/chmods, while private-files.ts already exports a stronger helper that rejects symlinks and non-directories. Auth and session code use the shared helper; settings reimplements a weaker copy, so symlink/non-directory parents are not refused consistently.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1c74fdd. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant