@maadb/core 0.0.1 → 0.7.9

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 (407) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +371 -3
  3. package/dist/architect.d.ts +2 -0
  4. package/dist/architect.d.ts.map +1 -0
  5. package/dist/architect.js +273 -0
  6. package/dist/architect.js.map +1 -0
  7. package/dist/auth/resolve.d.ts +36 -0
  8. package/dist/auth/resolve.d.ts.map +1 -0
  9. package/dist/auth/resolve.js +77 -0
  10. package/dist/auth/resolve.js.map +1 -0
  11. package/dist/auth/token-store.d.ts +82 -0
  12. package/dist/auth/token-store.d.ts.map +1 -0
  13. package/dist/auth/token-store.js +464 -0
  14. package/dist/auth/token-store.js.map +1 -0
  15. package/dist/auth/types.d.ts +75 -0
  16. package/dist/auth/types.d.ts.map +1 -0
  17. package/dist/auth/types.js +15 -0
  18. package/dist/auth/types.js.map +1 -0
  19. package/dist/backend/adapter.d.ts +57 -0
  20. package/dist/backend/adapter.d.ts.map +1 -0
  21. package/dist/backend/adapter.js +6 -0
  22. package/dist/backend/adapter.js.map +1 -0
  23. package/dist/backend/index.d.ts +3 -0
  24. package/dist/backend/index.d.ts.map +1 -0
  25. package/dist/backend/index.js +2 -0
  26. package/dist/backend/index.js.map +1 -0
  27. package/dist/backend/sqlite/index.d.ts +63 -0
  28. package/dist/backend/sqlite/index.d.ts.map +1 -0
  29. package/dist/backend/sqlite/index.js +521 -0
  30. package/dist/backend/sqlite/index.js.map +1 -0
  31. package/dist/backend/sqlite/schema.d.ts +2 -0
  32. package/dist/backend/sqlite/schema.d.ts.map +1 -0
  33. package/dist/backend/sqlite/schema.js +88 -0
  34. package/dist/backend/sqlite/schema.js.map +1 -0
  35. package/dist/claude-md.d.ts +2 -0
  36. package/dist/claude-md.d.ts.map +1 -0
  37. package/dist/claude-md.js +97 -0
  38. package/dist/claude-md.js.map +1 -0
  39. package/dist/cli/commands/audit.d.ts +4 -0
  40. package/dist/cli/commands/audit.d.ts.map +1 -0
  41. package/dist/cli/commands/audit.js +39 -0
  42. package/dist/cli/commands/audit.js.map +1 -0
  43. package/dist/cli/commands/auth.d.ts +8 -0
  44. package/dist/cli/commands/auth.d.ts.map +1 -0
  45. package/dist/cli/commands/auth.js +242 -0
  46. package/dist/cli/commands/auth.js.map +1 -0
  47. package/dist/cli/commands/discover.d.ts +5 -0
  48. package/dist/cli/commands/discover.d.ts.map +1 -0
  49. package/dist/cli/commands/discover.js +48 -0
  50. package/dist/cli/commands/discover.js.map +1 -0
  51. package/dist/cli/commands/maintain.d.ts +6 -0
  52. package/dist/cli/commands/maintain.d.ts.map +1 -0
  53. package/dist/cli/commands/maintain.js +168 -0
  54. package/dist/cli/commands/maintain.js.map +1 -0
  55. package/dist/cli/commands/read.d.ts +7 -0
  56. package/dist/cli/commands/read.d.ts.map +1 -0
  57. package/dist/cli/commands/read.js +139 -0
  58. package/dist/cli/commands/read.js.map +1 -0
  59. package/dist/cli/commands/write.d.ts +4 -0
  60. package/dist/cli/commands/write.d.ts.map +1 -0
  61. package/dist/cli/commands/write.js +99 -0
  62. package/dist/cli/commands/write.js.map +1 -0
  63. package/dist/cli/helpers.d.ts +8 -0
  64. package/dist/cli/helpers.d.ts.map +1 -0
  65. package/dist/cli/helpers.js +17 -0
  66. package/dist/cli/helpers.js.map +1 -0
  67. package/dist/cli/index.d.ts +3 -0
  68. package/dist/cli/index.d.ts.map +1 -0
  69. package/dist/cli/index.js +296 -0
  70. package/dist/cli/index.js.map +1 -0
  71. package/dist/cli.d.ts +3 -0
  72. package/dist/cli.d.ts.map +1 -0
  73. package/dist/cli.js +7 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/engine/audit.d.ts +15 -0
  76. package/dist/engine/audit.d.ts.map +1 -0
  77. package/dist/engine/audit.js +42 -0
  78. package/dist/engine/audit.js.map +1 -0
  79. package/dist/engine/composites.d.ts +6 -0
  80. package/dist/engine/composites.d.ts.map +1 -0
  81. package/dist/engine/composites.js +102 -0
  82. package/dist/engine/composites.js.map +1 -0
  83. package/dist/engine/context.d.ts +47 -0
  84. package/dist/engine/context.d.ts.map +1 -0
  85. package/dist/engine/context.js +55 -0
  86. package/dist/engine/context.js.map +1 -0
  87. package/dist/engine/docid-safe.d.ts +8 -0
  88. package/dist/engine/docid-safe.d.ts.map +1 -0
  89. package/dist/engine/docid-safe.js +0 -0
  90. package/dist/engine/docid-safe.js.map +1 -0
  91. package/dist/engine/helpers.d.ts +8 -0
  92. package/dist/engine/helpers.d.ts.map +1 -0
  93. package/dist/engine/helpers.js +102 -0
  94. package/dist/engine/helpers.js.map +1 -0
  95. package/dist/engine/index.d.ts +209 -0
  96. package/dist/engine/index.d.ts.map +1 -0
  97. package/dist/engine/index.js +489 -0
  98. package/dist/engine/index.js.map +1 -0
  99. package/dist/engine/indexing.d.ts +14 -0
  100. package/dist/engine/indexing.d.ts.map +1 -0
  101. package/dist/engine/indexing.js +225 -0
  102. package/dist/engine/indexing.js.map +1 -0
  103. package/dist/engine/journal.d.ts +32 -0
  104. package/dist/engine/journal.d.ts.map +1 -0
  105. package/dist/engine/journal.js +111 -0
  106. package/dist/engine/journal.js.map +1 -0
  107. package/dist/engine/logger.d.ts +19 -0
  108. package/dist/engine/logger.d.ts.map +1 -0
  109. package/dist/engine/logger.js +40 -0
  110. package/dist/engine/logger.js.map +1 -0
  111. package/dist/engine/maintenance.d.ts +15 -0
  112. package/dist/engine/maintenance.d.ts.map +1 -0
  113. package/dist/engine/maintenance.js +87 -0
  114. package/dist/engine/maintenance.js.map +1 -0
  115. package/dist/engine/mutex.d.ts +24 -0
  116. package/dist/engine/mutex.d.ts.map +1 -0
  117. package/dist/engine/mutex.js +50 -0
  118. package/dist/engine/mutex.js.map +1 -0
  119. package/dist/engine/pathguard.d.ts +16 -0
  120. package/dist/engine/pathguard.d.ts.map +1 -0
  121. package/dist/engine/pathguard.js +41 -0
  122. package/dist/engine/pathguard.js.map +1 -0
  123. package/dist/engine/reads.d.ts +24 -0
  124. package/dist/engine/reads.d.ts.map +1 -0
  125. package/dist/engine/reads.js +701 -0
  126. package/dist/engine/reads.js.map +1 -0
  127. package/dist/engine/types.d.ts +350 -0
  128. package/dist/engine/types.d.ts.map +1 -0
  129. package/dist/engine/types.js +5 -0
  130. package/dist/engine/types.js.map +1 -0
  131. package/dist/engine/writes.d.ts +10 -0
  132. package/dist/engine/writes.d.ts.map +1 -0
  133. package/dist/engine/writes.js +606 -0
  134. package/dist/engine/writes.js.map +1 -0
  135. package/dist/engine.d.ts +3 -0
  136. package/dist/engine.d.ts.map +1 -0
  137. package/dist/engine.js +6 -0
  138. package/dist/engine.js.map +1 -0
  139. package/dist/errors.d.ts +20 -0
  140. package/dist/errors.d.ts.map +1 -0
  141. package/dist/errors.js +17 -0
  142. package/dist/errors.js.map +1 -0
  143. package/dist/extractor/fields.d.ts +3 -0
  144. package/dist/extractor/fields.d.ts.map +1 -0
  145. package/dist/extractor/fields.js +58 -0
  146. package/dist/extractor/fields.js.map +1 -0
  147. package/dist/extractor/index.d.ts +7 -0
  148. package/dist/extractor/index.d.ts.map +1 -0
  149. package/dist/extractor/index.js +22 -0
  150. package/dist/extractor/index.js.map +1 -0
  151. package/dist/extractor/normalizers.d.ts +22 -0
  152. package/dist/extractor/normalizers.d.ts.map +1 -0
  153. package/dist/extractor/normalizers.js +250 -0
  154. package/dist/extractor/normalizers.js.map +1 -0
  155. package/dist/extractor/objects.d.ts +3 -0
  156. package/dist/extractor/objects.d.ts.map +1 -0
  157. package/dist/extractor/objects.js +33 -0
  158. package/dist/extractor/objects.js.map +1 -0
  159. package/dist/extractor/relationships.d.ts +3 -0
  160. package/dist/extractor/relationships.d.ts.map +1 -0
  161. package/dist/extractor/relationships.js +58 -0
  162. package/dist/extractor/relationships.js.map +1 -0
  163. package/dist/git/commit.d.ts +63 -0
  164. package/dist/git/commit.d.ts.map +1 -0
  165. package/dist/git/commit.js +161 -0
  166. package/dist/git/commit.js.map +1 -0
  167. package/dist/git/diff.d.ts +4 -0
  168. package/dist/git/diff.d.ts.map +1 -0
  169. package/dist/git/diff.js +56 -0
  170. package/dist/git/diff.js.map +1 -0
  171. package/dist/git/index.d.ts +41 -0
  172. package/dist/git/index.d.ts.map +1 -0
  173. package/dist/git/index.js +86 -0
  174. package/dist/git/index.js.map +1 -0
  175. package/dist/git/log.d.ts +13 -0
  176. package/dist/git/log.d.ts.map +1 -0
  177. package/dist/git/log.js +116 -0
  178. package/dist/git/log.js.map +1 -0
  179. package/dist/git/snapshot.d.ts +4 -0
  180. package/dist/git/snapshot.d.ts.map +1 -0
  181. package/dist/git/snapshot.js +65 -0
  182. package/dist/git/snapshot.js.map +1 -0
  183. package/dist/instance/config.d.ts +19 -0
  184. package/dist/instance/config.d.ts.map +1 -0
  185. package/dist/instance/config.js +107 -0
  186. package/dist/instance/config.js.map +1 -0
  187. package/dist/instance/pool.d.ts +138 -0
  188. package/dist/instance/pool.d.ts.map +1 -0
  189. package/dist/instance/pool.js +335 -0
  190. package/dist/instance/pool.js.map +1 -0
  191. package/dist/instance/session.d.ts +140 -0
  192. package/dist/instance/session.d.ts.map +1 -0
  193. package/dist/instance/session.js +267 -0
  194. package/dist/instance/session.js.map +1 -0
  195. package/dist/logging.d.ts +108 -0
  196. package/dist/logging.d.ts.map +1 -0
  197. package/dist/logging.js +120 -0
  198. package/dist/logging.js.map +1 -0
  199. package/dist/maad-md.d.ts +11 -0
  200. package/dist/maad-md.d.ts.map +1 -0
  201. package/dist/maad-md.js +252 -0
  202. package/dist/maad-md.js.map +1 -0
  203. package/dist/mcp/bulk-cap.d.ts +10 -0
  204. package/dist/mcp/bulk-cap.d.ts.map +1 -0
  205. package/dist/mcp/bulk-cap.js +37 -0
  206. package/dist/mcp/bulk-cap.js.map +1 -0
  207. package/dist/mcp/config.d.ts +18 -0
  208. package/dist/mcp/config.d.ts.map +1 -0
  209. package/dist/mcp/config.js +20 -0
  210. package/dist/mcp/config.js.map +1 -0
  211. package/dist/mcp/ctx.d.ts +17 -0
  212. package/dist/mcp/ctx.d.ts.map +1 -0
  213. package/dist/mcp/ctx.js +7 -0
  214. package/dist/mcp/ctx.js.map +1 -0
  215. package/dist/mcp/guardrails.d.ts +21 -0
  216. package/dist/mcp/guardrails.d.ts.map +1 -0
  217. package/dist/mcp/guardrails.js +39 -0
  218. package/dist/mcp/guardrails.js.map +1 -0
  219. package/dist/mcp/idempotency.d.ts +69 -0
  220. package/dist/mcp/idempotency.d.ts.map +1 -0
  221. package/dist/mcp/idempotency.js +168 -0
  222. package/dist/mcp/idempotency.js.map +1 -0
  223. package/dist/mcp/instance-reload.d.ts +23 -0
  224. package/dist/mcp/instance-reload.d.ts.map +1 -0
  225. package/dist/mcp/instance-reload.js +126 -0
  226. package/dist/mcp/instance-reload.js.map +1 -0
  227. package/dist/mcp/kinds.d.ts +22 -0
  228. package/dist/mcp/kinds.d.ts.map +1 -0
  229. package/dist/mcp/kinds.js +110 -0
  230. package/dist/mcp/kinds.js.map +1 -0
  231. package/dist/mcp/lifecycle.d.ts +8 -0
  232. package/dist/mcp/lifecycle.d.ts.map +1 -0
  233. package/dist/mcp/lifecycle.js +65 -0
  234. package/dist/mcp/lifecycle.js.map +1 -0
  235. package/dist/mcp/notifications.d.ts +87 -0
  236. package/dist/mcp/notifications.d.ts.map +1 -0
  237. package/dist/mcp/notifications.js +154 -0
  238. package/dist/mcp/notifications.js.map +1 -0
  239. package/dist/mcp/query-depth.d.ts +28 -0
  240. package/dist/mcp/query-depth.d.ts.map +1 -0
  241. package/dist/mcp/query-depth.js +43 -0
  242. package/dist/mcp/query-depth.js.map +1 -0
  243. package/dist/mcp/rate-limit.d.ts +60 -0
  244. package/dist/mcp/rate-limit.d.ts.map +1 -0
  245. package/dist/mcp/rate-limit.js +203 -0
  246. package/dist/mcp/rate-limit.js.map +1 -0
  247. package/dist/mcp/reload-signal.d.ts +13 -0
  248. package/dist/mcp/reload-signal.d.ts.map +1 -0
  249. package/dist/mcp/reload-signal.js +68 -0
  250. package/dist/mcp/reload-signal.js.map +1 -0
  251. package/dist/mcp/response.d.ts +109 -0
  252. package/dist/mcp/response.d.ts.map +1 -0
  253. package/dist/mcp/response.js +132 -0
  254. package/dist/mcp/response.js.map +1 -0
  255. package/dist/mcp/roles.d.ts +7 -0
  256. package/dist/mcp/roles.d.ts.map +1 -0
  257. package/dist/mcp/roles.js +56 -0
  258. package/dist/mcp/roles.js.map +1 -0
  259. package/dist/mcp/server.d.ts +33 -0
  260. package/dist/mcp/server.d.ts.map +1 -0
  261. package/dist/mcp/server.js +242 -0
  262. package/dist/mcp/server.js.map +1 -0
  263. package/dist/mcp/shutdown.d.ts +32 -0
  264. package/dist/mcp/shutdown.d.ts.map +1 -0
  265. package/dist/mcp/shutdown.js +130 -0
  266. package/dist/mcp/shutdown.js.map +1 -0
  267. package/dist/mcp/tools/audit.d.ts +4 -0
  268. package/dist/mcp/tools/audit.d.ts.map +1 -0
  269. package/dist/mcp/tools/audit.js +45 -0
  270. package/dist/mcp/tools/audit.js.map +1 -0
  271. package/dist/mcp/tools/auth.d.ts +4 -0
  272. package/dist/mcp/tools/auth.d.ts.map +1 -0
  273. package/dist/mcp/tools/auth.js +181 -0
  274. package/dist/mcp/tools/auth.js.map +1 -0
  275. package/dist/mcp/tools/discover.d.ts +4 -0
  276. package/dist/mcp/tools/discover.d.ts.map +1 -0
  277. package/dist/mcp/tools/discover.js +83 -0
  278. package/dist/mcp/tools/discover.js.map +1 -0
  279. package/dist/mcp/tools/instance.d.ts +15 -0
  280. package/dist/mcp/tools/instance.d.ts.map +1 -0
  281. package/dist/mcp/tools/instance.js +207 -0
  282. package/dist/mcp/tools/instance.js.map +1 -0
  283. package/dist/mcp/tools/maintain.d.ts +4 -0
  284. package/dist/mcp/tools/maintain.d.ts.map +1 -0
  285. package/dist/mcp/tools/maintain.js +118 -0
  286. package/dist/mcp/tools/maintain.js.map +1 -0
  287. package/dist/mcp/tools/read.d.ts +4 -0
  288. package/dist/mcp/tools/read.d.ts.map +1 -0
  289. package/dist/mcp/tools/read.js +260 -0
  290. package/dist/mcp/tools/read.js.map +1 -0
  291. package/dist/mcp/tools/write.d.ts +4 -0
  292. package/dist/mcp/tools/write.d.ts.map +1 -0
  293. package/dist/mcp/tools/write.js +342 -0
  294. package/dist/mcp/tools/write.js.map +1 -0
  295. package/dist/mcp/transport/auth.d.ts +41 -0
  296. package/dist/mcp/transport/auth.d.ts.map +1 -0
  297. package/dist/mcp/transport/auth.js +115 -0
  298. package/dist/mcp/transport/auth.js.map +1 -0
  299. package/dist/mcp/transport/http.d.ts +62 -0
  300. package/dist/mcp/transport/http.d.ts.map +1 -0
  301. package/dist/mcp/transport/http.js +357 -0
  302. package/dist/mcp/transport/http.js.map +1 -0
  303. package/dist/mcp/transport/pin.d.ts +15 -0
  304. package/dist/mcp/transport/pin.d.ts.map +1 -0
  305. package/dist/mcp/transport/pin.js +71 -0
  306. package/dist/mcp/transport/pin.js.map +1 -0
  307. package/dist/mcp/transport/telemetry.d.ts +79 -0
  308. package/dist/mcp/transport/telemetry.d.ts.map +1 -0
  309. package/dist/mcp/transport/telemetry.js +97 -0
  310. package/dist/mcp/transport/telemetry.js.map +1 -0
  311. package/dist/mcp/with-session.d.ts +26 -0
  312. package/dist/mcp/with-session.d.ts.map +1 -0
  313. package/dist/mcp/with-session.js +275 -0
  314. package/dist/mcp/with-session.js.map +1 -0
  315. package/dist/parser/annotations.d.ts +3 -0
  316. package/dist/parser/annotations.d.ts.map +1 -0
  317. package/dist/parser/annotations.js +41 -0
  318. package/dist/parser/annotations.js.map +1 -0
  319. package/dist/parser/blocks.d.ts +3 -0
  320. package/dist/parser/blocks.d.ts.map +1 -0
  321. package/dist/parser/blocks.js +99 -0
  322. package/dist/parser/blocks.js.map +1 -0
  323. package/dist/parser/frontmatter.d.ts +9 -0
  324. package/dist/parser/frontmatter.d.ts.map +1 -0
  325. package/dist/parser/frontmatter.js +33 -0
  326. package/dist/parser/frontmatter.js.map +1 -0
  327. package/dist/parser/index.d.ts +11 -0
  328. package/dist/parser/index.d.ts.map +1 -0
  329. package/dist/parser/index.js +54 -0
  330. package/dist/parser/index.js.map +1 -0
  331. package/dist/parser/matter.d.ts +3 -0
  332. package/dist/parser/matter.d.ts.map +1 -0
  333. package/dist/parser/matter.js +32 -0
  334. package/dist/parser/matter.js.map +1 -0
  335. package/dist/parser/tags.d.ts +3 -0
  336. package/dist/parser/tags.d.ts.map +1 -0
  337. package/dist/parser/tags.js +32 -0
  338. package/dist/parser/tags.js.map +1 -0
  339. package/dist/parser/verbatim.d.ts +4 -0
  340. package/dist/parser/verbatim.d.ts.map +1 -0
  341. package/dist/parser/verbatim.js +121 -0
  342. package/dist/parser/verbatim.js.map +1 -0
  343. package/dist/parser/yaml-profile.d.ts +4 -0
  344. package/dist/parser/yaml-profile.d.ts.map +1 -0
  345. package/dist/parser/yaml-profile.js +73 -0
  346. package/dist/parser/yaml-profile.js.map +1 -0
  347. package/dist/registry/index.d.ts +2 -0
  348. package/dist/registry/index.d.ts.map +1 -0
  349. package/dist/registry/index.js +2 -0
  350. package/dist/registry/index.js.map +1 -0
  351. package/dist/registry/loader.d.ts +4 -0
  352. package/dist/registry/loader.d.ts.map +1 -0
  353. package/dist/registry/loader.js +147 -0
  354. package/dist/registry/loader.js.map +1 -0
  355. package/dist/registry/types.d.ts +2 -0
  356. package/dist/registry/types.d.ts.map +1 -0
  357. package/dist/registry/types.js +5 -0
  358. package/dist/registry/types.js.map +1 -0
  359. package/dist/scanner.d.ts +57 -0
  360. package/dist/scanner.d.ts.map +1 -0
  361. package/dist/scanner.js +223 -0
  362. package/dist/scanner.js.map +1 -0
  363. package/dist/schema/index.d.ts +3 -0
  364. package/dist/schema/index.d.ts.map +1 -0
  365. package/dist/schema/index.js +3 -0
  366. package/dist/schema/index.js.map +1 -0
  367. package/dist/schema/loader.d.ts +4 -0
  368. package/dist/schema/loader.d.ts.map +1 -0
  369. package/dist/schema/loader.js +303 -0
  370. package/dist/schema/loader.js.map +1 -0
  371. package/dist/schema/precision.d.ts +6 -0
  372. package/dist/schema/precision.d.ts.map +1 -0
  373. package/dist/schema/precision.js +59 -0
  374. package/dist/schema/precision.js.map +1 -0
  375. package/dist/schema/validator.d.ts +21 -0
  376. package/dist/schema/validator.d.ts.map +1 -0
  377. package/dist/schema/validator.js +200 -0
  378. package/dist/schema/validator.js.map +1 -0
  379. package/dist/schema-md.d.ts +8 -0
  380. package/dist/schema-md.d.ts.map +1 -0
  381. package/dist/schema-md.js +98 -0
  382. package/dist/schema-md.js.map +1 -0
  383. package/dist/skill-files.d.ts +3 -0
  384. package/dist/skill-files.d.ts.map +1 -0
  385. package/dist/skill-files.js +362 -0
  386. package/dist/skill-files.js.map +1 -0
  387. package/dist/skills-scaffold.d.ts +10 -0
  388. package/dist/skills-scaffold.d.ts.map +1 -0
  389. package/dist/skills-scaffold.js +52 -0
  390. package/dist/skills-scaffold.js.map +1 -0
  391. package/dist/types.d.ts +309 -0
  392. package/dist/types.d.ts.map +1 -0
  393. package/dist/types.js +111 -0
  394. package/dist/types.js.map +1 -0
  395. package/dist/writer/index.d.ts +7 -0
  396. package/dist/writer/index.d.ts.map +1 -0
  397. package/dist/writer/index.js +32 -0
  398. package/dist/writer/index.js.map +1 -0
  399. package/dist/writer/serializer.d.ts +4 -0
  400. package/dist/writer/serializer.d.ts.map +1 -0
  401. package/dist/writer/serializer.js +103 -0
  402. package/dist/writer/serializer.js.map +1 -0
  403. package/dist/writer/template.d.ts +3 -0
  404. package/dist/writer/template.d.ts.map +1 -0
  405. package/dist/writer/template.js +27 -0
  406. package/dist/writer/template.js.map +1 -0
  407. package/package.json +59 -7
@@ -0,0 +1,168 @@
1
+ // ============================================================================
2
+ // Idempotency Cache — dedupes retried writes per (project, tool, key).
3
+ //
4
+ // Scope intentionally per-project, not per-session: a client whose connection
5
+ // drops mid-retry reconnects with a fresh session ID and re-issues the write.
6
+ // Session-scoped cache would miss and create a duplicate. Collision across
7
+ // unrelated clients is the client's responsibility (use UUIDs).
8
+ //
9
+ // Replay returns the original response body byte-for-byte, with a fresh `_meta`
10
+ // envelope: { replayed: true, original_request_id, original_completed_at }.
11
+ // Clients that ignore `_meta` see a normal successful response.
12
+ //
13
+ // Bounded: 10-minute TTL, 10k-entry LRU cap. Tunable via env. In-memory only —
14
+ // process restart drops the cache; documented behavior.
15
+ // ============================================================================
16
+ const DEFAULT_TTL_MS = 10 * 60 * 1000;
17
+ const DEFAULT_MAX_ENTRIES = 10_000;
18
+ export class IdempotencyCache {
19
+ ttlMs;
20
+ maxEntries;
21
+ now;
22
+ // JS Map preserves insertion order; we exploit that for O(1) LRU:
23
+ // every successful get() reinserts the entry to move it to the tail.
24
+ entries = new Map();
25
+ constructor(opts = {}) {
26
+ this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
27
+ this.maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;
28
+ this.now = opts.now ?? (() => Date.now());
29
+ }
30
+ /** Compose the cache key. Always use this — never pass raw strings. */
31
+ static composeKey(projectName, toolName, clientKey) {
32
+ return `${projectName}\u0000${toolName}\u0000${clientKey}`;
33
+ }
34
+ /**
35
+ * Return a cached entry if present and not expired, else null. Reinserts on
36
+ * hit so recent hits survive eviction.
37
+ */
38
+ get(key) {
39
+ const entry = this.entries.get(key);
40
+ if (!entry)
41
+ return null;
42
+ if (this.now() - entry.insertedAtMs > this.ttlMs) {
43
+ this.entries.delete(key);
44
+ return null;
45
+ }
46
+ // Bump recency: delete + reinsert moves to the Map's tail.
47
+ this.entries.delete(key);
48
+ this.entries.set(key, entry);
49
+ return entry;
50
+ }
51
+ /**
52
+ * Store a response. Evicts the least-recently-used entry if the cap is full.
53
+ * Only call this for successful responses — failures must not short-circuit
54
+ * retries.
55
+ */
56
+ put(key, entry) {
57
+ if (this.entries.has(key)) {
58
+ // Refresh existing entry
59
+ this.entries.delete(key);
60
+ }
61
+ this.entries.set(key, { ...entry, insertedAtMs: this.now() });
62
+ while (this.entries.size > this.maxEntries) {
63
+ const oldestKey = this.entries.keys().next().value;
64
+ if (oldestKey === undefined)
65
+ break;
66
+ this.entries.delete(oldestKey);
67
+ }
68
+ }
69
+ size() {
70
+ return this.entries.size;
71
+ }
72
+ clear() {
73
+ this.entries.clear();
74
+ }
75
+ }
76
+ // ---- Module-level singleton (same pattern as response.ts provenance) --------
77
+ let cache = new IdempotencyCache();
78
+ /** Replace the singleton cache — called once from server startup with env-derived config. */
79
+ export function initIdempotencyCache(opts) {
80
+ cache = new IdempotencyCache(opts);
81
+ }
82
+ /** Access the current singleton. Never returns null. */
83
+ export function getIdempotencyCache() {
84
+ return cache;
85
+ }
86
+ // ---- Config from env --------------------------------------------------------
87
+ export function readIdempotencyEnv() {
88
+ const ttl = process.env.MAAD_IDEMPOTENCY_TTL_MS;
89
+ const max = process.env.MAAD_IDEMPOTENCY_MAX;
90
+ const opts = {};
91
+ if (ttl && !Number.isNaN(Number(ttl)))
92
+ opts.ttlMs = Number(ttl);
93
+ if (max && !Number.isNaN(Number(max)))
94
+ opts.maxEntries = Number(max);
95
+ return opts;
96
+ }
97
+ /**
98
+ * Returns true if the response body (parsed from content[0].text) has
99
+ * `ok: true`. Silent false on parse failure — never cache anything we can't
100
+ * confirm succeeded.
101
+ */
102
+ export function isSuccessfulResponse(response) {
103
+ const first = response.content[0];
104
+ if (!first || first.type !== 'text')
105
+ return false;
106
+ try {
107
+ const parsed = JSON.parse(first.text);
108
+ return parsed.ok === true;
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ /**
115
+ * Build a replay response: identical body to the cached original, plus a fresh
116
+ * `_meta` envelope identifying this as a replay. Clients that ignore `_meta`
117
+ * see a normal successful response.
118
+ */
119
+ export function buildReplayResponse(cached, currentRequestId) {
120
+ const original = cached.response;
121
+ const first = original.content[0];
122
+ if (!first || first.type !== 'text')
123
+ return original;
124
+ let parsed;
125
+ try {
126
+ parsed = JSON.parse(first.text);
127
+ }
128
+ catch {
129
+ return original;
130
+ }
131
+ parsed._meta = {
132
+ request_id: currentRequestId,
133
+ replayed: true,
134
+ original_request_id: cached.originalRequestId,
135
+ original_completed_at: cached.originalCompletedAt,
136
+ };
137
+ return { content: [{ type: 'text', text: JSON.stringify(parsed) }] };
138
+ }
139
+ /**
140
+ * Wrapper for mutating tool handlers. If `clientKey` is provided, checks the
141
+ * cache for a prior completed call matching `(projectName, toolName, clientKey)`.
142
+ * On hit: returns the cached response with fresh replay metadata.
143
+ * On miss: runs `fn()`, caches if successful, returns the result.
144
+ *
145
+ * `currentRequestId` is the request ID for this specific call (used both for
146
+ * _meta on replays and as `originalRequestId` when caching a fresh response).
147
+ * H6 will supply a real request ID from the MCP wrapper; for now callers can
148
+ * pass `crypto.randomUUID()` to satisfy the signature.
149
+ */
150
+ export async function withIdempotency(projectName, toolName, clientKey, currentRequestId, fn) {
151
+ if (!clientKey)
152
+ return fn();
153
+ const cacheKey = IdempotencyCache.composeKey(projectName, toolName, clientKey);
154
+ const cached = cache.get(cacheKey);
155
+ if (cached) {
156
+ return buildReplayResponse(cached, currentRequestId);
157
+ }
158
+ const response = await fn();
159
+ if (isSuccessfulResponse(response)) {
160
+ cache.put(cacheKey, {
161
+ response,
162
+ originalRequestId: currentRequestId,
163
+ originalCompletedAt: new Date().toISOString(),
164
+ });
165
+ }
166
+ return response;
167
+ }
168
+ //# sourceMappingURL=idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/mcp/idempotency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Result } from '../errors.js';
2
+ import type { InstanceCtx } from './ctx.js';
3
+ export type InstanceReloadSource = 'tool' | 'sighup';
4
+ export interface InstanceReloadResult {
5
+ source: InstanceReloadSource;
6
+ projectsAdded: string[];
7
+ projectsRemoved: string[];
8
+ sessionsCancelled: string[];
9
+ sessionsPruned: string[];
10
+ durationMs: number;
11
+ }
12
+ /**
13
+ * Run a full instance reload from the config file recorded on the live
14
+ * InstanceConfig. Emits progress + audit log lines around the critical steps.
15
+ *
16
+ * Error codes that flow back to the caller (tool wraps them as MCP responses):
17
+ * - INSTANCE_RELOAD_SYNTHETIC (synthetic instance, no config file)
18
+ * - INSTANCE_RELOAD_IN_PROGRESS (another reload is active)
19
+ * - INSTANCE_RELOAD_FAILED (parse error, file read error, etc.)
20
+ * - INSTANCE_MUTATION_UNSUPPORTED (existing project path/role changed)
21
+ */
22
+ export declare function performInstanceReload(ctx: InstanceCtx, source: InstanceReloadSource): Promise<Result<InstanceReloadResult>>;
23
+ //# sourceMappingURL=instance-reload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-reload.d.ts","sourceRoot":"","sources":["../../src/mcp/instance-reload.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAI5C,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CA4GvC"}
@@ -0,0 +1,126 @@
1
+ // ============================================================================
2
+ // Instance reload orchestrator — shared by maad_instance_reload tool and the
3
+ // SIGHUP handler. Re-parses the instance config from disk, delegates the diff
4
+ // + eviction to EnginePool.reloadInstance, then propagates the new config to
5
+ // SessionRegistry and cancels / prunes sessions whose projects were removed.
6
+ //
7
+ // Both call sites (tool handler, SIGHUP handler) invoke this with a `source`
8
+ // string that flows into the audit event so operators can tell apart
9
+ // operator-initiated reloads from OS-signal reloads.
10
+ //
11
+ // Failure modes never leave the runtime half-applied: diff mutations are
12
+ // detected + rejected before any eviction, and the instance ref swap happens
13
+ // only after the pool has finished its part.
14
+ // ============================================================================
15
+ import { ok, singleErr } from '../errors.js';
16
+ import { loadInstance } from '../instance/config.js';
17
+ import { logInstanceReload, logInstanceReloadProgress } from '../logging.js';
18
+ /**
19
+ * Run a full instance reload from the config file recorded on the live
20
+ * InstanceConfig. Emits progress + audit log lines around the critical steps.
21
+ *
22
+ * Error codes that flow back to the caller (tool wraps them as MCP responses):
23
+ * - INSTANCE_RELOAD_SYNTHETIC (synthetic instance, no config file)
24
+ * - INSTANCE_RELOAD_IN_PROGRESS (another reload is active)
25
+ * - INSTANCE_RELOAD_FAILED (parse error, file read error, etc.)
26
+ * - INSTANCE_MUTATION_UNSUPPORTED (existing project path/role changed)
27
+ */
28
+ export async function performInstanceReload(ctx, source) {
29
+ const startedAt = Date.now();
30
+ // Acquire the reload slot FIRST, before any I/O — otherwise concurrent
31
+ // callers can both pass the in-progress check while one is still parsing
32
+ // its yaml. tryBeginReload also handles the synthetic-instance fast path
33
+ // so both checks live in one place.
34
+ const begin = ctx.pool.tryBeginReload();
35
+ if (!begin.ok) {
36
+ const message = begin.code === 'INSTANCE_RELOAD_SYNTHETIC'
37
+ ? 'Synthetic (legacy --project) instances cannot be reloaded. Start the server with --instance <path> to enable reload.'
38
+ : 'Another instance reload is already running. Retry once it completes.';
39
+ return singleErr(begin.code, message);
40
+ }
41
+ // From here on, every return path must call ctx.pool.endReload to release
42
+ // the slot and record success/failure stats.
43
+ let outcome = { ok: false };
44
+ try {
45
+ const configPath = ctx.instance.configPath;
46
+ if (!configPath) {
47
+ // Defense: file-source instances should always carry configPath. Treat
48
+ // missing as a failed reload rather than a silent no-op.
49
+ return singleErr('INSTANCE_RELOAD_FAILED', 'Instance has source="file" but no configPath recorded; cannot re-parse.');
50
+ }
51
+ logInstanceReloadProgress({ source, phase: 'start' });
52
+ // Re-parse the config file. Parse errors leave the running instance intact.
53
+ const loaded = await loadInstance(configPath);
54
+ if (!loaded.ok) {
55
+ const first = loaded.errors[0];
56
+ const detail = loaded.errors.map(e => `${e.code}: ${e.message}`).join('; ');
57
+ logInstanceReloadProgress({
58
+ source,
59
+ phase: 'failed',
60
+ code: first?.code ?? 'INSTANCE_RELOAD_FAILED',
61
+ message: detail,
62
+ durationMs: Date.now() - startedAt,
63
+ });
64
+ return singleErr('INSTANCE_RELOAD_FAILED', `Failed to load instance config from ${configPath}: ${detail}`);
65
+ }
66
+ const newInstance = loaded.value;
67
+ // Pool applies the diff: mutation check + eviction of removed engines.
68
+ const diffResult = await ctx.pool.applyDiff(newInstance);
69
+ if (!diffResult.ok) {
70
+ const first = diffResult.errors[0];
71
+ logInstanceReloadProgress({
72
+ source,
73
+ phase: 'failed',
74
+ code: first?.code ?? 'INSTANCE_RELOAD_FAILED',
75
+ message: first?.message ?? 'Apply diff failed',
76
+ durationMs: Date.now() - startedAt,
77
+ });
78
+ return diffResult;
79
+ }
80
+ const diff = diffResult.value;
81
+ // Propagate the new config to downstream refs that hold their own copy.
82
+ ctx.instance = newInstance;
83
+ ctx.sessions.setInstance(newInstance);
84
+ // Session fallout: single-mode sessions on removed projects → cancelled;
85
+ // multi-mode sessions → whitelist pruned (cancelled only if it drains).
86
+ const cancelled = [];
87
+ const pruned = [];
88
+ for (const name of diff.removed) {
89
+ cancelled.push(...ctx.sessions.cancelByProject(name));
90
+ const { prunedSessions, cancelledSessions } = ctx.sessions.pruneProjectFromWhitelist(name);
91
+ pruned.push(...prunedSessions);
92
+ cancelled.push(...cancelledSessions);
93
+ }
94
+ const durationMs = Date.now() - startedAt;
95
+ logInstanceReload({
96
+ source,
97
+ projectsAdded: diff.added.length,
98
+ projectsRemoved: diff.removed.length,
99
+ projectsAddedNames: diff.added,
100
+ projectsRemovedNames: diff.removed,
101
+ sessionsCancelled: cancelled.length,
102
+ sessionsPruned: pruned.length,
103
+ durationMs,
104
+ });
105
+ logInstanceReloadProgress({
106
+ source,
107
+ phase: 'complete',
108
+ projectsAdded: diff.added.length,
109
+ projectsRemoved: diff.removed.length,
110
+ durationMs,
111
+ });
112
+ outcome = { ok: true, diff };
113
+ return ok({
114
+ source,
115
+ projectsAdded: diff.added,
116
+ projectsRemoved: diff.removed,
117
+ sessionsCancelled: cancelled,
118
+ sessionsPruned: pruned,
119
+ durationMs,
120
+ });
121
+ }
122
+ finally {
123
+ ctx.pool.endReload(outcome);
124
+ }
125
+ }
126
+ //# sourceMappingURL=instance-reload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-reload.js","sourceRoot":"","sources":["../../src/mcp/instance-reload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type OperationKind = 'read' | 'write';
2
+ export declare const READ_TOOLS: ReadonlySet<string>;
3
+ export declare const WRITE_TOOLS: ReadonlySet<string>;
4
+ export declare const ENGINE_LESS_TOOLS: ReadonlySet<string>;
5
+ /**
6
+ * Returns the operation kind for a tool that flows through `withEngine`.
7
+ * Returns null for engine-less tools OR unknown names — callers must
8
+ * distinguish via {@link isEngineLess}.
9
+ */
10
+ export declare function getKindForTool(name: string): OperationKind | null;
11
+ /**
12
+ * True if the tool is instance/session-scoped and does not pass through
13
+ * `withEngine`. Callers using {@link getKindForTool} should check this
14
+ * before treating a null return as "missing annotation".
15
+ */
16
+ export declare function isEngineLess(name: string): boolean;
17
+ /**
18
+ * Every engine-bound tool name currently registered. Used by CI tests that
19
+ * cross-check against the MCP server's actual registrations to catch drift.
20
+ */
21
+ export declare function allEngineToolNames(): string[];
22
+ //# sourceMappingURL=kinds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../../src/mcp/kinds.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAI7C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,MAAM,CAiBzC,CAAC;AAIH,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,CAQ1C,CAAC;AAKH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAchD,CAAC;AAqBH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIjE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
@@ -0,0 +1,110 @@
1
+ // ============================================================================
2
+ // Operation kind metadata — every MCP tool that flows through `withEngine`
3
+ // declares read vs write. Reads invoke the handler directly; writes wrap it
4
+ // in `engine.runExclusive` so the per-engine FIFO mutex serializes them.
5
+ //
6
+ // The classification is the source of truth at the request boundary. The
7
+ // engine itself no longer self-wraps its mutation methods (0.5.0 R4) — the
8
+ // mutex lives at the MCP entry point where concurrency policy belongs.
9
+ //
10
+ // Missing annotations are caught at:
11
+ // - module load (disjointness assertion below)
12
+ // - runtime in `withEngine` (MISSING_OPERATION_KIND for any tool that
13
+ // passes through without a registered kind)
14
+ // - CI (tests/mcp/kinds.test.ts cross-checks against registered tools)
15
+ // ============================================================================
16
+ // Tools that flow through withEngine and do not mutate git / SQLite /
17
+ // in-memory cache / filesystem state.
18
+ export const READ_TOOLS = new Set([
19
+ 'maad_get',
20
+ 'maad_query',
21
+ 'maad_search',
22
+ 'maad_related',
23
+ 'maad_schema',
24
+ 'maad_aggregate',
25
+ 'maad_verify',
26
+ 'maad_join',
27
+ 'maad_changes_since',
28
+ 'maad_history',
29
+ 'maad_audit',
30
+ 'maad_scan',
31
+ 'maad_summary',
32
+ 'maad_describe',
33
+ 'maad_validate',
34
+ 'maad_health',
35
+ ]);
36
+ // Tools that flow through withEngine and may mutate engine state. Must
37
+ // acquire the write mutex.
38
+ export const WRITE_TOOLS = new Set([
39
+ 'maad_create',
40
+ 'maad_update',
41
+ 'maad_bulk_create',
42
+ 'maad_bulk_update',
43
+ 'maad_delete',
44
+ 'maad_reindex',
45
+ 'maad_reload',
46
+ ]);
47
+ // Tools that do not flow through withEngine — they operate on session /
48
+ // instance state only and never resolve an engine. OperationKind does not
49
+ // apply. Listed here so kind-coverage assertions know to skip them.
50
+ export const ENGINE_LESS_TOOLS = new Set([
51
+ 'maad_projects',
52
+ 'maad_use_project',
53
+ 'maad_use_projects',
54
+ 'maad_current_session',
55
+ 'maad_instance_reload',
56
+ 'maad_subscribe',
57
+ 'maad_unsubscribe',
58
+ 'maad_subscriptions',
59
+ 'maad_issue_token',
60
+ 'maad_revoke_token',
61
+ 'maad_rotate_token',
62
+ 'maad_list_tokens',
63
+ 'maad_show_token',
64
+ ]);
65
+ // Assert the three sets are disjoint. A tool belongs to exactly one bucket.
66
+ // Runs at module load — a bad entry crashes the process at startup rather
67
+ // than silently shipping.
68
+ (function assertDisjoint() {
69
+ const seen = new Map();
70
+ const register = (bucket, names) => {
71
+ for (const name of names) {
72
+ const prev = seen.get(name);
73
+ if (prev) {
74
+ throw new Error(`kinds.ts: tool "${name}" listed in both "${prev}" and "${bucket}"`);
75
+ }
76
+ seen.set(name, bucket);
77
+ }
78
+ };
79
+ register('READ_TOOLS', READ_TOOLS);
80
+ register('WRITE_TOOLS', WRITE_TOOLS);
81
+ register('ENGINE_LESS_TOOLS', ENGINE_LESS_TOOLS);
82
+ })();
83
+ /**
84
+ * Returns the operation kind for a tool that flows through `withEngine`.
85
+ * Returns null for engine-less tools OR unknown names — callers must
86
+ * distinguish via {@link isEngineLess}.
87
+ */
88
+ export function getKindForTool(name) {
89
+ if (READ_TOOLS.has(name))
90
+ return 'read';
91
+ if (WRITE_TOOLS.has(name))
92
+ return 'write';
93
+ return null;
94
+ }
95
+ /**
96
+ * True if the tool is instance/session-scoped and does not pass through
97
+ * `withEngine`. Callers using {@link getKindForTool} should check this
98
+ * before treating a null return as "missing annotation".
99
+ */
100
+ export function isEngineLess(name) {
101
+ return ENGINE_LESS_TOOLS.has(name);
102
+ }
103
+ /**
104
+ * Every engine-bound tool name currently registered. Used by CI tests that
105
+ * cross-check against the MCP server's actual registrations to catch drift.
106
+ */
107
+ export function allEngineToolNames() {
108
+ return [...READ_TOOLS, ...WRITE_TOOLS];
109
+ }
110
+ //# sourceMappingURL=kinds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../src/mcp/kinds.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,4EAA4E;AAC5E,yEAAyE;AACzE,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,uEAAuE;AACvE,EAAE;AACF,qCAAqC;AACrC,iDAAiD;AACjD,wEAAwE;AACxE,gDAAgD;AAChD,yEAAyE;AACzE,+EAA+E;AAI/E,sEAAsE;AACtE,sCAAsC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC;IACrD,UAAU;IACV,YAAY;IACZ,aAAa;IACb,cAAc;IACd,aAAa;IACb,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,oBAAoB;IACpB,cAAc;IACd,YAAY;IACZ,WAAW;IACX,cAAc;IACd,eAAe;IACf,eAAe;IACf,aAAa;CACd,CAAC,CAAC;AAEH,uEAAuE;AACvE,2BAA2B;AAC3B,MAAM,CAAC,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC;IACtD,aAAa;IACb,aAAa;IACb,kBAAkB;IAClB,kBAAkB;IAClB,aAAa;IACb,cAAc;IACd,aAAa;CACd,CAAC,CAAC;AAEH,wEAAwE;AACxE,0EAA0E;AAC1E,oEAAoE;AACpE,MAAM,CAAC,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC;IAC5D,eAAe;IACf,kBAAkB;IAClB,mBAAmB;IACnB,sBAAsB;IACtB,sBAAsB;IACtB,gBAAgB;IAChB,kBAAkB;IAClB,oBAAoB;IACpB,kBAAkB;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,iBAAiB;CAClB,CAAC,CAAC;AAEH,4EAA4E;AAC5E,0EAA0E;AAC1E,0BAA0B;AAC1B,CAAC,SAAS,cAAc;IACtB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,KAA0B,EAAE,EAAE;QAC9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,qBAAqB,IAAI,UAAU,MAAM,GAAG,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC;IACF,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACrC,QAAQ,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;AACnD,CAAC,CAAC,EAAE,CAAC;AAEL;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IACxC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,GAAG,UAAU,EAAE,GAAG,WAAW,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { MaadEngine } from '../engine.js';
2
+ export interface StartupResult {
3
+ engine: MaadEngine;
4
+ warnings: string[];
5
+ }
6
+ export declare function startupEngine(projectRoot: string): Promise<StartupResult>;
7
+ export declare function registerShutdownHooks(engine: MaadEngine | null, cleanup?: () => Promise<void>): void;
8
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/mcp/lifecycle.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C/E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAYpG"}
@@ -0,0 +1,65 @@
1
+ // ============================================================================
2
+ // MCP Lifecycle — startup validation, engine init, shutdown hooks
3
+ // Extracted from server.ts to keep server focused on transport.
4
+ // ============================================================================
5
+ import { existsSync } from 'node:fs';
6
+ import path from 'node:path';
7
+ import { MaadEngine } from '../engine.js';
8
+ import { logger } from '../engine/logger.js';
9
+ import { ensureProjectSkills } from '../skills-scaffold.js';
10
+ export async function startupEngine(projectRoot) {
11
+ const resolved = path.resolve(projectRoot);
12
+ const warnings = [];
13
+ // Validate project exists
14
+ if (!existsSync(resolved)) {
15
+ throw new Error(`Project directory not found: ${resolved}`);
16
+ }
17
+ // Init engine — self-heals _registry, _schema, _backend on empty projects
18
+ const engine = new MaadEngine();
19
+ const initResult = await engine.init(resolved);
20
+ if (!initResult.ok) {
21
+ const messages = initResult.errors.map(e => `${e.code}: ${e.message}`).join('; ');
22
+ throw new Error(`Engine initialization failed: ${messages}`);
23
+ }
24
+ // Ensure _skills/ guide files exist for the agent. Non-blocking: a failed
25
+ // write (permissions, read-only FS) logs a warning but does not crash the
26
+ // server — engine is already up and usable without the skills.
27
+ if (!engine.isReadOnly()) {
28
+ const skillsResult = ensureProjectSkills(resolved);
29
+ if (skillsResult.created.length > 0) {
30
+ logger.info('lifecycle', 'startup', `Scaffolded skills: ${skillsResult.created.join(', ')}`);
31
+ }
32
+ for (const e of skillsResult.errors) {
33
+ logger.bestEffort('lifecycle', 'startup', `Failed to write ${e.file}: ${e.message}`);
34
+ warnings.push(`skills scaffold: ${e.file} — ${e.message}`);
35
+ }
36
+ }
37
+ // Check for recovery actions
38
+ const recovery = engine.getStartupRecovery();
39
+ if (recovery.length > 0) {
40
+ for (const action of recovery) {
41
+ logger.info('lifecycle', 'startup', action);
42
+ warnings.push(action);
43
+ }
44
+ }
45
+ // Log health
46
+ const health = engine.health();
47
+ logger.info('lifecycle', 'startup', `Engine ready: ${health.totalDocuments} docs, ${health.registeredTypes} types, git: ${health.gitAvailable}`);
48
+ return { engine, warnings };
49
+ }
50
+ export function registerShutdownHooks(engine, cleanup) {
51
+ // Legacy shim retained for any caller that still uses the single-engine
52
+ // flow. The modern path is installSignalHandlers(target, opts) from
53
+ // src/mcp/shutdown.ts with pool + rate limiter. Server.ts uses that path.
54
+ const shutdown = async () => {
55
+ logger.info('lifecycle', 'shutdown', 'Shutting down...');
56
+ if (engine)
57
+ engine.close();
58
+ if (cleanup)
59
+ await cleanup();
60
+ process.exit(0);
61
+ };
62
+ process.on('SIGINT', shutdown);
63
+ process.on('SIGTERM', shutdown);
64
+ }
65
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/mcp/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import type { InstanceCtx } from './ctx.js';
2
+ /**
3
+ * Event shape emitted on durable writes. Used both as the payload mapped into
4
+ * MCP's `notifications/resources/updated` and as the match target for
5
+ * per-session filters.
6
+ */
7
+ export interface ChangeEvent {
8
+ action: 'create' | 'update' | 'delete';
9
+ docId: string;
10
+ docType: string;
11
+ project: string;
12
+ updatedAt: string;
13
+ }
14
+ /**
15
+ * Callback that pushes a ChangeEvent to a single MCP session's client. The
16
+ * transport layer (HTTP or stdio) registers this closure when it builds the
17
+ * per-session McpServer. Failures are logged but never thrown — a broken
18
+ * notifier channel must not kill the write that triggered it.
19
+ */
20
+ export type Notifier = (event: ChangeEvent) => Promise<void>;
21
+ /**
22
+ * Register a notifier for a session. Called by the transport once the
23
+ * per-session McpServer is connected and ready to emit. Overwrites any
24
+ * prior registration for the same sessionId (transport reconnect path).
25
+ */
26
+ export declare function registerNotifier(sessionId: string, fn: Notifier): void;
27
+ /**
28
+ * Remove a notifier. Called when a session is destroyed (SessionRegistry
29
+ * close handler fans this out). Safe to call with an unknown sessionId.
30
+ */
31
+ export declare function unregisterNotifier(sessionId: string): void;
32
+ /**
33
+ * Current count of registered notifiers. Used by maad_health telemetry and
34
+ * by zero-overhead fast-path detection in `notifyWrite`.
35
+ */
36
+ export declare function notifierCount(): number;
37
+ /**
38
+ * Test hook — drops every registered notifier. Production code never calls
39
+ * this; vitest suites that reuse the process need it between cases.
40
+ */
41
+ export declare function __resetNotifiers(): void;
42
+ /**
43
+ * Fan-out entry point called by MCP write tool handlers after a successful
44
+ * durable commit. Iterates sessions with subscriptions, matches the filter,
45
+ * and invokes each session's notifier. Zero overhead when no session has a
46
+ * subscription (the count check bypasses the iteration).
47
+ *
48
+ * Caller MUST only invoke this when `writeDurable === true` on the engine
49
+ * result — the durability gate is upstream, not here. Delete operations
50
+ * should pass `action: 'delete'` and the docType recorded before deletion.
51
+ */
52
+ export declare function notifyWrite(ctx: InstanceCtx, event: ChangeEvent): Promise<void>;
53
+ /**
54
+ * 0.6.12 — Inventory of active subscriptions across an instance. Produced
55
+ * by `maad_subscriptions` (admin-only). Extracted here so the aggregation
56
+ * logic is unit-testable without spinning up a full MCP server.
57
+ *
58
+ * `byProject` reflects "who would receive an event for project X": single-mode
59
+ * sessions bin under their activeProject; multi-mode sessions without an
60
+ * explicit project filter bin under every whitelisted project; sessions with
61
+ * an explicit filter bin only under that project.
62
+ *
63
+ * `byDocType` uses `*` as the any-type bucket (subscribers that omitted the
64
+ * docTypes filter) so admins can tell at a glance how many "firehose" vs
65
+ * "type-narrowed" subscribers are active.
66
+ */
67
+ export interface SubscriptionInventoryEntry {
68
+ sessionId: string;
69
+ mode: string | null;
70
+ activeProject: string | null;
71
+ whitelist: string[] | null;
72
+ subscription: {
73
+ docTypes: string[] | null;
74
+ project: string | null;
75
+ createdAt: string;
76
+ };
77
+ bindingSource: string | null;
78
+ lastActivityAt: string;
79
+ }
80
+ export interface SubscriptionInventory {
81
+ totalSubscriptions: number;
82
+ subscriptions: SubscriptionInventoryEntry[];
83
+ byProject: Record<string, number>;
84
+ byDocType: Record<string, number>;
85
+ }
86
+ export declare function collectSubscriptions(sessions: InstanceCtx['sessions']): SubscriptionInventory;
87
+ //# sourceMappingURL=notifications.d.ts.map