Conventions
Layering
- Only
packages/obsidian-adaptermay importobsidian; everything else talks to Cordis service interfaces; - Obsidian runtime APIs missing from the type surface (
app.commands/app.setting/app.viewRegistry…) are accessed via structural casts inapps/plugin/src/obsidian-bridge.ts; - esbuild must keep the
node-module-shimplugin (dsh-llm'screateRequirecrashes in Obsidian; solved byapps/plugin/shims/node-module.ts).
Internal protocol names (do not change)
- Data dir
.obsidian/harness-like/, user plugins dir.obsidian/harness-like-plugins/; - Service keys
ctx.sessionLog / toolsCompat / llmCaller / sandbox / approval / dshI18n; - Event domains
dsh/session/event,dsh/waiting-approval,dsh/settings-updated; log prefix[dsh]; - The
dshfield in user plugin manifests (dsh.idetc.).
Security model
- Sandbox whitelist: read = whole vault; write = notes + data dir + plugins dir + temp dir; never other config-dir areas;
- Dynamic plugins execute only local files, requiring authorization (single/double-check);
- Write approval chain: per-tool policy → current-note mode → directory whitelist → approval dialog;
- Only Create mode can create/modify plugins.
i18n
- Dictionaries per language in
apps/plugin/src/i18n/{zh,en}.ts; API ini18n/index.ts(t()/resolveLanguage()/registerLocale); uiLanguagepreference:auto(default, follows Obsidian's app language vialocalStorage['language']) or explicitzh/en;- All user-visible strings must go through
t('key')— no hardcoded Chinese.