PID-scope the Playwright-MCP stall recovery — pkill -f ms-playwright-mcp is the same shared-host reap as #586 #596

Open
opened 2026-07-25 12:28:29 +02:00 by timothy · 0 comments
Owner

Split out from #586 rather than widened into it, because reversing an existing decision record is a lifecycle operation (docs.decision-lifecycle: supersede + relocate, never line-edit) and #586's PR is a docs/shell hygiene change.

Problem

The active record testing.playwright-mcp-download-and-recovery (docs/decisions/workflow-process.md) prescribes:

if browser tools stall repeatedly, pkill -f ms-playwright-mcp and drive a fresh session

That is exactly the pattern-kill hazard #586 just recorded as forbidden. On this shared Mac, several sessions can be driving Playwright-MCP at once, so pkill -f ms-playwright-mcp reaps every session's MCP server, not just the stalled one. Same failure shape as the #586 near-miss and the #406 peak-anon incident: reaping a shared-host resource you did not create, in a way that does not fail loudly for the victim.

#586's new record testing.e2e-cleanup-scope-by-pid states its rule generally ("any pattern that can match a process this run did not start"), so it already covers this case in principle — the two records are in visible tension until one is reconciled. #586 documents the tension inline and defers the fix here.

Why it wasn't just fixed in #586

Two reasons, both worth preserving:

  1. The MCP-recovery record is a different decision with its own key; superseding it means adding a successor record and relocating the predecessor to archive/ with a reciprocal supersedes/superseded-by pair. That is a lifecycle edit, not a typo fix.
  2. The right replacement recipe needs a moment's thought (below) — worth doing deliberately rather than as a drive-by inside an unrelated PR.

Suggested resolution

Supersede testing.playwright-mcp-download-and-recovery with a version whose recovery step is PID-scoped. The download-endpoint half of that record (curl, never a browser tab) is unaffected and should carry over unchanged — enumerate both behaviors before rewriting it (process.enumerate-workaround-behaviors-before-deleting).

Recovery recipe to validate before recording:

pgrep -f ms-playwright-mcp          # identify; expect possibly SEVERAL, not all yours
# narrow to your own — e.g. by parent PID / start time / the port your session drives
kill "$PID"                          # the one you identified

The honest open question: is a session's own MCP server actually identifiable from the outside? If Playwright-MCP servers are indistinguishable across sessions (no per-session port/arg), then a safe PID-scoped recovery may not exist as written, and the correct record may instead be "restart the MCP server through the client, never from the shell." Determine this first — do not record a recipe that cannot be executed.

Done-when

  • Determined whether a session's own ms-playwright-mcp process is externally identifiable (evidence, not assumption)
  • testing.playwright-mcp-download-and-recovery superseded by a record whose recovery step is PID-scoped (or client-side), predecessor relocated to docs/decisions/archive/ with a reciprocal supersedes/superseded-by pair
  • The download-endpoint half of the original record carried over intact
  • The tension paragraph in testing.e2e-cleanup-scope-by-pid updated to point at the successor instead of "tracked as a follow-up"
  • PYTHONPATH=. python3 scripts/decisions_validate.py green and docs/decisions/README.md regenerated
  • Adversarial review passed
Split out from #586 rather than widened into it, because reversing an existing decision record is a lifecycle operation (`docs.decision-lifecycle`: supersede + relocate, never line-edit) and #586's PR is a docs/shell hygiene change. ## Problem The active record `testing.playwright-mcp-download-and-recovery` (`docs/decisions/workflow-process.md`) prescribes: > if browser tools stall repeatedly, `pkill -f ms-playwright-mcp` and drive a fresh session That is **exactly the pattern-kill hazard** #586 just recorded as forbidden. On this shared Mac, several sessions can be driving Playwright-MCP at once, so `pkill -f ms-playwright-mcp` reaps every session's MCP server, not just the stalled one. Same failure shape as the #586 near-miss and the #406 peak-anon incident: reaping a shared-host resource you did not create, in a way that does not fail loudly for the victim. #586's new record `testing.e2e-cleanup-scope-by-pid` states its rule generally ("any pattern that can match a process this run did not start"), so it already **covers** this case in principle — the two records are in visible tension until one is reconciled. #586 documents the tension inline and defers the fix here. ## Why it wasn't just fixed in #586 Two reasons, both worth preserving: 1. The MCP-recovery record is a **different decision** with its own key; superseding it means adding a successor record and relocating the predecessor to `archive/` with a reciprocal `supersedes`/`superseded-by` pair. That is a lifecycle edit, not a typo fix. 2. The right replacement recipe needs a moment's thought (below) — worth doing deliberately rather than as a drive-by inside an unrelated PR. ## Suggested resolution Supersede `testing.playwright-mcp-download-and-recovery` with a version whose recovery step is PID-scoped. The download-endpoint half of that record (curl, never a browser tab) is unaffected and should carry over unchanged — **enumerate both behaviors before rewriting it** (`process.enumerate-workaround-behaviors-before-deleting`). Recovery recipe to validate before recording: ```bash pgrep -f ms-playwright-mcp # identify; expect possibly SEVERAL, not all yours # narrow to your own — e.g. by parent PID / start time / the port your session drives kill "$PID" # the one you identified ``` The honest open question: **is a session's own MCP server actually identifiable from the outside?** If Playwright-MCP servers are indistinguishable across sessions (no per-session port/arg), then a safe PID-scoped recovery may not exist as written, and the correct record may instead be "restart the MCP server through the client, never from the shell." Determine this first — do not record a recipe that cannot be executed. ## Done-when - [ ] Determined whether a session's own `ms-playwright-mcp` process is externally identifiable (evidence, not assumption) - [ ] `testing.playwright-mcp-download-and-recovery` superseded by a record whose recovery step is PID-scoped (or client-side), predecessor relocated to `docs/decisions/archive/` with a reciprocal `supersedes`/`superseded-by` pair - [ ] The download-endpoint half of the original record carried over intact - [ ] The tension paragraph in `testing.e2e-cleanup-scope-by-pid` updated to point at the successor instead of "tracked as a follow-up" - [ ] `PYTHONPATH=. python3 scripts/decisions_validate.py` green and `docs/decisions/README.md` regenerated - [ ] Adversarial review passed
timothy added the ci-cdpriority: low labels 2026-07-25 12:28:29 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: timothy/ersatztv#596