Confusables — terms that look alike and aren't
Parent: architecture
The vocabulary collisions in this system, each split precisely. When a doc says one of these words unqualified, check here.
1. The two MCP planes
| term | our role | what it is | auth |
|---|---|---|---|
| capability plane | MCP host | our agent's tools: mcp-servers/ stdio children + owner-attached ext-mcp, via mcpclient/capreg | none — process-local (capsocket) |
| service handle (as-MCP) | MCP server | the outward /mcp/* facade (as-mcp-facade): the owner's own AI pushes corpus (the thesis loop), other people's agents read | Sigv1 |
Same protocol, opposite directions: on the service handle the arrow points into us (we serve); on the capability plane the arrow starts from our agent (we host and consume).
Rule: never say bare "MCP" in engineering docs — say capability plane or service handle. (Third-party MCP servers that design docs mention in passing — e.g. job-loop's Playwright MCP, which the owner's Claude consumes — live entirely outside our box and are neither plane.)
2. The two plugin axes (and connectors are NOT MCP)
- MCP capability plugins (mcp-capability-plugins) — tools for our agent; speak the MCP wire protocol; manifest + Origin trust tiers.
- Connector plugins (connector-plugins) — credentialed external integrations (calendar/mail/…); speak contracts (
CalendarProxy), NOT MCP; consumers get a call handle, never creds. A capability may Require a connector (connector-deps) — that dependency edge is the only place the two axes touch.
3. Connector: action mode vs sync mode
Same Hub, two directions: action = proxy calls out at session time (booking, mail); sync = ingest data in at curation time (the destiny of Obsidian vault sync). An "installed connector" tells you nothing about which until you look at the mode.
4. ext-mcp vs mcp-servers/
Both live on the capability plane; they differ only in Origin: mcp-servers/ are builtin (ship with the repo, loaded at boot), ext-mcp are owner-registered third-party servers. Same protocol, different trust tier (mcp-capability-plugins).
5. Skills vs capabilities
A capability is a tool the agent can call. A skill is an authored artifact (managed like prompts: library/CRUD/attach-to-role), rendered to SKILL.md, exposed through 3-level progressive disclosure (skills-progressive-disclosure) — it rides on capabilities (skill_use, skill_run_script), it isn't one.
6. The writings estate vs the corpus three tiers
Two separate data estates that both look like "the content" — since 2026-07-09 both live in the one corpus_notes table, told apart by the genre column (backend/db/schema.sql):
- corpus =
genreraw → wiki → output(+subjectivity) + thenote_refsedge table (renamed fromwiki_refs) (three-tier-corpus-promotion); - writings =
genre='writing'+writing_refs— standalone long-form posts, its own ref rebuild. The vault sync (writings-import-export) used to touch writings only; sinceSyncVaultit routes every top-level folder to a genre — wiki / subjectivity / raw / writing (backend/internal/corpus/obsidian/sync.go:2,sync_classify.go:64); "wiki" in this wiki's name and "wiki" the corpus tier are also not the same thing.
7. Setup token vs owner keypair
Setup token = first-run instance claim (boot-printed, sha256 into instance_settings, consumed once). Keypair = ongoing Sigv1 auth for the service handle, created later via the admin API. Bootstrap vs operation — unrelated lifecycles (owner-keypair-auth).
8. Access code = invitation (deliberately ONE thing)
Not a confusable to split but one to collapse: the job-loop design unified them — one access_codes table, no parallel "Invitation" concept. If you see "invitation" anywhere, it IS an access code (acl-and-quota-granularity).
9. Frozen vs live (the ACL timing split)
Global capability settings are live (flip → running sessions die). Role and code layers are frozen at issue into the RoleSnapshot. "The owner changed X, why does the visitor still see the old rules?" — because that layer freezes; "why did the session die instantly?" — because that one doesn't (role-snapshot-frozen, acl-and-quota-granularity).
10. corpus.search vs corpus_search — a dot and an underscore, two backends
corpus.search (dot) is the owner/admin op behind /api/admin/corpus/{genre}/search. It calls repo.Search → Postgres SearchNotes, and never touches Meili. corpus_search (underscore) is the visitor agent's tool; it goes through the corpus lister, which uses Meili when configured and falls back to Postgres FTS when not.
This cost real time: attaching the lexical index to production and then verifying on the admin surface produced results byte-identical to before, which reads exactly like "the change did nothing". Measuring a retrieval change on one of these tells you nothing about the other (corpus-retrieval).
11. Authoritative vs partial import — the same endpoint, opposite deletion semantics
POST /api/admin/obsidian/import has a SyncMode. Its zero value is partial: upsert only, nothing pruned. Authoritative means this upload IS the whole vault, so anything vault-imported and absent from the batch is deleted — which is what the owner's directory-picker sends.
The flag is a plain form value, so it is dropped by omission rather than by error, and a full-vault sync then silently degrades into add-only. The reverse mistake is worse: a nine-file partial upload sent as authoritative would prune the other thousand.
12. publish (vault) vs published (corpus) vs show_as_source (retrieval)
Three near-synonyms on three different layers. publish: true is frontmatter the owner writes in their vault. published is the corpus column it maps to, and it gates the public reader pages only. Retrieval does not consult it — an entry can be retrievable to a coded visitor while being invisible on the public web, which is the whole point of codes. show_as_source is separate again: whether a note may be cited in an answer.
"Is this note public?" is therefore three questions, and the vault's own frontmatter schema knew about none of them for months — publish was not in its allow-list, so every commit adding it was blocked.