feat(v0.11): ADR 0011 freeze + Track A — sentinel install one-shot - #47
Merged
Conversation
Complete implementation of first-install flow following ADR 0011 §D2 sequence: 1. Install method detection (reuses ADR 0010 D1) 2. Config initialization from template (idempotent) 3. Data directory creation 4. LaunchAgent plist generation + write 5. launchctl load 6. Daemon liveness check (2s sleep + launchctl list) 7. Post-install banner (per ADR 0011 §D8) Implemented modules: - sentinel_mac/installer/plist.py — plist generation, conflict detection (D5) - sentinel_mac/installer/config_init.py — config template handling - sentinel_mac/installer/verify.py — daemon liveness + banner builder - sentinel_mac/commands/install.py — full 7-step orchestrator Features: - D4 Idempotency: handles partial installs, --force override - D5 Conflict detection: detects dev .venv vs PIPX, guides migration - Exit codes: 0 (success), 1 (error), 2 (already installed), 3 (unsupported method) - Flags: --force, --no-launchagent, --yes, --json - Non-TTY behavior: auto-cancel with WARNING (ADR 0009 pattern) - JSON output: ADR 0004 §D2 envelope format - Rollback on failure: cleans up newly created artifacts Tests: 43 new tests covering happy path, idempotency, conflicts, unsupported methods, non-interactive mode, JSON output, dispatch entry point. Code quality: - mypy: clean - ruff: clean (fixed all lint issues, proper exception chaining) - pytest: 950 tests pass (907 existing + 43 new) ADR amendment: D2 step 7 updated to document subprocess pattern for doctor (following ADR 0010 §D3 consistency). Package data: config.example.yaml now included in wheel via pyproject.toml setup.py-style package-data configuration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
v0.11 사이클 첫 PR. 사용자 피드백 — "이번 업그레이드 경험은 매우 간단했어. 그런데 첫 설치 경험은 너무 복잡하고 어려웠어." — 닫기.
이전:
v0.11 이후:
ADR 0011 freeze (Status: Proposed)
sentinel install [--force|--no-launchagent|--yes|--json]. exit 0/1/2/3--force로 전체 재생성.venv/bin/sentinel패턴) 충돌 시 abort + 안내.--force로 백업 후 덮어쓰기sentinel uninstall대칭ADR amendment (planner 초안 → 사용 시점에 수정): D2 step 7의 doctor verify를 direct call → subprocess 호출로 변경. ADR 0010 §D3
verify_running_version패턴 일관 + 두 호출 지점 동기화 부담 제거.Track A 구현
신규:
sentinel_mac/installer/__init__.pysentinel_mac/installer/plist.py(~150 LOC) — pure plist XML 생성, 0o644 write, 기존 plist binary path parsing (D5 conflict detection)sentinel_mac/installer/config_init.py(~85 LOC) —config.example.yaml템플릿에서 idempotent config 생성 (importlib.resources)sentinel_mac/installer/verify.py(~101 LOC) —launchctl list→ PID 추출 →sentinel --versionsubprocess 매칭 →sentinel doctorsubprocesssentinel_mac/commands/install.py(~341 LOC) — D2 7단계 오케스트레이션 + rollback + JSON envelope (kind=install)sentinel_mac/config.example.yaml— 패키지 동봉 (wheel에 포함되도록pyproject.toml[tool.setuptools.package-data]명시)tests/test_cmd_install.py(18 tests) — happy path / idempotent / unsupported method / D5 conflict / non-TTY / --json / --force rollbacktests/test_installer_plist.py(15 tests) — XML validity / field 정확도 / 권한 / 기존 plist parsingtests/test_installer_config_init.py(10 tests) — 템플릿 발견 / 생성 / idempotency / force overwrite수정:
sentinel_mac/core.py— argparseinstallsubcommand dispatch (5줄)pyproject.toml—[tool.setuptools.package-data]추가 (config.example.yaml 동봉)docs/decisions/0011-first-install-flow.md— ADR + D2 step 7 subprocess 명시CHANGELOG.md[Unreleased]에 freeze + Track A 항목총 +2254 LOC.
Verification
Test 시나리오 (43개)
.venvplist 충돌 — abort + migration 안내--force— 백업 후 덮어쓰기--yes— auto-cancel + WARNING (ADR 0009)--no-launchagent— plist/load skip--json— ADR 0004 §D2 envelopekind="install"/"install_error"Next steps (이 PR 머지 후)
sentinel uninstall대칭 명령 (별도 PR, 작은 작업)Test plan
🤖 Generated with Claude Code