Skip to content

feat(mcp): add a safe Unix stdio reload tool - #484

Merged
neusse merged 2 commits into
mixelpixx:mainfrom
neusse:neusse/reconstruct-176
Sep 10, 2026
Merged

feat(mcp): add a safe Unix stdio reload tool#484
neusse merged 2 commits into
mixelpixx:mainfrom
neusse:neusse/reconstruct-176

Conversation

@neusse

@neusse neusse commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Reconstructs #176 on current main, preserving Jean-Yves POCHEZ's original authorship while implementing the safety rework requested in review.

What changed

  • Keeps the existing seven meta-tools as the cross-platform baseline.
  • Advertises and dispatches reload_server only from the standalone Unix executable when it runs exclusively over stdio.
  • Does not expose the tool on Windows, HTTP, mixed HTTP+stdio, or embedded/KiCad-hosted sessions.
  • Preserves every original argument after argv[0], including an explicit --config path.
  • Opens the installed executable once and proves its version before queuing the handoff.
  • On Linux/Android, probes and executes the already-open file through /proc/self/fd, so a concurrent pathname replacement cannot change the selected executable.
  • On macOS and other Unix targets without a portable fexecve, records device, inode, length, and modification time and revalidates both the open file and named path immediately before exec; ordinary atomic build/install replacement is refused.
  • Refuses downgrades and requires allow_same_version=true for an intentional same-version development rebuild.
  • Queues a one-shot reload plan instead of starting a timer inside the handler.
  • Flushes the response and synchronous notifications, stops accepting requests, releases the run-registry record, and only then performs the one-way exec.
  • Keeps the irreversible exec function in the standalone binary. The embedded library explicitly refuses any impossible reload handoff as defense in depth.

Why the transport handoff matters

The original 250 ms timer allowed the stdio loop to accept a second mutation before exec, potentially interrupting a write before cleanup guards ran. The transport now returns a sealed handoff before reading another request. The standalone entry point drops its run-record guard before exec, so the replacement process can register the same PID cleanly.

Evidence

Windows-local evidence:

  • Focused reload tests cover capability gating, one-shot handoff, disabled dispatch, upgrade/equal/downgrade policy, and exact argument preservation.
  • Negative control: temporarily neutralizing the downgrade refusal makes the version-policy regression test fail; restoring the guard makes it pass.
  • Full gate passed:
    • cargo fmt --all -- --check
    • cargo clippy --workspace --locked --all-targets -- -D warnings
    • cargo test --workspace --locked --lib --tests
    • cargo test --workspace --locked --doc

Hosted Unix tests exercise the platform-specific handoff guards:

  • Linux copies and opens the test executable, removes its pathname, and proves the open executable can still be invoked through its descriptor.
  • macOS captures the candidate identity, proves an unchanged candidate is accepted, atomically replaces the named candidate, and proves the final handoff is refused.

Risk and rollback

The tool is absent unless the process proves the supported capability combination. The irreversible action requires confirm=true; same-version builds require a second explicit opt-in. The PR contains the preserved contributor commit plus one focused safety/adaptation commit, either of which can be reverted normally.

Supersedes #176.

@neusse
neusse requested a review from mixelpixx as a code owner September 7, 2026 16:29
@neusse neusse added the status:waiting-on-review Next actor: maintainer label Sep 7, 2026
@neusse neusse added status:waiting-on-dependency Next actor: the dependency owner — see linked blocking issue status:waiting-on-author Next actor: the PR author — one checklist, 14-day target and removed status:waiting-on-review Next actor: maintainer status:waiting-on-dependency Next actor: the dependency owner — see linked blocking issue labels Sep 7, 2026
@neusse

neusse commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

Please reconstruct this PR from current main with only the unique Unix stdio reload change, then rerun all ten checks.

#442 has now merged, so the dependency is resolved, but this head is DIRTY against the resulting platform/startup code. The least-resistance path is a clean reconstruction rather than resolving the old cumulative history in place:

  1. start from current upstream/main (296641b at this review);
  2. carry only commit e106549a's unique reload behavior, adapting it to the merged run registry;
  3. regenerate tool counts with cargo xtask fix-doc-counts if the tool remains in the final design;
  4. verify the unique commit list and diff, then run the complete gate;
  5. push the reconstructed exact head for review.

This is now status:waiting-on-author; it can re-enter the queue after that focused head is clean and green.

Reconstruct reload_server on current main while preserving the original contributor authorship and closing the safety gaps found in review.

Registration is conditional: only a Unix server running exclusively over stdio advertises or dispatches the tool. Windows, HTTP, and mixed transports retain the seven-tool baseline.

The handler validates confirmation and the on-disk version, refuses downgrades, requires an explicit override for same-version development builds, preserves the original argv, and queues a one-shot reload plan. The stdio loop performs exec only after flushing the response and notifications and before accepting another request.

Documentation describes the conditional eighth tool without changing cross-platform tool counts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@neusse
neusse force-pushed the neusse/reconstruct-176 branch from e106549 to 37f6f51 Compare September 10, 2026 19:22
@neusse neusse added status:waiting-on-review Next actor: maintainer and removed status:waiting-on-author Next actor: the PR author — one checklist, 14-day target labels Sep 10, 2026
@neusse
neusse force-pushed the neusse/reconstruct-176 branch from 37f6f51 to e1b6c1f Compare September 10, 2026 19:26
@neusse
neusse force-pushed the neusse/reconstruct-176 branch from e1b6c1f to 59354a3 Compare September 10, 2026 19:37
@neusse
neusse merged commit c47a9fc into mixelpixx:main Sep 10, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:waiting-on-review Next actor: maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants