Skip to content

Harden persistent MCP runtime, recovery, and stdio isolation - #362

Closed
andrebarros78 wants to merge 6 commits into
CursorTouch:mainfrom
andrebarros78:codex/mcp-resilience-security
Closed

Harden persistent MCP runtime, recovery, and stdio isolation#362
andrebarros78 wants to merge 6 commits into
CursorTouch:mainfrom
andrebarros78:codex/mcp-resilience-security

Conversation

@andrebarros78

Copy link
Copy Markdown

Summary

  • hardens the persistent Windows MCP supervisor, queue, heartbeat, checkpoint, and atomic persistence flow;
  • isolates PowerShell timeout failures to the child process tree;
  • enforces the managed stdio command and a 336-hour MCP connection TTL;
  • validates tunnel and MCP recovery without duplicate or orphan runtimes;
  • preserves upstream v0.8.5 startup guards and COM cache fixes;
  • moves screenshot worker IPC from stdout to a JSON sidecar file so stdio JSON-RPC cannot be corrupted;
  • documents final validation and requirement-to-evidence mapping.

Validation

  • Ruff: passed
  • Pytest: 571 passed
  • Build: windows_mcp-0.8.5 wheel and sdist passed
  • Controlled tunnel recovery: passed with 60-second stability proof
  • Runtime after environment sync: healthy, one tunnel, no orphan MCP processes

Operational note

Screenshot capture remains safely quarantined when the Windows graphics session cannot support isolated capture. The failure is localized and does not terminate the MCP server or tunnel.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Harden persistent MCP runtime supervision and stdio tool isolation (Windows)

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add a persistent Windows supervisor with atomic queue/state/heartbeat/checkpoint persistence.
• Isolate stdio tool failures (PowerShell timeouts, screenshot capture) to child processes.
• Enforce managed tunnel profile command + 336h TTL, preventing duplicate/orphan runtimes.
Diagram

graph TD
  A(["Windows Scheduled Task"]) --> B(["Persistent Supervisor"]) --> C(["tunnel-client runtime"]) --> D(["windows_mcp stdio server"])
  B --> E[(".orquestrador state")]
  D --> F(["Screenshot tool"]) --> G(["Screenshot worker proc"])
  D --> H(["SystemQuery (allowlist)"])
  D --> I(["PowerShell executor"])
  subgraph Legend
    direction LR
    _entry(["Process/Component"]) ~~~ _state[("Persisted state")
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Windows Service instead of Scheduled Task
  • ➕ More standard long-running daemon semantics (service recovery, SCM visibility).
  • ➕ Can run under a dedicated service account with explicit privileges.
  • ➖ Higher operational complexity (install/uninstall, permissions, debugging).
  • ➖ May complicate interactive desktop access assumptions for certain tools.
2. Move supervisor into packaged module (not scripts/)
  • ➕ Versioned and shipped with the wheel; fewer "ops-only" scripts to distribute.
  • ➕ Easier to integrate with CLI flags/config and reuse internal utilities.
  • ➖ Increases coupling between runtime supervision and library surface.
  • ➖ Packaging/entrypoint changes may be riskier for upstream syncs.
3. Use OS-native IPC for worker results (named pipe) instead of JSON sidecar
  • ➕ Avoids temp-file IO and potential antivirus/file-lock contention.
  • ➕ Can support streaming results if expanded later.
  • ➖ More Windows-specific complexity and error cases.
  • ➖ Harder to troubleshoot than a persisted JSON artifact.

Recommendation: The PR’s approach (scheduled-task supervisor + atomic file-backed queue + isolated child processes for risky operations) is the best fit for Windows reliability while keeping deployment simple. A Windows Service is viable if the environment requires SCM-managed recovery, but the current design already addresses the primary failure modes (duplicate tunnels, orphan MCP runtimes, stdio corruption) with lower operational overhead.

Files changed (55) +5704 / -133

Enhancement (9) +2685 / -0
enqueue_supervisor_task.pyAdd atomic inbox task enqueuer for supervisor +116/-0

Add atomic inbox task enqueuer for supervisor

• Introduces a CLI to enqueue allowed supervisor tasks via an atomic JSON write into the inbox directory. Supports task metadata like timeouts, resumability, and targeted recovery parameters.

scripts/enqueue_supervisor_task.py

run_supervisor_task.pyAdd persisted task runner with isolated process termination +199/-0

Add persisted task runner with isolated process termination

• Implements a standalone task runner that reads a spec JSON, runs a command with redirected stdout/stderr to evidence logs, and atomically persists results. Ensures timeouts kill only the spawned process tree.

scripts/run_supervisor_task.py

test_supervisor_recovery.pyAdd Python recovery probe for tunnel/MCP health and orphan detection +355/-0

Add Python recovery probe for tunnel/MCP health and orphan detection

• Adds a recovery validation harness that inspects tunnel processes, queries health endpoints, and detects orphan MCP runtimes by normalized command matching. Produces structured JSON evidence for controlled recovery runs.

scripts/test_supervisor_recovery.py

windows_mcp_supervisor.pyIntroduce persistent supervisor with health gating, recovery, and atomic persistence +1433/-0

Introduce persistent supervisor with health gating, recovery, and atomic persistence

• Adds a full persistent supervisor implementation that enforces single-instance locking, managed tunnel profile command + 336h TTL, transport-aware health checks, and orphan/duplicate cleanup. Implements an atomic, file-backed queue/inbox model with detached task runners, heartbeat/state/checkpoint persistence, log rotation, and restart backoff/limits.

scripts/windows_mcp_supervisor.py

screenshot_worker.pyAdd isolated screenshot worker entrypoint +79/-0

Add isolated screenshot worker entrypoint

• Implements a CLI worker that performs in-process capture and writes a JSON status file plus PNG output. Ensures errors are written to stderr and summarized in the JSON sidecar for the parent process.

src/windows_mcp/desktop/screenshot_worker.py

__init__.pyRegister new safety/health/system query tools +6/-0

Register new safety/health/system query tools

• Adds 'Health', 'SystemQuery', and 'SafetyDryRun' to the tool module registry so they appear in stdio tool listings. Ensures these are available as safe first-call diagnostics and security rejection probes.

src/windows_mcp/tools/init.py

health.pyAdd read-only Health tool for safe first-call probing +51/-0

Add read-only Health tool for safe first-call probing

• Introduces a minimal 'Health' tool that confirms server liveness without PowerShell, file IO, screenshots, or network access. Returns process/version/uptime metadata with read-only annotations.

src/windows_mcp/tools/health.py

system_query.pyAdd allowlisted SystemQuery tool with bounded IO/timeouts +373/-0

Add allowlisted SystemQuery tool with bounded IO/timeouts

• Implements structured, read-only project/system queries with path confinement, blocked secret-like path parts, suffix allowlists, and strict output limits. Runs external allowlisted commands without a shell, without inherited pipes, with hard timeouts and process-tree termination; implements local-metadata 'git_status' to avoid slow git processes.

src/windows_mcp/tools/system_query.py

safety_dry_run.pyAdd SafetyDryRun tool for rejection/isolation verification +73/-0

Add SafetyDryRun tool for rejection/isolation verification

• Adds a non-destructive probe tool that returns allow decisions for safe scenarios and raises per-call denials for dangerous ones. Intended to prove that tool rejection does not terminate the MCP session.

src/windows_mcp/tools/safety_dry_run.py

Bug fix (7) +270 / -75
__main__.pyApply stdio-safe runtime defaults before server construction +21/-11

Apply stdio-safe runtime defaults before server construction

• Adds '_configure_transport_runtime()' to set stable stdio defaults (disable watchdog by default, prefer MSS backend, enable screenshot isolation/quarantine defaults, enforce NO_COLOR). Simplifies missing-dependency startup messaging while preserving stderr-only output for stdio.

src/windows_mcp/main.py

screenshot.pyIsolate screenshot capture in a child process with circuit breaker +169/-2

Isolate screenshot capture in a child process with circuit breaker

• Introduces optional isolated screenshot capture via a disposable worker process, returning results via an image file + JSON sidecar (no stdout contamination). Adds timeout handling, failure threshold/cooldown circuit breaker, and a quarantine gate that blocks capture without affecting other tools.

src/windows_mcp/desktop/screenshot.py

config.pyResolve a writable config dir even without HOME/USERPROFILE +21/-1

Resolve a writable config dir even without HOME/USERPROFILE

• Replaces a fixed '~/.windows-mcp' default with a resolver that honors 'WINDOWS_MCP_CONFIG_DIR', then HOME/USERPROFILE, then LOCALAPPDATA/APPDATA/temp. Improves robustness for non-interactive/limited environments.

src/windows_mcp/infrastructure/config.py

utils.pyPrevent PowerShell timeouts from killing the MCP host process group +45/-57

Prevent PowerShell timeouts from killing the MCP host process group

• Stops using console control signals and instead kills only the spawned subprocess tree via 'taskkill /T /F'. Forces isolated process groups + no-window creation flags to avoid propagating CTRL events to the long-running MCP host.

src/windows_mcp/powershell/utils.py

shell.pyReserve stdio cleanup time for PowerShell tool calls +10/-2

Reserve stdio cleanup time for PowerShell tool calls

• Subtracts a small reserved window from user-provided timeouts so the transport has time to clean up after command termination. Keeps behavior consistent with isolated timeout termination in PowerShell utilities.

src/windows_mcp/tools/shell.py

snapshot.pyConvert screenshot failures into ToolError (no session drop) +4/-1

Convert screenshot failures into ToolError (no session drop)

• Changes screenshot error handling to raise a 'ToolError' with an explicit quarantine/isolation message instead of returning error text. This makes failures clearly per-call and prevents protocol/host confusion.

src/windows_mcp/tools/snapshot.py

ia2.pyRemove unused comtypes.client import in IA2 initialization +0/-1

Remove unused comtypes.client import in IA2 initialization

• Eliminates an unnecessary import while preserving COM initialization semantics. Helps keep upstream COM cache fixes intact and reduces import surface.

src/windows_mcp/tree/ia2.py

Refactor (13) +61 / -44
__init__.pyDefine explicit filesystem public API ('__all__') +16/-0

Define explicit filesystem public API ('all')

• Adds an explicit '__all__' list for filesystem exports to make the module surface predictable and tooling-friendly.

src/windows_mcp/filesystem/init.py

service.pyMinor cleanup in directory info aggregation +1/-2

Minor cleanup in directory info aggregation

• Removes an unused import and normalizes whitespace in directory content counting. No functional behavior changes intended.

src/windows_mcp/filesystem/service.py

__init__.pyDefine explicit registry public API ('__all__') +9/-0

Define explicit registry public API ('all')

• Adds '__all__' to make the registry module’s exported functions/types explicit and stable.

src/windows_mcp/registry/init.py

clipboard.pySimplify exception handling in clipboard tool +1/-1

Simplify exception handling in clipboard tool

• Removes unused exception variable binding while preserving re-raise behavior. No functional change expected.

src/windows_mcp/tools/clipboard.py

filesystem.pySimplify exception handling in filesystem tool +1/-1

Simplify exception handling in filesystem tool

• Removes unused exception variable binding while preserving re-raise behavior. No functional change expected.

src/windows_mcp/tools/filesystem.py

notification.pySimplify exception handling in notification tool +1/-1

Simplify exception handling in notification tool

• Removes unused exception variable binding while preserving re-raise behavior. No functional change expected.

src/windows_mcp/tools/notification.py

process.pySimplify exception handling in process tool +1/-1

Simplify exception handling in process tool

• Removes unused exception variable binding while preserving re-raise behavior. No functional change expected.

src/windows_mcp/tools/process.py

registry.pySimplify exception handling in registry tool +1/-1

Simplify exception handling in registry tool

• Removes unused exception variable binding while preserving re-raise behavior. No functional change expected.

src/windows_mcp/tools/registry.py

cache_utils.pyTyping/import cleanups in cache utilities +25/-25

Typing/import cleanups in cache utilities

• Drops unused typing imports and normalizes whitespace. Keeps cache request factory and cached-control helper behavior unchanged.

src/windows_mcp/tree/cache_utils.py

service.pyWhitespace-only cleanup in tree traversal +2/-2

Whitespace-only cleanup in tree traversal

• Normalizes whitespace in tree traversal logic without behavioral changes. Improves diff cleanliness for upstream syncs.

src/windows_mcp/tree/service.py

comtypes_cache.pyFix missing newline at EOF +1/-1

Fix missing newline at EOF

• Adds a trailing newline to satisfy tooling expectations. No runtime behavior change.

src/windows_mcp/uia/comtypes_cache.py

exceptions.pyTrim unused enum imports from UIA exception module +1/-1

Trim unused enum imports from UIA exception module

• Removes unused imports while preserving the public UIAException type hierarchy and COMError re-export semantics.

src/windows_mcp/uia/exceptions.py

controls.pyResolve upstream conflict and remove unused imports/variables +1/-8

Resolve upstream conflict and remove unused imports/variables

• Cleans up unused imports and minor debug variables, and simplifies exception binding in a hotkey thread helper. Keeps upstream v0.8.5 protections while reducing dead code.

src/windows_mcp/uia/controls.py

Tests (14) +1580 / -4
conftest.pyStabilize screenshot-related env defaults for tests +3/-1

Stabilize screenshot-related env defaults for tests

• Forces flash disabled and explicitly sets screenshot isolation/quarantine off in test environment. Prevents flaky behavior from inherited env defaults during unit tests.

tests/conftest.py

test_cli_legacy_flags.pyUpdate CLI install test to stub PowerShell registration path +5/-0

Update CLI install test to stub PowerShell registration path

• Stubs '_register_task_powershell' in addition to schtasks to keep legacy-flag install tests deterministic. Avoids executing real PowerShell during tests.

tests/test_cli_legacy_flags.py

test_config_directory.pyAdd tests for config dir resolution fallbacks +34/-0

Add tests for config dir resolution fallbacks

• Verifies config directory selection precedence across explicit env var, USERPROFILE/HOME, and LOCALAPPDATA fallback. Ensures behavior remains stable across headless environments.

tests/test_config_directory.py

test_filesystem_service.pyRemove unused imports in filesystem service tests +0/-2

Remove unused imports in filesystem service tests

• Cleans up unused imports to keep the test module minimal. No behavioral change expected.

tests/test_filesystem_service.py

test_health_tool.pyAdd tests for Health tool safety contract +36/-0

Add tests for Health tool safety contract

• Verifies the Health tool returns expected fields and is annotated read-only/idempotent/open-world false. Uses a fake MCP registry to validate registration behavior.

tests/test_health_tool.py

test_multi_tools.pyFix newline-at-EOF in multi-tool test +1/-1

Fix newline-at-EOF in multi-tool test

• Adds missing newline at EOF to satisfy formatting/tooling expectations. No behavioral change expected.

tests/test_multi_tools.py

test_powershell_timeout_isolation.pyAdd tests for PowerShell timeout isolation and timeout reserve +84/-0

Add tests for PowerShell timeout isolation and timeout reserve

• Asserts timeout handling kills only the child process tree and does not send console control signals. Also verifies the PowerShell tool reserves cleanup time from user timeouts.

tests/test_powershell_timeout_isolation.py

test_screenshot_quarantine.pyAdd tests for screenshot worker isolation + quarantine + circuit breaker +111/-0

Add tests for screenshot worker isolation + quarantine + circuit breaker

• Covers stdio defaults, isolated child capture success, timeout-triggered circuit breaker, native crash code formatting, and quarantine short-circuiting before child start. Ensures failures remain per-call and do not cascade.

tests/test_screenshot_quarantine.py

test_supervisor_recovery_probe.pyAdd tests for recovery probe and migration safeguards +113/-0

Add tests for recovery probe and migration safeguards

• Validates process-tree traversal limits/cycle handling, confirms destructive probes are guarded without explicit execution, and checks migration script disables conflicting legacy tasks. Also tests runtime orphan filtering by command normalization.

tests/test_supervisor_recovery_probe.py

test_supervisor_task_runner.pyAdd tests for persisted task runner and queue recovery semantics +361/-0

Add tests for persisted task runner and queue recovery semantics

• Covers atomic result writing, timeout persistence, queue recovery behavior for live/dead runners, resumable task cloning, and reconciliation from persisted result files. Ensures supervisor restart does not duplicate work or lose evidence.

tests/test_supervisor_task_runner.py

test_system_query_security.pyAdd tests for SystemQuery allowlist and safety_dry_run denials +108/-0

Add tests for SystemQuery allowlist and safety_dry_run denials

• Verifies project-root confinement, secret-path blocking, non-operation rejection for arbitrary commands, isolated command timeouts, and local-metadata git_status behavior. Confirms dangerous probes are denied per-call without session termination.

tests/test_system_query_security.py

test_validate_project_script.pyAdd tests for validation script artifact uniqueness and logging +21/-0

Add tests for validation script artifact uniqueness and logging

• Asserts validation artifacts embed timestamp+PID+GUID uniqueness and that logging functions accept empty output lines. Keeps the operational script safe to run concurrently.

tests/test_validate_project_script.py

test_watchdog_toggle.pyAdd tests for stdio runtime defaults around watchdog/NO_COLOR +24/-0

Add tests for stdio runtime defaults around watchdog/NO_COLOR

• Verifies stdio mode disables watchdog only when unset and preserves explicit operator settings. Confirms non-stdio transports do not mutate watchdog env state.

tests/test_watchdog_toggle.py

test_windows_mcp_supervisor.pyAdd extensive unit tests for supervisor profile/health/queue logic +679/-0

Add extensive unit tests for supervisor profile/health/queue logic

• Covers command normalization, profile guard repairs (uv.run removal, TTL enforcement), transport-aware health evaluation, and observation/operator-controlled settings. Provides regression coverage for duplicate tunnel avoidance and persistence expectations.

tests/test_windows_mcp_supervisor.py

Documentation (3) +193 / -0
final-validation.mdAdd final operational validation report +38/-0

Add final operational validation report

• Documents the final validated runtime state, including single-tunnel invariants, 336h TTL, atomic persistence, and isolation behavior. Records evidence locations and upstream v0.8.5 sync details.

docs/final-validation.md

requirement-evidence-matrix.mdAdd requirement-to-evidence matrix +22/-0

Add requirement-to-evidence matrix

• Maps resilience/security requirements to concrete objective evidence and test coverage. Highlights supervisor persistence, isolation guarantees, TTL enforcement, and build/test proof points.

docs/requirement-evidence-matrix.md

resilience-operations.mdDocument resilient runtime architecture and ops commands +133/-0

Document resilient runtime architecture and ops commands

• Describes the persistent supervisor architecture, health gates, restart policy, atomic persistence model, and tool isolation constraints. Provides operational commands for enqueuing tasks and validating recovery behavior.

docs/resilience-operations.md

Other (9) +915 / -10
publish.ymlNormalize publish workflow formatting +7/-7

Normalize publish workflow formatting

• Cleans up whitespace in the PyPI publish workflow without functional changes. Keeps the version-consistency gate and uv build/publish steps intact.

.github/workflows/publish.yml

.gitignoreIgnore local runtime/supervisor artifacts +8/-1

Ignore local runtime/supervisor artifacts

• Adds ignores for '.orquestrador/' and '.tunnel-client/' plus local plugin packaging directories. Prevents operational state/evidence from being committed.

.gitignore

pyproject.tomlAdd MSS screenshot backend dependency +1/-0

Add MSS screenshot backend dependency

• Adds 'mss>=10.2.0' as a runtime dependency to support the preferred stable screenshot backend for stdio mode.

pyproject.toml

uv.lockLock MSS dependency (and update lock metadata) +13/-2

Lock MSS dependency (and update lock metadata)

• Adds the 'mss' package to the lockfile and wires it into the project dependency set. Also reflects lockfile normalization changes for some transitive dependency markers.

uv.lock

test_supervisor_recovery.ps1Add PowerShell controlled recovery test with evidence capture +129/-0

Add PowerShell controlled recovery test with evidence capture

• Provides a guarded, opt-in destructive test that kills a managed tunnel and asserts the supervisor restores a single healthy runtime within a deadline. Captures heartbeat, runtime state, and process tree evidence.

scripts/test_supervisor_recovery.ps1

migrate_supervisor_v4.ps1Add migration script to v4 supervisor topology +190/-0

Add migration script to v4 supervisor topology

• Implements a guarded migration that disables conflicting legacy scheduled tasks, validates the managed profile command/TTL, and verifies stability after restart. Writes progress and evidence JSON artifacts for auditability.

scripts/migrate_supervisor_v4.ps1

probe_stdio_tool_isolation.pyAdd stdio tool isolation probe harness +132/-0

Add stdio tool isolation probe harness

• Adds an async stdio client harness that repeatedly calls tools and verifies 'Health' succeeds before/after the target call. Captures stderr and structured results to evidence files.

scripts/probe_stdio_tool_isolation.py

reproduce_stdio_resilience.pyAdd stdio resilience reproduction script +243/-0

Add stdio resilience reproduction script

• Creates a more comprehensive stdio probe that validates tool availability and exercises rejection/isolation scenarios over multiple iterations/concurrency. Produces structured evidence suitable for operational validation.

scripts/reproduce_stdio_resilience.py

validate_project.ps1Add validation runner with atomic logging and evidence artifacts +192/-0

Add validation runner with atomic logging and evidence artifacts

• Adds a PowerShell validation pipeline that runs lint/tests/build steps with redirected native output and robust atomic logging. Produces unique run IDs and writes summary JSON for traceability.

scripts/validate_project.ps1

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (4) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 16 rules

Grey Divider


Action required

1. Hardcoded project root 🐞 Bug ≡ Correctness
Description
The supervisor/task scripts hardcode ROOT (and EXPECTED_MCP_COMMAND) to
D:\Projetos\WINDOWS-MCP-TEST, so they will read/write state and attempt to spawn the tunnel/MCP from
a non-existent path on other installations. This makes the persistent runtime tooling non-portable
and can cause immediate operational failure outside that exact directory layout.
Code

scripts/windows_mcp_supervisor.py[R17-41]

+ROOT = Path(r"D:\Projetos\WINDOWS-MCP-TEST")
+STATE_ROOT = ROOT / ".orquestrador" / "supervisor"
+CHECKPOINT = ROOT / ".orquestrador" / "checkpoints" / "runtime-supervision.json"
+LEGACY_CHECKPOINTS = (
+    ROOT / ".orquestrador" / "checkpoints" / "loop-280h.json",
+    ROOT / ".orquestrador" / "checkpoints" / "loop-15h.json",
+)
+LOCK_FILE = STATE_ROOT / "lock.json"
+STATE_FILE = STATE_ROOT / "state.json"
+QUEUE_FILE = STATE_ROOT / "queue.json"
+INBOX_DIR = STATE_ROOT / "inbox"
+REJECTED_INBOX_DIR = STATE_ROOT / "inbox-rejected"
+HEARTBEAT_FILE = STATE_ROOT / "heartbeat.json"
+LOG_DIR = STATE_ROOT / "logs"
+LOG_FILE = LOG_DIR / "supervisor.log"
+TASK_EVIDENCE_DIR = STATE_ROOT / "task-evidence"
+TASK_SPEC_DIR = STATE_ROOT / "task-specs"
+TASK_RESULT_DIR = STATE_ROOT / "task-results"
+TASK_RUNNER = ROOT / "scripts" / "run_supervisor_task.py"
+TUNNEL_BIN = ROOT / ".tunnel-client" / "bin" / "tunnel-client.exe"
+PROFILE_DIR = ROOT / ".tunnel-client" / "profiles"
+PROFILE_NAME = "windows-mcp-gpt-managed"
+PROFILE_FILE = PROFILE_DIR / f"{PROFILE_NAME}.yaml"
+EXPECTED_MCP_COMMAND = "D:/Projetos/WINDOWS-MCP-TEST/.venv/Scripts/python.exe -m windows_mcp serve --transport stdio"
+MCP_CONNECTION_MAX_TTL = "336h"
Relevance

●●● Strong

Hardcoded absolute ROOT breaks portability; likely to be changed to config/env or relative path.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The supervisor and task enqueue entrypoint embed an absolute local path as ROOT and as the managed
MCP command, and the operational documentation also assumes that same fixed path, demonstrating the
scripts are currently tied to one workstation layout.

scripts/windows_mcp_supervisor.py[17-41]
scripts/enqueue_supervisor_task.py[11-20]
docs/resilience-operations.md[11-15]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Operational supervisor scripts hardcode a workstation-specific project root and Python command path. This will break the supervisor, queue inbox, and managed command enforcement when the repo/venv is not located at `D:\Projetos\WINDOWS-MCP-TEST`.

## Issue Context
These scripts appear intended for production resilience/recovery, so they should either (a) derive paths dynamically from the current checkout / script location, or (b) accept an explicit `--project-root` / env var and validate it.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[17-52]
- scripts/enqueue_supervisor_task.py[11-20]

## Suggested fix
- Replace `ROOT = Path(r"D:\Projetos\WINDOWS-MCP-TEST")` with something like:
 - `ROOT = Path(os.environ.get("WINDOWS_MCP_PROJECT_ROOT") or Path(__file__).resolve().parents[1]).resolve()`
- Derive `PYTHON`, `TASK_RUNNER`, and `EXPECTED_MCP_COMMAND` from `ROOT` (and/or `sys.executable`) instead of embedding absolute paths.
- Add validation that computed files exist (venv python, tunnel-client.exe, profiles dir) and emit a clear error if not.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Racy supervisor lock 🐞 Bug ☼ Reliability
Description
acquire_single_instance() uses a read-then-write PID file without an OS-level lock, so two
supervisors starting concurrently can both pass the check and run at the same time. This violates
the documented exclusivity requirement and risks duplicated tunnel management and conflicting state
writes.
Code

scripts/windows_mcp_supervisor.py[R219-224]

+def acquire_single_instance() -> None:
+    existing = load_json(LOCK_FILE, {})
+    existing_pid = existing.get("pid") if isinstance(existing, dict) else None
+    if pid_alive(existing_pid):
+        raise SystemExit(0)
+    atomic_json(LOCK_FILE, {"pid": os.getpid(), "started_at": now_iso()})
Relevance

●● Moderate

Fix needs OS-level locking approach; may be deferred if current PID-file is deemed sufficient.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The code shows a check-then-write PID file pattern with no OS-level lock, which is inherently
race-prone under concurrent startups, while the docs explicitly require exclusivity (single
supervisor managing the runtime).

scripts/windows_mcp_supervisor.py[219-225]
docs/resilience-operations.md[18-22]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The supervisor attempts single-instance behavior via `lock.json`, but the implementation is not atomic: two processes can simultaneously observe no live PID and both proceed.

## Issue Context
This supervisor is intended to be the sole manager of the persistent runtime; concurrent supervisors can race on queue/state/heartbeat and tunnel restarts.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[219-225]
- docs/resilience-operations.md[18-22]

## Suggested fix
- Use a Windows-enforced mutual exclusion primitive:
 - A named mutex via `ctypes` (`CreateMutexW` + `GetLastError()==ERROR_ALREADY_EXISTS`), or
 - An exclusive lock file handle kept open for process lifetime (e.g., `msvcrt.locking` or `CreateFile` with exclusive sharing).
- Keep writing diagnostic info (PID/timestamps) for observability, but make the *exclusivity decision* depend on the OS-level lock rather than a read/replace JSON file.
- Consider PID reuse/stale locks: on startup, if lock exists but owner process is gone, allow takeover; otherwise exit cleanly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. SystemQuery tool bypasses service 📘 Rule violation ⌂ Architecture
Description
The SystemQuery MCP entry-point tool delegates to execute_query within the tool module, which
performs direct OS/filesystem/process interrogation instead of delegating to a Desktop service
layer. This violates the required layering for MCP entry-point tools.
Code

src/windows_mcp/tools/system_query.py[R344-373]

+def register(
+    mcp: Any,
+    *,
+    get_desktop: Callable[[], Any],
+    get_analytics: Callable[[], Any],
+) -> None:
+    @mcp.tool(
+        name="SystemQuery",
+        description=(
+            "Structured read-only Windows and project query. Use instead of PowerShell for date/time, "
+            "file listing, ordinary text-file reads, process or service status, Git status, program "
+            "versions, tunnel/runtime status, and log tails. It does not accept arbitrary commands, "
+            "does not write, blocks secret-like paths, and keeps all file access inside the project."
+        ),
+        annotations=ToolAnnotations(
+            title="Safe System Query",
+            readOnlyHint=True,
+            destructiveHint=False,
+            idempotentHint=True,
+            openWorldHint=False,
+        ),
+    )
+    @with_analytics(get_analytics(), "SystemQuery-Tool")
+    def system_query_tool(
+        operation: str,
+        target: str | None = None,
+        limit: int = 50,
+        ctx: Context = None,
+    ) -> object:
+        return execute_query(operation, target, limit)
Relevance

●● Moderate

Layering refactor to a Desktop service is architectural and may be postponed despite rule text.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 222807 requires MCP entry-point tools to delegate to a Desktop service layer.
system_query_tool calls execute_query(...), and execute_query contains multiple operation
branches and performs direct platform interactions (file access and process/service inspection)
within the tool module rather than a Desktop service.

Rule 222807: MCP entry-point tools must delegate to Desktop service layer
src/windows_mcp/tools/system_query.py[344-373]
src/windows_mcp/tools/system_query.py[280-337]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
MCP entry-point tools must be thin adapters that delegate business/OS logic to the Desktop service layer, but `SystemQuery` implements/owns the logic in the tool module.

## Issue Context
The compliance checklist requires entry-point tools to limit themselves to input parsing/validation and service calls, avoiding direct platform access and branching logic.

## Fix Focus Areas
- src/windows_mcp/tools/system_query.py[280-337]
- src/windows_mcp/tools/system_query.py[344-373]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Profile format mismatch 🐞 Bug ☼ Reliability
Description
ensure_profile_command() parses and overwrites a *.yaml tunnel profile using
json.loads/json.dumps, so any YAML profile that is not strict JSON syntax (e.g., comments or typical
YAML scalars) will be rejected and the supervisor will refuse to start/recover the tunnel. The file
extension and parser/writer mismatch also makes the on-disk profile format misleading for operators
and tooling.
Code

scripts/windows_mcp_supervisor.py[R161-190]

+def ensure_profile_command() -> dict[str, Any]:
+    try:
+        data = json.loads(PROFILE_FILE.read_text(encoding="utf-8-sig"))
+        mcp = data.setdefault("mcp", {})
+        commands = mcp.get("commands")
+        expected = [{"channel": "main", "command": EXPECTED_MCP_COMMAND}]
+        current = commands if isinstance(commands, list) else []
+        current_ok = current == expected
+        ttl_ok = str(mcp.get("connection_max_ttl") or "") == MCP_CONNECTION_MAX_TTL
+        forbidden_uv = any(
+            "uv.exe" in normalize_command(item.get("command", ""))
+            for item in current
+            if isinstance(item, dict)
+        )
+        if current_ok and ttl_ok and not forbidden_uv:
+            return {
+                "ok": True,
+                "repaired": False,
+                "command": EXPECTED_MCP_COMMAND,
+                "connection_max_ttl": MCP_CONNECTION_MAX_TTL,
+                "error": "",
+            }
+        PROFILE_BACKUP_DIR.mkdir(parents=True, exist_ok=True)
+        stamp = datetime.now().astimezone().strftime("%Y%m%d-%H%M%S-%f")
+        backup = PROFILE_BACKUP_DIR / f"{PROFILE_NAME}.{stamp}.json"
+        backup.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
+        mcp["commands"] = expected
+        mcp["connection_max_ttl"] = MCP_CONNECTION_MAX_TTL
+        atomic_json(PROFILE_FILE, data)
+        log(
Relevance

●● Moderate

YAML/JSON mismatch seems risky; may be intentional if tunnel client actually expects JSON despite
.yaml extension.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script declares the profile file with a .yaml extension but uses json.loads() to parse it
and atomic_json() to write JSON back to that same .yaml path, which is incompatible with
non-JSON YAML syntax.

scripts/windows_mcp_supervisor.py[37-40]
scripts/windows_mcp_supervisor.py[161-190]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The tunnel profile is stored as `*.yaml` but the supervisor reads/writes it as JSON (`json.loads`, `json.dumps`). This will fail for YAML profiles that contain YAML-only constructs, and it also misleads operators/tools about the file format.

## Issue Context
JSON is a subset of YAML, so JSON text inside a `.yaml` file can work, but the current implementation makes the supervisor brittle to legitimate YAML formatting.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[39-40]
- scripts/windows_mcp_supervisor.py[161-190]

## Suggested fix options
1) **Preferable:** Parse and write YAML consistently (e.g., `yaml.safe_load` / `yaml.safe_dump`) and keep `.yaml`.
2) **Alternative (no YAML dep):** Rename the profile to `.json` everywhere (including any tunnel-client expectations/docs/scripts) and keep JSON parsing/writing.

Also ensure the migration scripts/ops docs use the same format choice to avoid split-brain behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Long EXPECTED_MCP_COMMAND line 📘 Rule violation ✧ Quality
Description
The EXPECTED_MCP_COMMAND assignment exceeds the 100-character maximum line length. This reduces
readability and violates the configured formatting requirement.
Code

scripts/windows_mcp_supervisor.py[40]

+EXPECTED_MCP_COMMAND = "D:/Projetos/WINDOWS-MCP-TEST/.venv/Scripts/python.exe -m windows_mcp serve --transport stdio"
Relevance

●●● Strong

Line-length violation is a trivial formatting fix; team likely to wrap/split the command string.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 222796 requires that no non-comment, non-whitespace line in changed files exceeds
100 characters. The EXPECTED_MCP_COMMAND = ... assignment is a single long line over that limit.

Rule 222796: Enforce maximum line length of 100 characters
scripts/windows_mcp_supervisor.py[40-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A newly added non-comment line exceeds 100 characters.

## Issue Context
The compliance checklist requires a strict 100-character maximum line length for changed files.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[40-40]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Single quotes in getattr 📘 Rule violation ✧ Quality
Description
New code uses single-quoted string literals in getattr(...) calls. This violates the requirement
to use double quotes for all string literals.
Code

src/windows_mcp/tools/system_query.py[R26-27]

+_CREATE_NO_WINDOW = getattr(subprocess, 'CREATE_NO_WINDOW', 0)
+_CREATE_NEW_PROCESS_GROUP = getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0)
Relevance

●●● Strong

Switching to double quotes is a trivial mechanical change and matches repo style rules.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 222799 requires double quotes for string literals. The added `getattr(subprocess,
'CREATE_NO_WINDOW', 0) and getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0)` lines introduce
single-quoted literals.

Rule 222799: Enforce double quotes for all string literals
src/windows_mcp/tools/system_query.py[26-27]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New/modified string literals must use double quotes, but single quotes are used.

## Issue Context
The compliance checklist enforces consistent quoting for all string literals.

## Fix Focus Areas
- src/windows_mcp/tools/system_query.py[26-27]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. parse_rect() missing docstring 📘 Rule violation ✧ Quality
Description
The new public function parse_rect has no Google-style docstring as its first statement. This
violates the requirement for structured docstrings on public functions/classes.
Code

src/windows_mcp/desktop/screenshot_worker.py[R14-20]

+def parse_rect(value: str | None) -> Rect | None:
+    if not value:
+        return None
+    parts = [int(part.strip()) for part in value.split(",")]
+    if len(parts) != 4:
+        raise ValueError("rect must contain left,top,right,bottom")
+    return Rect(*parts)
Relevance

●●● Strong

Team has accepted adding/updating Google-style docstrings for public functions recently.

PR-#358
PR-#353

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 222802 requires Google-style docstrings on public functions/classes in changed
files. parse_rect is a public function (no leading underscore) and its body starts immediately
with logic rather than a docstring.

Rule 222802: Require Google-style docstrings on public functions and classes
src/windows_mcp/desktop/screenshot_worker.py[14-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Public functions/classes must have Google-style docstrings, but `parse_rect` is missing one.

## Issue Context
The compliance checklist requires a triple-quoted docstring with Google-style sections (e.g., `Args:`, `Returns:`) for public APIs.

## Fix Focus Areas
- src/windows_mcp/desktop/screenshot_worker.py[14-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

PROFILE_DIR = ROOT / ".tunnel-client" / "profiles"
PROFILE_NAME = "windows-mcp-gpt-managed"
PROFILE_FILE = PROFILE_DIR / f"{PROFILE_NAME}.yaml"
EXPECTED_MCP_COMMAND = "D:/Projetos/WINDOWS-MCP-TEST/.venv/Scripts/python.exe -m windows_mcp serve --transport stdio"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Informational

1. Long expected_mcp_command line 📘 Rule violation ✧ Quality

The EXPECTED_MCP_COMMAND assignment exceeds the 100-character maximum line length. This reduces
readability and violates the configured formatting requirement.
Agent Prompt
## Issue description
A newly added non-comment line exceeds 100 characters.

## Issue Context
The compliance checklist requires a strict 100-character maximum line length for changed files.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[40-40]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +26 to +27
_CREATE_NO_WINDOW = getattr(subprocess, 'CREATE_NO_WINDOW', 0)
_CREATE_NEW_PROCESS_GROUP = getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Informational

2. Single quotes in getattr 📘 Rule violation ✧ Quality

New code uses single-quoted string literals in getattr(...) calls. This violates the requirement
to use double quotes for all string literals.
Agent Prompt
## Issue description
New/modified string literals must use double quotes, but single quotes are used.

## Issue Context
The compliance checklist enforces consistent quoting for all string literals.

## Fix Focus Areas
- src/windows_mcp/tools/system_query.py[26-27]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +14 to +20
def parse_rect(value: str | None) -> Rect | None:
if not value:
return None
parts = [int(part.strip()) for part in value.split(",")]
if len(parts) != 4:
raise ValueError("rect must contain left,top,right,bottom")
return Rect(*parts)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Informational

3. parse_rect() missing docstring 📘 Rule violation ✧ Quality

The new public function parse_rect has no Google-style docstring as its first statement. This
violates the requirement for structured docstrings on public functions/classes.
Agent Prompt
## Issue description
Public functions/classes must have Google-style docstrings, but `parse_rect` is missing one.

## Issue Context
The compliance checklist requires a triple-quoted docstring with Google-style sections (e.g., `Args:`, `Returns:`) for public APIs.

## Fix Focus Areas
- src/windows_mcp/desktop/screenshot_worker.py[14-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +344 to +373
def register(
mcp: Any,
*,
get_desktop: Callable[[], Any],
get_analytics: Callable[[], Any],
) -> None:
@mcp.tool(
name="SystemQuery",
description=(
"Structured read-only Windows and project query. Use instead of PowerShell for date/time, "
"file listing, ordinary text-file reads, process or service status, Git status, program "
"versions, tunnel/runtime status, and log tails. It does not accept arbitrary commands, "
"does not write, blocks secret-like paths, and keeps all file access inside the project."
),
annotations=ToolAnnotations(
title="Safe System Query",
readOnlyHint=True,
destructiveHint=False,
idempotentHint=True,
openWorldHint=False,
),
)
@with_analytics(get_analytics(), "SystemQuery-Tool")
def system_query_tool(
operation: str,
target: str | None = None,
limit: int = 50,
ctx: Context = None,
) -> object:
return execute_query(operation, target, limit)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. systemquery tool bypasses service 📘 Rule violation ⌂ Architecture

The SystemQuery MCP entry-point tool delegates to execute_query within the tool module, which
performs direct OS/filesystem/process interrogation instead of delegating to a Desktop service
layer. This violates the required layering for MCP entry-point tools.
Agent Prompt
## Issue description
MCP entry-point tools must be thin adapters that delegate business/OS logic to the Desktop service layer, but `SystemQuery` implements/owns the logic in the tool module.

## Issue Context
The compliance checklist requires entry-point tools to limit themselves to input parsing/validation and service calls, avoiding direct platform access and branching logic.

## Fix Focus Areas
- src/windows_mcp/tools/system_query.py[280-337]
- src/windows_mcp/tools/system_query.py[344-373]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +17 to +41
ROOT = Path(r"D:\Projetos\WINDOWS-MCP-TEST")
STATE_ROOT = ROOT / ".orquestrador" / "supervisor"
CHECKPOINT = ROOT / ".orquestrador" / "checkpoints" / "runtime-supervision.json"
LEGACY_CHECKPOINTS = (
ROOT / ".orquestrador" / "checkpoints" / "loop-280h.json",
ROOT / ".orquestrador" / "checkpoints" / "loop-15h.json",
)
LOCK_FILE = STATE_ROOT / "lock.json"
STATE_FILE = STATE_ROOT / "state.json"
QUEUE_FILE = STATE_ROOT / "queue.json"
INBOX_DIR = STATE_ROOT / "inbox"
REJECTED_INBOX_DIR = STATE_ROOT / "inbox-rejected"
HEARTBEAT_FILE = STATE_ROOT / "heartbeat.json"
LOG_DIR = STATE_ROOT / "logs"
LOG_FILE = LOG_DIR / "supervisor.log"
TASK_EVIDENCE_DIR = STATE_ROOT / "task-evidence"
TASK_SPEC_DIR = STATE_ROOT / "task-specs"
TASK_RESULT_DIR = STATE_ROOT / "task-results"
TASK_RUNNER = ROOT / "scripts" / "run_supervisor_task.py"
TUNNEL_BIN = ROOT / ".tunnel-client" / "bin" / "tunnel-client.exe"
PROFILE_DIR = ROOT / ".tunnel-client" / "profiles"
PROFILE_NAME = "windows-mcp-gpt-managed"
PROFILE_FILE = PROFILE_DIR / f"{PROFILE_NAME}.yaml"
EXPECTED_MCP_COMMAND = "D:/Projetos/WINDOWS-MCP-TEST/.venv/Scripts/python.exe -m windows_mcp serve --transport stdio"
MCP_CONNECTION_MAX_TTL = "336h"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

5. Hardcoded project root 🐞 Bug ≡ Correctness

The supervisor/task scripts hardcode ROOT (and EXPECTED_MCP_COMMAND) to
D:\Projetos\WINDOWS-MCP-TEST, so they will read/write state and attempt to spawn the tunnel/MCP from
a non-existent path on other installations. This makes the persistent runtime tooling non-portable
and can cause immediate operational failure outside that exact directory layout.
Agent Prompt
## Issue description
Operational supervisor scripts hardcode a workstation-specific project root and Python command path. This will break the supervisor, queue inbox, and managed command enforcement when the repo/venv is not located at `D:\Projetos\WINDOWS-MCP-TEST`.

## Issue Context
These scripts appear intended for production resilience/recovery, so they should either (a) derive paths dynamically from the current checkout / script location, or (b) accept an explicit `--project-root` / env var and validate it.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[17-52]
- scripts/enqueue_supervisor_task.py[11-20]

## Suggested fix
- Replace `ROOT = Path(r"D:\Projetos\WINDOWS-MCP-TEST")` with something like:
  - `ROOT = Path(os.environ.get("WINDOWS_MCP_PROJECT_ROOT") or Path(__file__).resolve().parents[1]).resolve()`
- Derive `PYTHON`, `TASK_RUNNER`, and `EXPECTED_MCP_COMMAND` from `ROOT` (and/or `sys.executable`) instead of embedding absolute paths.
- Add validation that computed files exist (venv python, tunnel-client.exe, profiles dir) and emit a clear error if not.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +161 to +190
def ensure_profile_command() -> dict[str, Any]:
try:
data = json.loads(PROFILE_FILE.read_text(encoding="utf-8-sig"))
mcp = data.setdefault("mcp", {})
commands = mcp.get("commands")
expected = [{"channel": "main", "command": EXPECTED_MCP_COMMAND}]
current = commands if isinstance(commands, list) else []
current_ok = current == expected
ttl_ok = str(mcp.get("connection_max_ttl") or "") == MCP_CONNECTION_MAX_TTL
forbidden_uv = any(
"uv.exe" in normalize_command(item.get("command", ""))
for item in current
if isinstance(item, dict)
)
if current_ok and ttl_ok and not forbidden_uv:
return {
"ok": True,
"repaired": False,
"command": EXPECTED_MCP_COMMAND,
"connection_max_ttl": MCP_CONNECTION_MAX_TTL,
"error": "",
}
PROFILE_BACKUP_DIR.mkdir(parents=True, exist_ok=True)
stamp = datetime.now().astimezone().strftime("%Y%m%d-%H%M%S-%f")
backup = PROFILE_BACKUP_DIR / f"{PROFILE_NAME}.{stamp}.json"
backup.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
mcp["commands"] = expected
mcp["connection_max_ttl"] = MCP_CONNECTION_MAX_TTL
atomic_json(PROFILE_FILE, data)
log(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

6. Profile format mismatch 🐞 Bug ☼ Reliability

ensure_profile_command() parses and overwrites a *.yaml tunnel profile using
json.loads/json.dumps, so any YAML profile that is not strict JSON syntax (e.g., comments or typical
YAML scalars) will be rejected and the supervisor will refuse to start/recover the tunnel. The file
extension and parser/writer mismatch also makes the on-disk profile format misleading for operators
and tooling.
Agent Prompt
## Issue description
The tunnel profile is stored as `*.yaml` but the supervisor reads/writes it as JSON (`json.loads`, `json.dumps`). This will fail for YAML profiles that contain YAML-only constructs, and it also misleads operators/tools about the file format.

## Issue Context
JSON is a subset of YAML, so JSON text inside a `.yaml` file can work, but the current implementation makes the supervisor brittle to legitimate YAML formatting.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[39-40]
- scripts/windows_mcp_supervisor.py[161-190]

## Suggested fix options
1) **Preferable:** Parse and write YAML consistently (e.g., `yaml.safe_load` / `yaml.safe_dump`) and keep `.yaml`.
2) **Alternative (no YAML dep):** Rename the profile to `.json` everywhere (including any tunnel-client expectations/docs/scripts) and keep JSON parsing/writing.

Also ensure the migration scripts/ops docs use the same format choice to avoid split-brain behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +219 to +224
def acquire_single_instance() -> None:
existing = load_json(LOCK_FILE, {})
existing_pid = existing.get("pid") if isinstance(existing, dict) else None
if pid_alive(existing_pid):
raise SystemExit(0)
atomic_json(LOCK_FILE, {"pid": os.getpid(), "started_at": now_iso()})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

7. Racy supervisor lock 🐞 Bug ☼ Reliability

acquire_single_instance() uses a read-then-write PID file without an OS-level lock, so two
supervisors starting concurrently can both pass the check and run at the same time. This violates
the documented exclusivity requirement and risks duplicated tunnel management and conflicting state
writes.
Agent Prompt
## Issue description
The supervisor attempts single-instance behavior via `lock.json`, but the implementation is not atomic: two processes can simultaneously observe no live PID and both proceed.

## Issue Context
This supervisor is intended to be the sole manager of the persistent runtime; concurrent supervisors can race on queue/state/heartbeat and tunnel restarts.

## Fix Focus Areas
- scripts/windows_mcp_supervisor.py[219-225]
- docs/resilience-operations.md[18-22]

## Suggested fix
- Use a Windows-enforced mutual exclusion primitive:
  - A named mutex via `ctypes` (`CreateMutexW` + `GetLastError()==ERROR_ALREADY_EXISTS`), or
  - An exclusive lock file handle kept open for process lifetime (e.g., `msvcrt.locking` or `CreateFile` with exclusive sharing).
- Keep writing diagnostic info (PID/timestamps) for observability, but make the *exclusivity decision* depend on the OS-level lock rather than a read/replace JSON file.
- Consider PID reuse/stale locks: on startup, if lock exists but owner process is gone, allow takeover; otherwise exit cleanly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@Jeomon

Jeomon commented Aug 1, 2026

Copy link
Copy Markdown
Member

Pls the make the pr into multiple ones so that it is easy for me to go through it

@andrebarros78

Copy link
Copy Markdown
Author

Thank you for the review and the feedback. I will close this PR and reorganize the changes into smaller, focused pull requests to make the review easier. Thanks!

@Jeomon

Jeomon commented Aug 2, 2026

Copy link
Copy Markdown
Member

Also pls create an issuse stating the problem you faced the the fix you proposing then make pr because people can help you

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.

2 participants