pi-obsidian-memory 0.0.0 → 0.1.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 (572) hide show
  1. package/README.md +173 -7
  2. package/package.json +45 -7
  3. package/skills/obsidian-memory/SKILL.md +101 -0
  4. package/src/domain/capture/constants.ts +5 -0
  5. package/src/domain/capture/index.ts +6 -0
  6. package/src/domain/capture/input-problems.ts +9 -0
  7. package/src/domain/capture/schemas.ts +92 -0
  8. package/src/domain/capture/tally.ts +26 -0
  9. package/src/domain/capture/types.ts +49 -0
  10. package/src/domain/capture/validate.ts +75 -0
  11. package/src/domain/command-flags/constants.ts +141 -0
  12. package/src/domain/command-flags/index.ts +1 -0
  13. package/src/domain/config/change.ts +105 -0
  14. package/src/domain/config/constants.ts +25 -0
  15. package/src/domain/config/diagnostics.ts +35 -0
  16. package/src/domain/config/disclosures.ts +8 -0
  17. package/src/domain/config/fields.ts +7 -0
  18. package/src/domain/config/index.ts +11 -0
  19. package/src/domain/config/inspection.ts +43 -0
  20. package/src/domain/config/invariants.ts +68 -0
  21. package/src/domain/config/legacy-capture.ts +17 -0
  22. package/src/domain/config/observations.ts +109 -0
  23. package/src/domain/config/parse.ts +25 -0
  24. package/src/domain/config/paths.ts +61 -0
  25. package/src/domain/config/registration.ts +34 -0
  26. package/src/domain/config/repair.ts +36 -0
  27. package/src/domain/config/resources.ts +65 -0
  28. package/src/domain/config/rules.ts +49 -0
  29. package/src/domain/config/schemas.ts +155 -0
  30. package/src/domain/config/settings.ts +23 -0
  31. package/src/domain/config/types.ts +239 -0
  32. package/src/domain/decision-model/constants.ts +7 -0
  33. package/src/domain/decision-model/cutoffs.ts +8 -0
  34. package/src/domain/decision-model/endpoint.ts +11 -0
  35. package/src/domain/decision-model/failure-detail.ts +8 -0
  36. package/src/domain/decision-model/index.ts +6 -0
  37. package/src/domain/decision-model/rank.ts +36 -0
  38. package/src/domain/decision-model/types.ts +77 -0
  39. package/src/domain/embeddings/constants.ts +55 -0
  40. package/src/domain/embeddings/identity.ts +30 -0
  41. package/src/domain/embeddings/index.ts +5 -0
  42. package/src/domain/embeddings/schemas.ts +25 -0
  43. package/src/domain/embeddings/types.ts +52 -0
  44. package/src/domain/embeddings/vectors.ts +53 -0
  45. package/src/domain/folder-index/constants.ts +9 -0
  46. package/src/domain/folder-index/display.ts +22 -0
  47. package/src/domain/folder-index/index.ts +5 -0
  48. package/src/domain/folder-index/listing.ts +58 -0
  49. package/src/domain/folder-index/render.ts +114 -0
  50. package/src/domain/folder-index/types.ts +41 -0
  51. package/src/domain/index.ts +22 -0
  52. package/src/domain/lifecycle/index.ts +2 -0
  53. package/src/domain/lifecycle/lifecycle.ts +39 -0
  54. package/src/domain/lifecycle/types.ts +17 -0
  55. package/src/domain/loaded-memory/budget.ts +14 -0
  56. package/src/domain/loaded-memory/constants.ts +9 -0
  57. package/src/domain/loaded-memory/index.ts +4 -0
  58. package/src/domain/loaded-memory/render.ts +30 -0
  59. package/src/domain/loaded-memory/types.ts +19 -0
  60. package/src/domain/memory/draft.ts +12 -0
  61. package/src/domain/memory/index.ts +4 -0
  62. package/src/domain/memory/schemas.ts +15 -0
  63. package/src/domain/memory/target.ts +27 -0
  64. package/src/domain/memory/types.ts +20 -0
  65. package/src/domain/memory-agent/index.ts +5 -0
  66. package/src/domain/memory-agent/input-problems.ts +9 -0
  67. package/src/domain/memory-agent/refusal.ts +6 -0
  68. package/src/domain/memory-agent/schemas.ts +112 -0
  69. package/src/domain/memory-agent/types.ts +25 -0
  70. package/src/domain/memory-agent/validate.ts +67 -0
  71. package/src/domain/names/constants.ts +32 -0
  72. package/src/domain/names/index.ts +2 -0
  73. package/src/domain/names/names.ts +83 -0
  74. package/src/domain/note/check.ts +68 -0
  75. package/src/domain/note/constants.ts +15 -0
  76. package/src/domain/note/frontmatter-fields.ts +175 -0
  77. package/src/domain/note/frontmatter.ts +138 -0
  78. package/src/domain/note/index.ts +9 -0
  79. package/src/domain/note/parse.ts +41 -0
  80. package/src/domain/note/render.ts +27 -0
  81. package/src/domain/note/schema-errors.ts +41 -0
  82. package/src/domain/note/schemas.ts +38 -0
  83. package/src/domain/note/types.ts +53 -0
  84. package/src/domain/note/validate.ts +19 -0
  85. package/src/domain/path-platform/index.ts +2 -0
  86. package/src/domain/path-platform/path-module.ts +11 -0
  87. package/src/domain/path-platform/types.ts +1 -0
  88. package/src/domain/search-catalog/constants.ts +1 -0
  89. package/src/domain/search-catalog/coverage.ts +35 -0
  90. package/src/domain/search-catalog/dont-forget.ts +10 -0
  91. package/src/domain/search-catalog/fingerprint.ts +9 -0
  92. package/src/domain/search-catalog/index.ts +10 -0
  93. package/src/domain/search-catalog/inspection.ts +47 -0
  94. package/src/domain/search-catalog/plan.ts +68 -0
  95. package/src/domain/search-catalog/ranking.ts +27 -0
  96. package/src/domain/search-catalog/schemas.ts +49 -0
  97. package/src/domain/search-catalog/types.ts +103 -0
  98. package/src/domain/search-catalog/vector-refresh.ts +22 -0
  99. package/src/domain/shell-edit/command-segments.ts +28 -0
  100. package/src/domain/shell-edit/command-words.ts +22 -0
  101. package/src/domain/shell-edit/constants.ts +125 -0
  102. package/src/domain/shell-edit/executed-files.ts +154 -0
  103. package/src/domain/shell-edit/index.ts +6 -0
  104. package/src/domain/shell-edit/powershell-files.ts +38 -0
  105. package/src/domain/shell-edit/rules.ts +19 -0
  106. package/src/domain/shell-edit/types.ts +75 -0
  107. package/src/domain/tool-flags/constants.ts +178 -0
  108. package/src/domain/tool-flags/index.ts +2 -0
  109. package/src/domain/tool-flags/types.ts +7 -0
  110. package/src/domain/validation/constants.ts +1 -0
  111. package/src/domain/validation/describe.ts +137 -0
  112. package/src/domain/validation/index.ts +3 -0
  113. package/src/domain/validation/types.ts +3 -0
  114. package/src/domain/vault-access/absolute-candidate.ts +81 -0
  115. package/src/domain/vault-access/argument-tokens.ts +22 -0
  116. package/src/domain/vault-access/command-mentions-vault.ts +115 -0
  117. package/src/domain/vault-access/constants.ts +54 -0
  118. package/src/domain/vault-access/index.ts +7 -0
  119. package/src/domain/vault-access/types.ts +18 -0
  120. package/src/domain/vault-access/vault-access-refusal.ts +36 -0
  121. package/src/domain/vault-access/vault-location.ts +22 -0
  122. package/src/domain/vault-assets/index.ts +2 -0
  123. package/src/domain/vault-assets/render.ts +51 -0
  124. package/src/domain/vault-assets/types.ts +36 -0
  125. package/src/domain/vault-catalog/analyze.ts +37 -0
  126. package/src/domain/vault-catalog/classify.ts +37 -0
  127. package/src/domain/vault-catalog/dont-forget.ts +6 -0
  128. package/src/domain/vault-catalog/export-entries.ts +10 -0
  129. package/src/domain/vault-catalog/index.ts +5 -0
  130. package/src/domain/vault-catalog/types.ts +114 -0
  131. package/src/domain/vault-diagnosis/diagnose.ts +79 -0
  132. package/src/domain/vault-diagnosis/index.ts +2 -0
  133. package/src/domain/vault-diagnosis/types.ts +31 -0
  134. package/src/domain/vault-path/constants.ts +13 -0
  135. package/src/domain/vault-path/index.ts +2 -0
  136. package/src/domain/vault-path/vault-path.ts +65 -0
  137. package/src/pi/capture/cadence.ts +49 -0
  138. package/src/pi/capture/completion.ts +26 -0
  139. package/src/pi/capture/constants.ts +5 -0
  140. package/src/pi/capture/handlers.ts +30 -0
  141. package/src/pi/capture/index.ts +8 -0
  142. package/src/pi/capture/runtime.ts +83 -0
  143. package/src/pi/capture/schemas.ts +8 -0
  144. package/src/pi/capture/tool-calls.ts +6 -0
  145. package/src/pi/capture/transcript.ts +55 -0
  146. package/src/pi/capture/types.ts +46 -0
  147. package/src/pi/change-report/constants.ts +15 -0
  148. package/src/pi/change-report/index.ts +3 -0
  149. package/src/pi/change-report/report.ts +54 -0
  150. package/src/pi/change-report/types.ts +8 -0
  151. package/src/pi/context/constants.ts +5 -0
  152. package/src/pi/context/index.ts +3 -0
  153. package/src/pi/context/status.ts +15 -0
  154. package/src/pi/context/types.ts +98 -0
  155. package/src/pi/extension.ts +100 -0
  156. package/src/pi/index.ts +26 -0
  157. package/src/pi/memory-add/constants.ts +13 -0
  158. package/src/pi/memory-add/index.ts +5 -0
  159. package/src/pi/memory-add/memory-add.ts +31 -0
  160. package/src/pi/memory-add/respond.ts +55 -0
  161. package/src/pi/memory-add/schemas.ts +29 -0
  162. package/src/pi/memory-add/types.ts +15 -0
  163. package/src/pi/memory-archive/constants.ts +8 -0
  164. package/src/pi/memory-archive/index.ts +4 -0
  165. package/src/pi/memory-archive/memory-archive.ts +29 -0
  166. package/src/pi/memory-archive/schemas.ts +15 -0
  167. package/src/pi/memory-archive/types.ts +8 -0
  168. package/src/pi/memory-block/block.ts +75 -0
  169. package/src/pi/memory-block/constants.ts +24 -0
  170. package/src/pi/memory-block/index.ts +4 -0
  171. package/src/pi/memory-block/render.ts +54 -0
  172. package/src/pi/memory-block/types.ts +24 -0
  173. package/src/pi/memory-doctor/constants.ts +43 -0
  174. package/src/pi/memory-doctor/index.ts +4 -0
  175. package/src/pi/memory-doctor/memory-doctor.ts +135 -0
  176. package/src/pi/memory-doctor/report.ts +101 -0
  177. package/src/pi/memory-doctor/types.ts +13 -0
  178. package/src/pi/memory-export/constants.ts +15 -0
  179. package/src/pi/memory-export/index.ts +4 -0
  180. package/src/pi/memory-export/memory-export.ts +57 -0
  181. package/src/pi/memory-export/name.ts +9 -0
  182. package/src/pi/memory-export/types.ts +4 -0
  183. package/src/pi/memory-get/constants.ts +12 -0
  184. package/src/pi/memory-get/index.ts +5 -0
  185. package/src/pi/memory-get/memory-get.ts +23 -0
  186. package/src/pi/memory-get/respond.ts +38 -0
  187. package/src/pi/memory-get/schemas.ts +13 -0
  188. package/src/pi/memory-get/types.ts +10 -0
  189. package/src/pi/memory-init/constants.ts +17 -0
  190. package/src/pi/memory-init/index.ts +2 -0
  191. package/src/pi/memory-init/memory-init.ts +63 -0
  192. package/src/pi/memory-search/constants.ts +16 -0
  193. package/src/pi/memory-search/index.ts +5 -0
  194. package/src/pi/memory-search/memory-search.ts +22 -0
  195. package/src/pi/memory-search/respond.ts +62 -0
  196. package/src/pi/memory-search/schemas.ts +11 -0
  197. package/src/pi/memory-search/types.ts +10 -0
  198. package/src/pi/memory-session/constants.ts +7 -0
  199. package/src/pi/memory-session/index.ts +4 -0
  200. package/src/pi/memory-session/keeper.ts +101 -0
  201. package/src/pi/memory-session/respond.ts +6 -0
  202. package/src/pi/memory-session/types.ts +23 -0
  203. package/src/pi/memory-settings/constants.ts +69 -0
  204. package/src/pi/memory-settings/edits.ts +46 -0
  205. package/src/pi/memory-settings/index.ts +9 -0
  206. package/src/pi/memory-settings/lines.ts +119 -0
  207. package/src/pi/memory-settings/models.ts +81 -0
  208. package/src/pi/memory-settings/projects.ts +46 -0
  209. package/src/pi/memory-settings/providers.ts +77 -0
  210. package/src/pi/memory-settings/save.ts +16 -0
  211. package/src/pi/memory-settings/screen.ts +27 -0
  212. package/src/pi/memory-settings/types.ts +87 -0
  213. package/src/pi/memory-setup/constants.ts +33 -0
  214. package/src/pi/memory-setup/disclosure.ts +22 -0
  215. package/src/pi/memory-setup/index.ts +4 -0
  216. package/src/pi/memory-setup/memory-setup.ts +153 -0
  217. package/src/pi/memory-setup/types.ts +6 -0
  218. package/src/pi/memory-succeed/constants.ts +10 -0
  219. package/src/pi/memory-succeed/index.ts +4 -0
  220. package/src/pi/memory-succeed/memory-succeed.ts +34 -0
  221. package/src/pi/memory-succeed/schemas.ts +30 -0
  222. package/src/pi/memory-succeed/types.ts +8 -0
  223. package/src/pi/memory-update/constants.ts +8 -0
  224. package/src/pi/memory-update/index.ts +4 -0
  225. package/src/pi/memory-update/memory-update.ts +29 -0
  226. package/src/pi/memory-update/schemas.ts +24 -0
  227. package/src/pi/memory-update/types.ts +8 -0
  228. package/src/pi/paths/constants.ts +7 -0
  229. package/src/pi/paths/index.ts +2 -0
  230. package/src/pi/paths/paths.ts +15 -0
  231. package/src/pi/paths/platform.ts +7 -0
  232. package/src/pi/registrar.ts +25 -0
  233. package/src/pi/registration-report/constants.ts +13 -0
  234. package/src/pi/registration-report/index.ts +2 -0
  235. package/src/pi/registration-report/report.ts +26 -0
  236. package/src/pi/relevant-memory/constants.ts +3 -0
  237. package/src/pi/relevant-memory/index.ts +4 -0
  238. package/src/pi/relevant-memory/prompt.ts +23 -0
  239. package/src/pi/relevant-memory/runtime.ts +88 -0
  240. package/src/pi/relevant-memory/types.ts +14 -0
  241. package/src/pi/semantic/constants.ts +3 -0
  242. package/src/pi/semantic/index.ts +2 -0
  243. package/src/pi/semantic/runtime.ts +59 -0
  244. package/src/pi/session-start/constants.ts +7 -0
  245. package/src/pi/session-start/index.ts +3 -0
  246. package/src/pi/session-start/session-start.ts +48 -0
  247. package/src/pi/session-start/types.ts +5 -0
  248. package/src/pi/shell-edit-guard/guard.ts +41 -0
  249. package/src/pi/shell-edit-guard/index.ts +3 -0
  250. package/src/pi/shell-edit-guard/prompt.ts +30 -0
  251. package/src/pi/shell-edit-guard/types.ts +13 -0
  252. package/src/pi/types.ts +44 -0
  253. package/src/pi/vault-guard/constants.ts +1 -0
  254. package/src/pi/vault-guard/index.ts +4 -0
  255. package/src/pi/vault-guard/request.ts +39 -0
  256. package/src/pi/vault-guard/types.ts +5 -0
  257. package/src/pi/vault-guard/vault-guard.ts +21 -0
  258. package/src/services/capture-cadence/domain-rules.ts +8 -0
  259. package/src/services/capture-cadence/index.ts +1 -0
  260. package/src/services/clock/clock.ts +7 -0
  261. package/src/services/clock/index.ts +1 -0
  262. package/src/services/config/canonicalize.ts +163 -0
  263. package/src/services/config/constants.ts +1 -0
  264. package/src/services/config/fully-qualified-path.ts +14 -0
  265. package/src/services/config/index.ts +12 -0
  266. package/src/services/config/path-identity.ts +65 -0
  267. package/src/services/config/publication.ts +75 -0
  268. package/src/services/config/read.ts +47 -0
  269. package/src/services/config/registration.ts +26 -0
  270. package/src/services/config/resolve-input.ts +27 -0
  271. package/src/services/config/snapshot.ts +26 -0
  272. package/src/services/config/target.ts +2 -0
  273. package/src/services/config/types.ts +97 -0
  274. package/src/services/config/vault-access.ts +2 -0
  275. package/src/services/config/volume-namespace.ts +5 -0
  276. package/src/services/config/write.ts +63 -0
  277. package/src/services/decision-model/constants.ts +16 -0
  278. package/src/services/decision-model/decide.ts +42 -0
  279. package/src/services/decision-model/diagnostics.ts +6 -0
  280. package/src/services/decision-model/endpoint.ts +1 -0
  281. package/src/services/decision-model/failure-detail.ts +1 -0
  282. package/src/services/decision-model/index.ts +7 -0
  283. package/src/services/decision-model/interruption.ts +29 -0
  284. package/src/services/decision-model/jev.ts +61 -0
  285. package/src/services/decision-model/laya-batch.ts +64 -0
  286. package/src/services/decision-model/laya-http-failure.ts +41 -0
  287. package/src/services/decision-model/laya-response.ts +95 -0
  288. package/src/services/decision-model/laya.ts +35 -0
  289. package/src/services/decision-model/preflight.ts +24 -0
  290. package/src/services/decision-model/prompts.ts +36 -0
  291. package/src/services/decision-model/schemas.ts +43 -0
  292. package/src/services/decision-model/score-candidates.ts +41 -0
  293. package/src/services/decision-model/types.ts +182 -0
  294. package/src/services/embeddings/asset-download.ts +45 -0
  295. package/src/services/embeddings/asset-fetch.ts +39 -0
  296. package/src/services/embeddings/asset-inspection.ts +36 -0
  297. package/src/services/embeddings/batch.ts +32 -0
  298. package/src/services/embeddings/chunks.ts +80 -0
  299. package/src/services/embeddings/configuration.ts +8 -0
  300. package/src/services/embeddings/constants.ts +24 -0
  301. package/src/services/embeddings/errors.ts +11 -0
  302. package/src/services/embeddings/google.ts +90 -0
  303. package/src/services/embeddings/http.ts +64 -0
  304. package/src/services/embeddings/index.ts +17 -0
  305. package/src/services/embeddings/inference.ts +35 -0
  306. package/src/services/embeddings/local.ts +138 -0
  307. package/src/services/embeddings/model-asset.ts +68 -0
  308. package/src/services/embeddings/model-cache.ts +30 -0
  309. package/src/services/embeddings/openai.ts +64 -0
  310. package/src/services/embeddings/operation.ts +31 -0
  311. package/src/services/embeddings/responses.ts +41 -0
  312. package/src/services/embeddings/runtime.ts +13 -0
  313. package/src/services/embeddings/schemas.ts +53 -0
  314. package/src/services/embeddings/types.ts +116 -0
  315. package/src/services/id/id.ts +5 -0
  316. package/src/services/id/index.ts +1 -0
  317. package/src/services/index.ts +11 -0
  318. package/src/services/llm/capture.ts +19 -0
  319. package/src/services/llm/check-chat-models.ts +38 -0
  320. package/src/services/llm/complete.ts +57 -0
  321. package/src/services/llm/constants.ts +32 -0
  322. package/src/services/llm/domain-rules.ts +2 -0
  323. package/src/services/llm/index.ts +6 -0
  324. package/src/services/llm/lifetime.ts +16 -0
  325. package/src/services/llm/retrieve.ts +19 -0
  326. package/src/services/llm/schemas.ts +9 -0
  327. package/src/services/llm/types.ts +94 -0
  328. package/src/services/search-index/catalog-query.ts +34 -0
  329. package/src/services/search-index/catalog-statements.ts +33 -0
  330. package/src/services/search-index/catalog.ts +19 -0
  331. package/src/services/search-index/cleanup.ts +13 -0
  332. package/src/services/search-index/close.ts +5 -0
  333. package/src/services/search-index/constants.ts +102 -0
  334. package/src/services/search-index/dont-forget.ts +1 -0
  335. package/src/services/search-index/fingerprint.ts +17 -0
  336. package/src/services/search-index/folder-index-statements.ts +17 -0
  337. package/src/services/search-index/folder-index-storage.ts +54 -0
  338. package/src/services/search-index/folder-indexes.ts +13 -0
  339. package/src/services/search-index/index.ts +14 -0
  340. package/src/services/search-index/inspection.ts +1 -0
  341. package/src/services/search-index/inventory.ts +67 -0
  342. package/src/services/search-index/legacy.ts +64 -0
  343. package/src/services/search-index/location.ts +12 -0
  344. package/src/services/search-index/open.ts +46 -0
  345. package/src/services/search-index/query.ts +39 -0
  346. package/src/services/search-index/ranking.ts +12 -0
  347. package/src/services/search-index/reconcile.ts +93 -0
  348. package/src/services/search-index/recovery.ts +56 -0
  349. package/src/services/search-index/refusals.ts +21 -0
  350. package/src/services/search-index/schema.ts +42 -0
  351. package/src/services/search-index/schemas.ts +181 -0
  352. package/src/services/search-index/search.ts +5 -0
  353. package/src/services/search-index/statements.ts +18 -0
  354. package/src/services/search-index/storage.ts +207 -0
  355. package/src/services/search-index/types.ts +113 -0
  356. package/src/services/search-index/vector-statements.ts +18 -0
  357. package/src/services/search-index/vector-storage.ts +169 -0
  358. package/src/services/search-index/vectors.ts +18 -0
  359. package/src/services/search-index/write.ts +9 -0
  360. package/src/services/shell-edit/ask.ts +53 -0
  361. package/src/services/shell-edit/domain-rules.ts +2 -0
  362. package/src/services/shell-edit/index.ts +4 -0
  363. package/src/services/shell-edit/schemas.ts +23 -0
  364. package/src/services/shell-edit/types.ts +61 -0
  365. package/src/services/shell-scripts/constants.ts +1 -0
  366. package/src/services/shell-scripts/files.ts +16 -0
  367. package/src/services/shell-scripts/index.ts +5 -0
  368. package/src/services/shell-scripts/package-scripts.ts +74 -0
  369. package/src/services/shell-scripts/schemas.ts +3 -0
  370. package/src/services/shell-scripts/scripts.ts +27 -0
  371. package/src/services/shell-scripts/types.ts +11 -0
  372. package/src/services/vault/archive.ts +31 -0
  373. package/src/services/vault/bootstrap/ensure.ts +50 -0
  374. package/src/services/vault/bootstrap/index.ts +2 -0
  375. package/src/services/vault/bootstrap/paths.ts +57 -0
  376. package/src/services/vault/bootstrap/types.ts +17 -0
  377. package/src/services/vault/bootstrap/write.ts +47 -0
  378. package/src/services/vault/catalog/bytes.ts +51 -0
  379. package/src/services/vault/catalog/dont-forget.ts +1 -0
  380. package/src/services/vault/catalog/enumerate.ts +69 -0
  381. package/src/services/vault/catalog/export.ts +21 -0
  382. package/src/services/vault/catalog/failures.ts +16 -0
  383. package/src/services/vault/catalog/index.ts +10 -0
  384. package/src/services/vault/catalog/inspect.ts +41 -0
  385. package/src/services/vault/catalog/observe.ts +35 -0
  386. package/src/services/vault/catalog/resolve.ts +94 -0
  387. package/src/services/vault/catalog/stat.ts +23 -0
  388. package/src/services/vault/catalog/types.ts +69 -0
  389. package/src/services/vault/catalog/visit.ts +58 -0
  390. package/src/services/vault/complete-blank.ts +66 -0
  391. package/src/services/vault/constants.ts +3 -0
  392. package/src/services/vault/context/index.ts +1 -0
  393. package/src/services/vault/context/types.ts +10 -0
  394. package/src/services/vault/create.ts +19 -0
  395. package/src/services/vault/display.ts +6 -0
  396. package/src/services/vault/domain-rules.ts +10 -0
  397. package/src/services/vault/draft.ts +2 -0
  398. package/src/services/vault/filesystem/failures.ts +53 -0
  399. package/src/services/vault/filesystem/hash.ts +5 -0
  400. package/src/services/vault/filesystem/index.ts +5 -0
  401. package/src/services/vault/filesystem/read.ts +61 -0
  402. package/src/services/vault/filesystem/types.ts +36 -0
  403. package/src/services/vault/filesystem/write.ts +80 -0
  404. package/src/services/vault/find.ts +27 -0
  405. package/src/services/vault/folder-contents.ts +31 -0
  406. package/src/services/vault/folder-index/index.ts +2 -0
  407. package/src/services/vault/folder-index/read.ts +87 -0
  408. package/src/services/vault/folder-index/types.ts +19 -0
  409. package/src/services/vault/folder-listing.ts +1 -0
  410. package/src/services/vault/index.ts +21 -0
  411. package/src/services/vault/inspect-folder.ts +13 -0
  412. package/src/services/vault/list.ts +121 -0
  413. package/src/services/vault/memory-folder.ts +24 -0
  414. package/src/services/vault/paths.ts +11 -0
  415. package/src/services/vault/publish.ts +52 -0
  416. package/src/services/vault/read.ts +46 -0
  417. package/src/services/vault/refresh-folders.ts +197 -0
  418. package/src/services/vault/refresh-plan.ts +79 -0
  419. package/src/services/vault/refresh.ts +8 -0
  420. package/src/services/vault/refusals.ts +23 -0
  421. package/src/services/vault/relocate.ts +131 -0
  422. package/src/services/vault/relocation-checks.ts +89 -0
  423. package/src/services/vault/resolve-stored-file.ts +43 -0
  424. package/src/services/vault/resolve.ts +109 -0
  425. package/src/services/vault/succeed.ts +45 -0
  426. package/src/services/vault/types.ts +199 -0
  427. package/src/services/vault/update-file.ts +58 -0
  428. package/src/services/vault/update.ts +22 -0
  429. package/src/services/vault/write-new-file.ts +37 -0
  430. package/src/shared/index.ts +1 -0
  431. package/src/shared/result/index.ts +1 -0
  432. package/src/shared/result/types.ts +17 -0
  433. package/src/usecases/add-memory/add-memory.ts +83 -0
  434. package/src/usecases/add-memory/index.ts +4 -0
  435. package/src/usecases/add-memory/maintenance.ts +23 -0
  436. package/src/usecases/add-memory/schemas.ts +12 -0
  437. package/src/usecases/add-memory/types.ts +47 -0
  438. package/src/usecases/archive-memory/archive-memory.ts +27 -0
  439. package/src/usecases/archive-memory/index.ts +3 -0
  440. package/src/usecases/archive-memory/schemas.ts +11 -0
  441. package/src/usecases/archive-memory/types.ts +17 -0
  442. package/src/usecases/capture-memory/apply.ts +73 -0
  443. package/src/usecases/capture-memory/capture-memory.ts +117 -0
  444. package/src/usecases/capture-memory/constants.ts +15 -0
  445. package/src/usecases/capture-memory/index.ts +5 -0
  446. package/src/usecases/capture-memory/observe.ts +122 -0
  447. package/src/usecases/capture-memory/settings.ts +20 -0
  448. package/src/usecases/capture-memory/types.ts +103 -0
  449. package/src/usecases/check-shell-edit/check-shell-edit.ts +28 -0
  450. package/src/usecases/check-shell-edit/index.ts +2 -0
  451. package/src/usecases/check-shell-edit/types.ts +30 -0
  452. package/src/usecases/check-vault-access/check-vault-access.ts +23 -0
  453. package/src/usecases/check-vault-access/constants.ts +7 -0
  454. package/src/usecases/check-vault-access/index.ts +4 -0
  455. package/src/usecases/check-vault-access/raw-device.ts +10 -0
  456. package/src/usecases/check-vault-access/targets.ts +49 -0
  457. package/src/usecases/check-vault-access/types.ts +33 -0
  458. package/src/usecases/complete-blank-memory/complete-blank-memory.ts +48 -0
  459. package/src/usecases/complete-blank-memory/constants.ts +3 -0
  460. package/src/usecases/complete-blank-memory/index.ts +4 -0
  461. package/src/usecases/complete-blank-memory/schemas.ts +14 -0
  462. package/src/usecases/complete-blank-memory/types.ts +28 -0
  463. package/src/usecases/diagnose-memory/constants.ts +3 -0
  464. package/src/usecases/diagnose-memory/decision.ts +36 -0
  465. package/src/usecases/diagnose-memory/diagnose-memory.ts +52 -0
  466. package/src/usecases/diagnose-memory/embeddings.ts +39 -0
  467. package/src/usecases/diagnose-memory/index.ts +5 -0
  468. package/src/usecases/diagnose-memory/types.ts +86 -0
  469. package/src/usecases/diagnose-memory/vault.ts +33 -0
  470. package/src/usecases/export-memory/collect.ts +20 -0
  471. package/src/usecases/export-memory/constants.ts +3 -0
  472. package/src/usecases/export-memory/export-memory.ts +84 -0
  473. package/src/usecases/export-memory/index.ts +3 -0
  474. package/src/usecases/export-memory/types.ts +28 -0
  475. package/src/usecases/get-memory/get-memory.ts +97 -0
  476. package/src/usecases/get-memory/index.ts +2 -0
  477. package/src/usecases/get-memory/types.ts +25 -0
  478. package/src/usecases/index.ts +25 -0
  479. package/src/usecases/list-memory/index.ts +2 -0
  480. package/src/usecases/list-memory/leased/index.ts +2 -0
  481. package/src/usecases/list-memory/leased/read.ts +16 -0
  482. package/src/usecases/list-memory/leased/types.ts +21 -0
  483. package/src/usecases/list-memory/list-memory.ts +33 -0
  484. package/src/usecases/list-memory/types.ts +8 -0
  485. package/src/usecases/load-dont-forget/index.ts +2 -0
  486. package/src/usecases/load-dont-forget/load-dont-forget.ts +111 -0
  487. package/src/usecases/load-dont-forget/types.ts +26 -0
  488. package/src/usecases/memory-change/change.ts +42 -0
  489. package/src/usecases/memory-change/index.ts +5 -0
  490. package/src/usecases/memory-change/maintenance.ts +11 -0
  491. package/src/usecases/memory-change/partial.ts +18 -0
  492. package/src/usecases/memory-change/receipt.ts +40 -0
  493. package/src/usecases/memory-change/types.ts +44 -0
  494. package/src/usecases/operation-context/context.ts +37 -0
  495. package/src/usecases/operation-context/index.ts +2 -0
  496. package/src/usecases/operation-context/types.ts +19 -0
  497. package/src/usecases/registration/check.ts +6 -0
  498. package/src/usecases/registration/entry.ts +33 -0
  499. package/src/usecases/registration/index.ts +8 -0
  500. package/src/usecases/registration/init.ts +94 -0
  501. package/src/usecases/registration/prepare-init.ts +43 -0
  502. package/src/usecases/registration/prepare.ts +35 -0
  503. package/src/usecases/registration/propose.ts +34 -0
  504. package/src/usecases/registration/publication.ts +90 -0
  505. package/src/usecases/registration/setup.ts +41 -0
  506. package/src/usecases/registration/types.ts +107 -0
  507. package/src/usecases/relevant-memory/agent.ts +55 -0
  508. package/src/usecases/relevant-memory/constants.ts +28 -0
  509. package/src/usecases/relevant-memory/cutoffs.ts +29 -0
  510. package/src/usecases/relevant-memory/decision.ts +102 -0
  511. package/src/usecases/relevant-memory/index.ts +11 -0
  512. package/src/usecases/relevant-memory/loaded.ts +31 -0
  513. package/src/usecases/relevant-memory/refresh.ts +30 -0
  514. package/src/usecases/relevant-memory/retrieve-memory.ts +62 -0
  515. package/src/usecases/relevant-memory/schemas.ts +20 -0
  516. package/src/usecases/relevant-memory/session-memory.ts +53 -0
  517. package/src/usecases/relevant-memory/track-dont-forget.ts +13 -0
  518. package/src/usecases/relevant-memory/types.ts +106 -0
  519. package/src/usecases/resolve-memory/index.ts +2 -0
  520. package/src/usecases/resolve-memory/leased/index.ts +2 -0
  521. package/src/usecases/resolve-memory/leased/resolve.ts +109 -0
  522. package/src/usecases/resolve-memory/leased/types.ts +35 -0
  523. package/src/usecases/resolve-memory/resolve-memory.ts +23 -0
  524. package/src/usecases/resolve-memory/types.ts +7 -0
  525. package/src/usecases/search-memory/constants.ts +1 -0
  526. package/src/usecases/search-memory/index.ts +3 -0
  527. package/src/usecases/search-memory/search-memory.ts +132 -0
  528. package/src/usecases/search-memory/types.ts +39 -0
  529. package/src/usecases/semantic/constants.ts +7 -0
  530. package/src/usecases/semantic/index.ts +5 -0
  531. package/src/usecases/semantic/prepare.ts +30 -0
  532. package/src/usecases/semantic/rank.ts +83 -0
  533. package/src/usecases/semantic/refresh-vectors.ts +95 -0
  534. package/src/usecases/semantic/types.ts +17 -0
  535. package/src/usecases/semantic-port/index.ts +1 -0
  536. package/src/usecases/semantic-port/types.ts +20 -0
  537. package/src/usecases/semantic-provider/constants.ts +6 -0
  538. package/src/usecases/semantic-provider/index.ts +5 -0
  539. package/src/usecases/semantic-provider/local.ts +33 -0
  540. package/src/usecases/semantic-provider/remote.ts +10 -0
  541. package/src/usecases/semantic-provider/size.ts +10 -0
  542. package/src/usecases/semantic-provider/types.ts +19 -0
  543. package/src/usecases/session/index.ts +2 -0
  544. package/src/usecases/session/lease.ts +70 -0
  545. package/src/usecases/session/receipts.ts +46 -0
  546. package/src/usecases/session/state.ts +106 -0
  547. package/src/usecases/session/types.ts +45 -0
  548. package/src/usecases/settings/change.ts +142 -0
  549. package/src/usecases/settings/index.ts +3 -0
  550. package/src/usecases/settings/prepare.ts +24 -0
  551. package/src/usecases/settings/types.ts +32 -0
  552. package/src/usecases/succeed-memory/index.ts +3 -0
  553. package/src/usecases/succeed-memory/schemas.ts +13 -0
  554. package/src/usecases/succeed-memory/succeed-memory.ts +34 -0
  555. package/src/usecases/succeed-memory/types.ts +18 -0
  556. package/src/usecases/synchronize-memory/index.ts +2 -0
  557. package/src/usecases/synchronize-memory/leased/aliases.ts +55 -0
  558. package/src/usecases/synchronize-memory/leased/folder-states.ts +58 -0
  559. package/src/usecases/synchronize-memory/leased/index.ts +2 -0
  560. package/src/usecases/synchronize-memory/leased/inspection.ts +32 -0
  561. package/src/usecases/synchronize-memory/leased/maintenance.ts +41 -0
  562. package/src/usecases/synchronize-memory/leased/publication.ts +55 -0
  563. package/src/usecases/synchronize-memory/leased/scan.ts +37 -0
  564. package/src/usecases/synchronize-memory/leased/synchronize.ts +102 -0
  565. package/src/usecases/synchronize-memory/leased/types.ts +60 -0
  566. package/src/usecases/synchronize-memory/synchronize-memory.ts +26 -0
  567. package/src/usecases/synchronize-memory/types.ts +5 -0
  568. package/src/usecases/update-memory/index.ts +3 -0
  569. package/src/usecases/update-memory/schemas.ts +14 -0
  570. package/src/usecases/update-memory/types.ts +16 -0
  571. package/src/usecases/update-memory/update-memory.ts +31 -0
  572. package/CHANGELOG.md +0 -6
package/README.md CHANGED
@@ -1,15 +1,181 @@
1
1
  # pi-obsidian-memory
2
2
 
3
- Memória de longo prazo para o [pi coding agent](https://pi.dev), gravada em vaults do [Obsidian](https://obsidian.md). O OneDrive é opcional.
3
+ Long-term memory for the [pi coding agent](https://pi.dev), stored in [Obsidian](https://obsidian.md) vaults.
4
4
 
5
- > **Status:** em especificação (fase F0). Ainda não há código utilizável: esta versão só reserva o nome no npm.
5
+ Coding agents forget everything between sessions. This extension gives pi durable memory that changes its future
6
+ behavior, that you can read and edit in Obsidian, and that lives in any folder you choose. Memory is two layers of
7
+ dedicated vaults: one global vault about you (how to address you, preferences, patterns, lessons) and one vault per
8
+ project. Notes are plain Markdown, written in English whatever language you speak, and never deleted: retired notes
9
+ move to `archive/`. See [docs/VISION.md](docs/VISION.md) for the decisions behind it.
6
10
 
7
- - Um vault **global**, com os aprendizados sobre o usuário, e um vault **por projeto**.
8
- - Notas nativas do Obsidian, com índice e templates: só aprendizados e pontos importantes.
9
- - Tudo configurável, com onboarding (`/memory-setup` e `/memory-init`).
11
+ > **Status:** runs on Windows, macOS and Linux; CI runs the unit tests on all three and the end-to-end suite runs on
12
+ > Windows. Requires Node 22.19 or later.
10
13
 
11
- Documentação do projeto em [`docs/`](docs/). Decisões em [`docs/OPEN-QUESTIONS.md`](docs/OPEN-QUESTIONS.md).
14
+ ## Install
12
15
 
13
- ## Licença
16
+ From git:
17
+
18
+ ```bash
19
+ pi install git:github.com/DavyMassoneto/pi-obsidian-memory
20
+ ```
21
+
22
+ From a local clone (loaded from that path, not copied; pi does not install its dependencies, so do it first):
23
+
24
+ ```bash
25
+ npm install --omit=dev --prefix ./pi-obsidian-memory
26
+ pi install ./pi-obsidian-memory
27
+ ```
28
+
29
+ Both write the package to `~/.pi/agent/settings.json`; add `--local` to write `.pi/settings.json` instead (pi reads it
30
+ only after project trust is granted). You can also add the source yourself:
31
+
32
+ ```json
33
+ {
34
+ "packages": ["git:github.com/DavyMassoneto/pi-obsidian-memory"]
35
+ }
36
+ ```
37
+
38
+ `pi list` shows installed packages. To try it for one run without installing:
39
+ `pi -e git:github.com/DavyMassoneto/pi-obsidian-memory`. Pi's own docs cover every option (`docs/packages.md`).
40
+
41
+ ## Quick start
42
+
43
+ 1. `/memory-setup` chooses where the global vault lives (create a new one or attach an existing folder), asks which
44
+ chat model to use for capture (the model in use is the default) and for the memory agent (a small, cheap one is
45
+ enough; the list is sorted by price, cheapest first), shows the
46
+ warnings that apply and writes the config. Run again, it is the settings screen: every setting, and the projects,
47
+ one select at a time.
48
+ 2. In a project folder, `/memory-init` registers it with its own vault (created when missing). An unregistered folder
49
+ gets the global vault only.
50
+
51
+ Both commands need pi's UI. Until `/memory-setup` is done there is no memory, and session start says so. The config is
52
+ `pi-obsidian-memory/config.json` in the pi agent directory, outside the vaults; every key is described in
53
+ [docs/config.md](docs/config.md). Nothing needs editing by hand. Changing a vault leaves the old one as it was.
54
+
55
+ ## What works
56
+
57
+ ### Tools
58
+
59
+ The LLM uses these; the ones that write act only on your explicit request ("remember this"), and nothing in the prompt
60
+ nudges it to save on its own.
61
+
62
+ | Tool | Does |
63
+ |---|---|
64
+ | `memory_search` | Finds notes in the global vault, the project vault or both (words and meaning together) |
65
+ | `memory_get` | Reads a note in full with its problems, a folder's index, or anything under `archive/` |
66
+ | `memory_add` | Saves a new note when you ask to remember something |
67
+ | `memory_update` | Changes a note you asked to change; keeps its identity |
68
+ | `memory_archive` | Moves a note to `archive/` |
69
+ | `memory_succeed` | Replaces a note with a successor; the two link to each other |
70
+
71
+ `memory_update`, `memory_archive` and `memory_succeed` first need a `memory_get` of the same note in the session, and
72
+ refuse a note that changed on disk since (an edit you made in Obsidian is never overwritten). A shipped skill,
73
+ `obsidian-memory`, teaches the agent the layout, note types and these rules; it is never written to a vault.
74
+
75
+ ### Commands
76
+
77
+ | Command | Does |
78
+ |---|---|
79
+ | `/memory-setup` | First setup (vault and models); afterwards the settings screen for every setting and the projects |
80
+ | `/memory-init` | Registers the working folder as a project with its own vault |
81
+ | `/memory-doctor` | Reports problems in the vaults and the config; offers to complete blank notes after you confirm |
82
+ | `/memory-export` | Writes both vaults to a new `.zip` (never overwrites; refuses a folder inside a vault) |
83
+
84
+ `/memory-doctor` lists invalid notes, blank notes, duplicate ids, leftover temporary files and folders over the
85
+ notes-per-folder limit, then checks the chat model, the embeddings and the decision model. Every other problem is left
86
+ as it is on disk.
87
+
88
+ ### Memory in the conversation
89
+
90
+ - **Don't forget.** Mark a note with `dontForget: true` in its frontmatter. Every such note, in both vaults, is loaded
91
+ in full at session start, with no limit.
92
+ - **Relevant memory per message.** On each message, a fast decision model (a classifier that answers yes/no
93
+ probabilities; it never searches or generates) decides whether memory is needed. If so, the memory agent (a chat model)
94
+ searches and reads, the decision model scores each candidate note, and the relevant ones are added after your message. Earlier
95
+ messages are never rewritten, so the prompt cache holds; a loaded note that changed is added again, marked as
96
+ replacing the earlier copy. A loaded note that is gone is reported as "the note was archived or deleted"; one still
97
+ there but unusable, as "the note is still there but cannot be used (<problem>)"; one whose state is unknown, an
98
+ invalid config included, as "the note cannot be read (<problem>)". Session start also loads relevant notes within
99
+ `context.budgetChars` (12,000 by default). The decision model is Jev by default (by API; it needs `TYPESAFE_API_KEY`;
100
+ $0.042 per million input tokens, per docs.typesafe.ai), working from TypeSafe's starting cutoffs (0.5/0.5). Laya,
101
+ run locally, is an optional choice that needs explicit `gateThreshold` and `relevanceThreshold`: it ships none
102
+ because its gate measured at chance (see [decision-thresholds](docs/decision-thresholds.md)), so with Laya and no
103
+ cutoffs per-message memory is off and each session tells you. Setup steps are in
104
+ [Running the decision model](docs/config.md#running-the-decision-model). If the decision model is unavailable
105
+ nothing is added and you are told once per session; no other model takes over.
106
+ - **Automatic capture.** As in pi-hermes-memory, a background review of the conversation saves, updates, archives and
107
+ succeeds notes every `capture.nudgeInterval` assistant turns (10) or `capture.nudgeToolCalls` tool calls (15), once
108
+ the session has three user messages. What was not yet reviewed is also reviewed before compaction and when the
109
+ session ends, once it has `capture.flushMinTurns` user messages (6). It never asks you anything: what it is unsure
110
+ of is not saved. Its judgement quality is not yet proven against a real model.
111
+ - **Semantic search.** `memory_search` fuses words and meaning. The default is a local multilingual model (about
112
+ 135 MB), downloaded when needed, without asking; OpenAI and Google are the alternatives. The index lives outside the
113
+ vaults and is rebuilt from the notes whenever needed.
114
+
115
+ ### Vault guard
116
+
117
+ The LLM reaches vault files only through the memory tools. The extension refuses `read`, `write`, `edit`, `grep`, `find`
118
+ and `ls` on a vault, `bash`/`powershell` commands that write a vault path out, and junctions and symlinks into a vault.
119
+ You, and Obsidian, are not the LLM and stay free.
120
+
121
+ Accepted as they are (your decision, 2026-10-17): reading a vault through a path the shell builds indirectly
122
+ (variables, globs, scripts), tools of other extensions, and foreground subagents, which load no extensions. Creating
123
+ hardlinks through the shell is refused by the shell-edit guard. Details in
124
+ [docs/ROADMAP.md](docs/ROADMAP.md#2-memory-the-agent-can-read-vault-access-only).
125
+
126
+ Paths are compared ignoring case on Windows and macOS and with case on Linux, whatever the volume: a case-sensitive
127
+ macOS volume is still compared ignoring case, and a case-insensitive mount on Linux is still compared with case.
128
+
129
+ ### Shell-edit guard
130
+
131
+ Before every `bash`/`powershell` call, Jev (`jev-latest`, which needs `TYPESAFE_API_KEY`) scores whether the command
132
+ edits a file through a redirection, an in-place edit, inline code, a script that writes, a copy or download that
133
+ creates a file, or a hardlink. A score at or above its cutoff refuses the call and points to `edit` and `write`;
134
+ when Jev cannot answer, the call is refused. The cutoffs and how they were measured are in
135
+ [docs/shell-edit-cutoffs.md](docs/shell-edit-cutoffs.md).
136
+
137
+ ### Dashboard
138
+
139
+ Setup and init write `Memory.base` at each vault root when it is missing, with views for all notes, Don't forget and
140
+ Archive (file name, folder, type, Don't forget, updated). Your edits to it are kept. It only displays.
141
+
142
+ ## Privacy
143
+
144
+ - Capture and the memory agent send conversation and note content to the chat model you choose.
145
+ - Jev, the default decision model, sends your messages and candidate notes to TypeSafe; Laya, the optional local choice, runs on your machine.
146
+ - Choosing a remote embeddings provider (OpenAI, Google) sends note content and queries to it.
147
+ - `/memory-setup` warns about each of these before writing, as a plain warning with no question; nothing is asked at
148
+ runtime, and no other provider ever takes the place of the one you chose.
149
+ - Secrets are saved as written: the vault is yours, with no masking or blocking.
150
+ - Credentials come from pi or the environment; `config.json` never holds a key.
151
+
152
+ ## Development
153
+
154
+ Tested with pi `1.3.0` and TypeBox `1.3.27`, pinned as development dependencies. Pi provides both at runtime;
155
+ following its package contract, they are wildcard peers, not bundled runtime dependencies.
156
+
157
+ ```bash
158
+ npm install
159
+ npm run lint
160
+ npm run typecheck
161
+ npm test # offline: pure tests and tests on a real temporary disk
162
+ npm run test:e2e # the real pi over RPC, with a temporary agent folder and vaults
163
+ npm run test:model # live tests: real models and network
164
+ pi -e ./src/pi/extension.ts
165
+ ```
166
+
167
+ `npm test` needs no model and no network. `npm run test:e2e` uses the real Haiku (`cc/claude-haiku-5-5`) through
168
+ OmniRoute, loaded in pi by `pi-omniroute-sync`, and the real Jev. It reads `OMNIROUTE_URL`, `OMNIROUTE_API_KEY` and
169
+ `TYPESAFE_API_KEY` from the environment and runs one test file at a time. CI runs it on windows-latest (the secrets
170
+ have the same names). The Laya tests use a real `laya-serve` from `tmp/laya-venv` and run only on request:
171
+ `npx vitest run --project e2e-laya`.
172
+
173
+ `npm run test:model` downloads the local embedding model (about 135 MB) to a cache folder outside the repository
174
+ (`%LOCALAPPDATA%\pi-obsidian-memory-bench\models`) and is not part of `npm test`.
175
+
176
+ The roadmap is in [docs/ROADMAP.md](docs/ROADMAP.md); the note format is in
177
+ [docs/vault-format.md](docs/vault-format.md).
178
+
179
+ ## License
14
180
 
15
181
  [MIT](LICENSE)
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "pi-obsidian-memory",
3
- "version": "0.0.0",
4
- "description": "Memória de longo prazo para o pi coding agent em vaults do Obsidian (OneDrive opcional)",
3
+ "version": "0.1.0",
4
+ "description": "Long-term memory for the pi coding agent, stored in Obsidian vaults",
5
5
  "keywords": [
6
6
  "pi",
7
7
  "pi-coding-agent",
8
+ "pi-package",
8
9
  "obsidian",
9
10
  "memory",
10
11
  "agent-memory"
@@ -20,16 +21,53 @@
20
21
  "url": "https://github.com/DavyMassoneto/pi-obsidian-memory/issues"
21
22
  },
22
23
  "type": "module",
24
+ "imports": {
25
+ "#src/*": "./src/*/index.ts",
26
+ "#test-helpers": "./tests/helpers/index.ts"
27
+ },
23
28
  "engines": {
24
- "node": ">=24"
29
+ "node": ">=22.19.0"
25
30
  },
26
31
  "files": [
27
- "CHANGELOG.md"
32
+ "src",
33
+ "skills"
28
34
  ],
29
35
  "scripts": {
30
- "release": "node scripts/release.mjs"
36
+ "format": "biome check --write .",
37
+ "lint": "biome check .",
38
+ "test": "vitest run --project unit",
39
+ "test:model": "vitest run --project model",
40
+ "test:e2e": "vitest run --project e2e",
41
+ "typecheck": "tsc --noEmit"
42
+ },
43
+ "pi": {
44
+ "extensions": [
45
+ "./src/pi/extension.ts"
46
+ ],
47
+ "skills": [
48
+ "./skills"
49
+ ]
50
+ },
51
+ "peerDependencies": {
52
+ "@earendil-works/pi-coding-agent": "*",
53
+ "typebox": "*"
54
+ },
55
+ "devDependencies": {
56
+ "@biomejs/biome": "2.5.15",
57
+ "@earendil-works/pi-coding-agent": "1.3.0",
58
+ "@types/node": "24.19.1",
59
+ "@types/stopword": "2.0.3",
60
+ "git-cliff": "2.14.2",
61
+ "pi-omniroute-sync": "1.2.1",
62
+ "typebox": "1.3.27",
63
+ "typescript": "7.0.2",
64
+ "vitest": "5.0.3"
31
65
  },
32
- "publishConfig": {
33
- "access": "public"
66
+ "dependencies": {
67
+ "@huggingface/transformers": "4.3.1",
68
+ "fflate": "0.8.3",
69
+ "stopword": "3.1.5",
70
+ "ulid": "3.0.2",
71
+ "yaml": "2.9.1"
34
72
  }
35
73
  }
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: obsidian-memory
3
+ description: How to use the Obsidian long-term memory (global and project vaults) - where notes go, note types, what is not memory, and the memory tools. Load before searching or reading memory, before saving something the user asked to remember, or when a memory block appears in the context.
4
+ ---
5
+
6
+ # Obsidian memory
7
+
8
+ Long-term memory lives in Obsidian vaults. Notes are in English, whatever language the user speaks.
9
+
10
+ ## Two layers
11
+
12
+ - Global vault: about the user (how to address them, preferences, patterns, global lessons).
13
+ - Project vault: everything else about the current project.
14
+ - Classify each memory. When unsure which vault, ask the user.
15
+ - A folder with no registered project has the global vault only.
16
+
17
+ ## Layout and placement
18
+
19
+ - One folder per subject. Each folder holds short notes, one point per note. Subjects nest with no depth limit.
20
+ - Place a note from general to specific: `typescript/testing/`, not `testing/typescript/`.
21
+ - Reuse before creating: walk the existing tree (read folder indexes level by level) and use the path that already covers the subject.
22
+ - When two paths fit, ask the user.
23
+ - Every folder has an `index.md` listing its subfolders and its notes (type and don't forget mark). The system keeps it up to date; never write it by hand.
24
+ - Not subjects: hidden folders, and at the vault root `archive/` and `_templates/`.
25
+ - `index` (any case) is reserved: no note can use it as its statement.
26
+
27
+ ## Notes
28
+
29
+ - The file name is the statement: reading the name tells exactly what the note says. The body holds the detail.
30
+ - Keep notes short, one point each. A new point in the same subject is a new note in that folder.
31
+ - Name: at most 100 characters by default. It must be a valid Windows file name and must not contain `< > : " / \ | ? * [ ] # ^`, control characters, a leading or trailing space, or a trailing dot. No Windows reserved names (`CON`, `NUL`, `COM1`...).
32
+ - Body: never empty, at most 1,000 characters by default. Record the detail even when the name says it all.
33
+ - An invalid note is refused with every reason. Rewrite it or split it into smaller notes.
34
+ - A note can be marked Don't forget: it is loaded in full at session start.
35
+
36
+ ## Types
37
+
38
+ Pick exactly one. The list is closed. When unsure which type fits, ask the user.
39
+
40
+ - `rule`: how to do things; a user preference or a project convention.
41
+ - `procedure`: steps to do something in this project.
42
+ - `constraint`: a limit imposed from outside (platform, deadline, client).
43
+ - `fact`: how things are, about the user or the project.
44
+ - `issue`: a known problem that is still open, with its workaround.
45
+ - `question`: something still undecided or unknown.
46
+ - `decision`: a choice that was made, with its why.
47
+ - `lesson`: something learned from a mistake or a bug.
48
+ - `goal`: a committed objective for the future.
49
+ - `risk`: a problem that may happen.
50
+ - `idea`: a possibility not committed to yet.
51
+ - `reference`: where to find something external.
52
+
53
+ ## Not memory
54
+
55
+ - Tasks and TODOs.
56
+ - Session logs.
57
+ - Anything the code or git history already records.
58
+
59
+ Secrets (keys, passwords, tokens) are memory: the vault is the user's own safe. Save them like any other note, with no masking. When unsure whether something is memory at all, ask the user.
60
+
61
+ ## Reading
62
+
63
+ The memory block at session start, and the relevant notes added to a message, are only part of the memory. A note added again as replacing an earlier copy supersedes it; a note marked no longer valid must not be relied on. Search and read more when you need it.
64
+
65
+ - `memory_search`: search by words and, when semantic search is on, by meaning, over one or both vaults. When it says semantic search is off, try other words too. Each result gives the vault, the path, the type, the Don't forget mark and whether the note needs fixing. Archived notes and notes with invalid frontmatter are not searched.
66
+ - `memory_get`: takes a vault and a path.
67
+ - A note path returns the note in full, with every problem if it breaks any rule.
68
+ - A folder path returns its index. `""` is the vault root.
69
+ - Paths under `archive/` can be read.
70
+ - To place a note, read the root index and walk down the folder indexes with `memory_get`.
71
+
72
+ ## Saving
73
+
74
+ - Memory is captured, updated and retired automatically by a background review of the conversation; you don't need to save anything for it.
75
+ - Use `memory_add` only when the user explicitly asks you to remember something. Never save on your own initiative, and never nudge the user to save.
76
+ - Choose the vault, the folder and the type as described above. Ask when unsure.
77
+ - A name already taken (in any case) is refused with the existing note. If it is the same point, read it with `memory_get` and, only if the user asked for a change, use `memory_update`; otherwise choose a statement that says what is new.
78
+ - Do not save skills or instructions to a vault. Vaults hold only memory.
79
+
80
+ ## Changing and retiring
81
+
82
+ Use these only when the user explicitly asks. Always read the note with `memory_get` in this session first, with the exact vault and path; a note not read, or changed on disk since it was read, is refused.
83
+
84
+ - `memory_update`: changes the body, type or Don't forget mark of a note. It never renames: a different statement is a new note that replaces the old one.
85
+ - `memory_archive`: retires a note that stopped being true and has no successor. It moves to `archive/`; nothing is ever deleted.
86
+ - `memory_succeed`: replaces a note with a new one (new statement, folder, type and body). The old note moves to `archive/` and both are linked.
87
+ - Notes under `archive/` cannot be changed.
88
+ - After a partial result, do not call again: tell the user what was done and ask them to check the vault.
89
+
90
+ ## Vault access
91
+
92
+ - Never read or write vault files with file tools (`read`, `write`, `edit`, `grep`, `find`, `ls`) or with the shell, however the path is reached.
93
+ - Use only the memory tools. Files outside the vaults are unaffected.
94
+ - The user edits the vault freely in Obsidian; a note can change between sessions.
95
+
96
+ ## Setup
97
+
98
+ - With no global vault registered there is no memory: tell the user to run `/memory-setup`.
99
+ - A folder not registered as a project has global memory only: the user can run `/memory-init` to register it.
100
+ - Notes listed under Needs fixing, blank notes and duplicate ids: suggest the user run `/memory-doctor`.
101
+ - A copy of the memory as a zip: the user can run `/memory-export`.
@@ -0,0 +1,5 @@
1
+ import type { CaptureTally } from "./types.ts"
2
+
3
+ export const MIN_USER_MESSAGES_BEFORE_REVIEW = 3
4
+
5
+ export const EMPTY_TALLY: CaptureTally = { userMessages: 0, turnsSinceReview: 0, toolCallsSinceReview: 0 }
@@ -0,0 +1,6 @@
1
+ export * from "./constants.ts"
2
+ export * from "./input-problems.ts"
3
+ export * from "./schemas.ts"
4
+ export * from "./tally.ts"
5
+ export * from "./types.ts"
6
+ export * from "./validate.ts"
@@ -0,0 +1,9 @@
1
+ import { Value } from "typebox/value"
2
+
3
+ import { describeSchemaErrors } from "#src/domain/validation"
4
+ import { CaptureInputSchema } from "./schemas.ts"
5
+ import type { CaptureInput } from "./types.ts"
6
+
7
+ export function captureInputProblems(input: CaptureInput): string[] {
8
+ return describeSchemaErrors(Value.Errors(CaptureInputSchema, input), "capture input")
9
+ }
@@ -0,0 +1,92 @@
1
+ import Type from "typebox"
2
+
3
+ import {
4
+ AgentContextSchema,
5
+ HashSchema,
6
+ ObservationSchema,
7
+ PathSchema,
8
+ ReadActionSchema,
9
+ ReadObservationSchema,
10
+ TextSchema,
11
+ VaultSchema,
12
+ } from "#src/domain/memory-agent"
13
+ import { NoteIdSchema, NoteTypeSchema } from "#src/domain/note"
14
+
15
+ export const CaptureDraftSchema = Type.Object(
16
+ { folder: PathSchema, statement: TextSchema, body: TextSchema, type: NoteTypeSchema, dontForget: Type.Boolean() },
17
+ { additionalProperties: false },
18
+ )
19
+
20
+ export const CaptureActionSchema = Type.Union([
21
+ ReadActionSchema,
22
+ Type.Object(
23
+ { action: Type.Literal("add"), vault: VaultSchema, note: CaptureDraftSchema },
24
+ { additionalProperties: false },
25
+ ),
26
+ Type.Object(
27
+ {
28
+ action: Type.Enum(["update", "succeed"]),
29
+ vault: VaultSchema,
30
+ path: PathSchema,
31
+ id: NoteIdSchema,
32
+ expectedHash: HashSchema,
33
+ note: CaptureDraftSchema,
34
+ },
35
+ { additionalProperties: false },
36
+ ),
37
+ Type.Object(
38
+ {
39
+ action: Type.Literal("archive"),
40
+ vault: VaultSchema,
41
+ path: PathSchema,
42
+ id: NoteIdSchema,
43
+ expectedHash: HashSchema,
44
+ },
45
+ { additionalProperties: false },
46
+ ),
47
+ Type.Object({ action: Type.Literal("finish") }, { additionalProperties: false }),
48
+ ])
49
+
50
+ export const WriteObservationSchema = Type.Object(
51
+ {
52
+ kind: Type.Literal("write"),
53
+ operation: Type.Enum(["add", "update", "archive", "succeed"]),
54
+ status: Type.Enum(["applied", "conflict", "refused"]),
55
+ vault: VaultSchema,
56
+ path: PathSchema,
57
+ detail: TextSchema,
58
+ },
59
+ { additionalProperties: false },
60
+ )
61
+
62
+ export const RefusedObservationSchema = Type.Object(
63
+ {
64
+ kind: Type.Literal("refused"),
65
+ action: Type.Enum(["search", "get", "list", "add", "update", "archive", "succeed", "finish", "unparseable"]),
66
+ problems: Type.Array(TextSchema),
67
+ },
68
+ { additionalProperties: false },
69
+ )
70
+
71
+ export const CaptureObservationSchema = Type.Union([
72
+ ObservationSchema,
73
+ WriteObservationSchema,
74
+ RefusedObservationSchema,
75
+ ])
76
+
77
+ export const CaptureInputSchema = Type.Object(
78
+ {
79
+ context: AgentContextSchema,
80
+ transcriptDelta: Type.Array(
81
+ Type.Object({ role: Type.Enum(["user", "assistant"]), text: TextSchema }, { additionalProperties: false }),
82
+ { minItems: 1 },
83
+ ),
84
+ observations: Type.Array(CaptureObservationSchema),
85
+ explicitSaves: Type.Array(ReadObservationSchema),
86
+ limits: Type.Object(
87
+ { maxBodyChars: Type.Integer({ minimum: 1 }), maxStatementChars: Type.Integer({ minimum: 1 }) },
88
+ { additionalProperties: false },
89
+ ),
90
+ },
91
+ { additionalProperties: false },
92
+ )
@@ -0,0 +1,26 @@
1
+ import { MIN_USER_MESSAGES_BEFORE_REVIEW } from "./constants.ts"
2
+ import type { CaptureCadenceSettings, CaptureTally, FinishedTurn, FlushMoment, TurnOutcome } from "./types.ts"
3
+
4
+ export function tallyUserMessage(tally: CaptureTally): CaptureTally {
5
+ return { ...tally, userMessages: tally.userMessages + 1 }
6
+ }
7
+
8
+ export function tallyTurn(
9
+ tally: CaptureTally,
10
+ turn: FinishedTurn,
11
+ settings: CaptureCadenceSettings | null,
12
+ ): TurnOutcome {
13
+ const counted = { ...tally, turnsSinceReview: tally.turnsSinceReview + 1 }
14
+ if (!settings?.reviewEnabled || turn.reviewActive) return { tally: counted, review: false }
15
+ counted.toolCallsSinceReview += turn.toolCalls
16
+ const reached =
17
+ counted.turnsSinceReview >= settings.nudgeInterval || counted.toolCallsSinceReview >= settings.nudgeToolCalls
18
+ if (!reached || counted.userMessages < MIN_USER_MESSAGES_BEFORE_REVIEW) return { tally: counted, review: false }
19
+ return { tally: { ...counted, turnsSinceReview: 0, toolCallsSinceReview: 0 }, review: true }
20
+ }
21
+
22
+ export function shouldFlush(tally: CaptureTally, settings: CaptureCadenceSettings, moment: FlushMoment): boolean {
23
+ if (tally.userMessages < settings.flushMinTurns) return false
24
+ if (moment === "compact") return settings.flushOnCompact
25
+ return settings.flushOnShutdown
26
+ }
@@ -0,0 +1,49 @@
1
+ import type { Static } from "typebox"
2
+
3
+ import type { Failed, Succeeded } from "#src/shared"
4
+ import type {
5
+ CaptureActionSchema,
6
+ CaptureDraftSchema,
7
+ CaptureInputSchema,
8
+ CaptureObservationSchema,
9
+ } from "./schemas.ts"
10
+
11
+ export interface CaptureCadenceSettings {
12
+ nudgeInterval: number
13
+ nudgeToolCalls: number
14
+ flushMinTurns: number
15
+ reviewEnabled: boolean
16
+ flushOnCompact: boolean
17
+ flushOnShutdown: boolean
18
+ }
19
+
20
+ export interface CaptureTally {
21
+ userMessages: number
22
+ turnsSinceReview: number
23
+ toolCallsSinceReview: number
24
+ }
25
+
26
+ export interface FinishedTurn {
27
+ toolCalls: number
28
+ reviewActive: boolean
29
+ }
30
+
31
+ export interface TurnOutcome {
32
+ tally: CaptureTally
33
+ review: boolean
34
+ }
35
+
36
+ export type FlushMoment = "compact" | "shutdown"
37
+
38
+ export type CaptureDraft = Static<typeof CaptureDraftSchema>
39
+ export type CaptureAction = Static<typeof CaptureActionSchema>
40
+ export type CaptureInput = Static<typeof CaptureInputSchema>
41
+ export type CaptureObservation = Static<typeof CaptureObservationSchema>
42
+ export type CaptureResult = Succeeded<CaptureAction> | Failed
43
+ export type TranscriptMessage = CaptureInput["transcriptDelta"][number]
44
+
45
+ export interface AddDiscriminant {
46
+ action: "add"
47
+ }
48
+
49
+ export type CaptureAdd = Extract<CaptureAction, AddDiscriminant>
@@ -0,0 +1,75 @@
1
+ import { Value } from "typebox/value"
2
+
3
+ import { checkAgentVault, checkReadAction, hasReadIdentity, type MemoryIdentity } from "#src/domain/memory-agent"
4
+ import { checkNoteText } from "#src/domain/note"
5
+ import { checkMemoryFolder, checkVaultPath, joinVaultPath } from "#src/domain/vault-path"
6
+ import { CaptureActionSchema } from "./schemas.ts"
7
+ import type { CaptureAction, CaptureAdd, CaptureDraft, CaptureInput, CaptureResult } from "./types.ts"
8
+
9
+ export function parseCaptureAction(text: string, input: CaptureInput): CaptureResult {
10
+ try {
11
+ const action = JSON.parse(text)
12
+ if (!Value.Check(CaptureActionSchema, action)) {
13
+ return { succeeded: false, problems: ["Invalid capture action"] }
14
+ }
15
+ const problems = checkCaptureAction(action, input)
16
+ if (problems.length > 0) return { succeeded: false, problems }
17
+ return { succeeded: true, output: action }
18
+ } catch {
19
+ return { succeeded: false, problems: ["Invalid capture JSON"] }
20
+ }
21
+ }
22
+
23
+ function checkCaptureAction(action: CaptureAction, input: CaptureInput): string[] {
24
+ if (action.action === "finish") return []
25
+ if (action.action === "search" || action.action === "get" || action.action === "list") {
26
+ return checkReadAction(action, input.context)
27
+ }
28
+ const problems = checkAgentVault(action.vault, input.context)
29
+ if (action.action !== "add") {
30
+ const identity = { vault: action.vault, path: action.path, id: action.id, hash: action.expectedHash }
31
+ problems.push(...checkMutation(identity, input))
32
+ }
33
+ if (action.action !== "archive") problems.push(...checkDraft(action.note, input))
34
+ if (action.action === "add") problems.push(...checkDuplicate(action, input))
35
+ if ((action.action === "add" || action.action === "succeed") && action.note.folder.length === 0) {
36
+ problems.push("New capture notes require a subject folder")
37
+ }
38
+ if (
39
+ action.action === "update" &&
40
+ (action.path.slice(-3).toLowerCase() !== ".md" ||
41
+ action.path.slice(0, -3) !== joinVaultPath(action.note.folder, action.note.statement))
42
+ ) {
43
+ problems.push("Update must keep the read note's folder and statement")
44
+ }
45
+ return problems
46
+ }
47
+
48
+ function checkMutation(identity: MemoryIdentity, input: CaptureInput): string[] {
49
+ const latest = input.observations.findLast(
50
+ (item) =>
51
+ (item.kind === "read" || item.kind === "write") && item.vault === identity.vault && item.path === identity.path,
52
+ )
53
+ const reads = input.observations.filter((item) => item.kind !== "write" && item.kind !== "refused")
54
+ if (latest?.kind !== "read" || !hasReadIdentity(identity, reads)) {
55
+ return ["Mutation requires a fresh matching read identity and hash"]
56
+ }
57
+ return checkVaultPath(identity.path)
58
+ }
59
+
60
+ function checkDraft(note: CaptureDraft, input: CaptureInput): string[] {
61
+ return [...checkNoteText(note.statement, note.body, input.limits), ...checkMemoryFolder(note.folder)]
62
+ }
63
+
64
+ function checkDuplicate(action: CaptureAdd, input: CaptureInput): string[] {
65
+ const existing = [...input.explicitSaves, ...input.observations.filter((item) => item.kind === "read")]
66
+ const path = joinVaultPath(action.note.folder, `${action.note.statement}.md`).toLowerCase()
67
+ const duplicate = existing.some(
68
+ (read) =>
69
+ read.vault === action.vault &&
70
+ (read.path.toLowerCase() === path ||
71
+ (read.statement === action.note.statement && read.body === action.note.body)),
72
+ )
73
+ if (duplicate) return ["Existing point requires an update or finish, not a duplicate add"]
74
+ return []
75
+ }