Skip to content
GitHubBuy Me A Coffee

Governance

This is what makes it safe to give an AI write access to your notes.

The principle is fail-closed. If anything goes wrong during an approval check (a missing callback, an unloaded config, an unexpected error), the operation is denied. The agent never silently auto-approves. Every tool call, internal or MCP, flows through one central pipeline.

The pipeline

ToolExecutionPipeline (src/core/tool-execution/ToolExecutionPipeline.ts) is the single enforcement point. Nothing bypasses it.

Three questions, in order. Is the path allowed? Is the operation approved? Only then does the tool run, and the result is logged afterward.

Path protection

Two files in the vault root control which paths the agent can access:

FileEffect
.obsidian-agentignorePaths completely invisible to the agent. Uses gitignore syntax.
.obsidian-agentprotectedPaths readable but never writable, even with explicit approval.

Both files use glob patterns. A line like journal/private/** blocks everything under that folder.

Some paths are always blocked regardless of configuration: .git/, Obsidian workspace files, and cache files. The governance config files themselves are always write-protected, so the agent cannot edit its own restrictions.

The IgnoreService (src/core/governance/IgnoreService.ts) enforces this. If it hasn't finished loading its patterns yet, it denies all access. Fail-closed.

Approval categories

Every tool call routes through the auto-approval check. The pipeline classifies the call into one of twelve approval groups, then looks up the matching toggle under Settings > Vault Operator > Agents > Auto-approve. If the toggle is on, the call runs without asking. If it is off, the approval modal opens.

GroupExamplesDefault behaviour
readread_file, search_files, semantic_search, read_documentAuto-approved when the read toggle is on
note-editwrite_file, edit_file, append_to_file, update_frontmatter, ingest_document, ingest_deep, ingest_triageRequires approval unless the note-edits toggle is on
vault-changecreate_folder, delete_file, move_file, create_pptx, create_docx, create_xlsx, restore_checkpointRequires approval unless the vault-changes toggle is on
webweb_fetch, web_search, anti_echo_searchAuto-approved when the web toggle is on
agentattempt_completion, switch_agent, update_todo_list, find_tool, inspect_self, update_settingsAlways auto-approved
subtasknew_taskAuto-approved when the subtasks toggle is on
mcpuse_mcp_toolAuto-approved when the MCP toggle is on
skillexecute_command, invoke_skill, run_skill_script, enable_pluginAuto-approved when the skills toggle is on
plugin-apicall_plugin_apiTwo toggles, one for read calls and one for write calls. The pipeline picks the toggle based on the call shape.
recipeexecute_recipeAuto-approved when the recipes toggle is on
sandboxevaluate_expressionAlways asks. No auto-approve toggle.
self-modifymanage_source, update_soulAlways asks. No auto-approve toggle, no bypass.

The triage tool (ingest_triage) lives in the note-edit group because it writes the triage decision back into the source note frontmatter. The single-pass and deep ingest paths are also note-edit. There is no separate ingest group.

Self-modification is the strictest category. The agent can edit its own source code and settings, but a human approves every change. Skill authoring goes through the built-in skill-creator skill plus the regular file tools (write_file, edit_file), so each new SKILL.md still passes through note-edit approval.

For note edits, the approval modal can show a semantic diff grouped by Markdown structure (frontmatter, headings, lists, code blocks) instead of raw line hunks. You can approve, reject, or edit individual sections before confirming.

Checkpoints

Before any write operation, the pipeline takes a git snapshot of the affected file. This uses a shadow repository at {vault-parent}/vault-operator-shared/checkpoints/ (outside the vault, so Obsidian Sync and iCloud do not replicate it) powered by isomorphic-git (pure JavaScript, no native git binary needed).

GitCheckpointService (src/core/checkpoints/GitCheckpointService.ts) commits the file's current content into the shadow repo before the tool modifies it. Each checkpoint records the task ID, commit hash, timestamp, changed files, and the tool that triggered it. Files that didn't exist before the checkpoint are tracked separately so restore can delete them.

After any task, you can undo all changes. Every write operation gets its own checkpoint, so you can roll back to any intermediate state. The vault's own git history, if it has one, is never touched.

Audit log

Every tool call is logged to a JSONL file via OperationLogger (src/core/governance/OperationLogger.ts). One file per day, stored under the agent folder at .vault-operator/data/logs/YYYY-MM-DD.jsonl. Files older than 30 days get deleted automatically.

Each entry records:

FieldContent
timestampISO 8601
taskIdWhich task triggered the call
modeActive mode at the time
toolTool name
paramsInput parameters (PII-scrubbed)
resultOutput summary (capped at 2000 chars)
successWhether the call succeeded
durationMsExecution time

Sensitive values (passwords, tokens, API keys) are replaced with [REDACTED] before logging. File content fields are logged as [N chars] instead of the full text. URLs have credentials stripped.

The log is append-only during a session. You can read it with any tool that understands JSONL, or use the built-in read_agent_logs tool to have the agent analyze its own history.