oh-my-second-brain 0.18.1 → 0.19.0
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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +3 -4
- package/.codex-plugin/plugin.json +2 -2
- package/CHANGELOG-assets.md +12 -0
- package/CHANGELOG-cli.md +22 -0
- package/CHANGELOG-kernel.md +19 -0
- package/CHANGELOG-mcp.md +14 -0
- package/CHANGELOG-vendors.md +9 -0
- package/CHANGELOG.md +14 -0
- package/README.ko.md +235 -54
- package/README.md +235 -54
- package/assets/claude/CLAUDE.md +11 -6
- package/assets/claude/hooks/oms-guard.mjs +6 -6
- package/assets/codex/AGENTS.md +5 -4
- package/assets/codex/rules/oms.md +6 -6
- package/assets/hermes/README.md +10 -5
- package/assets/hermes/SOUL.md +11 -7
- package/assets/hermes-manifest.json +2 -2
- package/assets/readme/hero.svg +23 -0
- package/assets/skills/distill/SKILL.md +1 -1
- package/assets/skills/doctor/SKILL.md +7 -5
- package/assets/skills/interview/SKILL.md +39 -0
- package/assets/skills/search/SKILL.md +5 -2
- package/assets/skills/setup/SKILL.md +18 -11
- package/assets/skills/write/SKILL.md +10 -6
- package/dist/cli/audit.js +2 -2
- package/dist/cli/contract-command.d.ts +9 -0
- package/dist/cli/contract-command.js +117 -41
- package/dist/cli/contract-command.js.map +1 -1
- package/dist/cli/doctor-command.d.ts +7 -0
- package/dist/cli/doctor-command.js +125 -0
- package/dist/cli/doctor-command.js.map +1 -0
- package/dist/cli/engine-session.js +1 -1
- package/dist/cli/engine-session.js.map +1 -1
- package/dist/cli/graph-command.js +5 -12
- package/dist/cli/graph-command.js.map +1 -1
- package/dist/cli/host-commands.d.ts +1 -1
- package/dist/cli/host-commands.js +7 -7
- package/dist/cli/host-commands.js.map +1 -1
- package/dist/cli/index-command.js +9 -9
- package/dist/cli/index-command.js.map +1 -1
- package/dist/cli/interview-command.d.ts +10 -0
- package/dist/cli/interview-command.js +72 -0
- package/dist/cli/interview-command.js.map +1 -0
- package/dist/cli/model-command.js +1 -1
- package/dist/cli/model-command.js.map +1 -1
- package/dist/cli/note-command.js +1 -3
- package/dist/cli/note-command.js.map +1 -1
- package/dist/cli/oms.d.ts +0 -3
- package/dist/cli/oms.js +61 -95
- package/dist/cli/oms.js.map +1 -1
- package/dist/cli/package-command.js +7 -7
- package/dist/cli/package-command.js.map +1 -1
- package/dist/cli/removed-families.d.ts +6 -0
- package/dist/cli/removed-families.js +39 -0
- package/dist/cli/removed-families.js.map +1 -0
- package/dist/cli/search-usage.js +18 -9
- package/dist/cli/search-usage.js.map +1 -1
- package/dist/cli/search.d.ts +9 -1
- package/dist/cli/search.js +92 -50
- package/dist/cli/search.js.map +1 -1
- package/dist/cli/setup-command.d.ts +1 -1
- package/dist/cli/setup-command.js +46 -13
- package/dist/cli/setup-command.js.map +1 -1
- package/dist/cli/status-command.d.ts +5 -0
- package/dist/cli/status-command.js +63 -59
- package/dist/cli/status-command.js.map +1 -1
- package/dist/cli/usage.js +29 -35
- package/dist/cli/usage.js.map +1 -1
- package/dist/cli/write-command.d.ts +14 -0
- package/dist/cli/write-command.js +105 -0
- package/dist/cli/write-command.js.map +1 -0
- package/dist/kernel/contract/interpretation-fixture.d.ts +5 -0
- package/dist/kernel/contract/interpretation-fixture.js +97 -0
- package/dist/kernel/contract/interpretation-fixture.js.map +1 -0
- package/dist/kernel/contract/interpretation.d.ts +102 -0
- package/dist/kernel/contract/interpretation.js +211 -0
- package/dist/kernel/contract/interpretation.js.map +1 -0
- package/dist/kernel/contract/interview-log.d.ts +50 -0
- package/dist/kernel/contract/interview-log.js +194 -0
- package/dist/kernel/contract/interview-log.js.map +1 -0
- package/dist/kernel/contract/interview-resume.d.ts +65 -0
- package/dist/kernel/contract/interview-resume.js +163 -0
- package/dist/kernel/contract/interview-resume.js.map +1 -0
- package/dist/kernel/contract/interview.d.ts +71 -1
- package/dist/kernel/contract/interview.js +163 -61
- package/dist/kernel/contract/interview.js.map +1 -1
- package/dist/kernel/contract/scripted-interview.d.ts +28 -1
- package/dist/kernel/contract/scripted-interview.js +71 -4
- package/dist/kernel/contract/scripted-interview.js.map +1 -1
- package/dist/kernel/contract/state-dir.d.ts +50 -0
- package/dist/kernel/contract/state-dir.js +234 -0
- package/dist/kernel/contract/state-dir.js.map +1 -0
- package/dist/kernel/contract/status.d.ts +12 -1
- package/dist/kernel/contract/status.js +19 -7
- package/dist/kernel/contract/status.js.map +1 -1
- package/dist/kernel/contract/store.d.ts +7 -0
- package/dist/kernel/contract/store.js +13 -4
- package/dist/kernel/contract/store.js.map +1 -1
- package/dist/kernel/contract/types.d.ts +3 -1
- package/dist/kernel/contract/types.js +23 -23
- package/dist/kernel/contract/types.js.map +1 -1
- package/dist/kernel/conventions/note-exclude.js +2 -2
- package/dist/kernel/conventions/report.js +1 -1
- package/dist/kernel/conventions/report.js.map +1 -1
- package/dist/kernel/doctor/service.js +12 -2
- package/dist/kernel/doctor/service.js.map +1 -1
- package/dist/kernel/engine/embed/config.js +3 -3
- package/dist/kernel/engine/embed/config.js.map +1 -1
- package/dist/kernel/engine/index-update.d.ts +41 -0
- package/dist/kernel/engine/index-update.js +133 -0
- package/dist/kernel/engine/index-update.js.map +1 -0
- package/dist/kernel/engine/retrieval/folder-context.js +1 -1
- package/dist/kernel/engine/retrieval/template-source.js +3 -3
- package/dist/kernel/harness/surface-registry.d.ts +2 -0
- package/dist/kernel/harness/surface-registry.js +11 -19
- package/dist/kernel/harness/surface-registry.js.map +1 -1
- package/dist/kernel/install/asset-health.js +1 -1
- package/dist/kernel/install/asset-health.js.map +1 -1
- package/dist/kernel/link/convention-note.js +3 -3
- package/dist/kernel/link/convention-note.js.map +1 -1
- package/dist/kernel/search/read-exact.d.ts +43 -0
- package/dist/kernel/search/read-exact.js +135 -0
- package/dist/kernel/search/read-exact.js.map +1 -0
- package/dist/kernel/text/nfc.d.ts +11 -0
- package/dist/kernel/text/nfc.js +16 -0
- package/dist/kernel/text/nfc.js.map +1 -0
- package/dist/kernel/update/update.js +8 -8
- package/dist/kernel/update/update.js.map +1 -1
- package/dist/kernel/write/conform.d.ts +23 -0
- package/dist/kernel/write/conform.js +155 -0
- package/dist/kernel/write/conform.js.map +1 -0
- package/dist/kernel/write/frame.d.ts +40 -0
- package/dist/kernel/write/frame.js +67 -0
- package/dist/kernel/write/frame.js.map +1 -0
- package/dist/{mcp → kernel/write}/note-write.js +1 -1
- package/dist/kernel/write/note-write.js.map +1 -0
- package/dist/kernel/write/payload.d.ts +40 -0
- package/dist/kernel/write/payload.js +39 -0
- package/dist/kernel/write/payload.js.map +1 -0
- package/dist/kernel/write/pipeline.d.ts +59 -0
- package/dist/kernel/write/pipeline.js +84 -0
- package/dist/kernel/write/pipeline.js.map +1 -0
- package/dist/kernel/write/receipt.d.ts +42 -0
- package/dist/kernel/write/receipt.js +21 -0
- package/dist/kernel/write/receipt.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +68 -443
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/doctor.d.ts +4 -0
- package/dist/mcp/tools/doctor.js +71 -0
- package/dist/mcp/tools/doctor.js.map +1 -0
- package/dist/mcp/tools/interview.d.ts +27 -0
- package/dist/mcp/tools/interview.js +261 -0
- package/dist/mcp/tools/interview.js.map +1 -0
- package/dist/mcp/tools/link.d.ts +4 -0
- package/dist/mcp/tools/link.js +24 -0
- package/dist/mcp/tools/link.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +11 -0
- package/dist/mcp/tools/search.js +254 -0
- package/dist/mcp/tools/search.js.map +1 -0
- package/dist/mcp/tools/shared.d.ts +28 -0
- package/dist/mcp/tools/shared.js +34 -0
- package/dist/mcp/tools/shared.js.map +1 -0
- package/dist/mcp/tools/status.d.ts +9 -0
- package/dist/mcp/tools/status.js +39 -0
- package/dist/mcp/tools/status.js.map +1 -0
- package/dist/mcp/tools/write.d.ts +8 -0
- package/dist/mcp/tools/write.js +40 -0
- package/dist/mcp/tools/write.js.map +1 -0
- package/dist/mcp/update-notice.js +1 -1
- package/dist/mcp/update-notice.js.map +1 -1
- package/dist/vendors/codex/codex.js +2 -2
- package/dist/vendors/codex/codex.js.map +1 -1
- package/dist/vendors/hermes/hermes.d.ts +7 -0
- package/dist/vendors/hermes/hermes.js +121 -9
- package/dist/vendors/hermes/hermes.js.map +1 -1
- package/docs/adapters.md +5 -5
- package/docs/architecture.md +9 -9
- package/docs/cli-map.md +56 -46
- package/docs/conventions.md +7 -7
- package/docs/install.md +27 -28
- package/docs/migration-0.19.md +48 -0
- package/docs/verified-target.md +5 -5
- package/package.json +4 -2
- package/skills/distill/SKILL.md +1 -1
- package/skills/doctor/SKILL.md +7 -5
- package/skills/interview/SKILL.md +39 -0
- package/skills/search/SKILL.md +5 -2
- package/skills/setup/SKILL.md +18 -11
- package/skills/write/SKILL.md +10 -6
- package/assets/skills/link/SKILL.md +0 -30
- package/assets/skills/status/SKILL.md +0 -34
- package/dist/kernel/contract/extract.d.ts +0 -37
- package/dist/kernel/contract/extract.js +0 -101
- package/dist/kernel/contract/extract.js.map +0 -1
- package/dist/mcp/note-write.js.map +0 -1
- package/skills/link/SKILL.md +0 -30
- package/skills/status/SKILL.md +0 -34
- /package/dist/{mcp → kernel/write}/note-write.d.ts +0 -0
|
@@ -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.
|
|
13
|
+
"version": "0.19.0",
|
|
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.
|
|
40
|
+
"version": "0.19.0"
|
|
41
41
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oms",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Oh My Second Brain convention layer for Obsidian vaults —
|
|
3
|
+
"version": "0.19.0",
|
|
4
|
+
"description": "Oh My Second Brain convention layer for Obsidian vaults — six shared skills and four MCP tools under a user-owned contract.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "gobeumsu"
|
|
7
7
|
},
|
|
@@ -17,10 +17,9 @@
|
|
|
17
17
|
"skills": [
|
|
18
18
|
"./assets/skills/distill/",
|
|
19
19
|
"./assets/skills/doctor/",
|
|
20
|
-
"./assets/skills/
|
|
20
|
+
"./assets/skills/interview/",
|
|
21
21
|
"./assets/skills/search/",
|
|
22
22
|
"./assets/skills/setup/",
|
|
23
|
-
"./assets/skills/status/",
|
|
24
23
|
"./assets/skills/write/"
|
|
25
24
|
]
|
|
26
25
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
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
|
|
5
|
+
"_note": "oms setup host install writes Codex MCP config and provenance, installs ~/.codex/rules/oms.md, and installs the six shared skills under ~/.codex/skills/oms-*.",
|
|
6
6
|
"skills": "./assets/skills/",
|
|
7
7
|
"mcpServers": "./.mcp.codex.json"
|
|
8
8
|
}
|
package/CHANGELOG-assets.md
CHANGED
|
@@ -4,6 +4,18 @@ Skills, agents, templates, and host guidance changes belong here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.19.0] - 2026-09-28
|
|
8
|
+
|
|
9
|
+
- **Breaking: six shared skills.** `write`, `search`, `interview`, `distill`, `setup`, and `doctor`. The `link` skill is folded into `search` (suggest) and `doctor` (check), the `status` skill into `doctor` `op: "status"`, and the new `interview` skill reads the pending questions without sealing. Every skill and host guidance file uses the 0.19 command spellings.
|
|
10
|
+
|
|
11
|
+
- Refresh the English and Korean README with an original, self-contained constellation SVG inspired by beomsukoh.com, compact feature cards, a four-step quickstart, and navigable reference sections. Keep contract and host enforcement boundaries explicit, and align the setup skill count with the current seven-skill registry. Runtime behavior is unchanged.
|
|
12
|
+
|
|
13
|
+
- **The `setup` skill reads each template itself before asking anything.** It now submits `{source, observedHash, fields, headings}` per template with `--interpretations`, handles the `interpretation-required` and `interpretation-rejected` results, and is told plainly that a field left out of an interpretation is a question the owner is never asked, and that `observedHash` must come from reading the bytes rather than from copying the hash OMS printed.
|
|
14
|
+
|
|
15
|
+
## [0.18.3] - 2026-09-26
|
|
16
|
+
|
|
17
|
+
## [0.18.2] - 2026-09-26
|
|
18
|
+
|
|
7
19
|
## [0.18.1] - 2026-09-26
|
|
8
20
|
|
|
9
21
|
- 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.
|
package/CHANGELOG-cli.md
CHANGED
|
@@ -4,6 +4,28 @@ Changes to the `oms` command surface belong here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.19.0] - 2026-09-28
|
|
8
|
+
|
|
9
|
+
- **`oms write` takes `--if-match sha256:<rev>` and `--check`.** Overwriting an existing note without `--if-match` exits 1 with `WRITE_IF_MATCH_REQUIRED` and leaves the file unchanged; a stale revision reports the retryable `WRITE_TARGET_CHANGED`, and `--if-match` for a note that does not exist reports the retryable `WRITE_TARGET_ABSENT`. `--check` prints the frame, the note's current revision and any violations and writes nothing, not even an index row. Each flag may be given once, and `--if-match` requires a value. The receipt is the one MCP `write` returns.
|
|
10
|
+
|
|
11
|
+
- **`oms interview` continues an interrupted interview, and `--restart` starts over.** Every answer is logged beside the contract store, so closing the terminal mid-interview no longer loses the answers already given: the next `oms interview` replays them, says how many it continued with, asks only what is left, and reports any logged answer it dropped because its question changed. `--restart` logs the earlier run as abandoned and asks everything again. It still refuses without a TTY or under `OMS_NON_INTERACTIVE=1`, and a refused run logs nothing. A vault that was never sealed gets no `.oms/settings.json` until the seal; its answers are logged under a pending key outside the vault. `--vault --restart` is refused as a missing `--vault` value rather than read as a restart. `oms doctor contract` reports corrupt interview log lines by line number under `interviewLog`, exits 1, and repairs nothing. An unsafe entry in the state directory is reported as `STATE_DIR_UNSAFE` without echoing its path.
|
|
12
|
+
|
|
13
|
+
- **Breaking: the `oms` command surface is seven families.** `search`, `interview`, `write`, `setup`, `doctor`, `serve`, and the hidden `hook` replace the fourteen 0.18 families. A removed family (`note`, `link`, `status`, `contract`, `index`, `graph`, `host`, `model`, `package`, `bridge`) is not an alias: it exits 1, runs nothing, and prints its 0.19 spelling, for example ``[oms] Command `index` was removed in 0.19. Use `oms doctor sync-embeddings --mode sync|embed|repair`, `oms doctor cleanup`, or `oms doctor status`.`` `oms search <text>` takes `--mode`, `--context`, `--path`, and `--link`; `oms doctor` owns `status` (read-only), `contract`, `audit`, `link-check`, `sync-embeddings --mode sync|embed|repair`, `cleanup`, and `build-graph`; `oms setup` keeps the interview and gains the `extract`, `status`, `host`, `model`, `package`, and `bridge` leaves. `docs/migration-0.19.md` maps every 0.18 spelling, and `test/architecture/migration-table.test.ts` dispatches each row against the built CLI.
|
|
14
|
+
- **`oms doctor status --view status|collections|contexts` reaches the search-index views.** The 0.18 `oms index status` views were unreachable after the family was removed. `oms doctor status` now routes to them when `--view`, `--index` or `--collection` is given, stays read-only, and reports `No engine store` instead of creating one; an unknown view exits 1 with the usage line. Without those flags it still prints the vault health report. The dead `graph status` verb is gone: graph health is the `graph` section of `oms doctor status`.
|
|
15
|
+
- **`oms search --link` honours the resolved arguments.** The note path and `--json` are read from the resolved argv, so `oms search --link <note>` behaves the same wherever `--vault` appears.
|
|
16
|
+
- **`oms write <path>` writes a note from stdin through the same judge as MCP `write`.** It runs the same write pipeline, so a `cwd`-inferred target is refused, a violation exits 1 with `{field, kind}` violations and one guidance command and leaves the file untouched, and an allowed write prints the same receipt as the MCP tool.
|
|
17
|
+
- **`oms interview` runs the interactive interview.** Like `oms setup`, it refuses without a TTY or under `OMS_NON_INTERACTIVE=1`.
|
|
18
|
+
|
|
19
|
+
- **`oms search --path <rel>` reads one note exactly, without opening the index or loading a model.** It is the normalization-insensitive answer to the `oms note get` gap: an NFC request finds an NFD-named note on macOS and Linux alike. The output is the document shape `{available, documents: [{target, path, content, revision}]}`; a missing, ambiguous or escaping path prints `available: false` with a reason and exits 1. `--path` must come first and is mutually exclusive with `query`, `context`, `--mode` and every other search argument; a `--path` later in the arguments is refused. `oms search query` now accepts a `--` terminator, after which every token is query text, so `oms search query -- "--path"` searches for the literal text.
|
|
20
|
+
|
|
21
|
+
- **Every `oms` command starts faster, because the entrypoint loads only the command that runs.** `oms` used to import every command module, the MCP and HTTP servers, and the search engine with its native SQLite modules before it dispatched, so even `oms --version` paid about 400 ms. Each command family is now imported when it is dispatched, and `search` loads the engine only for `query`, `context` and `index`. `oms search --path` loads 12 modules and no native dependency; on the measurement machine its p50 fell to about 88 ms, `oms --version` fell from about 410 ms to 90 ms, and `note get` and `search query` fell by roughly 300-400 ms and 100-200 ms. Output and exit codes are unchanged. See `docs/measurements/latency-search-path.md`.
|
|
22
|
+
|
|
23
|
+
- **`oms setup` takes the template interpretations an agent read.** A vault with templates now ends `interpretation-required`, listing every template source with the `sourceHash` OMS computed, until `--interpretations <file|->` supplies what each one declares; the file stays outside the vault like the answers file. `interpretation-rejected` reports the templates whose interpretation the owner did not confirm, and it is not a refusal — a corrected interpretation may be submitted. `oms contract extract --template <path>` no longer prints fields and headings, since OMS does not parse template text; it reports the source and the hash an interpretation must match.
|
|
24
|
+
|
|
25
|
+
## [0.18.3] - 2026-09-26
|
|
26
|
+
|
|
27
|
+
## [0.18.2] - 2026-09-26
|
|
28
|
+
|
|
7
29
|
## [0.18.1] - 2026-09-26
|
|
8
30
|
|
|
9
31
|
- **`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:`.
|
package/CHANGELOG-kernel.md
CHANGED
|
@@ -4,6 +4,25 @@ Domain logic changes belong here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.19.0] - 2026-09-28
|
|
8
|
+
|
|
9
|
+
- **One write pipeline frames, conforms, judges, writes and indexes a note.** `runWritePipeline` in `src/kernel/write/pipeline.ts` replaces `verified-write`: it admits and resolves the target, builds the frame the note is judged in (`frame.ts`: sealed folder meaning, properties, the chosen template and its defaults), applies only mechanical fixes (`conform.ts`: `{{title}}`, `{{date}}` and `{{time}}` variables, date and datetime defaults on a new note, and the chosen template's missing headings), then runs the unchanged judge. Conform adds only that mechanical skeleton and those defaults: it never changes a value and never supplies a property the contract or a template requires (a date default is skipped for any name a template lists in `requiredProperties`, every template's when none is chosen), so a missing required property is still refused. The heading skeleton does, by design, satisfy a template's required headings, and inserted lines keep the note's CRLF or LF line endings. Overwriting an existing note needs `ifMatch`, the `sha256:` revision of its current bytes; without it the outcome is `if-match-required`, and a revision that no longer matches, a note that vanished, or an `ifMatch` sent for a note that does not exist (`absent`, retried without `ifMatch` to create it) is a retryable `retry`. `check` stops after the judge and reports the frame, the revision and the violations without touching disk. A written note returns the receipt built by `receipt.ts`, `{ok, path, revision, contractRevision, index: {keyword, vector}, conformed, missingDefaults}`, and `writePayload` in `payload.ts` shapes every outcome for both surfaces. `src/kernel/engine/index-update.ts` replaces the note's keyword rows in an existing engine store in the same call and queues its vectors in `engine_dirty`; it never creates a store, and doctor `sync-embeddings` drains the queue, reporting `queue: {drained, pending}`.
|
|
10
|
+
- **`TemplateContract.meaning` records what a template is for, and the seal manifest is version 2.** The field is optional; a version 1 manifest still reads, so an existing seal needs no reseal.
|
|
11
|
+
|
|
12
|
+
- **The interview keeps an append-only log beside the contract store, so an interrupted interview continues where it stopped.** `src/kernel/contract/state-dir.ts` owns `<root>/.<id>.state/{interview,evolution,generations}`: it sits next to the `<id>` link, never inside a `.<id>.<seq>` generation, and matches none of the names a seal collects, so a seal neither lists nor removes it and losing the link leaves the log in place. Every component is lstat-checked before and after creation (not a symlink, a directory owned by this user, not group- or other-writable), directories are created 0700 by chmod through a handle opened with `O_DIRECTORY | O_NOFOLLOW`, so a directory swapped for a symlink is refused rather than having its target's mode changed, and a file is opened with `O_NOFOLLOW | O_NONBLOCK` and checked through its handle to be a regular 0600 file; a symlink, FIFO, socket or foreign-owned entry is refused with `STATE_DIR_UNSAFE` and left exactly as found, without blocking; the message names the fix (`chmod go-w <path>` for a shared-writable entry, `chown` or removal for one owned by another user). Two appends that create the directory at the same moment no longer fail with `EEXIST`: the one that loses the race checks the directory the other created. `interview-log.ts` appends `asked`, `answered`, `proposed`, `sealed` and `abandoned` events as JSON lines. Appends are serialized within a process only, not across processes: `seq` is one more than the highest in the file, so two processes appending at once may write the same `seq`, and readers order events by line, not by `seq`. A truncated or malformed line is skipped and kept, and `contractDoctor` reports it read-only as `interviewLog: {corrupt, pendingCorrupt, unreadable}` with line numbers. Before the first seal a vault has no id, and the interview writes nothing into it: its log lives under a pending key derived from the vault's real path, `.pending-<sha256>.state`, and moves into `.<id>.state` when the seal mints the id, keeping any events already there. `interview-resume.ts` replays the answers logged since the last seal or restart, but only while the question still reads the same (its digest covers the prompt, options and default), and reports the rest as drift so they are asked again. An interrupted run that is resumed seals byte-for-byte the contract an uninterrupted run seals. `runInterview` takes a `record` hook, records each question as the terminal asks it (the MCP tool, which lists questions, does not) and the proposal digest before the seal question. After the seal it persists the template folder to `.oms/settings.json` first and then records `sealed` best-effort: a failed record leaves the seal in place and returns the warning `INTERVIEW_LOG_UNRECORDED`.
|
|
13
|
+
|
|
14
|
+
- **Deny guidance and the surface registry use the 0.19 spellings.** `GUIDANCE` now names `oms doctor contract`, `oms doctor contract --fix`, `oms doctor status`, `oms setup host sync`, and `oms setup`. The harness registry lists six skills, four MCP tools, and seven CLI families with `hook` hidden. `writePayload` in `src/kernel/write/payload.ts` builds the one payload shape that MCP `write` and `oms write` both print, so the two surfaces cannot drift.
|
|
15
|
+
|
|
16
|
+
- **`readExact` reads one note by its vault-relative path without the engine.** `src/kernel/search/read-exact.ts` matches each path segment against the directory listing (exact spelling, then NFC, then a single NFC-equal entry), so a note saved with an NFD Hangul name is found from its NFC spelling on every filesystem, not only where APFS happens to fold the two. It refuses `..`, absolute paths, a path ending in a separator, and symlinks that resolve outside the vault, while names that merely begin with two dots such as `..notes/x.md` read normally. Each directory is resolved and checked against the vault before it is listed, so a symlink out of the vault reports an escape whether or not the name behind it exists. The note is opened once, without following a final symlink and without blocking, and that one handle is checked to be a regular file and read, so a FIFO is refused as not a file instead of hanging. It names a missing note plainly, returns the on-disk spelling as a POSIX path and a `sha256:` revision of the bytes, and imports nothing from the engine or a native backend; `test/architecture/read-exact-isolation.test.ts` walks its import graph to keep it that way. `src/kernel/text/nfc.ts` provides the `toNfc` and `nfcEquals` helpers it uses.
|
|
17
|
+
|
|
18
|
+
- **A seal refuses when the template sources moved under the interview, and folder scope is injective.** The seal re-enumerates the template sources under the seal lock, before anything is written, and compares them with the snapshot the questions were built from; an added, removed or changed source aborts the seal with nothing sealed, instead of sealing stale bytes and reporting drift afterwards. A scoped template name now escapes each path component, so `a/b/meeting.md` and `a__b/meeting.md` no longer claim the same name and neither becomes unsealable; `rekeySealedTemplates` uses the same encoding and is idempotent. The condition-4 gate that keeps the write-checking judge away from the interpretation modules walks the TypeScript AST instead of one import regex, so a side-effect import, a re-export barrel and a literal dynamic `import()` are all followed.
|
|
19
|
+
|
|
20
|
+
- **OMS no longer reads template text; an agent's interpretation is the input.** The deterministic pre-analysis is gone, along with the in-band sentinel token it substituted for each template variable: a template can be Templater JavaScript, can put a variable where YAML expects a key, and can carry no frontmatter at all, so no mechanical reading of it was trustworthy. The interview now enumerates the template sources, computes each one's digest, and takes a submitted interpretation of each; a submission that names an unknown source, omits one, or carries an `observedHash` that is not the source's current digest is refused, and the digest the contract stores is always the one OMS computed. Template identity now carries the source's folder scope, so two templates of the same file name in different folders no longer collide, and a contract sealed under bare file names is rekeyed by source path in the same change rather than reading as removed. The first seal asks the owner to confirm each interpretation before any question is built from it, because an interpretation that leaves a field out is a question never asked; a declined interpretation seals nothing and can be resubmitted. Interpretation stays a seal-time cost: the write-checking judge does not reach it.
|
|
21
|
+
|
|
22
|
+
## [0.18.3] - 2026-09-26
|
|
23
|
+
|
|
24
|
+
## [0.18.2] - 2026-09-26
|
|
25
|
+
|
|
7
26
|
## [0.18.1] - 2026-09-26
|
|
8
27
|
|
|
9
28
|
- **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`.
|
package/CHANGELOG-mcp.md
CHANGED
|
@@ -4,6 +4,20 @@ MCP server tools and resources belong here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.19.0] - 2026-09-28
|
|
8
|
+
|
|
9
|
+
- **Breaking: `write` refuses to overwrite an existing note without `ifMatch`.** The input is `{path, content, template?, ifMatch?, check?}`. Replacing a note needs `ifMatch`, the `sha256:` revision from the previous receipt or a `check`; without it the call returns `WRITE_IF_MATCH_REQUIRED` and the file is unchanged, and a stale revision returns the retryable `WRITE_TARGET_CHANGED` (or `WRITE_TARGET_VANISHED`); an `ifMatch` for a note that does not exist returns the retryable `WRITE_TARGET_ABSENT`, and retrying without `ifMatch` creates it. `check: true` judges the note and returns `status: "checked"` with the frame, the current revision and any violations, writing nothing. A written note now returns the receipt `{ok, path, revision, contractRevision, index: {keyword, vector}, conformed, missingDefaults}` instead of `{ok, path, missingDefaults}`; when the vault has an engine store the note is keyword-searchable in the next call.
|
|
10
|
+
|
|
11
|
+
- **The `interview` tool runs the interview over several calls and can seal a first or non-loosening contract.** `op: "questions"` (the default) lists what is still unanswered and writes nothing. `op: "answer"` logs answers keyed by question id and, once nothing is left, returns `status: "proposed"` with the proposal digest and its preview. `op: "confirm"` records the owner's yes to that exact digest, and `op: "seal"` seals only when the log holds a confirmation of the latest proposal and the interview, replayed from the log, still proposes it; a confirmation of an older proposal is refused. Nothing is written into a vault that was never sealed before its seal: answers are logged under a pending key outside the vault. Retrying `seal` after the contract was sealed returns `sealed` without a new generation and appends the missing `sealed` event, and a seal whose log record failed still reports `sealed` with a `warnings` entry. `doctor` `op: "validate"` includes `interviewLog`, the corrupt interview log lines by line number, read-only. `answer`, `confirm` and `seal` require a verified target vault, and a vault inferred from the working directory may only list questions. Refusals are returned as data, `{ok: false, status: "rejected", rejection}`, not as tool errors. The tool never reclaims a stale seal lock: `CONTRACT_SEAL_LOCK_STALE` is returned as `INTERVIEW_SEAL_LOCK_STALE` with the terminal command that can reclaim it, while `CONTRACT_SEAL_BUSY` passes through as retryable. Loosening a sealed contract still belongs to the owner's terminal.
|
|
12
|
+
|
|
13
|
+
- **Breaking: the MCP server exposes four tools: `write`, `search`, `interview`, and `doctor`.** The `link` tool is removed; suggest links with `search` `op: "link"` and check them with `doctor` `op: "link-check"`. The `status` tool is removed; `doctor` `op: "status"` reports the same health read-only and creates no engine store. The new `interview` tool lists the questions the owner would be asked now, with the seal state, and seals nothing: answers still go through `oms setup --answers`, and loosening stays with the owner's terminal. Annotations are per tool, so `readTools` is now `[search]`. Hosts display `oms_write`, `oms_search`, `oms_interview`, and `oms_doctor`.
|
|
14
|
+
|
|
15
|
+
- **`search` accepts `{path}` with no `op` for an engine-free exact read of one note.** The call returns the same document shape as `oms search --path`, never opens the engine store or a model, and is refused when combined with `op` or any other argument. A path the caller got wrong returns `available: false`, while an I/O failure such as a missing vault root returns the same `Oh My Second Brain MCP error` result as every other tool; the tool schema advertises it as its own `oneOf` branch, so `op` is no longer top-level required for `search`.
|
|
16
|
+
|
|
17
|
+
## [0.18.3] - 2026-09-26
|
|
18
|
+
|
|
19
|
+
## [0.18.2] - 2026-09-26
|
|
20
|
+
|
|
7
21
|
## [0.18.1] - 2026-09-26
|
|
8
22
|
|
|
9
23
|
- `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`.
|
package/CHANGELOG-vendors.md
CHANGED
|
@@ -4,6 +4,15 @@ Per-host adapter and installer changes belong here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.19.0] - 2026-09-28
|
|
8
|
+
|
|
9
|
+
- **An ambiguous Codex managed block names the 0.19 commands.** The error now tells the user to rerun `oms setup host install` or `oms setup host remove` after the managed blocks are removed by hand.
|
|
10
|
+
- **Host guidance and the Claude guard name the 0.19 commands.** Deny reasons and the guard's transport-failure warning now point at `oms doctor contract`, `oms doctor status`, and `oms setup host sync`, and a new test spawns the real guard to prove every command it prints dispatches in the built CLI. The Claude, Codex, and Hermes registrations install the six shared skills (`interview` replaces `link` and `status`); run `oms setup host sync` after upgrading.
|
|
11
|
+
|
|
12
|
+
## [0.18.3] - 2026-09-26
|
|
13
|
+
|
|
14
|
+
## [0.18.2] - 2026-09-26
|
|
15
|
+
|
|
7
16
|
## [0.18.1] - 2026-09-26
|
|
8
17
|
|
|
9
18
|
## [0.18.0] - 2026-09-25
|
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,20 @@ This aggregate changelog contains changes that span multiple layers.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.19.0] - 2026-09-28
|
|
14
|
+
|
|
15
|
+
- **Upgrading from 0.18: run `oms setup host sync` first.** Installed host assets (the Claude guard hook, skills, and MCP wiring) still point at the 0.18 surface until they are re-synced. Then read [Migrating to 0.19](./docs/migration-0.19.md) for the full command map.
|
|
16
|
+
- **Breaking: OMS is organised around search, interview, and write.** The fourteen CLI families collapse into `search`, `interview`, `write`, `setup`, `doctor`, `serve`, and the hidden `hook`, and the five MCP tools become `write`, `search`, `interview`, and `doctor`. A removed command exits 1 and names its replacement rather than aliasing it. The judge, the sealed contract, and the verified-target rules are unchanged; `write` now runs one pipeline that conforms template variables and headings mechanically, judges, writes atomically with an optional `ifMatch` revision, and updates the keyword index in the same call while queueing vectors for `oms doctor sync-embeddings`. See the layer changelogs for details.
|
|
17
|
+
- **The contract stops guessing what a template declares.** OMS used to parse template text to decide which questions the seal interview asks, substituting an in-band sentinel token for each Templater variable so the rest would still parse as YAML. Real templates broke that: four of this vault's templates put a variable where YAML expects a key, and a Templater JavaScript template with no frontmatter passed silently as declaring nothing while it really declares ten properties and four headings. Reading a template is now the agent's job and deriving the contract stays the machine's: the agent submits an interpretation, OMS verifies it against the sources it enumerated and the digests it computed itself, the owner confirms the interpretation before it decides a single question, and every sealed value still comes only from the owner's answers.
|
|
18
|
+
|
|
19
|
+
## [0.18.3] - 2026-09-26
|
|
20
|
+
|
|
21
|
+
- **Ships the Hermes skill namespace from 0.18.2.** The 0.18.2 tag failed its release check on a flaky test and was never published to npm, so 0.18.3 is the first published release where Hermes installs the OMS skills as `oms-*` with `SKILL_CAPABILITY_GUIDE.md` (see 0.18.2 below). The read-only engine store tests now use a private temporary directory, so snapshot directories from parallel test files no longer break the check.
|
|
22
|
+
|
|
23
|
+
## [0.18.2] - 2026-09-26
|
|
24
|
+
|
|
25
|
+
- **Hermes can call every OMS skill by name again.** Hermes resolves a skill by its bare name across every installed bundle and refuses a name two bundles share, so OMS's `setup` and `status` were unreachable next to another bundle's skills of the same name. The Hermes installer now copies the seven shared skills as `oms-write`, `oms-search`, `oms-link`, `oms-distill`, `oms-setup`, `oms-status`, and `oms-doctor`, renaming both the directory and the frontmatter `name`, and writes `SKILL_CAPABILITY_GUIDE.md` beside them to map each skill to its MCP tool or mark it as an agent recipe. The shared sources and the Claude and Codex installs keep the unprefixed names. An existing Hermes install, including the old unprefixed layout, is replaced in place and its old skill directories are removed.
|
|
26
|
+
|
|
13
27
|
## [0.18.1] - 2026-09-26
|
|
14
28
|
|
|
15
29
|
## [0.18.0] - 2026-09-25
|
package/README.ko.md
CHANGED
|
@@ -1,90 +1,271 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./assets/readme/hero.svg" alt="Oh My Second Brain. 흩어진 생각이 연결되는 별자리." width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Oh My Second Brain</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>흩어진 지식이, 다시 하나의 별자리로.</strong><br />
|
|
9
|
+
Obsidian, Markdown, AI 에이전트를 잇는 사용자 소유의 지식·컨벤션 레이어.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/oh-my-second-brain"><img src="https://img.shields.io/npm/v/oh-my-second-brain?style=flat-square&color=8b9daa&label=npm" alt="npm 버전" /></a>
|
|
14
|
+
<a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-%E2%89%A520-80b89b?style=flat-square" alt="Node.js 20 이상" /></a>
|
|
15
|
+
<a href="#mcp-도구와-에이전트-연결"><img src="https://img.shields.io/badge/MCP-4_tools-97a8b1?style=flat-square" alt="MCP 도구 4개" /></a>
|
|
16
|
+
<a href="https://github.com/GoBeromsu/oh-my-second-brain/blob/main/package.json"><img src="https://img.shields.io/badge/license-MIT-d7c7a8?style=flat-square" alt="패키지 라이선스 MIT" /></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="#빠른-시작"><strong>빠른 시작</strong></a> ·
|
|
21
|
+
<a href="#동작-방식">동작 방식</a> ·
|
|
22
|
+
<a href="#문서">문서</a> ·
|
|
23
|
+
<a href="https://github.com/GoBeromsu/oh-my-second-brain/releases">릴리스</a> ·
|
|
24
|
+
<a href="./README.md">English</a>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
볼트에는 이미 아이디어, 결정, 배운 것들이 쌓여 있다. **OMS는 에이전트가 그 지식을 되찾고, 내가 정한 규칙 안에서 노트를 쓰도록 돕는다.** 새 노트 형식도, 정해진 폴더 체계도, 특정 호스트로의 지식 이전도 필요 없다.
|
|
30
|
+
|
|
31
|
+
Obsidian은 사령탑으로 남는다. OMS가 꺼져 있어도 노트는 사람이 읽고 고칠 수 있는 Markdown 파일이다. Claude Code, Codex, Hermes를 각 호스트의 통합 기능으로 같은 볼트에 연결할 수 있다.
|
|
32
|
+
|
|
33
|
+
## 왜 OMS인가?
|
|
34
|
+
|
|
35
|
+
<table>
|
|
36
|
+
<tr>
|
|
37
|
+
<td width="50%" valign="top">
|
|
38
|
+
<h3>이미 아는 것을 다시 찾기</h3>
|
|
39
|
+
기존 노트를 lexical 검색으로 찾는다. 필요할 때 vector, HyDE, 질의 확장, reranking을 명시적으로 선택한다.
|
|
40
|
+
</td>
|
|
41
|
+
<td width="50%" valign="top">
|
|
42
|
+
<h3>내 볼트의 언어 그대로</h3>
|
|
43
|
+
폴더, 속성, 템플릿의 의미는 내가 정한다. OMS가 제시하는 체계를 따르는 대신, 내 컨벤션을 기록한다.
|
|
44
|
+
</td>
|
|
45
|
+
</tr>
|
|
46
|
+
<tr>
|
|
47
|
+
<td width="50%" valign="top">
|
|
48
|
+
<h3>에이전트가 공유하는 계약</h3>
|
|
49
|
+
setup으로 볼트 규약을 봉인한다. 지원되는 쓰기 경로는 저장 전에 노트 전체가 그 계약에 맞는지 확인한다.
|
|
50
|
+
</td>
|
|
51
|
+
<td width="50%" valign="top">
|
|
52
|
+
<h3>파일의 소유권은 그대로</h3>
|
|
53
|
+
기존 Markdown 노트와 템플릿을 계속 쓴다. setup은 이 파일들을 다시 쓰지 않으며, 봉인된 계약은 볼트 밖에 둔다.
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
<tr>
|
|
57
|
+
<td width="50%" valign="top">
|
|
58
|
+
<h3>호스트를 넘어 연결하기</h3>
|
|
59
|
+
Claude Code, Codex, Hermes의 네이티브 통합을 사용한다. MCP 도구 4개와 공통 워크플로 스킬 6개를 제공한다.
|
|
60
|
+
</td>
|
|
61
|
+
<td width="50%" valign="top">
|
|
62
|
+
<h3>추측 대신 상태 확인</h3>
|
|
63
|
+
계약 상태, 노트 규약 준수, 색인, wikilink 제안을 확인한다. 검색과 상태 조회는 읽기 전용이다.
|
|
64
|
+
</td>
|
|
65
|
+
</tr>
|
|
66
|
+
</table>
|
|
67
|
+
|
|
68
|
+
## 빠른 시작
|
|
69
|
+
|
|
70
|
+
**Node.js 20 이상과 기존 Obsidian 또는 Markdown 볼트가 필요하다.** `/path/to/vault`를 볼트의 절대 경로로 바꾼다.
|
|
71
|
+
|
|
72
|
+
### 1. 설치
|
|
2
73
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
74
|
+
```bash
|
|
75
|
+
npm install -g oh-my-second-brain
|
|
76
|
+
oms --help
|
|
77
|
+
```
|
|
6
78
|
|
|
7
|
-
|
|
79
|
+
### 2. 볼트 규약 정의
|
|
8
80
|
|
|
9
|
-
|
|
81
|
+
터미널에서 setup을 실행한다. 폴더, 속성, 템플릿을 인터뷰한 뒤 계약을 봉인한다. 기존 노트는 수정하지 않는다.
|
|
10
82
|
|
|
11
|
-
|
|
83
|
+
```bash
|
|
84
|
+
oms setup --vault /path/to/vault
|
|
85
|
+
oms setup status --vault /path/to/vault
|
|
86
|
+
```
|
|
12
87
|
|
|
13
|
-
|
|
88
|
+
### 3. 에이전트 연결
|
|
14
89
|
|
|
15
|
-
|
|
90
|
+
사용하는 호스트의 통합 기능을 설치한다.
|
|
16
91
|
|
|
17
|
-
|
|
92
|
+
```bash
|
|
93
|
+
oms setup host install --runtime claude --vault /path/to/vault --yes
|
|
94
|
+
```
|
|
18
95
|
|
|
19
|
-
|
|
96
|
+
`claude` 대신 `codex` 또는 `hermes`를 쓸 수 있다. 세 호스트를 모두 설치하려면 `all`을 쓴다. CLI만 사용한다면 호스트 설치는 선택 사항이다. Hermes 프로필, 모델 설정, 제거 방법은 [설치 가이드](./docs/install.md)를 참고한다.
|
|
20
97
|
|
|
21
|
-
|
|
98
|
+
### 4. 지식 꺼내 쓰기
|
|
22
99
|
|
|
23
100
|
```bash
|
|
24
|
-
|
|
25
|
-
oms
|
|
101
|
+
# 파생 검색 색인을 명시적으로 만든다.
|
|
102
|
+
oms doctor sync-embeddings --mode sync --vault /path/to/vault
|
|
103
|
+
|
|
104
|
+
# vector 모델 없이 lexical 검색부터 시작한다.
|
|
105
|
+
oms search "프로젝트 결정" --vault /path/to/vault
|
|
26
106
|
```
|
|
27
107
|
|
|
28
|
-
|
|
108
|
+
**연결한 에이전트에게 이렇게 요청할 수 있다.**
|
|
29
109
|
|
|
30
|
-
|
|
110
|
+
> 이 프로젝트와 관련된 내 노트를 찾아서, 이전에 내린 결정을 보여줘.
|
|
31
111
|
|
|
32
|
-
|
|
33
|
-
oms bridge add|remove|status 저장소-볼트 target bridge 관리
|
|
34
|
-
oms contract setup|extract|status|doctor 볼트 계약 봉인, 조회, 진단
|
|
35
|
-
oms graph build|status 노트 그래프 생성 또는 조회
|
|
36
|
-
oms hook pre Claude 쓰기를 vault 계약으로 판정
|
|
37
|
-
oms host install|remove|sync|status 호스트 asset과 MCP 등록 관리
|
|
38
|
-
oms index sync|embed|repair|status|clean 파생 검색 상태 관리
|
|
39
|
-
oms link suggest|check 노트 wikilink 제안 또는 검사
|
|
40
|
-
oms model install|select|waive|status 로컬 모델 선택 관리
|
|
41
|
-
oms note audit|get 노트를 계약으로 감사하거나 읽기
|
|
42
|
-
oms package check|update OMS 패키지 확인 또는 업데이트
|
|
43
|
-
oms search query|context 명시적 질의 실행 또는 구조화 context 조회
|
|
44
|
-
oms serve mcp|http stdio MCP 또는 로컬 HTTP 서버 시작
|
|
45
|
-
oms setup 볼트를 인터뷰하고 계약 봉인
|
|
46
|
-
oms status 읽기 전용 통합 상태 표시
|
|
47
|
-
```
|
|
112
|
+
> 이 노트가 내 볼트 계약에 맞는지 검사하고, 확인할 부분을 알려줘.
|
|
48
113
|
|
|
49
|
-
|
|
114
|
+
> 파일은 바꾸지 말고, 함께 연결하면 좋을 노트를 제안해줘.
|
|
50
115
|
|
|
51
|
-
|
|
116
|
+
실행 결과를 캡처한 것이 아니라 요청 예시다. 워크플로와 쓰기 검사 범위는 아래의 호스트별 설명을 따른다.
|
|
52
117
|
|
|
53
|
-
|
|
118
|
+
## 동작 방식
|
|
54
119
|
|
|
55
|
-
|
|
120
|
+
**의미는 사용자가 정한다. 내용은 에이전트가 쓴다. 구조는 OMS가 검사한다.**
|
|
56
121
|
|
|
57
|
-
|
|
122
|
+
| 레이어 | 맡는 것 |
|
|
123
|
+
| :--- | :--- |
|
|
124
|
+
| **나의 볼트** | Markdown 노트, 폴더, 속성, 원본 템플릿. Obsidian이 사령탑으로 남는다. |
|
|
125
|
+
| **나의 계약** | `oms setup`에서 확인한 규약. 볼트 밖 `~/.oms/vaults/<vault-id>/`에 봉인한다. |
|
|
126
|
+
| **OMS** | 검색, 지원되는 쓰기의 계약 판정, 링크 검사, 명시적인 색인 유지보수. |
|
|
127
|
+
| **에이전트** | 맥락을 읽고 노트를 작성하며 호스트에 맞는 워크플로를 쓴다. 보존할 가치는 사용자와 에이전트가 판단한다. |
|
|
58
128
|
|
|
59
|
-
|
|
129
|
+
> [!IMPORTANT]
|
|
130
|
+
> **쓰기 검사를 신뢰하기 전에 계약부터 설정한다.** 이 기기에 봉인이 없는 볼트는 계약 판정을 하지 않는다. 일반적인 경로·입력 보호는 그대로 적용된다. 계약을 위반하는 쓰기는 파일을 바꾸지 않는다. 쓰기 허용은 구조 준수를 뜻하며, 사실의 정확성이나 품질 승인이 아니다.
|
|
60
131
|
|
|
61
|
-
|
|
132
|
+
<details>
|
|
133
|
+
<summary><strong>볼트 계약 자세히 보기</strong></summary>
|
|
62
134
|
|
|
63
|
-
|
|
135
|
+
- **의미는 사용자 소유다.** 폴더, 속성 pool, 템플릿을 함께 인터뷰한다. 속성 이름·폴더·페르소나를 하드코딩하지 않고 Inbox fallback도 없다.
|
|
136
|
+
- **볼트 안의 제어 파일은 하나다.** `.oms/settings.json`에 `version`, `vaultId`, `templateFolder`, `embedding`, `agentRepair`를 둔다. 다른 `.oms/` 항목은 무시하고 `oms doctor contract`가 예상하지 않은 제어 파일로 보고한다. `.obsidian/types.json`은 읽기 전용 관측값이며 봉인을 덮어쓰지 않는다.
|
|
137
|
+
- **템플릿은 원본으로 남는다.** OMS는 템플릿이 선언하는 것을 기록한다. 템플릿 파일을 다시 쓰거나 복사하지 않으며, Templater·JavaScript·전용 token 언어를 해석하거나 실행하지 않는다. 쓰기는 작성 중인 노트의 기계적인 부분만 채운다. `{{title}}`·`{{date}}`·`{{time}}` 변수, 새 노트의 date·datetime 기본값, 선택한 템플릿에서 빠진 heading이다. 필수 값을 대신 채우지는 않는다.
|
|
138
|
+
- **변경은 드러난다.** `oms setup status`는 템플릿 상태를 `active`, `drift`, `missing`으로 보고한다. 변경된 템플릿을 조용히 재봉인하지 않는다.
|
|
139
|
+
- **판정자는 하나다.** 거부 시 `{field, kind}` 위반과 안내 명령 하나만 반환한다. 규칙 값, 저장소 경로, 계약 본문은 반환하지 않는다.
|
|
140
|
+
- **봉인 증거가 맞지 않으면 쓰기를 거부한다.** 이 기기의 증거가 볼트와 어긋나면 `contract-unreadable`로 거부하고 소유자가 `oms setup`을 다시 실행해야 한다. 봉인이 아예 없는 기기에서는 판정하지 않는 것과 구별한다.
|
|
64
141
|
|
|
65
|
-
|
|
142
|
+
[아키텍처](./docs/architecture.md), [컨벤션](./docs/conventions.md), [ADR-007](https://github.com/GoBeromsu/oh-my-second-brain/blob/main/docs/decisions/ADR-007-vault-contract-ontology.md)을 참고한다.
|
|
66
143
|
|
|
67
|
-
|
|
144
|
+
</details>
|
|
68
145
|
|
|
69
|
-
|
|
146
|
+
<details>
|
|
147
|
+
<summary><strong>설정, 템플릿 해석, 복구</strong></summary>
|
|
70
148
|
|
|
71
|
-
|
|
149
|
+
터미널에서 `oms setup`을 실행하면 대화형 인터뷰를 거쳐 계약을 봉인한다. `oms interview`는 같은 터미널 인터뷰를 독립 명령으로 제공하며, 터미널이 필요하고 `OMS_NON_INTERACTIVE=1`이면 실행을 거부한다.
|
|
72
150
|
|
|
73
|
-
|
|
151
|
+
`setup` 스킬은 `oms setup --questions`로 질문을 받아 소유자에게 하나씩 묻고, `oms setup --answers <file|->`로 답을 제출한다. 이 경로는 첫 봉인이나 더 엄격한 계약만 봉인하며, 계약을 느슨하게 하는 재봉인은 소유자의 터미널에서 한다. MCP `interview` 도구는 질문과 봉인 상태만 보여 주며 아무것도 봉인하지 않는다.
|
|
74
152
|
|
|
75
|
-
|
|
153
|
+
`oms setup extract --template <path>`는 템플릿 원문과 계산한 hash를 반환한다. 에이전트는 각 템플릿을 읽어 `oms setup --interpretations <file>`로 해석을 제출한다. 소유자가 그 해석을 확인한 다음 인터뷰에 사용한다.
|
|
76
154
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
155
|
+
`oms doctor contract`는 봉인, 오래된 lock, 고아 generation, 예상하지 않은 제어 파일, hook 전송 실패를 진단한다. `--fix`는 이동했거나 색인되지 않은 볼트를 다시 색인할 뿐이다. 다른 봉인 문제는 `oms setup`으로 복구한다.
|
|
156
|
+
|
|
157
|
+
모델 수명주기는 별도다: `oms setup model install|select|waive|status`.
|
|
158
|
+
|
|
159
|
+
</details>
|
|
160
|
+
|
|
161
|
+
## MCP 도구와 에이전트 연결
|
|
162
|
+
|
|
163
|
+
**하나의 도메인 커널, 호스트에 맞는 연결 방식.**
|
|
164
|
+
|
|
165
|
+
`write` · `search` · `interview` · `doctor`
|
|
166
|
+
|
|
167
|
+
| MCP 도구 | 역할 |
|
|
168
|
+
| :--- | :--- |
|
|
169
|
+
| `write` | 노트 전체를 봉인된 계약으로 판정하고 허용된 쓰기를 저장한다. |
|
|
170
|
+
| `search` | 볼트를 바꾸지 않고 노트, 구조화된 맥락, wikilink 제안을 찾는다. |
|
|
171
|
+
| `interview` | 볼트 인터뷰 질문과 봉인 상태를 보여 준다. 아무것도 봉인하지 않는다. |
|
|
172
|
+
| `doctor` | 읽기 전용 `status`, 계약 진단, 노트 감사, 링크 검사, 명시적인 색인 유지보수를 수행한다. |
|
|
173
|
+
|
|
174
|
+
6개 스킬은 `distill`, `doctor`, `interview`, `search`, `setup`, `write`다.
|
|
175
|
+
|
|
176
|
+
`distill`과 `setup`은 대응 MCP 도구가 없는 워크플로다. 봉인에는 MCP 작업이 없고, 세부 기능은 네 도구 아래의 `op` 값으로 제공한다. 도구 annotation은 도구별로 정한다. `write`와 `doctor` 복구는 변경을 일으키고 `interview`는 보수적으로 두므로 읽기 전용으로 표시한 도구는 `search`뿐이다.
|
|
177
|
+
|
|
178
|
+
| 호스트 | 통합 방식 | 쓰기 검사 |
|
|
179
|
+
| :--- | :--- | :--- |
|
|
180
|
+
| **Claude Code** | 네이티브 plugin asset, 스킬, MCP | MCP `write`와 기본 Write·Edit·MultiEdit·NotebookEdit용 `oms hook pre`. |
|
|
181
|
+
| **Codex** | 네이티브 plugin asset, 가이드, MCP | MCP `write`만 검사. 기본 쓰기 hook은 없다. |
|
|
182
|
+
| **Hermes** | 프로필별 스킬, 가이드, MCP | MCP `write`만 검사. 기본 쓰기 hook은 없다. |
|
|
183
|
+
|
|
184
|
+
> [!NOTE]
|
|
185
|
+
> Claude hook은 판정된 계약 위반을 거부하지만, hook 자체를 실행할 수 없으면 경고와 함께 쓰기를 허용한다. Codex와 Hermes의 기본 파일 쓰기는 OMS 판정자를 거치지 않는다. 파일시스템 전체를 통제하는 sandbox가 아니다.
|
|
186
|
+
|
|
187
|
+
Gajae-Code에서는 `gjc plugin install oms@oms`로 marketplace plugin을 설치한다. 패키지 루트 `skills/` 경로에서 스킬 6개를 발견한다. 자세한 내용은 [호스트 asset](./docs/adapters.md)을 참고한다.
|
|
188
|
+
|
|
189
|
+
<details>
|
|
190
|
+
<summary><strong>호스트 유지보수와 볼트 선택</strong></summary>
|
|
191
|
+
|
|
192
|
+
호스트 설치는 `${XDG_CONFIG_HOME:-~/.config}/oms/vault.json`에 서명된 유지보수 포인터를 기록하고, 관리하는 호스트 항목에 `oms serve mcp --vault /path/to/vault`를 설정한다. `oms setup host install|remove|sync|status`만 이 포인터로 통합을 유지보수한다.
|
|
193
|
+
|
|
194
|
+
런타임은 이 포인터를 읽지 않는다. 우선순위는 **명시적 target → 로컬 볼트 제어 파일 → bridge → `OMS_VAULT` → 현재 디렉터리**다. 현재 디렉터리 fallback은 읽기 전용으로, 봉인·노트 쓰기·파생 상태 복구에는 쓸 수 없다.
|
|
195
|
+
|
|
196
|
+
`oms setup package update`는 패키지만 갱신한다. 설치된 호스트 asset은 `oms setup host sync`로 따로 동기화한다. [검증된 target](./docs/verified-target.md)을 참고한다.
|
|
197
|
+
|
|
198
|
+
</details>
|
|
199
|
+
|
|
200
|
+
## 필요한 방식으로 검색
|
|
201
|
+
|
|
202
|
+
**기본은 lexical. 추가 검색 채널은 직접 선택한다.** 계약을 통과하지 못하는 노트도 검색에 포함한다. 계약이 없거나 손상되어도 검색은 멈추지 않는다.
|
|
203
|
+
|
|
204
|
+
| 기능 | 선택 방법 | 필요 조건 |
|
|
205
|
+
| :--- | :--- | :--- |
|
|
206
|
+
| Lexical 검색 | `oms search <text>` | vector 모델 불필요. |
|
|
207
|
+
| Vector 검색 | `--vec <text>` | 완전한 `OMS_EMBEDDING_PROVIDER` / `OMS_EMBEDDING_MODEL` 쌍. |
|
|
208
|
+
| HyDE | `--hyde <text>` | embedding 쌍과 `OMS_GENERATE_PROVIDER` / `OMS_GENERATE_MODEL`. |
|
|
209
|
+
| 질의 확장 | `--expand` | 명시적인 G004 확장. `--max-queries`는 1–32. |
|
|
210
|
+
| Reranking | `--rerank` | 완전한 `OMS_RERANK_PROVIDER` / `OMS_RERANK_MODEL` 쌍. |
|
|
211
|
+
|
|
212
|
+
모델 선택이 없거나 불완전하거나 설치되지 않았다면 다른 기능으로 조용히 대체하지 않고 오류를 알린다. 사용 가능한 검색 선택지이며, 다른 엔진과의 동등성이나 우월성을 주장하지 않는다.
|
|
213
|
+
|
|
214
|
+
구조화된 맥락은 `oms search --context`, 노트 하나를 정확히 읽을 때는 `oms search --path <note>`를 쓴다. 색인 작업은 명시적으로 실행하며 `oms doctor sync-embeddings --mode sync|embed|repair`는 서로 다른 세 모드 중 하나를 고른다. 전체 작업은 [CLI 맵](./docs/cli-map.md)을 참고한다.
|
|
215
|
+
|
|
216
|
+
## CLI 레퍼런스
|
|
217
|
+
|
|
218
|
+
`oms`는 `oh-my-second-brain`의 짧은 별칭이며 CLI family는 7개다. 0.19에서 0.18 family를 교체했다. [0.19 마이그레이션 가이드](./docs/migration-0.19.md)를 참고한다.
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
oms search <text> 노트 검색. 기본은 lexical
|
|
222
|
+
oms search --path|--context|--link 노트 하나 읽기, 맥락 조회, 링크 제안
|
|
223
|
+
oms interview 터미널에서 볼트 소유자를 인터뷰하고 봉인
|
|
224
|
+
oms write <path> 계약이 허용하면 stdin의 노트를 저장
|
|
225
|
+
oms setup 계약 봉인 (에이전트는 --questions/--answers)
|
|
226
|
+
oms setup extract|status 템플릿 원문 또는 계약 상태 표시
|
|
227
|
+
oms setup host install|remove|sync|status 호스트 asset과 MCP 등록 관리
|
|
228
|
+
oms setup model install|select|waive|status 로컬 모델 선택 관리
|
|
229
|
+
oms setup package check|update OMS 패키지 확인 또는 갱신
|
|
230
|
+
oms setup bridge add|remove|status 저장소-볼트 bridge 관리
|
|
231
|
+
oms doctor status 읽기 전용 볼트 상태 표시
|
|
232
|
+
oms doctor contract|audit|link-check 계약, 노트, wikilink 진단
|
|
233
|
+
oms doctor sync-embeddings|cleanup|build-graph 파생 색인과 그래프 유지보수
|
|
234
|
+
oms serve mcp|http MCP 또는 로컬 HTTP 서버 시작
|
|
235
|
+
oms hook pre Claude 쓰기를 계약으로 판정
|
|
80
236
|
```
|
|
81
237
|
|
|
82
|
-
|
|
238
|
+
<details>
|
|
239
|
+
<summary><strong>명령 동작과 폐기된 작업</strong></summary>
|
|
240
|
+
|
|
241
|
+
인식되는 모든 명령은 `--help`와 `-h`를 받으며 exit 0, 부작용 없음으로 끝난다. 알 수 없는 명령과 `--help`를 함께 쓰면 exit 1이다. 0.19에서 제거된 family는 exit 1로 끝나며 대체 명령을 알려 준다.
|
|
242
|
+
|
|
243
|
+
`oms doctor audit`는 노트를 다시 쓰지 않고 `{path, field, kind}` 항목을 보고한다. 노트는 `oms write <path> < note.md` 또는 MCP `write {path, content, template?, ifMatch?, check?}`로 전체 내용을 쓴다. 둘 다 같은 쓰기 파이프라인을 거친다. 선택 사항인 `template`은 따르는 봉인된 템플릿 이름이다. 기존 노트를 덮어쓰려면 현재 `sha256:` revision을 `ifMatch`(`--if-match`)로 넘겨야 하고, `check`(`--check`)는 디스크를 건드리지 않고 판정만 한다. 허용된 쓰기는 새 revision이 담긴 receipt를 돌려주고, 엔진 저장소가 있으면 같은 호출에서 키워드 인덱스를 갱신하므로 노트를 바로 검색할 수 있다. 완료 호출이나 리뷰어 대화는 없다.
|
|
244
|
+
|
|
245
|
+
`oms doctor cleanup`은 제거 가능한 파생 상태를 지운다. `oms doctor build-graph`는 노트 그래프를 다시 만든다.
|
|
246
|
+
|
|
247
|
+
노트 `create`, `append`, `update`, `backfill`은 폐기된 작업이다. `link apply`, 노트 렌더러, 폐기된 작업을 위한 호환 경로는 없다.
|
|
248
|
+
|
|
249
|
+
</details>
|
|
250
|
+
|
|
251
|
+
## 문서
|
|
252
|
+
|
|
253
|
+
| 시작하기 | 더 알아보기 |
|
|
254
|
+
| :--- | :--- |
|
|
255
|
+
| [설치](./docs/install.md): 설치, setup, 모델, 제거 | [아키텍처](./docs/architecture.md): 권위와 도메인 경계 |
|
|
256
|
+
| [볼트 컨벤션](./docs/conventions.md): 설정과 봉인된 계약 | [CLI 맵](./docs/cli-map.md): 명령과 MCP 작업 매핑 |
|
|
257
|
+
| [호스트 통합](./docs/adapters.md): Claude Code, Codex, Hermes | [검증된 target](./docs/verified-target.md): 안전한 볼트 선택 |
|
|
258
|
+
| [릴리스](https://github.com/GoBeromsu/oh-my-second-brain/releases): 배포 버전 | [변경 이력](./CHANGELOG.md): 무엇이 왜 달라졌는가 |
|
|
259
|
+
|
|
260
|
+
## 기여와 크레딧
|
|
83
261
|
|
|
84
|
-
|
|
262
|
+
[기여 가이드](https://github.com/GoBeromsu/oh-my-second-brain/blob/main/CONTRIBUTING.md)를 읽거나, 재현 가능한 문제와 구체적인 제안을 [이슈](https://github.com/GoBeromsu/oh-my-second-brain/issues)로 남길 수 있다.
|
|
85
263
|
|
|
86
|
-
|
|
264
|
+
[ACKNOWLEDGMENTS](./ACKNOWLEDGMENTS.md)는 Ouroboros, Gajae Code의 deep-interview 등 설계에 영향을 준 아이디어를 기록한다. runtime 복제나 연구 결과를 뜻하지 않는다. 별자리 배너는 [beomsukoh.com](https://beomsukoh.com/)의 연결된 노트 풍경에서 착안한 자체 제작 일러스트다. 이미지는 개념을 설명하는 도식이며 제품 화면, host smoke 증거, 제품 gate 통과 결과가 아니다.
|
|
87
265
|
|
|
88
|
-
|
|
266
|
+
---
|
|
89
267
|
|
|
90
|
-
|
|
268
|
+
<p align="center">
|
|
269
|
+
<strong>노트의 주인은 계속 나다.</strong><br />
|
|
270
|
+
Built by <a href="https://github.com/GoBeromsu">Beomsu Koh</a> · Package licensed MIT
|
|
271
|
+
</p>
|