- Three opt-in env vars: OBSIDIAN_READ_PATHS / OBSIDIAN_WRITE_PATHS (comma-separated vault-relative folder allowlists, prefix-based with implicit recursion) and OBSIDIAN_READ_ONLY (global write-deny kill switch). All default unset/false — backwards compatible, full-vault behavior preserved.
- New typed path_forbidden error reason on every path-taking tool's errors[] contract — wire data echoes activeScope so the agent can self-correct without inspecting logs. subreason ∈ { outside_read_paths, outside_write_paths, read_only_mode }.
- Write tools and the command-palette pair are wrapped with disabledTool() when OBSIDIAN_READ_ONLY=true, removing them from tools/list while keeping them visible in the operator manifest.
- obsidian_search_notes silently post-filters hits against OBSIDIAN_READ_PATHS; obsidian_list_notes walk skips recursion into out-of-scope subdirs (marks them truncated) so root listings still surface top-level structure.
Closes #40.
See changelog/3.1.x/3.1.2.md for the full release notes.