@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,225 @@
1
+ // ============================================================================
2
+ // Indexing — indexAll, indexFile, processDocument, reindex
3
+ // ============================================================================
4
+ import { existsSync } from 'node:fs';
5
+ import { readFile } from 'node:fs/promises';
6
+ import { createHash } from 'node:crypto';
7
+ import path from 'node:path';
8
+ import { ok, err, singleErr } from '../errors.js';
9
+ import { docId as toDocId, docType as toDocType, filePath as toFilePath, } from '../types.js';
10
+ import { parseDocument } from '../parser/index.js';
11
+ import { validateFrontmatter } from '../schema/index.js';
12
+ import { extract } from '../extractor/index.js';
13
+ import { collectMarkdownFiles, computeNumericValue } from './helpers.js';
14
+ // 0.7.4 (fup-2026-093) — Per-type schema fingerprint covering the indexed
15
+ // field set. When a schema edit flips a field's `index: false → true` (or
16
+ // adds/removes an indexed field), the fingerprint changes; indexAll detects
17
+ // that and force-rebuilds docs of the affected type even when their file
18
+ // hashes are unchanged. Closes the silent "indexed: 0, skipped: N" footgun.
19
+ //
20
+ // Fingerprint covers: indexed field names + their types (so a type-change
21
+ // on an indexed field also triggers rebuild). Sorted+joined+hashed; first
22
+ // 16 hex chars are plenty of collision resistance for this use.
23
+ function computeIndexedFieldFingerprint(schema) {
24
+ const parts = [];
25
+ for (const [name, def] of schema.fields) {
26
+ if (def.index)
27
+ parts.push(`${name}:${def.type}`);
28
+ }
29
+ parts.sort();
30
+ return createHash('sha256').update(parts.join('|')).digest('hex').slice(0, 16);
31
+ }
32
+ const SCHEMA_FP_KEY_PREFIX = 'schema_index_fp:';
33
+ export async function indexAll(ctx, opts) {
34
+ const force = opts?.force ?? false;
35
+ const result = { scanned: 0, indexed: 0, skipped: 0, errors: [] };
36
+ // 0.7.4 — Detect schema-index changes per type. Types whose fingerprint
37
+ // changed (or was never recorded) join `dirtyTypes`, which overrides the
38
+ // file-hash skip path below so docs of those types reindex even if their
39
+ // markdown is byte-for-byte unchanged.
40
+ const dirtyTypes = new Set();
41
+ const currentFingerprints = new Map();
42
+ for (const [typeName] of ctx.registry.types) {
43
+ const schema = ctx.schemaStore.getSchemaForType(typeName);
44
+ if (!schema)
45
+ continue;
46
+ const fp = computeIndexedFieldFingerprint(schema);
47
+ currentFingerprints.set(typeName, fp);
48
+ if (force) {
49
+ dirtyTypes.add(typeName);
50
+ continue;
51
+ }
52
+ const stored = ctx.backend.getMeta(`${SCHEMA_FP_KEY_PREFIX}${typeName}`);
53
+ if (stored !== fp)
54
+ dirtyTypes.add(typeName);
55
+ }
56
+ const storedHashes = force ? new Map() : ctx.backend.getAllFileHashes();
57
+ const filesOnDisk = new Set();
58
+ for (const [typeName, regType] of ctx.registry.types) {
59
+ const isTypeDirty = dirtyTypes.has(typeName);
60
+ const dirPath = path.join(ctx.projectRoot, regType.path);
61
+ if (!existsSync(dirPath))
62
+ continue;
63
+ const files = await collectMarkdownFiles(dirPath);
64
+ for (const file of files) {
65
+ result.scanned++;
66
+ const fp = toFilePath(path.relative(ctx.projectRoot, file));
67
+ const absPath = toFilePath(file);
68
+ filesOnDisk.add(fp);
69
+ // Skip-by-hash only applies when neither --force nor a schema-fingerprint
70
+ // change is in play. Otherwise we rebuild even if disk content matches.
71
+ if (!force && !isTypeDirty) {
72
+ const raw = await readFile(file, 'utf-8');
73
+ const currentHash = createHash('sha256').update(raw).digest('hex');
74
+ const storedHash = storedHashes.get(fp);
75
+ if (storedHash === currentHash) {
76
+ result.skipped++;
77
+ continue;
78
+ }
79
+ }
80
+ const indexResult = await indexFile(ctx, absPath);
81
+ if (indexResult.ok) {
82
+ result.indexed++;
83
+ }
84
+ else {
85
+ result.errors.push(...indexResult.errors);
86
+ }
87
+ }
88
+ }
89
+ // Remove stale backend records
90
+ const allStoredPaths = ctx.backend.getAllFileHashes();
91
+ for (const [storedPath] of allStoredPaths) {
92
+ if (!filesOnDisk.has(storedPath)) {
93
+ const doc = ctx.backend.getDocumentByPath(storedPath);
94
+ if (doc) {
95
+ ctx.backend.removeDocument(doc.docId);
96
+ }
97
+ }
98
+ }
99
+ // 0.7.4 — Persist current fingerprints AFTER successful rebuild so a
100
+ // crash mid-reindex leaves the prior fingerprint in place; next run sees
101
+ // the diff again and retries.
102
+ for (const [typeName, fp] of currentFingerprints) {
103
+ ctx.backend.setMeta(`${SCHEMA_FP_KEY_PREFIX}${typeName}`, fp);
104
+ }
105
+ if (dirtyTypes.size > 0) {
106
+ result.rebuiltTypes = [...dirtyTypes].sort();
107
+ }
108
+ return result;
109
+ }
110
+ export async function indexFile(ctx, absolutePath) {
111
+ const parsed = await parseDocument(absolutePath, ctx.registry.subtypeMap);
112
+ if (!parsed.ok)
113
+ return parsed;
114
+ return processDocument(ctx, parsed.value);
115
+ }
116
+ export function processDocument(ctx, parsed) {
117
+ const fmDocType = parsed.frontmatter['doc_type'];
118
+ if (typeof fmDocType !== 'string') {
119
+ return singleErr('UNKNOWN_TYPE', `Document has no doc_type in frontmatter: ${parsed.filePath}`);
120
+ }
121
+ const dt = toDocType(fmDocType);
122
+ const schema = ctx.schemaStore.getSchemaForType(dt);
123
+ if (!schema) {
124
+ return singleErr('UNKNOWN_TYPE', `No schema found for doc_type "${fmDocType}"`);
125
+ }
126
+ const fmDocId = parsed.frontmatter['doc_id'];
127
+ if (typeof fmDocId !== 'string') {
128
+ return singleErr('INVALID_DOC_ID', `Document has no doc_id in frontmatter: ${parsed.filePath}`);
129
+ }
130
+ const regType = ctx.registry.types.get(dt);
131
+ if (!regType) {
132
+ return singleErr('UNKNOWN_TYPE', `Type "${fmDocType}" not in registry`);
133
+ }
134
+ // Index mode: structural validation only. Precision enforcement is write-
135
+ // time only — historical records on disk must stay indexable regardless
136
+ // of current schema precision declarations.
137
+ const validation = validateFrontmatter(parsed.frontmatter, schema, ctx.registry, parsed.filePath, { mode: 'index' });
138
+ const validatedFields = {};
139
+ for (const [fieldName, fieldDef] of schema.fields) {
140
+ const value = parsed.frontmatter[fieldName];
141
+ if (value !== undefined && value !== null) {
142
+ validatedFields[fieldName] = {
143
+ name: fieldName,
144
+ value,
145
+ fieldType: fieldDef.type,
146
+ role: fieldDef.role,
147
+ indexed: fieldDef.index,
148
+ };
149
+ }
150
+ }
151
+ const bound = {
152
+ parsed,
153
+ docId: toDocId(fmDocId),
154
+ docType: dt,
155
+ schemaRef: regType.schemaRef,
156
+ validatedFields,
157
+ validationResult: validation,
158
+ };
159
+ const extraction = extract(bound, schema, ctx.registry);
160
+ const relativePath = path.relative(ctx.projectRoot, parsed.filePath);
161
+ const existing = ctx.backend.getDocument(bound.docId);
162
+ // Only bump version when file content actually changed — reindex of unchanged files preserves version
163
+ const contentChanged = !existing || existing.fileHash !== parsed.fileHash;
164
+ const version = existing
165
+ ? (contentChanged ? existing.version + 1 : existing.version)
166
+ : 1;
167
+ const now = new Date().toISOString();
168
+ const docRecord = {
169
+ docId: bound.docId,
170
+ docType: bound.docType,
171
+ schemaRef: bound.schemaRef,
172
+ filePath: toFilePath(relativePath),
173
+ fileHash: parsed.fileHash,
174
+ version,
175
+ deleted: false,
176
+ indexedAt: now,
177
+ updatedAt: contentChanged ? now : (existing?.updatedAt ?? now),
178
+ };
179
+ const fieldIndex = [];
180
+ for (const [name, field] of Object.entries(validatedFields)) {
181
+ if (field.indexed) {
182
+ // List fields: one row per item so filters match individual values
183
+ if (field.fieldType === 'list' && Array.isArray(field.value)) {
184
+ for (const item of field.value) {
185
+ const itemValue = item instanceof Date
186
+ ? item.toISOString()
187
+ : String(item);
188
+ fieldIndex.push({
189
+ name,
190
+ value: itemValue,
191
+ numericValue: computeNumericValue(item, 'string'),
192
+ type: field.fieldType,
193
+ });
194
+ }
195
+ }
196
+ else {
197
+ const fieldValue = field.value instanceof Date
198
+ ? field.value.toISOString()
199
+ : String(field.value);
200
+ fieldIndex.push({
201
+ name,
202
+ value: fieldValue,
203
+ numericValue: computeNumericValue(field.value, field.fieldType),
204
+ type: field.fieldType,
205
+ });
206
+ }
207
+ }
208
+ }
209
+ ctx.backend.materializeDocument(docRecord, extraction.objects, extraction.relationships, parsed.blocks, fieldIndex);
210
+ return ok(extraction);
211
+ }
212
+ export async function reindex(ctx, opts) {
213
+ if (opts?.docId) {
214
+ const doc = ctx.backend.getDocument(opts.docId);
215
+ if (!doc)
216
+ return singleErr('FILE_NOT_FOUND', `Document "${opts.docId}" not found`);
217
+ const absPath = path.join(ctx.projectRoot, doc.filePath);
218
+ const result = await indexFile(ctx, toFilePath(absPath));
219
+ if (!result.ok)
220
+ return err(result.errors);
221
+ return ok({ scanned: 1, indexed: 1, skipped: 0, errors: [] });
222
+ }
223
+ return ok(await indexAll(ctx, { force: opts?.force ?? false }));
224
+ }
225
+ //# sourceMappingURL=indexing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexing.js","sourceRoot":"","sources":["../../src/engine/indexing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface JournalEntry {
2
+ id: string;
3
+ op: 'create' | 'update' | 'delete';
4
+ docId: string;
5
+ filePath: string;
6
+ tempPath?: string | undefined;
7
+ timestamp: string;
8
+ status: 'pending' | 'file_written' | 'indexed' | 'committed';
9
+ }
10
+ export declare class OperationJournal {
11
+ private journalPath;
12
+ private entries;
13
+ constructor(backendDir: string);
14
+ private load;
15
+ private save;
16
+ begin(op: JournalEntry['op'], docId: string, filePath: string, tempPath?: string): string;
17
+ advance(id: string, status: JournalEntry['status']): void;
18
+ complete(id: string): void;
19
+ getPending(): JournalEntry[];
20
+ /**
21
+ * Reconcile incomplete operations on startup.
22
+ * Returns a list of recovery actions taken.
23
+ */
24
+ reconcile(): string[];
25
+ }
26
+ /**
27
+ * Atomic file write: write to temp path, then rename.
28
+ * On failure, temp file is cleaned up.
29
+ */
30
+ export declare function atomicWriteSync(targetPath: string, content: string): string;
31
+ export declare function atomicWrite(targetPath: string, content: string): Promise<string>;
32
+ //# sourceMappingURL=journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/engine/journal.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;CAC9D;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAsB;gBAEzB,UAAU,EAAE,MAAM;IAK9B,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,IAAI;IAIZ,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAezF,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQzD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK1B,UAAU,IAAI,YAAY,EAAE;IAI5B;;;OAGG;IACH,SAAS,IAAI,MAAM,EAAE;CAgCtB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAK3E;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOtF"}
@@ -0,0 +1,111 @@
1
+ // ============================================================================
2
+ // Operation Journal — tracks pending writes for crash recovery
3
+ // Stored in _backend/journal.json. Reconciled on engine startup.
4
+ // ============================================================================
5
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, renameSync } from 'node:fs';
6
+ import path from 'node:path';
7
+ export class OperationJournal {
8
+ journalPath;
9
+ entries = [];
10
+ constructor(backendDir) {
11
+ this.journalPath = path.join(backendDir, 'journal.json');
12
+ this.load();
13
+ }
14
+ load() {
15
+ if (existsSync(this.journalPath)) {
16
+ try {
17
+ const raw = readFileSync(this.journalPath, 'utf-8');
18
+ this.entries = JSON.parse(raw);
19
+ }
20
+ catch {
21
+ this.entries = [];
22
+ }
23
+ }
24
+ }
25
+ save() {
26
+ writeFileSync(this.journalPath, JSON.stringify(this.entries, null, 2), 'utf-8');
27
+ }
28
+ begin(op, docId, filePath, tempPath) {
29
+ const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
30
+ this.entries.push({
31
+ id,
32
+ op,
33
+ docId,
34
+ filePath,
35
+ tempPath,
36
+ timestamp: new Date().toISOString(),
37
+ status: 'pending',
38
+ });
39
+ this.save();
40
+ return id;
41
+ }
42
+ advance(id, status) {
43
+ const entry = this.entries.find(e => e.id === id);
44
+ if (entry) {
45
+ entry.status = status;
46
+ this.save();
47
+ }
48
+ }
49
+ complete(id) {
50
+ this.entries = this.entries.filter(e => e.id !== id);
51
+ this.save();
52
+ }
53
+ getPending() {
54
+ return this.entries.filter(e => e.status !== 'committed');
55
+ }
56
+ /**
57
+ * Reconcile incomplete operations on startup.
58
+ * Returns a list of recovery actions taken.
59
+ */
60
+ reconcile() {
61
+ const actions = [];
62
+ const pending = this.getPending();
63
+ for (const entry of pending) {
64
+ if (entry.status === 'pending' && entry.tempPath) {
65
+ // Write never completed — clean up temp file
66
+ if (existsSync(entry.tempPath)) {
67
+ try {
68
+ unlinkSync(entry.tempPath);
69
+ actions.push(`Cleaned up incomplete temp file: ${entry.tempPath}`);
70
+ }
71
+ catch {
72
+ actions.push(`Failed to clean temp file: ${entry.tempPath}`);
73
+ }
74
+ }
75
+ }
76
+ else if (entry.status === 'file_written') {
77
+ // File written but not indexed — mark for reindex
78
+ actions.push(`File written but not indexed: ${entry.filePath} (doc: ${entry.docId}). Run reindex to recover.`);
79
+ }
80
+ else if (entry.status === 'indexed') {
81
+ // Indexed but git commit failed — non-critical, just note it
82
+ actions.push(`Indexed but git commit skipped: ${entry.filePath} (doc: ${entry.docId}).`);
83
+ }
84
+ }
85
+ // Clear all pending entries after reconciliation
86
+ if (pending.length > 0) {
87
+ this.entries = [];
88
+ this.save();
89
+ }
90
+ return actions;
91
+ }
92
+ }
93
+ /**
94
+ * Atomic file write: write to temp path, then rename.
95
+ * On failure, temp file is cleaned up.
96
+ */
97
+ export function atomicWriteSync(targetPath, content) {
98
+ const tempPath = targetPath + '.maad-tmp';
99
+ writeFileSync(tempPath, content, 'utf-8');
100
+ renameSync(tempPath, targetPath);
101
+ return targetPath;
102
+ }
103
+ export async function atomicWrite(targetPath, content) {
104
+ const { writeFile: fsWriteFile } = await import('node:fs/promises');
105
+ const { rename } = await import('node:fs/promises');
106
+ const tempPath = targetPath + '.maad-tmp';
107
+ await fsWriteFile(tempPath, content, 'utf-8');
108
+ await rename(tempPath, targetPath);
109
+ return targetPath;
110
+ }
111
+ //# sourceMappingURL=journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal.js","sourceRoot":"","sources":["../../src/engine/journal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type Severity = 'fatal' | 'error' | 'degraded' | 'best_effort' | 'info';
2
+ export interface LogEntry {
3
+ severity: Severity;
4
+ category: string;
5
+ operation: string;
6
+ message: string;
7
+ details?: Record<string, unknown> | undefined;
8
+ }
9
+ export type LogHandler = (entry: LogEntry) => void;
10
+ export declare function setLogHandler(h: LogHandler): void;
11
+ export declare function log(severity: Severity, category: string, operation: string, message: string, details?: Record<string, unknown>): void;
12
+ export declare const logger: {
13
+ fatal: (cat: string, op: string, msg: string, details?: Record<string, unknown>) => void;
14
+ error: (cat: string, op: string, msg: string, details?: Record<string, unknown>) => void;
15
+ degraded: (cat: string, op: string, msg: string, details?: Record<string, unknown>) => void;
16
+ bestEffort: (cat: string, op: string, msg: string, details?: Record<string, unknown>) => void;
17
+ info: (cat: string, op: string, msg: string, details?: Record<string, unknown>) => void;
18
+ };
19
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/engine/logger.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,MAAM,CAAC;AAE/E,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAwBnD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAEjD;AAED,wBAAgB,GAAG,CACjB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAEN;AAGD,eAAO,MAAM,MAAM;iBACJ,MAAM,MAAM,MAAM,OAAO,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;iBAClE,MAAM,MAAM,MAAM,OAAO,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBAC/D,MAAM,MAAM,MAAM,OAAO,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;sBAChE,MAAM,MAAM,MAAM,OAAO,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBACxE,MAAM,MAAM,MAAM,OAAO,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAC/E,CAAC"}
@@ -0,0 +1,40 @@
1
+ // ============================================================================
2
+ // Engine Logger — structured error/event logging with severity policy
3
+ // All engine operations log through this instead of console.warn/silent catch.
4
+ // Emits via the pino ops logger from src/logging.ts so output is JSON.
5
+ // ============================================================================
6
+ import { getOpsLog } from '../logging.js';
7
+ const severityToLevel = {
8
+ fatal: 'fatal',
9
+ error: 'error',
10
+ degraded: 'warn',
11
+ best_effort: 'warn',
12
+ info: 'info',
13
+ };
14
+ const defaultHandler = (entry) => {
15
+ const level = severityToLevel[entry.severity];
16
+ const log = getOpsLog();
17
+ const payload = {
18
+ event: 'engine',
19
+ category: entry.category,
20
+ operation: entry.operation,
21
+ ...(entry.details ?? {}),
22
+ };
23
+ log[level](payload, entry.message);
24
+ };
25
+ let handler = defaultHandler;
26
+ export function setLogHandler(h) {
27
+ handler = h;
28
+ }
29
+ export function log(severity, category, operation, message, details) {
30
+ handler({ severity, category, operation, message, details });
31
+ }
32
+ // Convenience shortcuts
33
+ export const logger = {
34
+ fatal: (cat, op, msg, details) => log('fatal', cat, op, msg, details),
35
+ error: (cat, op, msg, details) => log('error', cat, op, msg, details),
36
+ degraded: (cat, op, msg, details) => log('degraded', cat, op, msg, details),
37
+ bestEffort: (cat, op, msg, details) => log('best_effort', cat, op, msg, details),
38
+ info: (cat, op, msg, details) => log('info', cat, op, msg, details),
39
+ };
40
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/engine/logger.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,sEAAsE;AACtE,+EAA+E;AAC/E,uEAAuE;AACvE,+EAA+E;AAE/E,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAc1C,MAAM,eAAe,GAA0D;IAC7E,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,MAAM;IAChB,WAAW,EAAE,MAAM;IACnB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,cAAc,GAAe,CAAC,KAAK,EAAE,EAAE;IAC3C,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG;QACd,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;KACzB,CAAC;IACD,GAAG,CAAC,KAAK,CAAsC,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,IAAI,OAAO,GAAe,cAAc,CAAC;AAEzC,MAAM,UAAU,aAAa,CAAC,CAAa;IACzC,OAAO,GAAG,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,QAAkB,EAClB,QAAgB,EAChB,SAAiB,EACjB,OAAe,EACf,OAAiC;IAEjC,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,wBAAwB;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,EAAE,CAAC,GAAW,EAAE,EAAU,EAAE,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC;IACvH,KAAK,EAAE,CAAC,GAAW,EAAE,EAAU,EAAE,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC;IACvH,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAU,EAAE,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC;IAC7H,UAAU,EAAE,CAAC,GAAW,EAAE,EAAU,EAAE,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC;IAClI,IAAI,EAAE,CAAC,GAAW,EAAE,EAAU,EAAE,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC;CACtH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type Result } from '../errors.js';
2
+ import type { DocId } from '../types.js';
3
+ import type { EngineContext } from './context.js';
4
+ import type { ValidationReport } from './types.js';
5
+ export interface ValidateOptions {
6
+ /**
7
+ * 0.6.7 — opt in to scanning every date field with a declared
8
+ * store_precision and reporting any historical records whose stored value
9
+ * is coarser than the contract. Informational; never changes
10
+ * `valid`/`invalid` counts.
11
+ */
12
+ includePrecision?: boolean;
13
+ }
14
+ export declare function validate(ctx: EngineContext, docId?: DocId | undefined, options?: ValidateOptions): Promise<Result<ValidationReport>>;
15
+ //# sourceMappingURL=maintenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/engine/maintenance.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,aAAa,EAClB,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,EACzB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAwDnC"}
@@ -0,0 +1,87 @@
1
+ // ============================================================================
2
+ // Maintenance — validate
3
+ // ============================================================================
4
+ import { ok, singleErr } from '../errors.js';
5
+ import { validateFrontmatter } from '../schema/index.js';
6
+ import { detectPrecision, isCoarserThan } from '../schema/precision.js';
7
+ import { readFrontmatter } from './helpers.js';
8
+ export async function validate(ctx, docId, options) {
9
+ const includePrecision = options?.includePrecision ?? false;
10
+ if (docId) {
11
+ const doc = ctx.backend.getDocument(docId);
12
+ if (!doc)
13
+ return singleErr('FILE_NOT_FOUND', `Document "${docId}" not found`);
14
+ const schema = ctx.schemaStore.getSchemaForType(doc.docType);
15
+ if (!schema)
16
+ return singleErr('SCHEMA_NOT_FOUND', `No schema for type "${doc.docType}"`);
17
+ const frontmatter = await readFrontmatter(ctx.projectRoot, doc);
18
+ const result = validateFrontmatter(frontmatter, schema, ctx.registry, undefined, { mode: 'audit' });
19
+ const report = {
20
+ total: 1,
21
+ valid: result.valid ? 1 : 0,
22
+ invalid: result.valid ? 0 : 1,
23
+ errors: result.valid ? [] : [{ docId, errors: result.errors.map(e => ({ field: e.field, message: e.message })) }],
24
+ };
25
+ if (includePrecision) {
26
+ report.precisionDrift = collectPrecisionDrift(docId, frontmatter, schema);
27
+ }
28
+ return ok(report);
29
+ }
30
+ const allDocs = ctx.backend.findDocuments({ limit: 100000 });
31
+ const report = { total: 0, valid: 0, invalid: 0, errors: [] };
32
+ const drift = includePrecision ? [] : undefined;
33
+ for (const match of allDocs) {
34
+ report.total++;
35
+ const doc = ctx.backend.getDocument(match.docId);
36
+ if (!doc)
37
+ continue;
38
+ const schema = ctx.schemaStore.getSchemaForType(doc.docType);
39
+ if (!schema) {
40
+ report.invalid++;
41
+ report.errors.push({ docId: doc.docId, errors: [{ field: 'doc_type', message: 'No schema found' }] });
42
+ continue;
43
+ }
44
+ const frontmatter = await readFrontmatter(ctx.projectRoot, doc);
45
+ const result = validateFrontmatter(frontmatter, schema, ctx.registry, undefined, { mode: 'audit' });
46
+ if (result.valid) {
47
+ report.valid++;
48
+ }
49
+ else {
50
+ report.invalid++;
51
+ report.errors.push({ docId: doc.docId, errors: result.errors.map(e => ({ field: e.field, message: e.message })) });
52
+ }
53
+ if (drift) {
54
+ drift.push(...collectPrecisionDrift(doc.docId, frontmatter, schema));
55
+ }
56
+ }
57
+ if (drift)
58
+ report.precisionDrift = drift;
59
+ return ok(report);
60
+ }
61
+ function collectPrecisionDrift(docId, frontmatter, schema) {
62
+ const out = [];
63
+ for (const [fieldName, fieldDef] of schema.fields) {
64
+ if (fieldDef.type !== 'date' || fieldDef.storePrecision === null)
65
+ continue;
66
+ const value = frontmatter[fieldName];
67
+ if (value === undefined || value === null)
68
+ continue;
69
+ const actual = value instanceof Date
70
+ ? 'millisecond'
71
+ : typeof value === 'string'
72
+ ? detectPrecision(value)
73
+ : null;
74
+ if (actual === null)
75
+ continue; // malformed — structural handler's concern
76
+ if (!isCoarserThan(actual, fieldDef.storePrecision))
77
+ continue;
78
+ out.push({
79
+ docId,
80
+ field: fieldName,
81
+ declared: fieldDef.storePrecision,
82
+ actual,
83
+ });
84
+ }
85
+ return out;
86
+ }
87
+ //# sourceMappingURL=maintenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/engine/maintenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export type Release = () => void;
2
+ export declare class AsyncFifoMutex {
3
+ private queue;
4
+ private held;
5
+ /**
6
+ * Acquire the lock. Returns a release function. Callers MUST call release()
7
+ * in a finally block to avoid leaks.
8
+ *
9
+ * Ordering is FIFO: the first caller to await acquire() is the first to be
10
+ * granted the lock when it becomes available.
11
+ */
12
+ acquire(): Promise<Release>;
13
+ private release;
14
+ /**
15
+ * Current pressure on the lock: 1 if held and no waiters, >1 if waiters are
16
+ * queued, 0 if idle. Used for health reporting and drain loops.
17
+ */
18
+ depth(): number;
19
+ /**
20
+ * True if the lock is currently held by a caller.
21
+ */
22
+ isHeld(): boolean;
23
+ }
24
+ //# sourceMappingURL=mutex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutex.d.ts","sourceRoot":"","sources":["../../src/engine/mutex.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC;AAEjC,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,IAAI,CAAS;IAErB;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAc3B,OAAO,CAAC,OAAO;IAMf;;;OAGG;IACH,KAAK,IAAI,MAAM;IAIf;;OAEG;IACH,MAAM,IAAI,OAAO;CAGlB"}