# os-vault invariants Behavioral invariants of the plugin. Changing any of these requires explicit human approval. Enforced by `tests/harness.sh` (golden fixtures) unless noted otherwise. 1. **Episodic and semantic memory stay separate systems.** Vault notes hold evergreen, cross-project knowledge (ADR-012); session/event history goes to memsearch (ADR-015). `/os-vault:query` never answers "what happened when" questions — those route to memsearch. 2. **Six flat namespaced facets, plus `scope`.** Note frontmatter tags are `type/`/`client/`/`project/`/`domain/`/`tool/`/`convention/` (ADR-011); `scope` (`global`/`project`/`client`) is a frontmatter field, not a tag. `type/` is required on every note. Source of truth for the schema is `vault-conventions.md` at the vault root — never duplicated or paraphrased into plugin code or skills. 3. **Hooks are fail-open, never block a session.** Every hook (`session_start.py`, `session_context.py`, `post_tool_use_write.py`, `session_end.py`, `memsearch_sync.py`, `vault_sync.py`) degrades silently on error; none may disrupt session startup or shutdown. 4. **SessionStart returns sub-second.** Heavy work (graph rebuild) is detached to the background; `session_start.py` only does the staleness check and kicks off the detached rebuild. Context injection is a separate hook (`session_context.py`, UserPromptSubmit). 5. **Sync happens only at SessionEnd, in a fixed order.** `vault_sync.py` must run after `session_end.py` so the daily journal note it writes is included in the commit; `memsearch_sync.py` is a separate, independent SessionEnd entry (split by ADR-016) for the memsearch repo. Neither auto-commit runs mid-session. 6. **Vault-not-repo rule.** `/os-vault:write` writes only to the resolved vault root (`${OS_VAULT_PATH:-$HOME/Documents/SecondBrain}`), never to a project repository. The vault path is resolved mechanically at the start of every write — never hardcoded. 7. **Write is query-first.** Before creating a new note, check for an existing note on the same subject; a contradicting/extending fact updates the existing note (bumping `last_updated`) rather than creating a duplicate. 8. **No silent new note types.** A fact that fits no existing type is filed under the closest existing type with a visible `## Type-fit note` misfit marker, or escalated to `/os-vault:design-template` — never given an invented type silently.