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
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../src/engine/graph/resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../src/engine/graph/resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Link application: splice accepted candidates into a note body and persist
3
+ * through the capture kernel.
4
+ *
5
+ * This is the only linkify module with a side effect, and even here the effect
6
+ * is injected — `writeNote` arrives as a parameter, `node:fs` is never imported,
7
+ * and the capture kernel is referenced by TYPE only. mask.ts and suggest.ts stay
8
+ * pure; every disk decision (path safety, concept contract, postcondition
9
+ * re-read) remains the kernel's, unduplicated here.
10
+ *
11
+ * Optimistic concurrency: candidates carry absolute offsets into the body they
12
+ * were computed from. If that body changed, the offsets are lies. `applyLinks`
13
+ * therefore re-hashes the body it is handed and refuses to write on any
14
+ * mismatch, on any candidate whose recorded text no longer sits at its offsets,
15
+ * and on any overlapping pair — three independent ways the same corruption
16
+ * could otherwise reach disk.
17
+ */
18
+ import type { WriteNoteInput, WriteNoteResult } from "../../capture/safe.js";
19
+ import type { LinkCandidate } from "./types.js";
20
+ /** The capture-kernel seam apply persists through (structurally `writeNote`). */
21
+ export type WriteNoteLike = (input: WriteNoteInput) => Promise<WriteNoteResult>;
22
+ /** Everything the kernel needs to address the note, minus the body apply supplies. */
23
+ export type LinkifyWriteTarget = Omit<WriteNoteInput, "mode" | "dryRun" | "body" | "frontmatter">;
24
+ /** Why an apply attempt produced no write. */
25
+ export type ApplyRefusal = "note-changed" | "no-candidates" | "candidate-drift" | "overlapping-candidates" | "write-rejected";
26
+ /** Outcome of {@link applyLinks}: a written body, or a typed refusal. */
27
+ export type ApplyResult = {
28
+ readonly applied: true;
29
+ readonly body: string;
30
+ readonly contentHash: string;
31
+ readonly write: WriteNoteResult;
32
+ } | {
33
+ readonly applied: false;
34
+ readonly reason: ApplyRefusal;
35
+ readonly write?: WriteNoteResult;
36
+ };
37
+ /** Inputs for {@link applyLinks}, grouped so the call site stays readable. */
38
+ export interface ApplyLinksInput {
39
+ /** The note body the candidates were computed against. */
40
+ readonly body: string;
41
+ /** sha256 hex of that body, taken when the candidates were produced. */
42
+ readonly baseContentHash: string;
43
+ /** The candidates the caller (or user) accepted. */
44
+ readonly accepted: readonly LinkCandidate[];
45
+ readonly writeNote: WriteNoteLike;
46
+ readonly target: LinkifyWriteTarget;
47
+ }
48
+ /** sha256 hex digest of a note body — the optimistic-concurrency token. */
49
+ export declare function hashBody(body: string): string;
50
+ /**
51
+ * Apply accepted link candidates to a note body and persist the result.
52
+ *
53
+ * Returns `{ applied: false, reason }` — with no write attempted — whenever the
54
+ * body has drifted from the snapshot the candidates were computed against.
55
+ */
56
+ export declare function applyLinks(input: ApplyLinksInput): Promise<ApplyResult>;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Link application: splice accepted candidates into a note body and persist
3
+ * through the capture kernel.
4
+ *
5
+ * This is the only linkify module with a side effect, and even here the effect
6
+ * is injected — `writeNote` arrives as a parameter, `node:fs` is never imported,
7
+ * and the capture kernel is referenced by TYPE only. mask.ts and suggest.ts stay
8
+ * pure; every disk decision (path safety, concept contract, postcondition
9
+ * re-read) remains the kernel's, unduplicated here.
10
+ *
11
+ * Optimistic concurrency: candidates carry absolute offsets into the body they
12
+ * were computed from. If that body changed, the offsets are lies. `applyLinks`
13
+ * therefore re-hashes the body it is handed and refuses to write on any
14
+ * mismatch, on any candidate whose recorded text no longer sits at its offsets,
15
+ * and on any overlapping pair — three independent ways the same corruption
16
+ * could otherwise reach disk.
17
+ */
18
+ import { createHash } from "node:crypto";
19
+ /** sha256 hex digest of a note body — the optimistic-concurrency token. */
20
+ export function hashBody(body) {
21
+ return createHash("sha256").update(body, "utf-8").digest("hex");
22
+ }
23
+ /** True when any two candidates claim overlapping body ranges. */
24
+ function hasOverlap(sorted) {
25
+ return sorted.some((candidate, index) => {
26
+ const previous = sorted[index - 1];
27
+ return previous !== undefined && candidate.startOffset < previous.endOffset;
28
+ });
29
+ }
30
+ /** True when every candidate's recorded text still sits at its offsets. */
31
+ function offsetsIntact(body, candidates) {
32
+ return candidates.every((candidate) => body.slice(candidate.startOffset, candidate.endOffset) === candidate.matchedText);
33
+ }
34
+ /** Splice replacements right-to-left so untouched offsets stay valid. */
35
+ function splice(body, sorted) {
36
+ return sorted.reduceRight((acc, candidate) => acc.slice(0, candidate.startOffset) + candidate.renderedReplacement + acc.slice(candidate.endOffset), body);
37
+ }
38
+ /**
39
+ * Apply accepted link candidates to a note body and persist the result.
40
+ *
41
+ * Returns `{ applied: false, reason }` — with no write attempted — whenever the
42
+ * body has drifted from the snapshot the candidates were computed against.
43
+ */
44
+ export async function applyLinks(input) {
45
+ if (hashBody(input.body) !== input.baseContentHash) {
46
+ return { applied: false, reason: "note-changed" };
47
+ }
48
+ if (input.accepted.length < 1) {
49
+ return { applied: false, reason: "no-candidates" };
50
+ }
51
+ const sorted = input.accepted.slice().sort((a, b) => a.startOffset - b.startOffset);
52
+ if (hasOverlap(sorted)) {
53
+ return { applied: false, reason: "overlapping-candidates" };
54
+ }
55
+ if (!offsetsIntact(input.body, sorted)) {
56
+ return { applied: false, reason: "candidate-drift" };
57
+ }
58
+ const body = splice(input.body, sorted);
59
+ const write = await input.writeNote({ ...input.target, mode: "update", dryRun: false, body });
60
+ if (write.status !== "written") {
61
+ return { applied: false, reason: "write-rejected", write };
62
+ }
63
+ return { applied: true, body, contentHash: hashBody(body), write };
64
+ }
65
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/engine/linkify/apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Korean josa (조사) table + stem matcher for the linkify span detector.
3
+ *
4
+ * Why this exists: Korean is agglutinative, so a vault term almost never appears
5
+ * bare in prose — "아타락시아" shows up as "아타락시아를", "아타락시아는",
6
+ * "아타락시아에서". A plain word-boundary matcher misses every one of them, and a
7
+ * plain prefix matcher over-matches ("학교" inside "학교폭력").
8
+ *
9
+ * The rule this module encodes: a term matches a token when the term is a prefix
10
+ * and the remainder is a KNOWN particle from the table below (or empty). An
11
+ * unknown remainder is NOT a match — there is no morphological analysis here and
12
+ * no guessing. Latin-script terms get ordinary case-insensitive whole-token
13
+ * matching; particle logic never applies to them.
14
+ *
15
+ * Pure module: no I/O, no state. Tokenisation grain matches
16
+ * src/engine/graph/node.ts::tokenize (\p{L}/\p{N} runs), so callers can feed it
17
+ * whitespace/punctuation-delimited tokens directly.
18
+ */
19
+ /**
20
+ * Common Korean particles, ≤2 syllables, that may directly follow a noun.
21
+ *
22
+ * Plain reviewable data, grouped by role. Deliberately conservative: only
23
+ * particles that attach to a bare noun stem are listed, because anything longer
24
+ * or more contextual (verb endings such as "하게", "이라는") is exactly the case
25
+ * the matcher must reject rather than guess at.
26
+ */
27
+ export declare const KOREAN_PARTICLES: readonly ["이", "가", "께서", "은", "는", "을", "를", "의", "에", "에서", "에게", "께", "한테", "으로", "로", "와", "과", "하고", "이랑", "랑", "보다", "부터", "까지", "에도", "에는", "도", "만", "조차", "마저", "밖에", "이나", "이란", "란", "이다"];
28
+ /** A particle string drawn from {@link KOREAN_PARTICLES}. */
29
+ export type KoreanParticle = (typeof KOREAN_PARTICLES)[number];
30
+ /**
31
+ * Outcome of matching a term against a single token.
32
+ *
33
+ * Offsets are UTF-16 code-unit indices into the token, so `token.slice(stemStart,
34
+ * stemEnd)` yields the stem the caller should wrap. Particle fields are null on
35
+ * a bare match (no trailing particle).
36
+ */
37
+ export type JosaMatch = {
38
+ readonly kind: "match";
39
+ readonly stem: string;
40
+ readonly stemStart: number;
41
+ readonly stemEnd: number;
42
+ readonly particle: string | null;
43
+ readonly particleStart: number | null;
44
+ readonly particleEnd: number | null;
45
+ } | {
46
+ readonly kind: "no_match";
47
+ };
48
+ /** True when the remainder is a known particle short enough to be one. */
49
+ export declare function isKnownParticle(remainder: string): boolean;
50
+ /**
51
+ * Match `term` inside a single whitespace/punctuation-delimited `token`.
52
+ *
53
+ * Korean-final terms accept one trailing particle from {@link KOREAN_PARTICLES};
54
+ * the returned span covers the stem only. Every other trailing remainder is a
55
+ * no-match. Latin/other-script terms require the whole token to equal the term
56
+ * (case-insensitive) — no particle absorption, no partial-word hits.
57
+ */
58
+ export declare function matchTermInToken(term: string, token: string): JosaMatch;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Korean josa (조사) table + stem matcher for the linkify span detector.
3
+ *
4
+ * Why this exists: Korean is agglutinative, so a vault term almost never appears
5
+ * bare in prose — "아타락시아" shows up as "아타락시아를", "아타락시아는",
6
+ * "아타락시아에서". A plain word-boundary matcher misses every one of them, and a
7
+ * plain prefix matcher over-matches ("학교" inside "학교폭력").
8
+ *
9
+ * The rule this module encodes: a term matches a token when the term is a prefix
10
+ * and the remainder is a KNOWN particle from the table below (or empty). An
11
+ * unknown remainder is NOT a match — there is no morphological analysis here and
12
+ * no guessing. Latin-script terms get ordinary case-insensitive whole-token
13
+ * matching; particle logic never applies to them.
14
+ *
15
+ * Pure module: no I/O, no state. Tokenisation grain matches
16
+ * src/engine/graph/node.ts::tokenize (\p{L}/\p{N} runs), so callers can feed it
17
+ * whitespace/punctuation-delimited tokens directly.
18
+ */
19
+ // ---------------------------------------------------------------------------
20
+ // Particle table
21
+ // ---------------------------------------------------------------------------
22
+ /**
23
+ * Common Korean particles, ≤2 syllables, that may directly follow a noun.
24
+ *
25
+ * Plain reviewable data, grouped by role. Deliberately conservative: only
26
+ * particles that attach to a bare noun stem are listed, because anything longer
27
+ * or more contextual (verb endings such as "하게", "이라는") is exactly the case
28
+ * the matcher must reject rather than guess at.
29
+ */
30
+ export const KOREAN_PARTICLES = [
31
+ // subject (주격)
32
+ "이",
33
+ "가",
34
+ "께서",
35
+ // topic (보조사 — 주제)
36
+ "은",
37
+ "는",
38
+ // object (목적격)
39
+ "을",
40
+ "를",
41
+ // possessive (관형격)
42
+ "의",
43
+ // locative / directional (부사격)
44
+ "에",
45
+ "에서",
46
+ "에게",
47
+ "께",
48
+ "한테",
49
+ "으로",
50
+ "로",
51
+ // comitative / conjunctive (접속)
52
+ "와",
53
+ "과",
54
+ "하고",
55
+ "이랑",
56
+ "랑",
57
+ // comparative / source (부사격)
58
+ "보다",
59
+ "부터",
60
+ "까지",
61
+ "에도",
62
+ "에는",
63
+ // auxiliary (보조사)
64
+ "도",
65
+ "만",
66
+ "조차",
67
+ "마저",
68
+ "밖에",
69
+ "이나",
70
+ "이란",
71
+ "란",
72
+ // copula attached straight to a noun
73
+ "이다",
74
+ ];
75
+ const PARTICLE_SET = new Set(KOREAN_PARTICLES);
76
+ const NO_MATCH = { kind: "no_match" };
77
+ // ---------------------------------------------------------------------------
78
+ // Matcher
79
+ // ---------------------------------------------------------------------------
80
+ const HANGUL_SYLLABLE = /^[\uAC00-\uD7A3]+$/u;
81
+ /** True when the string's last character is a Hangul syllable. */
82
+ function endsWithHangul(text) {
83
+ const last = text.slice(-1);
84
+ return last.length > 0 && HANGUL_SYLLABLE.test(last);
85
+ }
86
+ /** True when the remainder is a known particle short enough to be one. */
87
+ export function isKnownParticle(remainder) {
88
+ return remainder.length <= 2 && PARTICLE_SET.has(remainder);
89
+ }
90
+ /**
91
+ * Match `term` inside a single whitespace/punctuation-delimited `token`.
92
+ *
93
+ * Korean-final terms accept one trailing particle from {@link KOREAN_PARTICLES};
94
+ * the returned span covers the stem only. Every other trailing remainder is a
95
+ * no-match. Latin/other-script terms require the whole token to equal the term
96
+ * (case-insensitive) — no particle absorption, no partial-word hits.
97
+ */
98
+ export function matchTermInToken(term, token) {
99
+ if (term.length < 1 || token.length < 1)
100
+ return NO_MATCH;
101
+ if (!endsWithHangul(term)) {
102
+ return token.toLowerCase() === term.toLowerCase() ? bareMatch(term.length, token) : NO_MATCH;
103
+ }
104
+ if (!token.startsWith(term))
105
+ return NO_MATCH;
106
+ const remainder = token.slice(term.length);
107
+ if (remainder.length < 1)
108
+ return bareMatch(term.length, token);
109
+ if (!isKnownParticle(remainder))
110
+ return NO_MATCH;
111
+ return {
112
+ kind: "match",
113
+ stem: token.slice(0, term.length),
114
+ stemStart: 0,
115
+ stemEnd: term.length,
116
+ particle: remainder,
117
+ particleStart: term.length,
118
+ particleEnd: token.length,
119
+ };
120
+ }
121
+ /** Whole-token match with no trailing particle. */
122
+ function bareMatch(stemEnd, token) {
123
+ return {
124
+ kind: "match",
125
+ stem: token.slice(0, stemEnd),
126
+ stemStart: 0,
127
+ stemEnd,
128
+ particle: null,
129
+ particleStart: null,
130
+ particleEnd: null,
131
+ };
132
+ }
133
+ //# sourceMappingURL=josa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"josa.js","sourceRoot":"","sources":["../../../src/engine/linkify/josa.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Body masking: split a note body into regions the linkifier may rewrite and
3
+ * regions it must leave byte-for-byte alone.
4
+ *
5
+ * Why this exists: inserting `[[…]]` into a code fence, a URL, an existing
6
+ * wikilink, or a heading corrupts the note. The span detector therefore never
7
+ * sees the raw body — it sees only the FREE spans this module returns.
8
+ *
9
+ * Design: one collector pass per construct family, then a sort-and-merge into
10
+ * disjoint ascending ranges, then the complement. Merging (rather than
11
+ * precedence rules) is what makes overlapping constructs — a URL inside a
12
+ * markdown link target, a wikilink inside a heading — safe: the union is
13
+ * protected and nothing is double-counted. Malformed input degrades toward MORE
14
+ * protection (an unterminated fence protects to end of body), never less.
15
+ *
16
+ * Pure module: no I/O, no state. Offsets are UTF-16 indices into the input.
17
+ */
18
+ import type { MaskResult } from "./types.js";
19
+ /**
20
+ * Partition `body` into protected and free spans.
21
+ *
22
+ * Together the two lists tile `[0, body.length)` exactly once, ascending, with
23
+ * no zero-length entries. Callers scan `freeSpans` and never touch the rest.
24
+ */
25
+ export declare function maskBody(body: string): MaskResult;
26
+ /** True when `offset` falls inside any protected span. */
27
+ export declare function isProtected(mask: MaskResult, offset: number): boolean;
28
+ /** The body slices the span detector is allowed to scan, in document order. */
29
+ export declare function freeText(body: string, mask: MaskResult): string[];
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Body masking: split a note body into regions the linkifier may rewrite and
3
+ * regions it must leave byte-for-byte alone.
4
+ *
5
+ * Why this exists: inserting `[[…]]` into a code fence, a URL, an existing
6
+ * wikilink, or a heading corrupts the note. The span detector therefore never
7
+ * sees the raw body — it sees only the FREE spans this module returns.
8
+ *
9
+ * Design: one collector pass per construct family, then a sort-and-merge into
10
+ * disjoint ascending ranges, then the complement. Merging (rather than
11
+ * precedence rules) is what makes overlapping constructs — a URL inside a
12
+ * markdown link target, a wikilink inside a heading — safe: the union is
13
+ * protected and nothing is double-counted. Malformed input degrades toward MORE
14
+ * protection (an unterminated fence protects to end of body), never less.
15
+ *
16
+ * Pure module: no I/O, no state. Offsets are UTF-16 indices into the input.
17
+ */
18
+ // ---------------------------------------------------------------------------
19
+ // Collectors — each returns raw (possibly overlapping) protected ranges
20
+ // ---------------------------------------------------------------------------
21
+ /** Leading `---\n … \n---` YAML block only; a mid-body `---` is a thematic break. */
22
+ function frontmatterSpan(body) {
23
+ if (!body.startsWith("---\n") && !body.startsWith("---\r\n"))
24
+ return [];
25
+ const close = /^---[ \t]*\r?$/m.exec(body.slice(3));
26
+ if (!close || close.index === undefined)
27
+ return [];
28
+ return [{ start: 0, end: 3 + close.index + close[0].length, kind: "frontmatter" }];
29
+ }
30
+ /**
31
+ * Fenced code blocks (``` or ~~~), including the fence lines themselves.
32
+ * An unterminated fence protects everything to the end of the body.
33
+ */
34
+ function fencedCodeSpans(body) {
35
+ const spans = [];
36
+ const fence = /^[ \t]*(`{3,}|~{3,})[^\n]*$/gm;
37
+ let match;
38
+ while ((match = fence.exec(body)) !== null) {
39
+ const marker = match[1];
40
+ if (marker === undefined)
41
+ continue;
42
+ const opening = match.index;
43
+ const closer = new RegExp(`^[ \\t]*${marker[0] === "\`" ? "`" : "~"}{${String(marker.length)},}[ \\t]*$`, "m");
44
+ const rest = body.slice(fence.lastIndex);
45
+ const closeMatch = closer.exec(rest);
46
+ const end = closeMatch && closeMatch.index !== undefined
47
+ ? fence.lastIndex + closeMatch.index + closeMatch[0].length
48
+ : body.length;
49
+ spans.push({ start: opening, end, kind: "fenced-code" });
50
+ fence.lastIndex = end;
51
+ }
52
+ return spans;
53
+ }
54
+ /**
55
+ * Inline code spans: a run of N backticks closed by another run of exactly N
56
+ * on the same logical block. An unclosed run protects nothing extra — the
57
+ * fenced-code pass already covers the block-level case.
58
+ */
59
+ function inlineCodeSpans(body) {
60
+ const spans = [];
61
+ const run = /`+/g;
62
+ let match;
63
+ while ((match = run.exec(body)) !== null) {
64
+ const ticks = match[0];
65
+ const closeIndex = body.indexOf(ticks, match.index + ticks.length);
66
+ if (closeIndex < 0)
67
+ continue;
68
+ const inner = body.slice(match.index + ticks.length, closeIndex);
69
+ if (inner.includes("\n\n"))
70
+ continue;
71
+ const end = closeIndex + ticks.length;
72
+ spans.push({ start: match.index, end, kind: "inline-code" });
73
+ run.lastIndex = end;
74
+ }
75
+ return spans;
76
+ }
77
+ /** Regex-driven collectors that need no cursor bookkeeping. */
78
+ const SIMPLE_PATTERNS = [
79
+ // image embeds first so their `!` prefix is inside the span, not left free
80
+ { kind: "image-embed", pattern: /!\[\[[^\]\n]*\]\]/g },
81
+ { kind: "image-embed", pattern: /!\[[^\]\n]*\]\([^)\n]*\)/g },
82
+ { kind: "wikilink", pattern: /\[\[[^\]\n]*\]\]/g },
83
+ { kind: "markdown-link", pattern: /\[[^\]\n]*\]\([^)\n]*\)/g },
84
+ { kind: "html", pattern: /<\/?[A-Za-z][^<>\n]*>/g },
85
+ { kind: "heading", pattern: /^[ \t]{0,3}#{1,6}[ \t][^\n]*$/gm },
86
+ { kind: "heading", pattern: /^[^\n]+\r?\n[ \t]{0,3}(?:=+|-{2,})[ \t]*$/gm },
87
+ { kind: "url", pattern: /\b(?:https?|ftp|obsidian|mailto):[^\s<>()[\]]+/g },
88
+ { kind: "block-id", pattern: /(?<=\s)\^[A-Za-z0-9-]+[ \t]*$/gm },
89
+ { kind: "tag", pattern: /(?<=^|\s)#[\p{L}\p{N}][\p{L}\p{N}/_-]*/gu },
90
+ ];
91
+ function simpleSpans(body) {
92
+ const spans = [];
93
+ for (const { kind, pattern } of SIMPLE_PATTERNS) {
94
+ const scanner = new RegExp(pattern.source, pattern.flags);
95
+ let match;
96
+ while ((match = scanner.exec(body)) !== null) {
97
+ if (match[0].length < 1) {
98
+ scanner.lastIndex += 1;
99
+ continue;
100
+ }
101
+ spans.push({ start: match.index, end: match.index + match[0].length, kind });
102
+ }
103
+ }
104
+ return spans;
105
+ }
106
+ // ---------------------------------------------------------------------------
107
+ // Merge + complement
108
+ // ---------------------------------------------------------------------------
109
+ /**
110
+ * Sort by start (earlier wins, longer wins on tie) and fuse overlaps into one
111
+ * span carrying the first contributor's kind — the union is what matters to the
112
+ * detector; the kind is reviewer-facing provenance.
113
+ */
114
+ function mergeSpans(raw) {
115
+ const sorted = raw
116
+ .filter((s) => s.end > s.start)
117
+ .slice()
118
+ .sort((a, b) => a.start - b.start || b.end - a.end);
119
+ const merged = [];
120
+ for (const span of sorted) {
121
+ const last = merged[merged.length - 1];
122
+ if (last !== undefined && span.start <= last.end) {
123
+ if (span.end > last.end) {
124
+ merged[merged.length - 1] = { start: last.start, end: span.end, kind: last.kind };
125
+ }
126
+ continue;
127
+ }
128
+ merged.push(span);
129
+ }
130
+ return merged;
131
+ }
132
+ /** The complement of `protectedSpans` within `[0, length)`. */
133
+ function complement(protectedSpans, length) {
134
+ const free = [];
135
+ let cursor = 0;
136
+ for (const span of protectedSpans) {
137
+ if (span.start > cursor)
138
+ free.push({ start: cursor, end: span.start });
139
+ cursor = span.end;
140
+ }
141
+ if (cursor < length)
142
+ free.push({ start: cursor, end: length });
143
+ return free;
144
+ }
145
+ // ---------------------------------------------------------------------------
146
+ // Public API
147
+ // ---------------------------------------------------------------------------
148
+ /**
149
+ * Partition `body` into protected and free spans.
150
+ *
151
+ * Together the two lists tile `[0, body.length)` exactly once, ascending, with
152
+ * no zero-length entries. Callers scan `freeSpans` and never touch the rest.
153
+ */
154
+ export function maskBody(body) {
155
+ if (body.length < 1)
156
+ return { protectedSpans: [], freeSpans: [] };
157
+ const protectedSpans = mergeSpans([
158
+ ...frontmatterSpan(body),
159
+ ...fencedCodeSpans(body),
160
+ ...inlineCodeSpans(body),
161
+ ...simpleSpans(body),
162
+ ]);
163
+ return { protectedSpans, freeSpans: complement(protectedSpans, body.length) };
164
+ }
165
+ /** True when `offset` falls inside any protected span. */
166
+ export function isProtected(mask, offset) {
167
+ return mask.protectedSpans.some((span) => span.start <= offset && offset < span.end);
168
+ }
169
+ /** The body slices the span detector is allowed to scan, in document order. */
170
+ export function freeText(body, mask) {
171
+ return mask.freeSpans.map((span) => body.slice(span.start, span.end));
172
+ }
173
+ //# sourceMappingURL=mask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.js","sourceRoot":"","sources":["../../../src/engine/linkify/mask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Span detection: propose `[[wikilink]]` insertions for a note body.
3
+ *
4
+ * The pipeline is surface-anchored by construction. A candidate exists ONLY
5
+ * because a term's basename or frontmatter alias literally appears in a FREE
6
+ * region of the body (see mask.ts). Retrieval signals never create candidates:
7
+ * an injected lexical ranker may only reorder what the surface already found,
8
+ * and an injected vector predicate may only veto. This is what keeps the
9
+ * feature from hallucinating links into a user's vault.
10
+ *
11
+ * Two rules encode judgement the machine must not make on its own:
12
+ * - FIRST occurrence per target note only — a term linked ten times is noise.
13
+ * - Ambiguity (2+ notes claiming one span) is REPORTED, never resolved. The
14
+ * resolver's shortest-path tie-break is right for reading an existing link
15
+ * and wrong for creating a new one.
16
+ *
17
+ * Pure given its injected dependencies: no I/O, no globals, no clock.
18
+ */
19
+ import type { LinkCandidate, TermNote } from "./types.js";
20
+ /** The ontology concept whose notes are the default link universe. */
21
+ export declare const TERM_CONCEPT = "term";
22
+ /** Minimal shape of `EngineStore.queryLex` results — only what ranking needs. */
23
+ export interface LexHit {
24
+ readonly docPath: string;
25
+ readonly score: number;
26
+ }
27
+ /** Options for {@link suggestLinks}; every dependency is optional and injected. */
28
+ export interface SuggestOptions {
29
+ /** Vault-relative path of the note being linkified; never linked to itself. */
30
+ readonly notePath: string;
31
+ /** Optional lexical re-ranker. Reorders surface-anchored candidates only. */
32
+ readonly queryLex?: (text: string, k: number) => readonly LexHit[];
33
+ /** Optional semantic veto, honoured only when `embeddingConfigured` is true. */
34
+ readonly vectorVeto?: (candidate: LinkCandidate) => boolean;
35
+ /** ADR-007 gate; when false the vector veto is inert. Defaults to true. */
36
+ readonly embeddingConfigured?: boolean;
37
+ }
38
+ /**
39
+ * Restrict a candidate set to notes bound to the `term` concept.
40
+ *
41
+ * Offered as a helper rather than applied inside {@link suggestLinks} so the
42
+ * caller owns the universe decision (a vault may want a wider set).
43
+ */
44
+ export declare function termBoundNotes(notes: readonly TermNote[]): TermNote[];
45
+ /**
46
+ * Propose link candidates for `body` against `notes`.
47
+ *
48
+ * Candidates are returned ranked (highest confidence first, earliest offset
49
+ * breaking ties) and are guaranteed to be non-overlapping, first-occurrence
50
+ * only, outside every protected region, and never self-referential.
51
+ */
52
+ export declare function suggestLinks(body: string, notes: readonly TermNote[], options: SuggestOptions): LinkCandidate[];