oh-my-second-brain 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +3 -2
  3. package/.codex-plugin/plugin.json +2 -2
  4. package/CHANGELOG-assets.md +9 -0
  5. package/CHANGELOG-cli.md +9 -0
  6. package/CHANGELOG-kernel.md +10 -0
  7. package/CHANGELOG-mcp.md +9 -0
  8. package/CHANGELOG-vendors.md +6 -0
  9. package/CHANGELOG.md +7 -0
  10. package/README.ko.md +4 -4
  11. package/README.md +3 -3
  12. package/assets/claude/CLAUDE.md +6 -4
  13. package/assets/claude/hooks/oms-guard.mjs +46 -6
  14. package/assets/codex/AGENTS.md +6 -4
  15. package/assets/codex/rules/oms.md +3 -2
  16. package/assets/hermes/README.md +7 -2
  17. package/assets/hermes/SOUL.md +8 -4
  18. package/assets/hermes-manifest.json +2 -2
  19. package/assets/skills/doctor/SKILL.md +2 -2
  20. package/assets/skills/search/SKILL.md +1 -1
  21. package/assets/skills/setup/SKILL.md +42 -0
  22. package/assets/skills/status/SKILL.md +4 -3
  23. package/assets/skills/write/SKILL.md +2 -2
  24. package/core/AGENTS.md +6 -3
  25. package/dist/cli/contract-command.js +103 -24
  26. package/dist/cli/contract-command.js.map +1 -1
  27. package/dist/cli/oms.js +12 -1
  28. package/dist/cli/oms.js.map +1 -1
  29. package/dist/cli/setup-command.js +10 -2
  30. package/dist/cli/setup-command.js.map +1 -1
  31. package/dist/cli/usage.js +1 -0
  32. package/dist/cli/usage.js.map +1 -1
  33. package/dist/kernel/contract/interview.d.ts +25 -7
  34. package/dist/kernel/contract/interview.js +112 -75
  35. package/dist/kernel/contract/interview.js.map +1 -1
  36. package/dist/kernel/contract/judge.d.ts +5 -1
  37. package/dist/kernel/contract/judge.js +11 -2
  38. package/dist/kernel/contract/judge.js.map +1 -1
  39. package/dist/kernel/contract/loosening.d.ts +30 -0
  40. package/dist/kernel/contract/loosening.js +205 -0
  41. package/dist/kernel/contract/loosening.js.map +1 -0
  42. package/dist/kernel/contract/pattern.d.ts +15 -0
  43. package/dist/kernel/contract/pattern.js +71 -0
  44. package/dist/kernel/contract/pattern.js.map +1 -0
  45. package/dist/kernel/contract/scripted-interview.d.ts +24 -0
  46. package/dist/kernel/contract/scripted-interview.js +59 -0
  47. package/dist/kernel/contract/scripted-interview.js.map +1 -0
  48. package/dist/kernel/contract/status.d.ts +4 -0
  49. package/dist/kernel/contract/status.js +7 -3
  50. package/dist/kernel/contract/status.js.map +1 -1
  51. package/dist/kernel/contract/store.js +18 -0
  52. package/dist/kernel/contract/store.js.map +1 -1
  53. package/dist/kernel/contract/types.d.ts +4 -2
  54. package/dist/kernel/contract/types.js.map +1 -1
  55. package/dist/kernel/engine/retrieval/template-source.js +12 -4
  56. package/dist/kernel/engine/retrieval/template-source.js.map +1 -1
  57. package/dist/kernel/harness/surface-registry.js +3 -0
  58. package/dist/kernel/harness/surface-registry.js.map +1 -1
  59. package/dist/mcp/note-write.d.ts +19 -2
  60. package/dist/mcp/note-write.js +36 -7
  61. package/dist/mcp/note-write.js.map +1 -1
  62. package/dist/mcp/server.js +1 -1
  63. package/dist/mcp/server.js.map +1 -1
  64. package/dist/vendors/hermes/hermes.js +1 -1
  65. package/dist/vendors/hermes/hermes.js.map +1 -1
  66. package/docs/adapters.md +1 -1
  67. package/docs/architecture.md +1 -1
  68. package/docs/cli-map.md +1 -1
  69. package/docs/conventions.md +1 -1
  70. package/docs/install.md +1 -1
  71. package/package.json +1 -1
  72. package/skills/doctor/SKILL.md +2 -2
  73. package/skills/search/SKILL.md +1 -1
  74. package/skills/setup/SKILL.md +42 -0
  75. package/skills/status/SKILL.md +4 -3
  76. package/skills/write/SKILL.md +2 -2
@@ -10,7 +10,7 @@
10
10
  {
11
11
  "name": "oms",
12
12
  "description": "Oh My Second Brain convention layer for Obsidian vaults — capture, retrieve, and validate knowledge under a declared semantic convention.",
13
- "version": "0.17.0",
13
+ "version": "0.18.1",
14
14
  "author": {
15
15
  "name": "gobeumsu",
16
16
  "email": "gobeumsu@gmail.com"
@@ -37,5 +37,5 @@
37
37
  ]
38
38
  }
39
39
  ],
40
- "version": "0.17.0"
40
+ "version": "0.18.1"
41
41
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oms",
3
- "version": "0.17.0",
4
- "description": "Oh My Second Brain convention layer for Obsidian vaults — eight shared skills and five MCP tools under a user-owned contract.",
3
+ "version": "0.18.1",
4
+ "description": "Oh My Second Brain convention layer for Obsidian vaults — seven shared skills and five MCP tools under a user-owned contract.",
5
5
  "author": {
6
6
  "name": "gobeumsu"
7
7
  },
@@ -19,6 +19,7 @@
19
19
  "./assets/skills/doctor/",
20
20
  "./assets/skills/link/",
21
21
  "./assets/skills/search/",
22
+ "./assets/skills/setup/",
22
23
  "./assets/skills/status/",
23
24
  "./assets/skills/write/"
24
25
  ]
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "oms",
3
- "version": "0.17.0",
3
+ "version": "0.18.1",
4
4
  "description": "Oh My Second Brain convention layer for Obsidian vaults — Codex native rules, skills, and MCP adapter.",
5
- "_note": "oms host install writes Codex MCP config and provenance, installs ~/.codex/rules/oms.md, and installs the eight shared skills under ~/.codex/skills/oms-*.",
5
+ "_note": "oms host install writes Codex MCP config and provenance, installs ~/.codex/rules/oms.md, and installs the seven shared skills under ~/.codex/skills/oms-*.",
6
6
  "skills": "./assets/skills/",
7
7
  "mcpServers": "./.mcp.codex.json"
8
8
  }
@@ -4,6 +4,15 @@ Skills, agents, templates, and host guidance changes belong here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.18.1] - 2026-09-26
8
+
9
+ - The Hermes README and SOUL name the skill category `knowledge-management`: filter with `skills_list(category="knowledge-management")`, since `knowledge-management/oms` matches nothing. The `status` skill describes `readTools` and `writeTools` separately.
10
+
11
+ ## [0.18.0] - 2026-09-25
12
+
13
+ - **The `setup` skill is added (seven skills).** It walks the owner through `oms setup --questions` and `oms setup --answers`, asking each question with the recommended option first, keeping the answers file outside the vault and deleting it afterwards, and sending any loosening reseal or seal recovery to the owner's terminal. Host guidance and the `doctor`, `status`, and `write` skills no longer say the agent never runs setup; they name the skill for a first or stricter seal and keep recovery and loosening with the terminal.
14
+ - **The `setup` skill spells out what it must never do.** It never runs `oms setup` or `oms contract setup` without `--questions` or `--answers`, never runs setup under a pty wrapper (`script`, `expect`, `unbuffer`), and never moves the vault or deletes, edits, or re-IDs `.oms/settings.json`. It notes that adding a folder, property, or template widens a closed axis, and sends a `pattern-unsafe` change to the owner's terminal. It says the skill path may add new entries, but changing a sealed template, even to make it stricter, is `template-tightened` and needs `oms setup` in the owner's terminal.
15
+
7
16
  ## [0.17.0] - 2026-09-25
8
17
 
9
18
  - **Breaking: host guidance describes the sealed contract.** The `interview` and `template` skills are deleted, leaving six skills. Guidance tells agents to write whole notes through `write {path, content, template?}`, to stay inside the sealed property pool, never to read or write `~/.oms/`, and to ask the user to run `oms setup` on `contract-unreadable`.
package/CHANGELOG-cli.md CHANGED
@@ -4,6 +4,15 @@ Changes to the `oms` command surface belong here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.18.1] - 2026-09-26
8
+
9
+ - **`oms --version` and `oms -v` print the installed package version.** Hosts and agents can now confirm the release from the CLI. An unknown flag or extra argument still exits 1 with `[oms] Unknown command:`.
10
+
11
+ ## [0.18.0] - 2026-09-25
12
+
13
+ - **`oms setup` and `oms contract setup` take `--questions` and `--answers <file|->`.** `--questions` prints the interview questions as JSON and seals nothing; `--answers` runs the same interview from a JSON object of answers by question id (`-` reads stdin) and seals. Missing answers return `incomplete` with the follow-up questions; an invalid, unknown, or malformed answer, an answers file inside the vault, or both flags together exit 1 and seal nothing. A reseal through `--answers` must be equal or stricter; loosening exits 1 with `status: loosening`, `{field, kind}` changes and no values, and points at `oms setup` in a terminal. The interactive setup is unchanged and keeps full authority, and the non-TTY refusal now names the two-step path.
14
+ - **`oms contract doctor` reports `unsafePatterns`.** Each entry is `{field, kind: "pattern-unsafe"}` for a sealed pattern the seal screen now refuses; the report is unhealthy and recovery is `oms setup` in a terminal. `--answers` now accepts an answers file whose name merely starts with two dots (such as `..answers.json`) only when it is actually outside the vault; one inside the vault is refused.
15
+
7
16
  ## [0.17.0] - 2026-09-25
8
17
 
9
18
  - **Breaking: `oms template` is removed; the contract lives under `oms setup` and `oms contract setup|extract|status|doctor`.** `oms setup` is interactive only and refuses to run without a TTY or under `OMS_NON_INTERACTIVE=1`. `oms note guide` and `oms note check` are removed; `oms note audit` judges existing notes against the seal. `oms hook pre` replaces the retired hook leaves. Older `.oms/*` files are ignored and a `templateRoots` settings key is rejected. Upgrade order: (1) install this release and run `oms host sync`; (2) back up `.oms/settings.json` and keep only `version`, `vaultId`, `templateFolder` (formerly `templateRoots`), `embedding`, and `agentRepair`; (3) run `oms setup` at a terminal to seal the vault; (4) run `oms contract doctor` and review the unexpected control files it lists under `.oms/`; (5) keep those backups while a rollback to 0.16.0 is still possible.
@@ -4,6 +4,16 @@ Domain logic changes belong here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.18.1] - 2026-09-26
8
+
9
+ - **The status `CONTRACT_OPEN` diagnostic uses the same wording and guidance as `oms contract doctor`.** A never-sealed vault reports `contract: none` with `run oms setup`, unreadable vault settings report `vault settings unreadable` with `run oms contract doctor`, and a missing vault says no contract applies. `SETTINGS_INVALID_FINDING` is exported from `src/kernel/contract/status.ts`.
10
+
11
+ ## [0.18.0] - 2026-09-25
12
+
13
+ - **The interview can run from scripted answers and refuse a loosening reseal.** `runInterview` takes `nonLoosening`, which accepts only a first seal or a reseal of a readable seal and, before sealing, compares the new contract with the sealed one through `looseningChanges` (`src/kernel/contract/loosening.ts`). Removing a folder, property, or template, opening an axis, dropping a requirement, heading, or search exclusion, changing a type, fixed value, pattern, or apply folder, and widening an allowed list or range are loosening; for a single-valued type, fixed and allowed rules compare as value sets. Moving a sealed template's source is `removed` under `templates.<name>.source`, since search exclusion is built from sealed sources, and apply folders compare after NFC and separator normalization. The result names `{field, kind}` only. `scriptedIO` (`src/kernel/contract/scripted-interview.ts`) answers questions by id, turns a re-ask into `CONTRACT_ANSWER_INVALID`, reports an unknown id as `CONTRACT_ANSWER_UNKNOWN`, and ends `incomplete` with the unanswered questions instead of sealing.
14
+ - **`looseningChanges` keeps a sealed template exactly as strict.** The judge enforces a scoped template on an edit only when the previous content passed it, so a stricter template would switch its checks off for notes that fail it. Under `nonLoosening`, an added required heading, required property, or narrowed rule, a narrower narrowed rule, or a narrowed property whose type becomes newly known is `template-tightened`; only a fixed value and an allowed list that accept the same single value count as equal, and headings compare after NFC normalization. Folder and property rules may still tighten, since the judge checks changed values against the next rules without relying on the previous content passing. `templateAxis` reads the property type with `Object.hasOwn`.
15
+ - **`looseningChanges` closes three gaps.** A fixed value and an allowed list imply each other only when the field's type is single-valued (`singleValued` in `judge.ts`); for a list type or an unregistered field they compare as different kinds. A template newly given an apply folder that equals, holds, or sits inside a sealed scoped template's folder is `apply-folder-overlap`. `unsafePatternChanges` names sealed pattern rules that `patternRefusal` now refuses as `pattern-unsafe`; the `nonLoosening` interview refuses them, and the full-authority interview asks for only those rules again and keeps the rest. `contractDoctor` reports them as `unsafePatterns` and points recovery at `oms setup`. Lookups use `Object.hasOwn`, and template `narrowedRules` are built on a null-prototype object, so a field named `constructor` or `__proto__` is compared as data.
16
+
7
17
  ## [0.17.0] - 2026-09-25
8
18
 
9
19
  - **Breaking: the sealed contract replaces the `.oms/` policy files.** Older `.oms/*` files (template policy, taxonomy, type projection) are no longer read; `oms contract doctor` reports them as unexpected control files. `.oms/settings.json` accepts only `version`, `vaultId`, `templateFolder`, `embedding`, and `agentRepair`, and a `templateRoots` key is rejected as `VAULT_SETTINGS_INVALID`. The contract is stored under `~/.oms/vaults/<vault-id>/` and one judge (`src/kernel/contract/judge.ts`) decides every write. Upgrade order: (1) install this release and run `oms host sync`; (2) back up `.oms/settings.json` and keep only `version`, `vaultId`, `templateFolder` (formerly `templateRoots`), `embedding`, and `agentRepair`; (3) run `oms setup` at a terminal to seal the vault; (4) run `oms contract doctor` and review the unexpected control files it lists under `.oms/`; (5) keep those backups while a rollback to 0.16.0 is still possible.
package/CHANGELOG-mcp.md CHANGED
@@ -4,6 +4,15 @@ MCP server tools and resources belong here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.18.1] - 2026-09-26
8
+
9
+ - `status` `readTools` lists only the read-only tools (`search`, `link`, `status`); it is now derived from each tool's `readOnlyHint`, so `write` no longer appears there. Writes stay described by `writeTools`.
10
+
11
+ ## [0.18.0] - 2026-09-25
12
+
13
+ - The five MCP tools are unchanged. Agent-driven setup is a tool-less skill over the CLI, not an MCP operation, so no tool can publish, edit, or read the contract.
14
+ - `doctor` `validate` output carries the contract doctor's `unsafePatterns` (`{field, kind}` only, no values). The `note-write.ts` header now notes that a crash between `link()` and removing the temp name leaves a second hard link to the new note, which nothing sweeps.
15
+
7
16
  ## [0.17.0] - 2026-09-25
8
17
 
9
18
  - **Breaking: `write` takes `{path, content, template?}` with no `op`.** The whole note is judged against the sealed contract and saved atomically only when allowed; a denial returns `{field, kind}` violations and one guidance command. The `guide`, `check`, and `template` operations and the `folderIntents` input are removed. `search` `templates` returns the sealed folders, property names and types, and templates; `doctor` `validate` diagnoses the seal, and `doctor` `regenerate-types` is removed with no alias.
@@ -4,6 +4,12 @@ Per-host adapter and installer changes belong here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.18.1] - 2026-09-26
8
+
9
+ ## [0.18.0] - 2026-09-25
10
+
11
+ - Claude, Codex, Hermes, and Gajae-Code register the new `setup` skill, so each host installs seven shared skills. Host discovery and installation now report the `setup` skill as installed.
12
+
7
13
  ## [0.17.0] - 2026-09-25
8
14
 
9
15
  - **Breaking: the Claude guard follows the judge.** The PostToolUse hook and the `oms-post-guard` bin are removed, and `OMS_GUARD` no longer exists. The PreToolUse write matcher is now `Write|Edit|MultiEdit|NotebookEdit`, and a second PreToolUse entry for `Read|Grep|Glob` denies access under `~/.oms/`. A write that the judge finds in violation is denied; when the judge cannot run, the call is allowed with a warning. The hook output format changed accordingly. Codex and Hermes still declare no write hook. Run `oms host sync` after upgrading to rewrite the registration.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,13 @@ This aggregate changelog contains changes that span multiple layers.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.18.1] - 2026-09-26
14
+
15
+ ## [0.18.0] - 2026-09-25
16
+
17
+ - **An agent can seal the vault contract by asking you each setup question.** The new tool-less `setup` skill runs `oms setup --questions`, asks the owner every question one at a time, and seals with `oms setup --answers <file|->`. That path seals a first contract or a reseal that only adds or tightens; a reseal that would loosen is refused with `{field, kind}` only and left to `oms setup` in the owner's own terminal, which keeps full authority. The public surface is seven skills, five MCP tools, and fourteen CLI families. See ADR-007 §3.
18
+ - **An agent reseal can no longer loosen the contract in the gaps a review found.** A fixed value and an allowed list stand in for each other only for a single-valued property, so a list property's `allowed` cannot turn into a looser `fixed`. A newly scoped template whose apply folder overlaps a sealed scoped template is `apply-folder-overlap`. A sealed pattern that today's seal screen refuses (such as one over the length cap sealed by 0.17.0) is `pattern-unsafe`: `--answers` refuses it, `oms contract doctor` reports it as `unsafePatterns` with `{field, kind}` only, and the terminal `oms setup` asks for just that rule again. A sealed template may not change at all through `--answers`, not even to become stricter: the judge enforces a template only where the previous content passed it, so a stricter template would stop checking notes that fail it. Such a change is `template-tightened` and belongs to the owner's terminal `oms setup`. ADR-007 records the residual risks of a pty wrapper and of a fresh first seal after the vault or `.oms/settings.json` is moved, deleted, or re-IDed.
19
+
13
20
  ## [0.17.0] - 2026-09-25
14
21
 
15
22
  - **Breaking: the vault contract is sealed once by the user and judged on every write.** The interactive `oms setup` interviews folders, the property pool, and templates together and seals the contract under `~/.oms/vaults/<vault-id>/`, outside the vault; `.oms/settings.json` is the only OMS file inside it. One judge decides MCP `write {path, content, template?}` and the Claude guard hook, and a violation is refused with `{field, kind}` entries and one guidance command. `oms template`, the MCP `write` guide, check, and template operations, the `interview` and `template` skills, the PostToolUse hook, and `OMS_GUARD` are removed. The public surface is six skills, five MCP tools, and fourteen CLI families. Upgrade order: (1) install this release and run `oms host sync`; (2) back up `.oms/settings.json` and keep only `version`, `vaultId`, `templateFolder` (formerly `templateRoots`), `embedding`, and `agentRepair`; (3) run `oms setup` at a terminal to seal the vault; (4) run `oms contract doctor` and review the unexpected control files it lists under `.oms/`; (5) keep those backups while a rollback to 0.16.0 is still possible.
package/README.ko.md CHANGED
@@ -18,7 +18,7 @@ Oh My Second Brain(`oms`)은 기존 Obsidian·Markdown 볼트를 AI 호스트와
18
18
 
19
19
  ## 설정
20
20
 
21
- `oms setup`은 `oms contract setup`과 같은 명령이다. 볼트 전체를 인터뷰해 계약을 봉인한다. 볼트 안에는 `.oms/settings.json`만 쓰고 노트는 수정하지 않는다. 대화형 터미널이 없거나 `OMS_NON_INTERACTIVE=1`이면 실행을 거부하므로 에이전트는 실행하지 않는다. 언제든 다시 실행해 재봉인할 수 있다.
21
+ `oms setup`은 `oms contract setup`과 같은 명령이다. 볼트 전체를 인터뷰해 계약을 봉인한다. 볼트 안에는 `.oms/settings.json`만 쓰고 노트는 수정하지 않는다. 대화형 인터뷰는 터미널이 없거나 `OMS_NON_INTERACTIVE=1`이면 실행을 거부한다. 에이전트는 `setup` 스킬로만 봉인한다: `oms setup --questions`로 질문을 받아 소유자에게 하나씩 묻고, `oms setup --answers <file|->`로 첫 봉인이나 더 엄격한 재봉인만 한다. 계약을 느슨하게 하는 재봉인은 거부되고 소유자의 터미널 몫이다. 언제든 다시 실행해 재봉인할 수 있다.
22
22
 
23
23
  ```bash
24
24
  oms setup --vault /path/to/vault
@@ -46,7 +46,7 @@ oms setup 볼트를 인터뷰하고 계약
46
46
  oms status 읽기 전용 통합 상태 표시
47
47
  ```
48
48
 
49
- `oh-my-second-brain`이 전체 명령이고 `oms`는 짧은 별칭이다. 이 14개 family, 6개 스킬, 5개 MCP 도구는 서로 다른 집합이다. leaf 목록은 [CLI 맵](./docs/cli-map.md)에 있다.
49
+ `oh-my-second-brain`이 전체 명령이고 `oms`는 짧은 별칭이다. 이 14개 family, 7개 스킬, 5개 MCP 도구는 서로 다른 집합이다. leaf 목록은 [CLI 맵](./docs/cli-map.md)에 있다.
50
50
 
51
51
  ### 도움말 계약
52
52
 
@@ -64,7 +64,7 @@ lexical, vector, HyDE, typed-axis 질의는 계약을 통과하지 못할 노트
64
64
 
65
65
  `write` · `search` · `link` · `status` · `doctor`
66
66
 
67
- 6개 스킬(`distill`, `doctor`, `link`, `search`, `status`, `write`)은 호스트 workflow다. `distill`은 도구가 없다.
67
+ 7개 스킬(`distill`, `doctor`, `link`, `search`, `setup`, `status`, `write`)은 호스트 workflow다. `distill`과 `setup`은 도구가 없다. `setup`은 소유자에게 setup 질문을 하나씩 묻고 첫 봉인이나 더 엄격한 재봉인만 한다.
68
68
 
69
69
  다섯 도구는 스킬의 부분집합이며, 두 집합 모두 14개 CLI family와 다르다. 세부 기능은 다섯 도구 아래의 `op` 값으로 남는다. 봉인에는 MCP 작업도 스킬도 없다.
70
70
 
@@ -79,7 +79,7 @@ npm install -g oh-my-second-brain
79
79
  oms host install --runtime all --vault /path/to/vault --yes
80
80
  ```
81
81
 
82
- Gajae-Code에서는 npm 패키지를 marketplace plugin으로 설치한다: `gjc plugin install oms@oms`. GJC는 패키지 루트의 `skills/` 관례 경로에서 여섯 OMS 스킬을 찾는다.
82
+ Gajae-Code에서는 npm 패키지를 marketplace plugin으로 설치한다: `gjc plugin install oms@oms`. GJC는 패키지 루트의 `skills/` 관례 경로에서 일곱 OMS 스킬을 찾는다.
83
83
 
84
84
  호스트 설치는 정식 볼트를 `${XDG_CONFIG_HOME:-~/.config}/oms/vault.json`에 기록하고, 관리하는 각 호스트 항목에 `oms serve mcp --vault /path/to/vault`를 새긴다. `oms host install|remove|sync|status`는 그 서명된 pointer를 호스트 통합 유지보수에만 쓴다. `oms package update`는 패키지를 업데이트하지만 호스트를 암묵적으로 sync하지 않는다. `oms host sync`를 따로 실행한다.
85
85
 
package/README.md CHANGED
@@ -18,7 +18,7 @@ The authority model is in [architecture](./docs/architecture.md). Vault files ar
18
18
 
19
19
  ## Setup
20
20
 
21
- `oms setup` is the same command as `oms contract setup`. It interviews the whole vault and seals the contract. It writes only `.oms/settings.json` inside the vault and never modifies notes. It refuses to run without an interactive terminal or under `OMS_NON_INTERACTIVE=1`, so an agent never runs it. Run it again at any time to re-seal.
21
+ `oms setup` is the same command as `oms contract setup`. It interviews the whole vault and seals the contract. It writes only `.oms/settings.json` inside the vault and never modifies notes. The interactive interview refuses to run without a terminal or under `OMS_NON_INTERACTIVE=1`. An agent seals only through the `setup` skill: `oms setup --questions` prints the questions, the agent asks the owner each one, and `oms setup --answers <file|->` seals a first or stricter contract. A reseal that loosens is refused there and left to the owner's terminal. Run it again at any time to re-seal.
22
22
 
23
23
  ```bash
24
24
  oms setup --vault /path/to/vault
@@ -46,7 +46,7 @@ oms setup Interview the vault and seal its
46
46
  oms status Show the read-only aggregate status
47
47
  ```
48
48
 
49
- `oh-my-second-brain` is the full command; `oms` is its short alias. These fourteen families, the six skills, and the five MCP tools are three different sets. The leaf map is [the CLI map](./docs/cli-map.md).
49
+ `oh-my-second-brain` is the full command; `oms` is its short alias. These fourteen families, the seven skills, and the five MCP tools are three different sets. The leaf map is [the CLI map](./docs/cli-map.md).
50
50
 
51
51
  ### Help contract
52
52
 
@@ -64,7 +64,7 @@ Lexical, vector, HyDE, and typed-axis queries still include notes that would fai
64
64
 
65
65
  `write` · `search` · `link` · `status` · `doctor`
66
66
 
67
- The six skills (`distill`, `doctor`, `link`, `search`, `status`, `write`) are host workflows. `distill` is tool-less.
67
+ The seven skills (`distill`, `doctor`, `link`, `search`, `setup`, `status`, `write`) are host workflows. `distill` and `setup` are tool-less; `setup` asks the owner each setup question and seals a first or stricter contract.
68
68
 
69
69
  The five tools are a subset of those skills, and neither set is the fourteen CLI families. Detail capabilities remain `op` values under the five tools. Sealing has no MCP operation and no skill.
70
70
 
@@ -2,8 +2,10 @@
2
2
 
3
3
  The vault owns its conventions. The user seals folders, properties, and
4
4
  templates once, in an interactive `oms setup` they run themselves at a terminal.
5
- You never run it. The sealed contract lives outside the vault, and it is not
6
- yours to read.
5
+ The `setup` skill may seal for them too: you ask each question, and `oms setup
6
+ --answers` seals a first or stricter contract only. Loosening a seal and
7
+ recovering a broken one stay with the user's terminal. The sealed contract lives
8
+ outside the vault, and it is not yours to read.
7
9
 
8
10
  ## Writing
9
11
 
@@ -38,5 +40,5 @@ about or guess the contract's location or values.
38
40
  backfills notes. A broken or missing seal is fixed by the user running
39
41
  `oms setup`.
40
42
 
41
- Six skills share five MCP tools: `write`, `search`, `link`, `distill`,
42
- `status`, and `doctor`.
43
+ Seven skills share five MCP tools: `write`, `search`, `link`, `distill`,
44
+ `setup`, `status`, and `doctor`. `distill` and `setup` have no tool.
@@ -3,9 +3,10 @@
3
3
  * oms-guard — PreToolUse wrapper for Claude Code settings.json.
4
4
  *
5
5
  * Order: parse stdin → normalise the tool name → deny `~/.oms/**` (reads and writes,
6
- * no spawn) → read tools decided here (no spawn) → deny writes to this guard file and the
7
- * installed oms package → writes inside a configured vault (the deepest one) are judged by
8
- * `oms hook pre --vault <vault>`; everything else passes without a spawn.
6
+ * no spawn) → read tools decided here (no spawn) → deny writes to this guard file, the
7
+ * installed oms package and Claude's settings files → writes inside a configured vault
8
+ * (the deepest one) are judged by `oms hook pre --vault <vault>`; everything else passes
9
+ * without a spawn.
9
10
  *
10
11
  * Configuration (env vars set by the settings.json hook definition):
11
12
  * OMS_VAULT — primary vault path
@@ -17,8 +18,13 @@
17
18
  * A payload that cannot be parsed (or exceeds the stdin cap) is denied when its raw text
18
19
  * names a configured vault or `~/.oms`, and otherwise allowed with one stderr line.
19
20
  *
20
- * Known limit: `~/.claude/settings.json`, where this hook is registered, is not protected;
21
- * the user edits it legitimately.
21
+ * Claude's settings files, where this hook is registered, are write-protected like the
22
+ * guard itself: `settings.json` and `settings.local.json` in `~/.claude` (or
23
+ * `$CLAUDE_CONFIG_DIR`, `$OMS_CLAUDE_HOME`) and in each configured vault's `.claude/`.
24
+ * Reads stay allowed; the user edits these files outside the agent.
25
+ *
26
+ * Known limit: only the tools in the hook matchers reach this guard. A Bash command that
27
+ * writes one of these files is not seen here.
22
28
  */
23
29
 
24
30
  import { spawnSync } from "node:child_process";
@@ -249,6 +255,38 @@ function rawNamesProtectedPath(raw, control) {
249
255
  return text.includes("~/.oms") || protectedRoots(control).some((root) => text.includes(root));
250
256
  }
251
257
 
258
+ const HOST_CONFIG_FILES = ["settings.json", "settings.local.json"];
259
+
260
+ /** Claude config directories whose settings files hold this hook's registration. */
261
+ function hostConfigDirs() {
262
+ const dirs = [path.join(homedir(), ".claude")];
263
+ for (const value of [process.env.CLAUDE_CONFIG_DIR, process.env.OMS_CLAUDE_HOME]) {
264
+ const expanded = value ? expandHome(value) : null;
265
+ if (expanded) dirs.push(path.resolve(expanded));
266
+ }
267
+ for (const vault of configuredVaults()) dirs.push(path.join(vault, ".claude"));
268
+ return dirs;
269
+ }
270
+
271
+ /** Each settings file as spelled and as resolved; a symlinked file or directory matches its target. */
272
+ function hostConfigFiles() {
273
+ const files = [];
274
+ for (const dir of hostConfigDirs()) {
275
+ for (const name of HOST_CONFIG_FILES) {
276
+ const file = path.join(dir, name);
277
+ files.push(file);
278
+ try { files.push(realTarget(file, process.cwd())); } catch { /* the spelled form still counts */ }
279
+ }
280
+ }
281
+ return files;
282
+ }
283
+
284
+ /** Case-insensitive, so a differently cased name on a case-insensitive disk is still caught. */
285
+ function isHostConfig(target, files = hostConfigFiles()) {
286
+ const wanted = target.toLowerCase();
287
+ return files.some((file) => file.toLowerCase() === wanted);
288
+ }
289
+
252
290
  const PACKAGE_RUNTIME = ["dist", "assets", "node_modules", "package.json"];
253
291
 
254
292
  /**
@@ -312,7 +350,8 @@ async function main() {
312
350
  target = realTarget(expanded, cwd);
313
351
  } catch {
314
352
  const textual = path.resolve(cwd, expanded);
315
- const exposed = protectedRoots(control).some((root) => atOrUnder(root, textual)) || (searches && under(textual, control));
353
+ const exposed = protectedRoots(control).some((root) => atOrUnder(root, textual)) || (searches && under(textual, control))
354
+ || (WRITE_TOOLS.has(tool) && isHostConfig(textual));
316
355
  if (exposed) { deny(UNSAFE_PATH_REASON); return; }
317
356
  process.stderr.write("[oms] guard could not resolve the target; allowed.\n");
318
357
  allow();
@@ -328,6 +367,7 @@ async function main() {
328
367
  }
329
368
 
330
369
  if (guardOwnedRoots().some((root) => atOrUnder(root, target))) { deny(CONTROL_PATH_REASON); return; }
370
+ if (isHostConfig(target)) { deny(CONTROL_PATH_REASON); return; }
331
371
 
332
372
  const vault = configuredVaults()
333
373
  .filter((root) => under(root, target))
@@ -6,8 +6,10 @@
6
6
 
7
7
  The vault owns its conventions. The user seals folders, properties, and
8
8
  templates once, in an interactive `oms setup` they run themselves at a terminal.
9
- You never run it. The sealed contract lives outside the vault, and it is not
10
- yours to read. `~/.oms` is off-limits. Inside the vault, `.oms/settings.json` is
9
+ The `setup` skill may seal for them too: you ask each question, and `oms setup
10
+ --answers` seals a first or stricter contract only. Loosening a seal and
11
+ recovering a broken one stay with the user's terminal. The sealed contract lives
12
+ outside the vault, and it is not yours to read. `~/.oms` is off-limits. Inside the vault, `.oms/settings.json` is
11
13
  the only OMS file.
12
14
 
13
15
  ## Writing
@@ -40,5 +42,5 @@ guess the contract's location or values.
40
42
  backfills notes. A broken or missing seal is fixed by the user running
41
43
  `oms setup`.
42
44
 
43
- Codex installs six shared skills (`write`, `search`, `link`, `distill`,
44
- `status`, `doctor`) backed by the five public MCP tools.
45
+ Codex installs seven shared skills (`write`, `search`, `link`, `distill`,
46
+ `setup`, `status`, `doctor`) backed by the five public MCP tools.
@@ -1,8 +1,9 @@
1
1
  # Oh My Second Brain for Codex
2
2
 
3
3
  The vault owns its conventions. The user seals them once with an interactive
4
- `oms setup` they run themselves. You never run it, and the sealed contract is
5
- not yours to read.
4
+ `oms setup` they run themselves, or through the `setup` skill, which seals a
5
+ first or stricter contract only. Loosening stays with their terminal, and the
6
+ sealed contract is not yours to read.
6
7
 
7
8
  | User intent | Preferred surface |
8
9
  |---|---|
@@ -5,10 +5,15 @@ Installed by `oms host install --runtime hermes` into:
5
5
  - `~/.hermes/skills/knowledge-management/oms/`
6
6
  - `~/.hermes/config.yaml` as `mcp_servers.oms`
7
7
 
8
- The shared skill bundle contains six skills: `write`, `search`, `link`,
9
- `distill`, `status`, and `doctor`. Runtime operations use the five MCP tools
8
+ The shared skill bundle contains seven skills: `write`, `search`, `link`,
9
+ `distill`, `setup`, `status`, and `doctor`. Runtime operations use the five MCP tools
10
10
  through `oms serve mcp`.
11
11
 
12
+ Hermes takes a skill's category from the first path segment only, so these
13
+ skills are listed under `knowledge-management`. Filter with
14
+ `skills_list(category="knowledge-management")`; the category
15
+ `knowledge-management/oms` matches nothing.
16
+
12
17
  Agents write notes with MCP `write {path, content, template?}`. OMS judges each
13
18
  note against the contract the user sealed with `oms setup`. A denial returns
14
19
  only `{field, kind}` and a guidance command. There is no completion operation
@@ -2,8 +2,10 @@
2
2
 
3
3
  The vault owns its conventions. The user seals folders, properties, and
4
4
  templates once, in an interactive `oms setup` they run themselves at a terminal.
5
- You never run it. The sealed contract lives outside the vault, and it is not
6
- yours to read. `~/.oms` is off-limits. Inside the vault, `.oms/settings.json` is
5
+ The `setup` skill may seal for them too: you ask each question, and `oms setup
6
+ --answers` seals a first or stricter contract only. Loosening a seal and
7
+ recovering a broken one stay with the user's terminal. The sealed contract lives
8
+ outside the vault, and it is not yours to read. `~/.oms` is off-limits. Inside the vault, `.oms/settings.json` is
7
9
  the only OMS file.
8
10
 
9
11
  ## Writing
@@ -35,5 +37,7 @@ about or guess the contract's location or values.
35
37
  notes or backfills guessed values. A broken or missing seal is fixed by the
36
38
  user running `oms setup`.
37
39
 
38
- Hermes uses six shared skills (`write`, `search`, `link`, `distill`, `status`,
39
- `doctor`) backed by the five public MCP tools.
40
+ Hermes uses seven shared skills (`write`, `search`, `link`, `distill`, `setup`,
41
+ `status`, `doctor`) backed by the five public MCP tools. Their skill category
42
+ is `knowledge-management`, so list them with
43
+ `skills_list(category="knowledge-management")`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oms",
3
- "version": "0.17.0",
3
+ "version": "0.18.1",
4
4
  "description": "Oh My Second Brain convention layer for Obsidian vaults — Hermes skill bundle and MCP adapter.",
5
- "_note": "oms host install writes ~/.hermes/config.yaml mcp_servers.oms and installs the six shared skills with provenance under ~/.hermes/skills/knowledge-management/oms/."
5
+ "_note": "oms host install writes ~/.hermes/config.yaml mcp_servers.oms and installs the seven shared skills with provenance under ~/.hermes/skills/knowledge-management/oms/."
6
6
  }
@@ -19,8 +19,8 @@ Diagnose the seal and derived indexes, then run only the repair the user named.
19
19
  - `build-graph` and `cleanup` repair the derived graph or semantic index the user named.
20
20
  - `sync-embeddings` takes exactly one `mode`: `sync`, `embed`, or `repair`. `repair` also requires `repairMode: "rebuild"` or `"drop"` and may set `dryRun`. It backs up the engine store and checks the rebuilt or absent result. It is not forced embedding. Do not send retired boolean `embed` or `force` switches, and do not send repair-only fields with `sync` or `embed`.
21
21
 
22
- A broken or missing seal is recovered by the user running `oms setup` at a terminal; you never run it. The only automatic seal repair is `oms contract doctor --fix`, which re-indexes a moved or unindexed vault and nothing else. `oms contract doctor` also names the unexpected `.oms` entries for the person at the CLI.
22
+ A broken or missing seal is recovered by the user running `oms setup` at a terminal; recovery is never done through the `setup` skill. The only automatic seal repair is `oms contract doctor --fix`, which re-indexes a moved or unindexed vault and nothing else. `oms contract doctor` also names the unexpected `.oms` entries for the person at the CLI.
23
23
 
24
24
  Index repairs run only when explicitly requested and do not edit notes. There is no default-value backfill: OMS never rewrites a note.
25
25
 
26
- The surface is five MCP tools and six skills.
26
+ The surface is five MCP tools and seven skills.
@@ -37,4 +37,4 @@ A typed axis fails loudly on an undeclared field. Remove the typed axis rather t
37
37
 
38
38
  Search never creates `.oms` and never mutates templates, notes, the contract, or indexes. A search call does not grant edit rights.
39
39
 
40
- The surface is five MCP tools and six skills.
40
+ The surface is five MCP tools and seven skills.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: setup
3
+ description: Seal the vault contract by asking the owner each setup question, then running `oms setup --answers`. Seals a first or stricter contract only.
4
+ ---
5
+
6
+ # setup
7
+
8
+ Seal the vault contract for the owner without a terminal interview. This is a host recipe skill: it has no MCP tool. It drives two CLI steps, `oms setup --questions` and `oms setup --answers <file>`, and the owner answers every question. You never invent, guess, or fill in an answer.
9
+
10
+ ```text
11
+ /setup [--reask] [--vault <path>]
12
+ ```
13
+
14
+ Always pass the vault with `--vault <path>`. A vault inferred from the current directory is refused.
15
+
16
+ ## Flow
17
+
18
+ 1. Run `oms setup --questions --vault <path>` (add `--reask` only when the owner wants to be asked again about items declined at an earlier seal). It prints JSON: `status` is `questions`, `questions` lists `{id, prompt, kind, choices?, default?}`, and `notes` holds interview lines worth showing the owner. It seals nothing.
19
+ 2. Ask the owner each question with AskUserQuestion, one question at a time, in the order printed. Put the recommended option first: the `default` when there is one, otherwise the first of `choices`. A `confirm` question takes yes or no, a `choice` question takes one of `choices`, and a `text` question takes the owner's own words. When the owner skips a question, leave its id out; never answer for them.
20
+ 3. Write the answers as one JSON object from question id to answer (`true`/`false` for confirm, the chosen string for choice, a string or number for text) to a temporary file outside the vault, for example under the system temp directory. Run `oms setup --answers <file> --vault <path>`.
21
+ 4. Read the JSON result and loop:
22
+ - `incomplete`: the answers opened follow-up questions, listed in `questions`. Ask those the same way, merge them into the same file, and run `--answers` again. When only `seal` remains, show the owner the `notes` (the contract preview), ask whether to seal, and set `"seal": true` only on a yes.
23
+ - `sealed`: done. Delete the answers file and run `oms contract doctor --vault <path>` to confirm the seal.
24
+ - `rejected`: the diagnostic names the question id and why (`CONTRACT_ANSWER_INVALID`, `CONTRACT_ANSWER_UNKNOWN`, `CONTRACT_ANSWERS_INVALID`). Ask the owner that question again and rerun. Nothing was sealed.
25
+ - `loosening`: the answers would loosen the sealed contract. `changes` names each field and kind of change, never a value. Nothing was sealed. Tell the owner that only they can loosen a contract, by running `oms setup` themselves in a terminal. Do not retry with other answers to get around it. A `template-tightened` change means the answers make a sealed template stricter; that is refused too, because the judge enforces a template relative to the note's previous content, so a stricter template would stop checking notes that fail it. A `pattern-unsafe` change means a sealed pattern that today's seal screen refuses (for example one over the length limit); only the owner's terminal `oms setup` can replace it, and it asks for just that rule again.
26
+ - `refused`: the seal needs recovery. Tell the owner to run `oms contract doctor`, then `oms setup` themselves in a terminal.
27
+ - `aborted`: the owner declined to seal. Nothing was sealed.
28
+
29
+ ## Rules
30
+
31
+ - The answers file is the only file you write. Keep it outside the vault (an answers file inside the vault is refused) and delete it when the run ends.
32
+ - Never read, list, or edit `~/.oms` or any sealed contract file. The CLI output is the whole interface.
33
+ - The values the owner gives (allowed values, patterns, ranges) are part of the hidden contract. Do not repeat them into notes, messages to others, or memory.
34
+ - `--answers` seals a first contract, or a reseal that only adds or tightens. Removing a folder, property, or template, dropping a requirement, or widening a rule is loosening, and it belongs to the owner's own terminal.
35
+ - The reseal may add new folders, properties, and templates, and tighten folder and property rules. Changing an existing sealed template, even to make it stricter, needs `oms setup` in the owner's terminal: the judge enforces templates relative to the previous content, so a stricter template stops checking notes that fail it. When a template's source changed, answer its questions exactly as before.
36
+ - Adding is allowed but is not neutral: registering a new folder, property, or template widens that closed axis, so notes the sealed contract refused there can be written afterwards. Ask the owner about every addition; never add one they did not answer for.
37
+ - A write denied as `unregistered-folder` or `unknown-property` is not yours to clear. Do not create the folder, add the type to `.obsidian/types.json`, or answer the registration question yourself so that the write passes. Ask the owner, and register the folder or property only when they answer. Nothing but that answer enforces this.
38
+ - Never run `oms setup` or `oms contract setup` without `--questions` or `--answers`. The interactive interview is the owner's, in their own terminal.
39
+ - Never run setup under a pseudo-terminal wrapper such as `script`, `expect`, or `unbuffer`, and never set up a terminal for it. The interactive gate only checks for a TTY, so a wrapper would take the owner's full authority, including loosening.
40
+ - Never move or rename the vault with Bash, and never delete, edit, or re-ID `.oms/settings.json`. Either makes the vault look never sealed, so `--answers` would take a fresh first seal in place of the owner's contract.
41
+
42
+ The surface is five MCP tools and seven skills.
@@ -20,14 +20,15 @@ With `op` absent, `status` returns the combined read-only view:
20
20
  - `generationDigest` and `diagnostics` for the derived state.
21
21
  - The runtime history for this host and vault.
22
22
  - `engineGraph`: graph status.
23
- - `writeTools` and `readTools`: whether writes are gated by a verified target and a readable contract, or disabled and why.
23
+ - `writeTools`: whether writes are gated by a verified target and a readable contract, or disabled and why.
24
+ - `readTools`: the read-only MCP tools (`search`, `link`, `status`). `write` and `doctor` are not listed because they can mutate the vault.
24
25
 
25
26
  Use `status { op: "graph" }` only for graph status. Do not send `graph` when requesting the combined view.
26
27
 
27
- A drifted or missing template is reported, never resealed here. The fix is the user running `oms setup` at a terminal; you never run it. `oms contract status` shows the same posture and template states from the CLI.
28
+ A drifted or missing template is reported, never resealed here. The fix is a reseal: the user running `oms setup` at a terminal, or the `setup` skill when the reseal only adds or tightens. `oms contract status` shows the same posture and template states from the CLI.
28
29
 
29
30
  Status never rebuilds indexes, repairs notes, creates `.oms`, or writes the vault. Do not turn a health report into a claim that a note is finished.
30
31
 
31
32
  Report runtime history separately: events live outside the vault and are scoped to the current host and vault. A missing event means unobserved, never unused. Distinguish actual mutation time from observation time; external drift gives a changed-between interval, not an invented modification timestamp. Surface `LEDGER_APPEND_FAILED` explicitly without claiming a successful vault write failed.
32
33
 
33
- The surface is five MCP tools and six skills.
34
+ The surface is five MCP tools and seven skills.
@@ -31,10 +31,10 @@ The judge answers allow or deny. Allow writes the note atomically and returns `{
31
31
 
32
32
  Placement is explicit: an explicit path, otherwise the folder meaning the user approved, otherwise ask. There is no Inbox fallback.
33
33
 
34
- A vault with no sealed contract accepts any note inside it. A contract that cannot be read denies writes until the user restores it with `oms setup`; you never run it. Paths outside the vault and the vault's control paths are always denied.
34
+ A vault with no sealed contract accepts any note inside it. A contract that cannot be read denies writes until the user restores it with `oms setup` at a terminal; the `setup` skill does not recover a broken seal. Paths outside the vault and the vault's control paths are always denied.
35
35
 
36
36
  ## Host file tools
37
37
 
38
38
  In Claude Code, native writes into the vault go through the same judge in the PreToolUse hook. When the hook cannot reach the judge, it allows the write with one warning and records the failure for `oms contract doctor`. Codex and Hermes declare no write hook, so use MCP `write` for vault notes there.
39
39
 
40
- The surface is five MCP tools and six skills.
40
+ The surface is five MCP tools and seven skills.
package/core/AGENTS.md CHANGED
@@ -7,9 +7,12 @@ Hermes, and others). The vault's meaning belongs to the user.
7
7
 
8
8
  The user states what the vault means once, by running the interactive `oms setup` at
9
9
  a terminal. The interview covers folders, the property pool, and the templates in the
10
- template folder together, and seals the result as the vault contract. Agents never
11
- seal: `oms setup` refuses to run without a terminal or under
12
- `OMS_NON_INTERACTIVE=1`, and there is no MCP operation or skill for it.
10
+ template folder together, and seals the result as the vault contract. The interactive
11
+ interview refuses to run without a terminal or under `OMS_NON_INTERACTIVE=1`. An agent
12
+ seals only through the `setup` skill: `oms setup --questions` prints the questions, the
13
+ agent asks the owner each one, and `oms setup --answers <file>` seals a first or stricter
14
+ contract. A reseal that loosens is refused there and belongs to the terminal. There is no
15
+ MCP operation for setup.
13
16
 
14
17
  - The sealed contract lives outside the vault under `~/.oms/`. That directory is
15
18
  off-limits: do not read, search, or write anything under it.