Skip to content

feat(install): report a rejected state root at install and doctor time, and offer to fix it - #794

Open
screenleon wants to merge 8 commits into
mainfrom
fix/doctor-state-root-preflight
Open

screenleon wants to merge 8 commits into
mainfrom
fix/doctor-state-root-preflight

Conversation

@screenleon

Copy link
Copy Markdown
Owner

Summary

Tests

  • test-doctor: case_doctor_unsafe_state_root_fails_with_remedy
  • test-install: test_install_reports_and_fixes_rejected_state_root
  • WSL: test-doctor 98/0; test-install 99 pass/0 fail before the 1700 s limit, new case passes alone. CI lints 19/0.
  • Not covered: the interactive prompt itself (needs a TTY).

Permanent test admissions: case_doctor_unsafe_state_root_fails_with_remedy, test_install_reports_and_fixes_rejected_state_root — contract tests for a user-facing failure and its remedy, added to existing suites.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7

screenleon and others added 8 commits November 12, 2026 18:52
…e, and offer to fix it

The state writer refuses a state root another account can write to. On a native Windows host with a
Codex sandbox account that is the default location, so every state-writing pmctl command stopped after
an install that looked fine.

- doctor fails with the reason and the fix instead of leaving the first pmctl call to be refused.
- install.sh ends with the same warning; --fix-state-root (or a yes at an interactive prompt) creates
  ~/.pm-dispatch-state owner-only, confirms the guard accepts it, and on native Windows records it as the
  user's PM_DISPATCH_STATE_ROOT. An existing directory is checked, never re-permissioned; the check
  stays on.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7
… a person cancel

The warning came after the install had finished. It now runs before any change: a person at a terminal
chooses y (use ~/.pm-dispatch-state), n (install unchanged) or c (cancel, nothing changed); a scripted
install still only warns, and --fix-state-root still repairs without asking.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7
… root exclusively, test repair and consent on every platform

Gate remediation: critic-F001 (icacls options rewritten by MSYS), qa-tester-F001/F002 (native-capable
repair and y/n/c/existing-destination coverage), security-reviewer-F001 (exclusive creation).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7
… real ACL grant

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7
…tage needs to delete an owner-only directory

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7
…account, not the profile name

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P8BvZ5Crn6vi6EA2J7
…tor's new check accepts them on native Windows

A state root made with mkdir -p under the temp root inherits a write grant for another principal on native Windows
(e.g. the Codex sandbox group), which Doctor now reports as a failure. The stale and indeterminate detached-run cases
create their state root with an owner-only helper instead.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P9zqMvS4GeAcn3S3Jw
…ve Windows

The repair promises to inspect an existing directory and never change its permissions. The Windows branch of the
existing-directory case checked contents and persistence only, so moving the icacls call outside the creation branch
would still pass. It now compares the directory's real ACL before and after the repair.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESW7P9zqMvS4GeAcn3S3Jw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant