Keep the contributors' fix (each llm_request / tool_request callback sees
the previous accepted rewrite; each gets its own copy of the payload and of
the original_* snapshot) in PluginManager.invoke_middleware, which stays the
single plugin-failure boundary, and drop the rest:
- the ~90-line iterative container walker in _safe_copy. It only runs when
deepcopy fails (an opaque leaf in the request); main's shallow-copy
fallback stays.
- the original_* freeze/copy in _run_execution_chain. Execution middleware
already composes via next_call; that was defensive isolation, not chaining.
- the second copy of an accepted return inside invoke_middleware
(_apply_request_chain already copies it).
- tests/hermes_cli/test_middleware_isolation.py and the test_plugins.py
additions; tests/hermes_cli/test_plugins_middleware_chain.py holds two
invariant tests (composition, in-place-mutation isolation), each over
both request kinds. test_plugins.py is over its size cap, so it gains
nothing.