Commit cf5fa64
fix(wrap): stop same-port persistent routing during claude unwrap (headroomlabs-ai#2340) (headroomlabs-ai#2350)
## Description
`headroom unwrap claude` currently removes Claude-local wrap state but
can still leave Claude effectively routed through Headroom when the same
port belongs to a managed persistent deployment. The command already
knows how to discover same-port persistent manifests, but its stop path
only kills the current pid and never uses that deployment metadata. This
patch keeps the existing local settings cleanup, then applies an
ownership-aware same-port audit: Claude-owned deployments are stopped
through the install lifecycle path, while ambiguous same-port residue is
surfaced with exact remediation instead of a false clean-success claim.
Refs headroomlabs-ai#2340.
## Type of Change
- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)
## Changes Made
- extend the Claude unwrap stop path in `headroom/cli/wrap.py` to
distinguish local pid stops, Claude-owned same-port persistent
deployments, and ambiguous same-port residue
- reuse the install lifecycle teardown path for Claude-owned persistent
deployments instead of re-implementing supervisor cleanup
- keep the existing Claude-local settings, hook, and base-url cleanup
unchanged
- add focused CLI regressions that prove a matching Claude-owned
deployment is stopped during unwrap, ambiguous same-port residue is
reported truthfully, and different-port manifests stay untouched
## Testing
- [x] Unit tests pass (`uv run pytest
tests/test_cli/test_unwrap_claude.py
tests/test_cli/test_wrap_persistent.py -q`)
- [x] Linting passes (`uv run ruff check headroom/cli/wrap.py
tests/test_cli/test_unwrap_claude.py`)
- [ ] Type checking passes (`uv run mypy headroom`)
- [x] New tests added for new functionality when applicable
- [x] Manual testing performed
### Test Output
```text
uv run pytest tests/test_cli/test_unwrap_claude.py tests/test_cli/test_wrap_persistent.py -q
============================= 43 passed in 0.51s ==============================
uv run pytest tests/test_cli/test_unwrap_claude.py -q
============================= 13 passed in 0.41s ==============================
uv run pytest tests/test_cli/test_wrap_persistent.py -q
============================= 30 passed in 0.39s ==============================
uv run ruff check headroom/cli/wrap.py tests/test_cli/test_unwrap_claude.py
All checks passed!
uv run ruff format headroom/cli/wrap.py tests/test_cli/test_unwrap_claude.py --check
2 files already formatted
```
## Real Behavior Proof
- Environment: Windows worktree
`D:\Repos\headroom-pr-2340-claude-unwrap-effective-routing` with `uv
sync --extra dev`
- Exact command / steps: run the focused pytest and Ruff commands above,
then run a constructed `CliRunner` replay against both
`D:\Repos\headroom` and this branch with the same same-port Claude-owned
manifest harness
- Observed result: base prints `base: exit=0; local=[8787];
deactivated=[]; stopped=[]` and still routes through the pid-only
helper; head prints `head: exit=0; local=[];
deactivated=['unwrap-2340']; stopped=['unwrap-2340']` and reports
`Stopped Claude-owned persistent deployment 'unwrap-2340' on port 8787.`
- Not tested: a live macOS launchd deployment on this host
## Review Readiness
- [x] I have performed a self-review
- [x] This PR is ready for human review
## Checklist
- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] I have updated the CHANGELOG.md if applicable
## Additional Notes
`CHANGELOG.md` is not applicable because Headroom derives release notes
from conventional commits.
Scope stays below the broader uninstall workflow in open PR `headroomlabs-ai#749`: this
patch makes Claude unwrap truthful and ownership-aware, but it does not
remove install artifacts or introduce a new uninstall command.
---------
Co-authored-by: JerrettDavis <mxjerrett@gmail.com>1 parent b759990 commit cf5fa64
2 files changed
Lines changed: 254 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3186 | 3186 | | |
3187 | 3187 | | |
3188 | 3188 | | |
| 3189 | + | |
| 3190 | + | |
| 3191 | + | |
| 3192 | + | |
| 3193 | + | |
| 3194 | + | |
| 3195 | + | |
| 3196 | + | |
| 3197 | + | |
| 3198 | + | |
| 3199 | + | |
| 3200 | + | |
| 3201 | + | |
| 3202 | + | |
| 3203 | + | |
| 3204 | + | |
| 3205 | + | |
| 3206 | + | |
| 3207 | + | |
| 3208 | + | |
| 3209 | + | |
| 3210 | + | |
| 3211 | + | |
| 3212 | + | |
| 3213 | + | |
| 3214 | + | |
| 3215 | + | |
| 3216 | + | |
| 3217 | + | |
| 3218 | + | |
| 3219 | + | |
| 3220 | + | |
| 3221 | + | |
| 3222 | + | |
| 3223 | + | |
| 3224 | + | |
| 3225 | + | |
| 3226 | + | |
| 3227 | + | |
| 3228 | + | |
| 3229 | + | |
| 3230 | + | |
| 3231 | + | |
| 3232 | + | |
| 3233 | + | |
| 3234 | + | |
| 3235 | + | |
| 3236 | + | |
| 3237 | + | |
| 3238 | + | |
| 3239 | + | |
| 3240 | + | |
| 3241 | + | |
| 3242 | + | |
| 3243 | + | |
| 3244 | + | |
| 3245 | + | |
| 3246 | + | |
| 3247 | + | |
| 3248 | + | |
| 3249 | + | |
| 3250 | + | |
| 3251 | + | |
| 3252 | + | |
| 3253 | + | |
| 3254 | + | |
| 3255 | + | |
| 3256 | + | |
| 3257 | + | |
| 3258 | + | |
| 3259 | + | |
| 3260 | + | |
| 3261 | + | |
| 3262 | + | |
| 3263 | + | |
| 3264 | + | |
| 3265 | + | |
| 3266 | + | |
| 3267 | + | |
| 3268 | + | |
| 3269 | + | |
| 3270 | + | |
| 3271 | + | |
| 3272 | + | |
| 3273 | + | |
| 3274 | + | |
| 3275 | + | |
| 3276 | + | |
| 3277 | + | |
| 3278 | + | |
| 3279 | + | |
| 3280 | + | |
| 3281 | + | |
| 3282 | + | |
| 3283 | + | |
| 3284 | + | |
| 3285 | + | |
| 3286 | + | |
| 3287 | + | |
| 3288 | + | |
| 3289 | + | |
| 3290 | + | |
| 3291 | + | |
| 3292 | + | |
| 3293 | + | |
| 3294 | + | |
| 3295 | + | |
| 3296 | + | |
| 3297 | + | |
| 3298 | + | |
| 3299 | + | |
| 3300 | + | |
| 3301 | + | |
| 3302 | + | |
| 3303 | + | |
| 3304 | + | |
| 3305 | + | |
| 3306 | + | |
| 3307 | + | |
| 3308 | + | |
| 3309 | + | |
| 3310 | + | |
| 3311 | + | |
| 3312 | + | |
| 3313 | + | |
| 3314 | + | |
| 3315 | + | |
| 3316 | + | |
| 3317 | + | |
| 3318 | + | |
| 3319 | + | |
| 3320 | + | |
| 3321 | + | |
| 3322 | + | |
| 3323 | + | |
| 3324 | + | |
| 3325 | + | |
3189 | 3326 | | |
3190 | 3327 | | |
3191 | 3328 | | |
| |||
4778 | 4915 | | |
4779 | 4916 | | |
4780 | 4917 | | |
4781 | | - | |
4782 | | - | |
4783 | | - | |
| 4918 | + | |
| 4919 | + | |
| 4920 | + | |
| 4921 | + | |
| 4922 | + | |
| 4923 | + | |
| 4924 | + | |
| 4925 | + | |
| 4926 | + | |
| 4927 | + | |
| 4928 | + | |
| 4929 | + | |
4784 | 4930 | | |
4785 | 4931 | | |
4786 | 4932 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
19 | 24 | | |
20 | 25 | | |
21 | 26 | | |
| |||
246 | 251 | | |
247 | 252 | | |
248 | 253 | | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
249 | 354 | | |
250 | 355 | | |
251 | 356 | | |
| |||
0 commit comments