oh-my-second-brain 0.1.8 → 0.2.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.
Files changed (466) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/README.ko.md +127 -0
  3. package/README.md +128 -0
  4. package/adapters/README.md +8 -8
  5. package/adapters/claude-code/.claude-plugin/plugin.json +3 -2
  6. package/adapters/claude-code/.mcp.json +8 -0
  7. package/adapters/claude-code/CLAUDE.md +5 -6
  8. package/adapters/claude-code/skills/compile/SKILL.md +10 -35
  9. package/adapters/claude-code/skills/distill/SKILL.md +6 -26
  10. package/adapters/claude-code/skills/link/SKILL.md +87 -0
  11. package/adapters/claude-code/skills/retrieve/SKILL.md +4 -7
  12. package/adapters/claude-code/skills/setup/SKILL.md +5 -6
  13. package/adapters/claude-code/skills/uninstall/SKILL.md +1 -1
  14. package/adapters/claude-code/skills/wiki/SKILL.md +49 -24
  15. package/adapters/claude-code/skills/write/SKILL.md +16 -0
  16. package/adapters/codex/.codex-plugin/plugin.json +1 -1
  17. package/adapters/codex/AGENTS.md +2 -2
  18. package/adapters/codex/rules/oms.md +1 -1
  19. package/adapters/codex/skills/oms-compile/SKILL.md +7 -9
  20. package/adapters/codex/skills/oms-distill/SKILL.md +4 -9
  21. package/adapters/codex/skills/oms-link/SKILL.md +35 -0
  22. package/adapters/codex/skills/oms-retrieve/SKILL.md +5 -6
  23. package/adapters/codex/skills/oms-wiki/SKILL.md +28 -8
  24. package/adapters/codex/skills/oms-write/SKILL.md +10 -0
  25. package/adapters/hermes/README.md +3 -1
  26. package/adapters/hermes/SOUL.md +2 -3
  27. package/adapters/hermes/manifest.json +1 -1
  28. package/adapters/hermes/skills/compile/SKILL.md +5 -7
  29. package/adapters/hermes/skills/distill/SKILL.md +1 -3
  30. package/adapters/hermes/skills/link/SKILL.md +18 -0
  31. package/adapters/hermes/skills/retrieve/SKILL.md +5 -6
  32. package/adapters/hermes/skills/setup/SKILL.md +5 -2
  33. package/adapters/hermes/skills/wiki/SKILL.md +4 -2
  34. package/adapters/hermes/skills/write/SKILL.md +10 -0
  35. package/core/AGENTS.md +4 -2
  36. package/core/agents/librarian.md +3 -2
  37. package/core/ontology/concepts/term.yaml +12 -0
  38. package/core/ontology/taxonomy.yaml +3 -0
  39. package/core/skills/compile/SKILL.md +19 -18
  40. package/core/skills/distill/SKILL.md +13 -24
  41. package/core/skills/link/SKILL.md +130 -0
  42. package/core/skills/retrieve/SKILL.md +0 -1
  43. package/core/skills/setup/SKILL.md +12 -14
  44. package/core/skills/vault-lint/SKILL.md +1 -1
  45. package/core/skills/wiki/SKILL.md +109 -30
  46. package/core/skills/write/SKILL.md +15 -0
  47. package/dist/capture/safe.d.ts +61 -1
  48. package/dist/capture/safe.js +489 -66
  49. package/dist/capture/safe.js.map +1 -1
  50. package/dist/cli/args.d.ts +29 -0
  51. package/dist/cli/args.js +156 -0
  52. package/dist/cli/args.js.map +1 -0
  53. package/dist/cli/audit.d.ts +6 -0
  54. package/dist/cli/audit.js +93 -0
  55. package/dist/cli/audit.js.map +1 -0
  56. package/dist/cli/claude-install-plan.d.ts +10 -0
  57. package/dist/cli/claude-install-plan.js +26 -0
  58. package/dist/cli/claude-install-plan.js.map +1 -0
  59. package/dist/cli/doctor-lint.d.ts +11 -0
  60. package/dist/cli/doctor-lint.js +86 -0
  61. package/dist/cli/doctor-lint.js.map +1 -0
  62. package/dist/cli/global-writeback.d.ts +31 -0
  63. package/dist/cli/global-writeback.js +73 -0
  64. package/dist/cli/global-writeback.js.map +1 -0
  65. package/dist/cli/host-commands.d.ts +30 -0
  66. package/dist/cli/host-commands.js +89 -0
  67. package/dist/cli/host-commands.js.map +1 -0
  68. package/dist/cli/link-command.d.ts +9 -0
  69. package/dist/cli/link-command.js +47 -0
  70. package/dist/cli/link-command.js.map +1 -0
  71. package/dist/cli/linkify.d.ts +23 -0
  72. package/dist/cli/linkify.js +118 -0
  73. package/dist/cli/linkify.js.map +1 -0
  74. package/dist/cli/oms.d.ts +8 -32
  75. package/dist/cli/oms.js +100 -703
  76. package/dist/cli/oms.js.map +1 -1
  77. package/dist/cli/semantic-args.d.ts +1 -2
  78. package/dist/cli/semantic-args.js +4 -7
  79. package/dist/cli/semantic-args.js.map +1 -1
  80. package/dist/cli/semantic-http.d.ts +0 -3
  81. package/dist/cli/semantic-http.js +40 -45
  82. package/dist/cli/semantic-http.js.map +1 -1
  83. package/dist/cli/semantic-usage.js +10 -9
  84. package/dist/cli/semantic-usage.js.map +1 -1
  85. package/dist/cli/semantic.js +99 -137
  86. package/dist/cli/semantic.js.map +1 -1
  87. package/dist/cli/setup-command.d.ts +11 -0
  88. package/dist/cli/setup-command.js +196 -0
  89. package/dist/cli/setup-command.js.map +1 -0
  90. package/dist/cli/setup-documents.d.ts +15 -0
  91. package/dist/cli/setup-documents.js +149 -0
  92. package/dist/cli/setup-documents.js.map +1 -0
  93. package/dist/cli/update-notice.d.ts +10 -0
  94. package/dist/cli/update-notice.js +42 -0
  95. package/dist/cli/update-notice.js.map +1 -0
  96. package/dist/cli/usage.d.ts +4 -0
  97. package/dist/cli/usage.js +102 -0
  98. package/dist/cli/usage.js.map +1 -0
  99. package/dist/conventions/lint.js +12 -33
  100. package/dist/conventions/lint.js.map +1 -1
  101. package/dist/conventions/report.d.ts +62 -0
  102. package/dist/conventions/report.js +217 -0
  103. package/dist/conventions/report.js.map +1 -0
  104. package/dist/conventions/validate.d.ts +1 -1
  105. package/dist/conventions/vault-walk.d.ts +38 -0
  106. package/dist/conventions/vault-walk.js +80 -0
  107. package/dist/conventions/vault-walk.js.map +1 -0
  108. package/dist/conventions/write-contract.d.ts +27 -0
  109. package/dist/conventions/write-contract.js +91 -0
  110. package/dist/conventions/write-contract.js.map +1 -0
  111. package/dist/conventions/write-protocol.d.ts +39 -0
  112. package/dist/conventions/write-protocol.js +44 -0
  113. package/dist/conventions/write-protocol.js.map +1 -0
  114. package/dist/core/ontology/loader.d.ts +2 -0
  115. package/dist/{ontology → core/ontology}/loader.js +11 -20
  116. package/dist/core/ontology/loader.js.map +1 -0
  117. package/dist/core/ontology/resolver.d.ts +2 -0
  118. package/dist/{ontology → core/ontology}/resolver.js +1 -15
  119. package/dist/core/ontology/resolver.js.map +1 -0
  120. package/dist/core/ontology/types.d.ts +47 -0
  121. package/dist/core/ontology/types.js +2 -0
  122. package/dist/core/ontology/types.js.map +1 -0
  123. package/dist/core/runtime/assets.d.ts +20 -0
  124. package/dist/core/runtime/assets.js +66 -0
  125. package/dist/core/runtime/assets.js.map +1 -0
  126. package/dist/engine/assemble.d.ts +28 -72
  127. package/dist/engine/assemble.js +77 -61
  128. package/dist/engine/assemble.js.map +1 -1
  129. package/dist/engine/conventions/vault-lint.d.ts +30 -2
  130. package/dist/engine/conventions/vault-lint.js +93 -97
  131. package/dist/engine/conventions/vault-lint.js.map +1 -1
  132. package/dist/engine/embed/deferred.d.ts +3 -4
  133. package/dist/engine/embed/deferred.js +10 -7
  134. package/dist/engine/embed/deferred.js.map +1 -1
  135. package/dist/engine/embed/identity.d.ts +11 -0
  136. package/dist/engine/embed/identity.js +15 -0
  137. package/dist/engine/embed/identity.js.map +1 -0
  138. package/dist/engine/embed/provider.d.ts +12 -13
  139. package/dist/engine/embed/provider.js +30 -27
  140. package/dist/engine/embed/provider.js.map +1 -1
  141. package/dist/engine/embed/store.d.ts +48 -27
  142. package/dist/engine/embed/store.js +281 -98
  143. package/dist/engine/embed/store.js.map +1 -1
  144. package/dist/engine/embed/sync.d.ts +17 -47
  145. package/dist/engine/embed/sync.js +233 -69
  146. package/dist/engine/embed/sync.js.map +1 -1
  147. package/dist/engine/graph/builder.d.ts +1 -1
  148. package/dist/engine/graph/builder.js +1 -1
  149. package/dist/engine/graph/explore.d.ts +2 -2
  150. package/dist/engine/graph/explore.js +0 -0
  151. package/dist/engine/graph/resolver.d.ts +17 -0
  152. package/dist/engine/graph/resolver.js +46 -11
  153. package/dist/engine/graph/resolver.js.map +1 -1
  154. package/dist/engine/linkify/apply.d.ts +56 -0
  155. package/dist/engine/linkify/apply.js +65 -0
  156. package/dist/engine/linkify/apply.js.map +1 -0
  157. package/dist/engine/linkify/josa.d.ts +58 -0
  158. package/dist/engine/linkify/josa.js +133 -0
  159. package/dist/engine/linkify/josa.js.map +1 -0
  160. package/dist/engine/linkify/mask.d.ts +29 -0
  161. package/dist/engine/linkify/mask.js +173 -0
  162. package/dist/engine/linkify/mask.js.map +1 -0
  163. package/dist/engine/linkify/suggest.d.ts +52 -0
  164. package/dist/engine/linkify/suggest.js +181 -0
  165. package/dist/engine/linkify/suggest.js.map +1 -0
  166. package/dist/engine/linkify/types.d.ts +68 -0
  167. package/dist/engine/linkify/types.js +12 -0
  168. package/dist/engine/linkify/types.js.map +1 -0
  169. package/dist/engine/mcp/facade.d.ts +12 -18
  170. package/dist/engine/mcp/facade.js +30 -80
  171. package/dist/engine/mcp/facade.js.map +1 -1
  172. package/dist/engine/mcp/op-mappers.d.ts +3 -9
  173. package/dist/engine/mcp/op-mappers.js +2 -30
  174. package/dist/engine/mcp/op-mappers.js.map +1 -1
  175. package/dist/engine/mcp/types.d.ts +5 -29
  176. package/dist/engine/tracer.js +6 -2
  177. package/dist/engine/tracer.js.map +1 -1
  178. package/dist/engine/types.d.ts +8 -3
  179. package/dist/graph/cache.d.ts +1 -11
  180. package/dist/graph/cache.js +1 -44
  181. package/dist/graph/cache.js.map +1 -1
  182. package/dist/graph/explore.js +88 -137
  183. package/dist/graph/explore.js.map +1 -1
  184. package/dist/harness/surface-registry.d.ts +56 -0
  185. package/dist/harness/surface-registry.js +397 -0
  186. package/dist/harness/surface-registry.js.map +1 -0
  187. package/dist/harness/validation.d.ts +9 -0
  188. package/dist/harness/validation.js +201 -0
  189. package/dist/harness/validation.js.map +1 -0
  190. package/dist/hook/post-tool-use.js +2 -2
  191. package/dist/hook/post-tool-use.js.map +1 -1
  192. package/dist/index.d.ts +7 -5
  193. package/dist/index.js +7 -5
  194. package/dist/index.js.map +1 -1
  195. package/dist/install/adapter-source.d.ts +14 -0
  196. package/dist/install/adapter-source.js +45 -0
  197. package/dist/install/adapter-source.js.map +1 -0
  198. package/dist/install/claude-hooks.d.ts +13 -0
  199. package/dist/install/claude-hooks.js +411 -0
  200. package/dist/install/claude-hooks.js.map +1 -0
  201. package/dist/install/claude-marketplace.d.ts +44 -0
  202. package/dist/install/claude-marketplace.js +89 -0
  203. package/dist/install/claude-marketplace.js.map +1 -0
  204. package/dist/install/claude.d.ts +4 -0
  205. package/dist/install/claude.js +216 -0
  206. package/dist/install/claude.js.map +1 -0
  207. package/dist/install/codex.d.ts +24 -0
  208. package/dist/install/codex.js +193 -0
  209. package/dist/install/codex.js.map +1 -0
  210. package/dist/install/common.d.ts +34 -0
  211. package/dist/install/common.js +122 -0
  212. package/dist/install/common.js.map +1 -0
  213. package/dist/install/hermes.d.ts +4 -0
  214. package/dist/install/hermes.js +78 -0
  215. package/dist/install/hermes.js.map +1 -0
  216. package/dist/install/hosts.d.ts +6 -56
  217. package/dist/install/hosts.js +65 -610
  218. package/dist/install/hosts.js.map +1 -1
  219. package/dist/install/types.d.ts +34 -0
  220. package/dist/install/types.js +2 -0
  221. package/dist/install/types.js.map +1 -0
  222. package/dist/link/convention-note.d.ts +10 -0
  223. package/dist/link/convention-note.js +59 -0
  224. package/dist/link/convention-note.js.map +1 -0
  225. package/dist/link/global-config.d.ts +22 -0
  226. package/dist/link/global-config.js +69 -0
  227. package/dist/link/global-config.js.map +1 -0
  228. package/dist/link/link.d.ts +101 -0
  229. package/dist/link/link.js +265 -0
  230. package/dist/link/link.js.map +1 -0
  231. package/dist/mcp/engine-morning-backend.d.ts +12 -17
  232. package/dist/mcp/engine-morning-backend.js +25 -131
  233. package/dist/mcp/engine-morning-backend.js.map +1 -1
  234. package/dist/mcp/link-tools.d.ts +81 -0
  235. package/dist/mcp/link-tools.js +157 -0
  236. package/dist/mcp/link-tools.js.map +1 -0
  237. package/dist/mcp/semantic-engine.d.ts +32 -0
  238. package/dist/mcp/semantic-engine.js +52 -0
  239. package/dist/mcp/semantic-engine.js.map +1 -0
  240. package/dist/mcp/semantic-retrieve-args.d.ts +1 -5
  241. package/dist/mcp/semantic-retrieve-args.js +1 -26
  242. package/dist/mcp/semantic-retrieve-args.js.map +1 -1
  243. package/dist/mcp/semantic-retrieve-schema.d.ts +0 -14
  244. package/dist/mcp/semantic-retrieve-schema.js +0 -5
  245. package/dist/mcp/semantic-retrieve-schema.js.map +1 -1
  246. package/dist/mcp/semantic-retrieve.d.ts +12 -18
  247. package/dist/mcp/semantic-retrieve.js +40 -71
  248. package/dist/mcp/semantic-retrieve.js.map +1 -1
  249. package/dist/mcp/semantic-tool-schemas.js +7 -24
  250. package/dist/mcp/semantic-tool-schemas.js.map +1 -1
  251. package/dist/mcp/server.d.ts +7 -0
  252. package/dist/mcp/server.js +224 -162
  253. package/dist/mcp/server.js.map +1 -1
  254. package/dist/mcp/update-notice.d.ts +51 -0
  255. package/dist/mcp/update-notice.js +196 -0
  256. package/dist/mcp/update-notice.js.map +1 -0
  257. package/dist/ontology/active.d.ts +7 -0
  258. package/dist/ontology/active.js +41 -0
  259. package/dist/ontology/active.js.map +1 -0
  260. package/dist/retrieve/morning.d.ts +10 -18
  261. package/dist/retrieve/morning.js +2 -26
  262. package/dist/retrieve/morning.js.map +1 -1
  263. package/dist/retrieve/semantic-contract.d.ts +10 -0
  264. package/dist/retrieve/semantic-contract.js +2 -0
  265. package/dist/retrieve/semantic-contract.js.map +1 -0
  266. package/dist/setup/axis.d.ts +22 -3
  267. package/dist/setup/axis.js +82 -35
  268. package/dist/setup/axis.js.map +1 -1
  269. package/dist/update/update.d.ts +12 -0
  270. package/dist/update/update.js +2 -2
  271. package/dist/update/update.js.map +1 -1
  272. package/docs/install.md +43 -7
  273. package/docs/release.md +109 -17
  274. package/package.json +11 -3
  275. package/scripts/install.sh +1 -1
  276. package/adapters/claude-code/skills/capture/SKILL.md +0 -50
  277. package/adapters/codex/skills/oms-capture/SKILL.md +0 -16
  278. package/adapters/hermes/skills/capture/SKILL.md +0 -16
  279. package/core/skills/capture/SKILL.md +0 -50
  280. package/dist/adapt/HostAdapter.d.ts +0 -21
  281. package/dist/adapt/HostAdapter.js +0 -10
  282. package/dist/adapt/HostAdapter.js.map +0 -1
  283. package/dist/adapt/claudeCode.d.ts +0 -9
  284. package/dist/adapt/claudeCode.js +0 -15
  285. package/dist/adapt/claudeCode.js.map +0 -1
  286. package/dist/adapt/codex.d.ts +0 -9
  287. package/dist/adapt/codex.js +0 -15
  288. package/dist/adapt/codex.js.map +0 -1
  289. package/dist/adapt/hermes.d.ts +0 -9
  290. package/dist/adapt/hermes.js +0 -15
  291. package/dist/adapt/hermes.js.map +0 -1
  292. package/dist/cli/semantic-metadata-commands.d.ts +0 -3
  293. package/dist/cli/semantic-metadata-commands.js +0 -115
  294. package/dist/cli/semantic-metadata-commands.js.map +0 -1
  295. package/dist/engine/compile/cascade.d.ts +0 -35
  296. package/dist/engine/compile/cascade.js +0 -59
  297. package/dist/engine/compile/cascade.js.map +0 -1
  298. package/dist/engine/compile/cot.d.ts +0 -30
  299. package/dist/engine/compile/cot.js +0 -153
  300. package/dist/engine/compile/cot.js.map +0 -1
  301. package/dist/engine/compile/phases.d.ts +0 -47
  302. package/dist/engine/compile/phases.js +0 -101
  303. package/dist/engine/compile/phases.js.map +0 -1
  304. package/dist/engine/compile/provenance.d.ts +0 -45
  305. package/dist/engine/compile/provenance.js +0 -103
  306. package/dist/engine/compile/provenance.js.map +0 -1
  307. package/dist/engine/compile/sha-cache.d.ts +0 -42
  308. package/dist/engine/compile/sha-cache.js +0 -86
  309. package/dist/engine/compile/sha-cache.js.map +0 -1
  310. package/dist/engine/compile/types.d.ts +0 -71
  311. package/dist/engine/compile/types.js +0 -9
  312. package/dist/engine/compile/types.js.map +0 -1
  313. package/dist/engine/compile/worker.d.ts +0 -47
  314. package/dist/engine/compile/worker.js +0 -75
  315. package/dist/engine/compile/worker.js.map +0 -1
  316. package/dist/engine/distill/analyzer.d.ts +0 -51
  317. package/dist/engine/distill/analyzer.js +0 -279
  318. package/dist/engine/distill/analyzer.js.map +0 -1
  319. package/dist/engine/distill/clean-room.d.ts +0 -46
  320. package/dist/engine/distill/clean-room.js +0 -131
  321. package/dist/engine/distill/clean-room.js.map +0 -1
  322. package/dist/engine/distill/report.d.ts +0 -23
  323. package/dist/engine/distill/report.js +0 -107
  324. package/dist/engine/distill/report.js.map +0 -1
  325. package/dist/engine/distill/types.d.ts +0 -89
  326. package/dist/engine/distill/types.js +0 -9
  327. package/dist/engine/distill/types.js.map +0 -1
  328. package/dist/engine/embed/pull.d.ts +0 -51
  329. package/dist/engine/embed/pull.js +0 -90
  330. package/dist/engine/embed/pull.js.map +0 -1
  331. package/dist/engine/graph/community.d.ts +0 -38
  332. package/dist/engine/graph/community.js +0 -122
  333. package/dist/engine/graph/community.js.map +0 -1
  334. package/dist/engine/index.d.ts +0 -5
  335. package/dist/engine/index.js +0 -2
  336. package/dist/engine/index.js.map +0 -1
  337. package/dist/engine/mcp/index.d.ts +0 -15
  338. package/dist/engine/mcp/index.js +0 -19
  339. package/dist/engine/mcp/index.js.map +0 -1
  340. package/dist/engine/mcp/retrieve-mapper.d.ts +0 -38
  341. package/dist/engine/mcp/retrieve-mapper.js +0 -96
  342. package/dist/engine/mcp/retrieve-mapper.js.map +0 -1
  343. package/dist/engine/setup/ambiguity.d.ts +0 -39
  344. package/dist/engine/setup/ambiguity.js +0 -50
  345. package/dist/engine/setup/ambiguity.js.map +0 -1
  346. package/dist/engine/setup/types.d.ts +0 -71
  347. package/dist/engine/setup/types.js +0 -22
  348. package/dist/engine/setup/types.js.map +0 -1
  349. package/dist/engine/setup/writer.d.ts +0 -32
  350. package/dist/engine/setup/writer.js +0 -77
  351. package/dist/engine/setup/writer.js.map +0 -1
  352. package/dist/engine/wiki/collection.d.ts +0 -91
  353. package/dist/engine/wiki/collection.js +0 -188
  354. package/dist/engine/wiki/collection.js.map +0 -1
  355. package/dist/engine/wiki/ledger.d.ts +0 -59
  356. package/dist/engine/wiki/ledger.js +0 -130
  357. package/dist/engine/wiki/ledger.js.map +0 -1
  358. package/dist/engine/wiki/lint.d.ts +0 -38
  359. package/dist/engine/wiki/lint.js +0 -186
  360. package/dist/engine/wiki/lint.js.map +0 -1
  361. package/dist/engine/wiki/navigation.d.ts +0 -40
  362. package/dist/engine/wiki/navigation.js +0 -83
  363. package/dist/engine/wiki/navigation.js.map +0 -1
  364. package/dist/engine/wiki/types.d.ts +0 -54
  365. package/dist/engine/wiki/types.js +0 -7
  366. package/dist/engine/wiki/types.js.map +0 -1
  367. package/dist/ontology/loader.d.ts +0 -13
  368. package/dist/ontology/loader.js.map +0 -1
  369. package/dist/ontology/resolver.d.ts +0 -13
  370. package/dist/ontology/resolver.js.map +0 -1
  371. package/dist/ontology/types.d.ts +0 -72
  372. package/dist/ontology/types.js +0 -12
  373. package/dist/ontology/types.js.map +0 -1
  374. package/dist/retrieve/embedding-sync.d.ts +0 -3
  375. package/dist/retrieve/embedding-sync.js +0 -21
  376. package/dist/retrieve/embedding-sync.js.map +0 -1
  377. package/dist/runtime/assets.d.ts +0 -7
  378. package/dist/runtime/assets.js +0 -13
  379. package/dist/runtime/assets.js.map +0 -1
  380. package/dist/search/semantic-collections.d.ts +0 -32
  381. package/dist/search/semantic-collections.js +0 -68
  382. package/dist/search/semantic-collections.js.map +0 -1
  383. package/dist/search/semantic-contexts.d.ts +0 -21
  384. package/dist/search/semantic-contexts.js +0 -28
  385. package/dist/search/semantic-contexts.js.map +0 -1
  386. package/dist/search/semantic-diagnostics.d.ts +0 -16
  387. package/dist/search/semantic-diagnostics.js +0 -110
  388. package/dist/search/semantic-diagnostics.js.map +0 -1
  389. package/dist/search/semantic-documents.d.ts +0 -3
  390. package/dist/search/semantic-documents.js +0 -150
  391. package/dist/search/semantic-documents.js.map +0 -1
  392. package/dist/search/semantic-embedding-hash.d.ts +0 -3
  393. package/dist/search/semantic-embedding-hash.js +0 -30
  394. package/dist/search/semantic-embedding-hash.js.map +0 -1
  395. package/dist/search/semantic-embedding-provider.d.ts +0 -9
  396. package/dist/search/semantic-embedding-provider.js +0 -58
  397. package/dist/search/semantic-embedding-provider.js.map +0 -1
  398. package/dist/search/semantic-index-build.d.ts +0 -13
  399. package/dist/search/semantic-index-build.js +0 -101
  400. package/dist/search/semantic-index-build.js.map +0 -1
  401. package/dist/search/semantic-index-core.d.ts +0 -21
  402. package/dist/search/semantic-index-core.js +0 -106
  403. package/dist/search/semantic-index-core.js.map +0 -1
  404. package/dist/search/semantic-index-io.d.ts +0 -19
  405. package/dist/search/semantic-index-io.js +0 -214
  406. package/dist/search/semantic-index-io.js.map +0 -1
  407. package/dist/search/semantic-index-types.d.ts +0 -50
  408. package/dist/search/semantic-index-types.js +0 -2
  409. package/dist/search/semantic-index-types.js.map +0 -1
  410. package/dist/search/semantic-index.d.ts +0 -4
  411. package/dist/search/semantic-index.js +0 -4
  412. package/dist/search/semantic-index.js.map +0 -1
  413. package/dist/search/semantic-listing.d.ts +0 -12
  414. package/dist/search/semantic-listing.js +0 -64
  415. package/dist/search/semantic-listing.js.map +0 -1
  416. package/dist/search/semantic-maintenance-shared.d.ts +0 -15
  417. package/dist/search/semantic-maintenance-shared.js +0 -43
  418. package/dist/search/semantic-maintenance-shared.js.map +0 -1
  419. package/dist/search/semantic-maintenance-types.d.ts +0 -103
  420. package/dist/search/semantic-maintenance-types.js +0 -2
  421. package/dist/search/semantic-maintenance-types.js.map +0 -1
  422. package/dist/search/semantic-maintenance.d.ts +0 -4
  423. package/dist/search/semantic-maintenance.js +0 -5
  424. package/dist/search/semantic-maintenance.js.map +0 -1
  425. package/dist/search/semantic-provider-types.d.ts +0 -34
  426. package/dist/search/semantic-provider-types.js +0 -2
  427. package/dist/search/semantic-provider-types.js.map +0 -1
  428. package/dist/search/semantic-query-types.d.ts +0 -83
  429. package/dist/search/semantic-query-types.js +0 -2
  430. package/dist/search/semantic-query-types.js.map +0 -1
  431. package/dist/search/semantic-query.d.ts +0 -2
  432. package/dist/search/semantic-query.js +0 -188
  433. package/dist/search/semantic-query.js.map +0 -1
  434. package/dist/search/semantic-sqlite-db.d.ts +0 -18
  435. package/dist/search/semantic-sqlite-db.js +0 -87
  436. package/dist/search/semantic-sqlite-db.js.map +0 -1
  437. package/dist/search/semantic-sqlite-query.d.ts +0 -2
  438. package/dist/search/semantic-sqlite-query.js +0 -128
  439. package/dist/search/semantic-sqlite-query.js.map +0 -1
  440. package/dist/search/semantic-sqlite-read.d.ts +0 -5
  441. package/dist/search/semantic-sqlite-read.js +0 -104
  442. package/dist/search/semantic-sqlite-read.js.map +0 -1
  443. package/dist/search/semantic-sqlite-write.d.ts +0 -7
  444. package/dist/search/semantic-sqlite-write.js +0 -66
  445. package/dist/search/semantic-sqlite-write.js.map +0 -1
  446. package/dist/search/semantic-store.d.ts +0 -15
  447. package/dist/search/semantic-store.js +0 -17
  448. package/dist/search/semantic-store.js.map +0 -1
  449. package/dist/search/semantic-sync-types.d.ts +0 -47
  450. package/dist/search/semantic-sync-types.js +0 -2
  451. package/dist/search/semantic-sync-types.js.map +0 -1
  452. package/dist/search/semantic-sync.d.ts +0 -13
  453. package/dist/search/semantic-sync.js +0 -131
  454. package/dist/search/semantic-sync.js.map +0 -1
  455. package/dist/search/semantic-test-fixtures.d.ts +0 -1
  456. package/dist/search/semantic-test-fixtures.js +0 -38
  457. package/dist/search/semantic-test-fixtures.js.map +0 -1
  458. package/dist/search/semantic-token.d.ts +0 -25
  459. package/dist/search/semantic-token.js +0 -114
  460. package/dist/search/semantic-token.js.map +0 -1
  461. package/dist/search/semantic-types.d.ts +0 -5
  462. package/dist/search/semantic-types.js +0 -2
  463. package/dist/search/semantic-types.js.map +0 -1
  464. package/dist/search/semantic.d.ts +0 -6
  465. package/dist/search/semantic.js +0 -6
  466. package/dist/search/semantic.js.map +0 -1
package/dist/cli/oms.js CHANGED
@@ -1,731 +1,111 @@
1
1
  #!/usr/bin/env node
2
2
  import { realpathSync } from "node:fs";
3
- import { readFile, readdir, mkdir, copyFile, writeFile } from "node:fs/promises";
4
3
  import path from "node:path";
5
4
  import { fileURLToPath } from "node:url";
6
- import { createInterface } from "node:readline/promises";
7
- import { stringify as yamlStringify, parse as yamlParse } from "yaml";
8
- import { loadOntology } from "../ontology/loader.js";
9
- import { resolveConcept } from "../ontology/resolver.js";
10
- import { parseNote } from "../conventions/frontmatter.js";
11
- import { validateFrontmatter } from "../conventions/validate.js";
12
- import { detectLinkIssues } from "../conventions/lint.js";
13
- import { runMcpServer } from "../mcp/server.js";
14
- import { runPreToolUse } from "../hook/pre-tool-use.js";
15
5
  import { runPostToolUse } from "../hook/post-tool-use.js";
16
- import { resolveBundledAssetPaths } from "../runtime/assets.js";
17
- import { collectObservedFields, mergeObservedFieldsIntoConcept, parseLensDefinitions, } from "../setup/axis.js";
18
- import { checkUpdateNotice, formatUpdateNotice, formatUpdateResult, runUpdate, } from "../update/update.js";
19
- import { formatHostOperationResults, runHostOperation, } from "../install/hosts.js";
6
+ import { runPreToolUse } from "../hook/pre-tool-use.js";
7
+ import { resolveEffectiveVault } from "../link/link.js";
8
+ import { runMcpServer } from "../mcp/server.js";
9
+ import { resolveBundledAssetPaths } from "../core/runtime/assets.js";
10
+ import { parseCliArgs } from "./args.js";
11
+ import { runAudit } from "./audit.js";
12
+ import { runDoctor, runLint } from "./doctor-lint.js";
13
+ import { runInstallOrUninstall, runUpdateCommand, runUpdateReconcile, } from "./host-commands.js";
14
+ import { nonFatalGlobalWriteback, registerGlobalVault } from "./global-writeback.js";
15
+ import { runLink } from "./link-command.js";
16
+ import { runLinkify } from "./linkify.js";
20
17
  import { isSemanticCliCommand, runSemanticCli } from "./semantic.js";
21
- // ---------------------------------------------------------------------------
22
- // Path helpers
23
- // ---------------------------------------------------------------------------
18
+ import { runSetup } from "./setup-command.js";
19
+ import { maybePrintUpdateNotice } from "./update-notice.js";
20
+ import { printUsage } from "./usage.js";
21
+ export { buildClaudeInstallPlan } from "./claude-install-plan.js";
22
+ export { runDoctor, runLint } from "./doctor-lint.js";
23
+ export { runAudit } from "./audit.js";
24
+ export { formatLinkResult, runLink, } from "./link-command.js";
25
+ export { runLinkify } from "./linkify.js";
26
+ export { runSetup, } from "./setup-command.js";
27
+ export { maybePrintUpdateNotice } from "./update-notice.js";
24
28
  const bundledAssets = resolveBundledAssetPaths();
25
- function bundledOntologyDir() {
26
- return bundledAssets.ontologyDir;
27
- }
28
- function bundledClaudeAdapterDir() {
29
- return bundledAssets.claudeAdapterDir;
30
- }
31
- function bundledAdapterRoot() {
32
- return bundledAssets.adapterRoot;
33
- }
34
- // ---------------------------------------------------------------------------
35
- // Helpers
36
- // ---------------------------------------------------------------------------
37
- /** Humanize a folder name: "references" → "References". */
38
- function humanize(name) {
39
- return name.charAt(0).toUpperCase() + name.slice(1);
40
- }
41
- /** Quote a value for copy/pasteable POSIX shell commands. */
42
- function shellQuote(value) {
43
- if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value)) {
44
- return value;
45
- }
46
- return `'${value.replace(/'/g, "'\\''")}'`;
29
+ function shouldResolveBridgeVault(command, vaultExplicit) {
30
+ return (!vaultExplicit &&
31
+ (command === "audit" ||
32
+ command === "linkify" ||
33
+ command === "doctor" ||
34
+ command === "lint" ||
35
+ command === "mcp" ||
36
+ isSemanticCliCommand(command)));
47
37
  }
48
- function isRecord(value) {
49
- return typeof value === "object" && value !== null && !Array.isArray(value);
50
- }
51
- async function readCurrentPackageVersion() {
52
- const packageJson = JSON.parse(await readFile(path.join(bundledAssets.packageRoot, "package.json"), "utf-8"));
53
- return isRecord(packageJson) && typeof packageJson["version"] === "string"
54
- ? packageJson["version"]
55
- : null;
56
- }
57
- function updateNoticeDisabled(env) {
58
- return env["OMS_UPDATE_NOTICE"] === "0" || env["OMS_NO_UPDATE_NOTICE"] === "1";
59
- }
60
- function parseUpdateNoticeTimeout(env) {
61
- const raw = env["OMS_UPDATE_NOTICE_TIMEOUT_MS"];
62
- if (raw === undefined)
63
- return undefined;
64
- const parsed = Number.parseInt(raw, 10);
65
- return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
66
- }
67
- export async function maybePrintUpdateNotice(options = {}) {
68
- const env = options.env ?? process.env;
69
- if (updateNoticeDisabled(env))
70
- return;
71
- const currentVersion = options.currentVersion ?? await readCurrentPackageVersion();
72
- const notice = await checkUpdateNotice({
73
- currentVersion,
74
- latestVersion: options.latestVersion ?? env["OMS_UPDATE_LATEST_VERSION"],
75
- timeoutMs: options.timeoutMs ?? parseUpdateNoticeTimeout(env),
76
- runner: options.runner,
77
- });
78
- const formatted = formatUpdateNotice(notice);
79
- if (formatted.length === 0)
38
+ async function main() {
39
+ const argv = process.argv.slice(2);
40
+ const parsedArgs = parseCliArgs(argv);
41
+ if (parsedArgs.error !== undefined) {
42
+ console.error(parsedArgs.error.message);
43
+ process.exitCode = 1;
80
44
  return;
81
- const write = options.write ?? ((message) => console.error(message));
82
- write(`\n${formatted}`);
83
- }
84
- function parseConceptRef(value) {
85
- if (value === null || value === undefined)
86
- return null;
87
- if (typeof value === "string")
88
- return value;
89
- if (Array.isArray(value) && value.every((item) => typeof item === "string"))
90
- return value;
91
- return null;
92
- }
93
- function parseFolderBinding(value) {
94
- if (!isRecord(value))
95
- return null;
96
- const rawIntent = value["intent"];
97
- return {
98
- intent: typeof rawIntent === "string" && rawIntent.trim() ? rawIntent : "",
99
- concept: parseConceptRef(value["concept"]),
100
- };
101
- }
102
- function parseConceptDocument(filePath, parsed) {
103
- const concept = {
104
- concept: typeof parsed["concept"] === "string" ? parsed["concept"] : path.basename(filePath, path.extname(filePath)),
105
- intent: typeof parsed["intent"] === "string" ? parsed["intent"] : "",
106
- folder: typeof parsed["folder"] === "string" ? parsed["folder"] : "",
107
- fields: Array.isArray(parsed["fields"]) ? parsed["fields"] : [],
108
- lenses: Array.isArray(parsed["lenses"]) ? parsed["lenses"] : [],
109
- };
110
- return { filePath, raw: parsed, concept };
111
- }
112
- async function readConceptDocuments(omsDir) {
113
- const documents = new Map();
114
- const conceptsDir = path.join(omsDir, "concepts");
115
- let entries;
116
- try {
117
- entries = await readdir(conceptsDir);
118
45
  }
119
- catch (error) {
120
- if (error instanceof Error)
121
- return documents;
122
- throw error;
46
+ let { command, vault, vaultExplicit, yes, apply, installClaude, suggestFields, runtime, dryRun, executeExternal, checkUpdate, timeoutMs, agentVault, verbose, json, maxPerConcept, folders, conventionNote, unknownFlags, } = parsedArgs;
47
+ // `mcp` keeps the FULL resolution result: the write surface trusts every
48
+ // source except `cwd`, so the server needs the source, not just the path.
49
+ let mcpTarget;
50
+ if (command === "mcp") {
51
+ mcpTarget = vaultExplicit
52
+ ? { vault, scope: null, source: "explicit" }
53
+ : await resolveEffectiveVault(process.cwd(), process.env);
54
+ vault = mcpTarget.vault;
123
55
  }
124
- for (const file of entries) {
125
- if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
126
- continue;
127
- const filePath = path.join(conceptsDir, file);
128
- const parsed = yamlParse(await readFile(filePath, "utf-8"));
129
- if (!isRecord(parsed))
130
- continue;
131
- const document = parseConceptDocument(filePath, parsed);
132
- documents.set(document.concept.concept, document);
56
+ else if (shouldResolveBridgeVault(command, vaultExplicit)) {
57
+ vault = (await resolveEffectiveVault(process.cwd(), process.env)).vault;
133
58
  }
134
- return documents;
135
- }
136
- function buildPromptConcepts(shippedConcepts, localDocuments) {
137
- const concepts = new Map(shippedConcepts);
138
- for (const [name, document] of localDocuments) {
139
- concepts.set(name, document.concept);
59
+ if (command === "setup") {
60
+ await runSetup({ vault, yes, installClaude, suggestFields });
61
+ await nonFatalGlobalWriteback(() => registerGlobalVault({ vault: path.resolve(vault), homeDir: undefined, overwrite: true }));
62
+ await maybePrintUpdateNotice();
140
63
  }
141
- return concepts;
142
- }
143
- async function readExistingTaxonomy(omsDir) {
144
- try {
145
- const raw = await readFile(path.join(omsDir, "taxonomy.yaml"), "utf-8");
146
- const parsed = yamlParse(raw);
147
- if (!isRecord(parsed))
148
- return null;
149
- const rawFolders = parsed["folders"];
150
- const folders = {};
151
- if (isRecord(rawFolders)) {
152
- for (const [folder, binding] of Object.entries(rawFolders)) {
153
- const parsedBinding = parseFolderBinding(binding);
154
- if (parsedBinding !== null) {
155
- folders[folder] = parsedBinding;
156
- }
157
- }
158
- }
159
- return {
160
- version: typeof parsed["version"] === "number" ? parsed["version"] : 0,
64
+ else if (command === "link") {
65
+ process.exitCode = await runLink({
66
+ cwd: process.cwd(),
67
+ vault,
68
+ vaultExplicit,
161
69
  folders,
162
- };
163
- }
164
- catch (error) {
165
- if (error instanceof Error)
166
- return null;
167
- throw error;
168
- }
169
- }
170
- function defaultConceptForFolder(concepts, folder) {
171
- for (const [name, concept] of concepts) {
172
- if (concept.folder === folder)
173
- return name;
174
- }
175
- return null;
176
- }
177
- function conceptRefToPromptDefault(concept) {
178
- if (Array.isArray(concept))
179
- return concept[0] ?? null;
180
- return concept;
181
- }
182
- function isFieldType(value) {
183
- switch (value) {
184
- case "string":
185
- case "url":
186
- case "date":
187
- case "list":
188
- case "number":
189
- case "boolean":
190
- return true;
191
- default:
192
- return false;
193
- }
194
- }
195
- function mergeAdditionalFields(concept, fields) {
196
- const existing = new Set(concept.fields.map((field) => field.name));
197
- const additions = fields.filter((field) => !existing.has(field.name));
198
- return {
199
- ...concept,
200
- fields: [...concept.fields, ...additions],
201
- lenses: concept.lenses ?? [],
202
- };
203
- }
204
- function mergeAdditionalLenses(concept, lenses) {
205
- const existing = new Set((concept.lenses ?? []).map((lens) => lens.name));
206
- const additions = lenses.filter((lens) => !existing.has(lens.name));
207
- return {
208
- ...concept,
209
- fields: concept.fields,
210
- lenses: [...(concept.lenses ?? []), ...additions],
211
- };
212
- }
213
- async function writeConcept(omsDir, concept, existingDocument) {
214
- const conceptsOutDir = path.join(omsDir, "concepts");
215
- await mkdir(conceptsOutDir, { recursive: true });
216
- const document = {
217
- ...(existingDocument?.raw ?? {}),
218
- concept: concept.concept,
219
- intent: concept.intent,
220
- folder: concept.folder,
221
- fields: concept.fields,
222
- lenses: concept.lenses ?? [],
223
- };
224
- await writeFile(existingDocument?.filePath ?? path.join(conceptsOutDir, `${concept.concept}.yaml`), yamlStringify(document), "utf-8");
225
- }
226
- export function buildClaudeInstallPlan(opts) {
227
- const pluginPath = bundledClaudeAdapterDir();
228
- return {
229
- pluginPath,
230
- pluginInstallCommand: `claude plugin install ${shellQuote(pluginPath)}`,
231
- mcpRegistrationCommand: `claude mcp add oms -- oms mcp --vault ${shellQuote(opts.vault)}`,
232
- mcpRuntimeStatus: "read-status-runtime",
233
- };
234
- }
235
- function printClaudeInstallPlan(plan) {
236
- console.log("Claude Code harness install plan (dry-run).");
237
- console.log(` Plugin path: ${plan.pluginPath}`);
238
- console.log(` Plugin command: ${plan.pluginInstallCommand}`);
239
- console.log(` MCP command: ${plan.mcpRegistrationCommand}`);
240
- console.log(" MCP status: status/read/cache/retrieval plus safe capture; commit is gated by vault confinement and contract validation.");
241
- }
242
- /** Walk a directory recursively, yielding relative paths for all .md files. */
243
- async function* walkMarkdown(dir, base, skipDirs) {
244
- let entries;
245
- try {
246
- entries = await readdir(dir, { withFileTypes: true });
247
- }
248
- catch {
249
- return;
250
- }
251
- for (const entry of entries) {
252
- if (entry.name.startsWith("."))
253
- continue;
254
- if (skipDirs.has(entry.name))
255
- continue;
256
- const full = path.join(dir, entry.name);
257
- if (entry.isDirectory()) {
258
- yield* walkMarkdown(full, base, skipDirs);
259
- }
260
- else if (entry.isFile() && entry.name.endsWith(".md")) {
261
- yield path.relative(base, full).replace(/\\/g, "/");
262
- }
263
- }
264
- }
265
- // ---------------------------------------------------------------------------
266
- // runSetup
267
- // ---------------------------------------------------------------------------
268
- export async function runSetup(opts) {
269
- const { vault, yes, installClaude = false, suggestFields = false } = opts;
270
- const nonInteractive = yes || process.env["OMS_NON_INTERACTIVE"] === "1";
271
- const ontologyDir = bundledOntologyDir();
272
- // Load shipped concepts so we can offer meaningful defaults.
273
- const ontology = await loadOntology(ontologyDir);
274
- const observedSummaries = await collectObservedFields({ vault });
275
- const observedByFolder = new Map(observedSummaries.map((summary) => [summary.folder, summary]));
276
- // Scan vault top-level directories (skip dotfiles).
277
- const topEntries = await readdir(vault, { withFileTypes: true });
278
- const folders = topEntries
279
- .filter((e) => e.isDirectory() && !e.name.startsWith("."))
280
- .map((e) => e.name);
281
- const omsDir = path.join(vault, ".oms");
282
- const existingTaxonomy = await readExistingTaxonomy(omsDir);
283
- const existingConceptDocuments = await readConceptDocuments(omsDir);
284
- const promptConcepts = buildPromptConcepts(ontology.concepts, existingConceptDocuments);
285
- const folderBindings = { ...(existingTaxonomy?.folders ?? {}) };
286
- const observedFieldsByConcept = new Map();
287
- const interactiveFieldsByConcept = new Map();
288
- const interactiveLensesByConcept = new Map();
289
- if (nonInteractive) {
290
- // Non-interactive: use defaults without readline.
291
- for (const folder of folders) {
292
- const existing = folderBindings[folder];
293
- const conceptName = conceptRefToPromptDefault(existing?.concept ?? null) ??
294
- defaultConceptForFolder(promptConcepts, folder);
295
- folderBindings[folder] = {
296
- intent: existing?.intent || humanize(folder),
297
- concept: conceptName,
298
- };
299
- if (suggestFields && conceptName !== null) {
300
- const summary = observedByFolder.get(folder);
301
- if (summary !== undefined) {
302
- observedFieldsByConcept.set(conceptName, [
303
- ...(observedFieldsByConcept.get(conceptName) ?? []),
304
- ...summary.fields,
305
- ]);
306
- }
307
- }
308
- }
309
- }
310
- else {
311
- // Interactive: ask intent and concept for each folder.
312
- const rl = opts.prompt ??
313
- createInterface({
314
- input: process.stdin,
315
- output: process.stdout,
316
- });
317
- const conceptNames = Array.from(promptConcepts.keys());
318
- try {
319
- console.log("\nOh My Second Brain Setup — adopting existing vault folders.\n");
320
- console.log(`Available concepts: ${conceptNames.join(", ") || "(none)"}\n`);
321
- for (const folder of folders) {
322
- const existing = folderBindings[folder];
323
- const defaultIntent = existing?.intent || humanize(folder);
324
- const rawIntent = await rl.question(`Folder "${folder}" — intent [${defaultIntent}]: `);
325
- const intent = rawIntent.trim() || defaultIntent;
326
- // Find default concept
327
- const defaultConcept = conceptRefToPromptDefault(existing?.concept ?? null) ??
328
- defaultConceptForFolder(promptConcepts, folder);
329
- const conceptPrompt = defaultConcept
330
- ? ` Bind concept [${defaultConcept}] (blank = ${defaultConcept}, "null" = none): `
331
- : ` Bind concept (${conceptNames.join("/") || "none"}, blank = none): `;
332
- const rawConcept = await rl.question(conceptPrompt);
333
- const trimmed = rawConcept.trim();
334
- let conceptName;
335
- if (trimmed === "null" || trimmed === "") {
336
- conceptName = trimmed === "null" ? null : (defaultConcept ?? null);
337
- }
338
- else if (promptConcepts.has(trimmed)) {
339
- conceptName = trimmed;
340
- }
341
- else {
342
- console.warn(` Unknown concept "${trimmed}"; binding as null.`);
343
- conceptName = null;
344
- }
345
- folderBindings[folder] = { intent, concept: conceptName };
346
- const summary = observedByFolder.get(folder);
347
- if (summary !== undefined && summary.fields.length > 0 && conceptName !== null) {
348
- const observedNames = summary.fields.map((field) => `${field.name}:${field.type}`).join(", ");
349
- console.log(` Observed fields: ${observedNames}`);
350
- for (const warning of summary.warnings) {
351
- console.warn(` Frontmatter warning: ${warning}`);
352
- }
353
- const rawFields = await rl.question(" Add observed fields (comma-separated names, blank = none): ");
354
- const requested = new Set(rawFields
355
- .split(",")
356
- .map((field) => field.trim())
357
- .filter((field) => field.length > 0));
358
- const selected = [];
359
- for (const observed of summary.fields) {
360
- if (!requested.has(observed.name))
361
- continue;
362
- const rawType = await rl.question(` Field "${observed.name}" type [${observed.type}]: `);
363
- const trimmedType = rawType.trim();
364
- const fieldType = isFieldType(trimmedType) ? trimmedType : observed.type;
365
- const rawRequired = await rl.question(` Field "${observed.name}" required? [n]: `);
366
- const rawFieldIntent = await rl.question(` Field "${observed.name}" intent [Observed ${observed.name}]: `);
367
- selected.push({
368
- name: observed.name,
369
- type: fieldType,
370
- required: /^y(?:es)?$/i.test(rawRequired.trim()),
371
- intent: rawFieldIntent.trim() || `Observed ${observed.name}`,
372
- });
373
- }
374
- if (selected.length > 0) {
375
- interactiveFieldsByConcept.set(conceptName, [
376
- ...(interactiveFieldsByConcept.get(conceptName) ?? []),
377
- ...selected,
378
- ]);
379
- }
380
- const knownFields = new Set([
381
- ...Array.from(promptConcepts.get(conceptName)?.fields ?? []).map((field) => field.name),
382
- ...selected.map((field) => field.name),
383
- ]);
384
- const rawLenses = await rl.question(" Retrieval lenses (name:field1,field2; blank = none): ");
385
- const lenses = parseLensDefinitions(rawLenses, knownFields);
386
- if (lenses.length > 0) {
387
- interactiveLensesByConcept.set(conceptName, [
388
- ...(interactiveLensesByConcept.get(conceptName) ?? []),
389
- ...lenses,
390
- ]);
391
- }
392
- }
393
- }
394
- }
395
- finally {
396
- rl.close();
397
- }
398
- }
399
- const taxonomy = { version: existingTaxonomy?.version ?? 0, folders: folderBindings };
400
- // Write the vault-local ontology. ``.oms/` IS the ontology directory:
401
- // `.oms/taxonomy.yaml` + `.oms/concepts/*.yaml`, matching loadOntology's
402
- // contract so `oms doctor` can load it directly.
403
- const conceptsOutDir = path.join(omsDir, "concepts");
404
- await mkdir(conceptsOutDir, { recursive: true });
405
- await writeFile(path.join(omsDir, "taxonomy.yaml"), yamlStringify(taxonomy), "utf-8");
406
- // Copy shipped concept yaml files into vault/.oms/concepts/
407
- const conceptsSourceDir = path.join(ontologyDir, "concepts");
408
- let copiedFiles = [];
409
- try {
410
- const conceptFiles = await readdir(conceptsSourceDir);
411
- for (const file of conceptFiles) {
412
- if (file.endsWith(".yaml") || file.endsWith(".yml")) {
413
- const target = path.join(conceptsOutDir, file);
414
- try {
415
- await readFile(target, "utf-8");
416
- }
417
- catch (error) {
418
- if (!(error instanceof Error))
419
- throw error;
420
- await copyFile(path.join(conceptsSourceDir, file), target);
421
- copiedFiles.push(file);
422
- }
423
- }
424
- }
425
- }
426
- catch (err) {
427
- console.warn("[oms] Could not copy concept files:", err);
428
- }
429
- const localOntology = await loadOntology(omsDir);
430
- const localConceptDocuments = await readConceptDocuments(omsDir);
431
- const conceptNamesToUpdate = new Set([
432
- ...observedFieldsByConcept.keys(),
433
- ...interactiveFieldsByConcept.keys(),
434
- ...interactiveLensesByConcept.keys(),
435
- ]);
436
- for (const conceptName of conceptNamesToUpdate) {
437
- const concept = localOntology.concepts.get(conceptName);
438
- if (concept === undefined)
439
- continue;
440
- const withObserved = mergeObservedFieldsIntoConcept(concept, observedFieldsByConcept.get(conceptName) ?? []);
441
- const withInteractiveFields = mergeAdditionalFields(withObserved, interactiveFieldsByConcept.get(conceptName) ?? []);
442
- const withLenses = mergeAdditionalLenses(withInteractiveFields, interactiveLensesByConcept.get(conceptName) ?? []);
443
- await writeConcept(omsDir, withLenses, localConceptDocuments.get(conceptName));
444
- }
445
- // Summary
446
- console.log(`\nOh My Second Brain setup complete.`);
447
- console.log(` Vault: ${vault}`);
448
- console.log(` Written: ${path.join(omsDir, "taxonomy.yaml")}`);
449
- console.log(` Concepts: ${copiedFiles.join(", ") || "(none)"}`);
450
- console.log(` Folders: ${Object.keys(folderBindings).join(", ") || "(none)"}`);
451
- console.log(`\nRun "oh-my-second-brain doctor" to validate existing notes.\n`);
452
- if (installClaude) {
453
- printClaudeInstallPlan(buildClaudeInstallPlan({ vault }));
454
- console.log("");
70
+ conventionNote,
71
+ });
72
+ await maybePrintUpdateNotice();
455
73
  }
456
- }
457
- // ---------------------------------------------------------------------------
458
- // runDoctor
459
- // ---------------------------------------------------------------------------
460
- export async function runDoctor(opts) {
461
- const { vault } = opts;
462
- // Doctor is non-blocking (onViolation: warn). It must ALWAYS exit 0 in v0,
463
- // even if the ontology is missing or unparseable — wrap the whole body so a
464
- // failure surfaces as a warning, never a non-zero exit.
465
- try {
466
- // Load ontology: prefer the vault-local `.oms/` ontology, fall back to the
467
- // bundled defaults. The vault-local layout is `.oms/taxonomy.yaml` +
468
- // `.oms/concepts/`, so `.oms/` itself is the ontology dir.
469
- const localOntologyDir = path.join(vault, ".oms");
470
- let ontologyDir;
471
- try {
472
- await readdir(path.join(localOntologyDir, "concepts"));
473
- ontologyDir = localOntologyDir;
474
- }
475
- catch {
476
- ontologyDir = bundledOntologyDir();
477
- }
478
- const ontology = await loadOntology(ontologyDir);
479
- const skipDirs = new Set(["node_modules"]);
480
- let totalNotes = 0;
481
- let totalViolations = 0;
482
- let notesWithViolations = 0;
483
- for await (const relPath of walkMarkdown(vault, vault, skipDirs)) {
484
- const concept = resolveConcept(ontology, relPath);
485
- if (!concept)
486
- continue;
487
- totalNotes++;
488
- const fullPath = path.join(vault, relPath);
489
- let raw;
490
- try {
491
- raw = await readFile(fullPath, "utf-8");
492
- }
493
- catch {
494
- console.warn(`[oms] Could not read ${relPath}`);
495
- continue;
496
- }
497
- const { frontmatter } = parseNote(raw);
498
- const result = validateFrontmatter(frontmatter, concept);
499
- if (result.violations.length > 0) {
500
- notesWithViolations++;
501
- totalViolations += result.violations.length;
502
- console.log(`\n ${relPath} [concept: ${concept.concept}]`);
503
- for (const v of result.violations) {
504
- console.log(` [${v.rule}] ${v.message}`);
505
- }
506
- }
507
- }
508
- console.log(`\nOh My Second Brain doctor: ${totalNotes} notes checked, ${notesWithViolations} with violations, ${totalViolations} total violations.`);
509
- console.log("All violations are warnings (onViolation: warn). Exit 0.\n");
510
- // Broken-link and orphan detection (C4 lint port).
511
- try {
512
- const lintResult = await detectLinkIssues(vault);
513
- if (lintResult.brokenLinks.length > 0) {
514
- console.log(`\n--- Broken wikilinks (${lintResult.brokenLinks.length}) ---`);
515
- for (const { notePath, target } of lintResult.brokenLinks) {
516
- console.log(` [broken-link] ${notePath} -> [[${target}]]`);
517
- }
518
- }
519
- else {
520
- console.log("Broken wikilinks: 0");
521
- }
522
- const orphanCount = lintResult.orphanPaths.length;
523
- if (orphanCount > 0) {
524
- console.log(`\n--- Orphan notes (no incoming links): ${orphanCount} ---`);
525
- for (const p of lintResult.orphanPaths.slice(0, 20)) {
526
- console.log(` [orphan] ${p}`);
527
- }
528
- if (orphanCount > 20) {
529
- console.log(` ... and ${orphanCount - 20} more`);
530
- }
531
- }
532
- else {
533
- console.log("Orphan notes: 0");
534
- }
535
- }
536
- catch (lintErr) {
537
- console.warn("[oms] lint detection could not complete:", lintErr);
538
- }
74
+ else if (command === "install" || command === "uninstall") {
75
+ process.exitCode = await runInstallOrUninstall(command, hostContext());
76
+ if (process.exitCode === 0)
77
+ await maybePrintUpdateNotice();
539
78
  }
540
- catch (err) {
541
- console.warn("[oms] doctor could not complete:", err);
79
+ else if (command === "update") {
80
+ process.exitCode = await runUpdateCommand(hostContext());
542
81
  }
543
- // Always exit 0 in v0 (non-blocking, onViolation: warn).
544
- return 0;
545
- }
546
- // ---------------------------------------------------------------------------
547
- // main
548
- // ---------------------------------------------------------------------------
549
- function printUsage() {
550
- console.log(`
551
- oh-my-second-brain — Oh My Second Brain convention layer for Obsidian vaults
552
-
553
- Usage:
554
- oh-my-second-brain setup [--vault <path>] [--yes] [--suggest-fields] [--install-claude]
555
- oh-my-second-brain install [--vault <path>] [--runtime <auto|all|claude|codex|hermes>] [--dry-run] [--execute] [--yes]
556
- oh-my-second-brain uninstall [--runtime <all|claude|codex|hermes>] [--dry-run] [--execute] [--yes]
557
- oh-my-second-brain update [--check] [--dry-run] [--yes] [--runtime <auto|all|claude|codex|hermes>] [--vault <path>]
558
- oh-my-second-brain doctor [--vault <path>]
559
- oh-my-second-brain semantic <status|sync|query|search|vsearch|get|multi-get|collection> [options]
560
- oh-my-second-brain mcp [--vault <path>]
561
- oh-my-second-brain hook pre-tool-use [--vault <path>]
562
- oh-my-second-brain hook post-tool-use [--vault <path>]
563
-
564
- Compatibility alias: oms <command>
565
-
566
- Commands:
567
- setup Adopt an existing vault into the Oh My Second Brain convention.
568
- install Install Oh My Second Brain host adapters and MCP registration.
569
- uninstall Remove Oh My Second Brain host adapters and MCP registration.
570
- update Check for or apply an explicit package update, then refresh host adapters.
571
- doctor Validate vault notes against the active ontology (includes broken-link and orphan detection).
572
- semantic Native markdown semantic index/search/get commands.
573
- mcp Start the read/status MCP stdio server.
574
- hook Vault guard hooks for Claude Code PreToolUse / PostToolUse events.
575
- pre-tool-use Read PreToolUse JSON from stdin; block unregistered folder creation.
576
- post-tool-use Read PostToolUse JSON from stdin; audit frontmatter + trigger graph build.
577
-
578
- Options:
579
- --vault <path> Path to the vault root (default: current directory).
580
- --yes Non-interactive setup, uninstall confirmation, or update execution.
581
- --suggest-fields During setup --yes, add conservative observed frontmatter fields to concepts.
582
- --install-claude Print Claude Code plugin install and MCP registration commands (dry-run).
583
- --runtime <name> Select host runtime (default: auto for install, all for uninstall).
584
- --dry-run Preview host config changes without writing files.
585
- --execute Allow external host CLIs such as \`claude\` to run when available.
586
- `);
587
- }
588
- async function main() {
589
- const argv = process.argv.slice(2);
590
- const command = argv[0];
591
- // Parse shared flags.
592
- let vault = process.cwd();
593
- let yes = false;
594
- let installClaude = false;
595
- let suggestFields = false;
596
- let runtime;
597
- let dryRun = false;
598
- let executeExternal = false;
599
- let checkUpdate = false;
600
- let timeoutMs;
601
- let agentVault;
602
- const unknownFlags = [];
603
- for (let i = 1; i < argv.length; i++) {
604
- if (argv[i] === "--vault" && argv[i + 1]) {
605
- vault = path.resolve(argv[i + 1]);
606
- i++;
607
- }
608
- else if (argv[i] === "--yes") {
609
- yes = true;
610
- }
611
- else if (argv[i] === "--install-claude") {
612
- installClaude = true;
613
- }
614
- else if (argv[i] === "--suggest-fields") {
615
- suggestFields = true;
616
- }
617
- else if (argv[i] === "--check") {
618
- checkUpdate = true;
619
- }
620
- else if (argv[i] === "--timeout-ms" && argv[i + 1]) {
621
- const parsed = Number.parseInt(argv[i + 1], 10);
622
- if (!Number.isFinite(parsed) || parsed <= 0) {
623
- console.error(`[oms] Unsupported timeout: ${argv[i + 1]}`);
624
- process.exitCode = 1;
625
- return;
626
- }
627
- timeoutMs = parsed;
628
- i++;
629
- }
630
- else if (argv[i] === "--runtime" && argv[i + 1]) {
631
- const rawRuntime = argv[i + 1];
632
- if (rawRuntime === "auto" ||
633
- rawRuntime === "all" ||
634
- rawRuntime === "claude" ||
635
- rawRuntime === "codex" ||
636
- rawRuntime === "hermes") {
637
- runtime = rawRuntime;
638
- }
639
- else {
640
- console.error(`[oms] Unsupported runtime: ${rawRuntime}`);
641
- process.exitCode = 1;
642
- return;
643
- }
644
- i++;
645
- }
646
- else if (argv[i] === "--agent-vault" && argv[i + 1]) {
647
- agentVault = path.resolve(argv[i + 1]);
648
- i++;
649
- }
650
- else if (argv[i] === "--dry-run") {
651
- dryRun = true;
652
- }
653
- else if (argv[i] === "--execute") {
654
- executeExternal = true;
655
- }
656
- else {
657
- unknownFlags.push(argv[i]);
658
- }
82
+ else if (command === "update-reconcile") {
83
+ process.exitCode = await runUpdateReconcile(hostContext());
659
84
  }
660
- if (command === "setup") {
661
- await runSetup({ vault, yes, installClaude, suggestFields });
85
+ else if (command === "doctor") {
86
+ process.exitCode = await runDoctor({ vault, verbose, json, maxPerConcept });
662
87
  await maybePrintUpdateNotice();
663
88
  }
664
- else if (command === "install" || command === "uninstall") {
665
- const selectedRuntime = runtime ?? (command === "install" ? "auto" : "all");
666
- if (command === "uninstall" && !yes && !dryRun && process.env["OMS_NON_INTERACTIVE"] !== "1") {
667
- console.error("[oms] Refusing uninstall without --yes or --dry-run.");
668
- process.exitCode = 1;
669
- return;
670
- }
671
- const results = await runHostOperation({
672
- action: command,
673
- runtime: selectedRuntime,
89
+ else if (command === "audit") {
90
+ process.exitCode = await runAudit({
674
91
  vault,
675
- agentVault,
676
- dryRun,
677
- executeExternal,
678
- yes,
679
- adapterRoot: bundledAdapterRoot(),
92
+ json,
93
+ folder: folders[0],
94
+ suggestFields,
680
95
  });
681
- console.log(formatHostOperationResults(results, dryRun));
682
96
  await maybePrintUpdateNotice();
683
97
  }
684
- else if (command === "update") {
685
- if (unknownFlags.length > 0) {
686
- console.error(`[oms] Unsupported update option: ${unknownFlags.join(", ")}`);
687
- process.exitCode = 1;
688
- return;
689
- }
690
- const currentVersion = await readCurrentPackageVersion();
691
- const latestVersion = process.env["OMS_UPDATE_LATEST_VERSION"];
692
- const result = await runUpdate({
693
- currentVersion,
694
- latestVersion,
695
- runtime: runtime ?? "all",
98
+ else if (command === "linkify") {
99
+ process.exitCode = await runLinkify({
696
100
  vault,
697
- check: checkUpdate,
698
- dryRun,
101
+ folder: folders[0],
102
+ apply,
699
103
  yes,
700
- executeExternal,
701
- timeoutMs,
702
- reconcileCommand: {
703
- command: process.execPath,
704
- argsPrefix: process.argv[1] === undefined ? [] : [process.argv[1]],
705
- },
706
- });
707
- console.log(formatUpdateResult(result));
708
- process.exitCode = result.success ? 0 : 1;
709
- }
710
- else if (command === "update-reconcile") {
711
- if (process.env["OMS_UPDATE_RECONCILE"] !== "1" && !dryRun) {
712
- console.error("[oms] update-reconcile is internal; run `oms update --yes` instead.");
713
- process.exitCode = 1;
714
- return;
715
- }
716
- const results = await runHostOperation({
717
- action: "install",
718
- runtime: runtime ?? "all",
719
- vault,
720
- dryRun,
721
- executeExternal,
722
- yes: true,
723
- adapterRoot: bundledAdapterRoot(),
724
104
  });
725
- console.log(formatHostOperationResults(results, dryRun));
105
+ await maybePrintUpdateNotice();
726
106
  }
727
- else if (command === "doctor") {
728
- process.exitCode = await runDoctor({ vault });
107
+ else if (command === "lint") {
108
+ process.exitCode = await runLint({ vault, verbose, json });
729
109
  await maybePrintUpdateNotice();
730
110
  }
731
111
  else if (isSemanticCliCommand(command)) {
@@ -736,7 +116,10 @@ async function main() {
736
116
  await maybePrintUpdateNotice();
737
117
  }
738
118
  else if (command === "mcp") {
739
- await runMcpServer({ vault });
119
+ await runMcpServer({
120
+ vault,
121
+ source: mcpTarget?.source ?? "explicit",
122
+ });
740
123
  }
741
124
  else if (command === "hook") {
742
125
  const subcommand = argv[1];
@@ -756,9 +139,23 @@ async function main() {
756
139
  printUsage();
757
140
  process.exitCode = 0;
758
141
  }
142
+ function hostContext() {
143
+ return {
144
+ vault,
145
+ vaultExplicit,
146
+ runtime,
147
+ agentVault,
148
+ dryRun,
149
+ executeExternal,
150
+ yes,
151
+ json,
152
+ checkUpdate,
153
+ timeoutMs,
154
+ unknownFlags,
155
+ adapterRoot: bundledAssets.adapterRoot,
156
+ };
157
+ }
759
158
  }
760
- // Guard: only run main() when this file is the entry point.
761
- // Works for both source (`src/cli/oms.ts`) and built (`dist/cli/oms.js`) paths.
762
159
  const __filename = fileURLToPath(import.meta.url);
763
160
  function sameEntrypoint(left, right) {
764
161
  const resolvedLeft = path.resolve(left);