@bitcobblers/wod-wiki-tools 0.53.2204 → 0.55.2206

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 (647) hide show
  1. package/dist/agentCommands-O6WPIGLW.mjs +586 -0
  2. package/dist/agentCommands-O6WPIGLW.mjs.map +1 -0
  3. package/dist/bin/wod.cjs +1071 -29
  4. package/dist/bin/wod.cjs.map +1 -1
  5. package/dist/bin/wod.mjs +2 -2
  6. package/dist/chunk-67JAEWEF.mjs +144 -0
  7. package/dist/chunk-67JAEWEF.mjs.map +1 -0
  8. package/dist/{chunk-SLCRIGUR.mjs → chunk-76CB4MGO.mjs} +168 -28
  9. package/dist/chunk-76CB4MGO.mjs.map +1 -0
  10. package/dist/{chunk-2EWCEE6N.mjs → chunk-FNEN33GQ.mjs} +106 -6
  11. package/dist/chunk-FNEN33GQ.mjs.map +1 -0
  12. package/dist/{chunk-LNBKPHEP.mjs → chunk-RVQB3DYE.mjs} +9 -4
  13. package/dist/chunk-RVQB3DYE.mjs.map +1 -0
  14. package/dist/{chunk-5NNSHRMZ.mjs → chunk-WKU3MRQI.mjs} +3 -3
  15. package/dist/chunk-WKU3MRQI.mjs.map +1 -0
  16. package/dist/index.cjs +1075 -29
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +68 -3
  19. package/dist/index.d.ts +68 -3
  20. package/dist/index.mjs +5 -4
  21. package/dist/mcp-XCK6B5JA.mjs +73 -0
  22. package/dist/mcp-XCK6B5JA.mjs.map +1 -0
  23. package/dist/{scaffoldFeed-TCRNXYQU.mjs → scaffoldFeed-MC4UX4CO.mjs} +3 -3
  24. package/dist/{scaffoldFeed-TCRNXYQU.mjs.map → scaffoldFeed-MC4UX4CO.mjs.map} +1 -1
  25. package/dist/server/app.cjs +239 -2
  26. package/dist/server/app.cjs.map +1 -1
  27. package/dist/server/app.d.cts +2 -0
  28. package/dist/server/app.d.ts +2 -0
  29. package/dist/server/app.mjs +3 -1
  30. package/dist/server-HQJMA7BU.mjs +13 -0
  31. package/dist/{server-SHNWCIIM.mjs.map → server-HQJMA7BU.mjs.map} +1 -1
  32. package/dist/skills/README.md +3 -0
  33. package/dist/skills/wod-agent-parity/SKILL.md +41 -0
  34. package/dist/skills/wod-cli/SKILL.md +127 -0
  35. package/dist/skills/wod-wql/SKILL.md +63 -0
  36. package/dist/web/playground/ai-skills/agent-parity.md +41 -0
  37. package/dist/web/playground/ai-skills/cli.md +127 -0
  38. package/dist/web/playground/ai-skills/wql.md +63 -0
  39. package/dist/web/{server/assets/feedSync.worker-O4TGLEj3.js → playground/assets/feedSync.worker-CJyLPLAX.js} +2 -2
  40. package/dist/web/playground/assets/main-CmNfdWYO.js +1160 -0
  41. package/dist/web/playground/assets/main-DedlsEjf.css +2 -0
  42. package/dist/web/playground/assets/{statementBuilderFlow-CQWO7k9W.js → statementBuilderFlow-CtEe1EOX.js} +2 -2
  43. package/dist/web/playground/assets/vendor-BUlwHBNF.js +255 -0
  44. package/dist/web/{server/assets/vendor-codemirror-B4BeZarI.js → playground/assets/vendor-codemirror-Bh6hyz5v.js} +11 -11
  45. package/dist/web/playground/index.html +4 -4
  46. package/dist/web/playground/llms-full.txt +1444 -0
  47. package/dist/web/playground/llms.txt +67 -0
  48. package/dist/web/{server/seed/core/chunks/canvas.deac64e3.json → playground/seed/core/chunks/canvas.6cf875a1.json} +1 -1
  49. package/dist/web/playground/seed/core/chunks/{dashboards.08301ab4.json → dashboards.277192c5.json} +1 -1
  50. package/dist/web/playground/seed/core/chunks/{efforts.47f650fe.json → efforts.b943edc6.json} +1 -1
  51. package/dist/web/playground/seed/core/chunks/{equipment.79146d31.json → equipment.3cc3e02c.json} +1 -1
  52. package/dist/web/playground/seed/core/indexes/notebooks/canvas.json +180 -180
  53. package/dist/web/playground/seed/core/indexes/notebooks/dashboards.json +16 -16
  54. package/dist/web/playground/seed/core/indexes/notebooks/efforts.json +326 -326
  55. package/dist/web/playground/seed/core/indexes/notebooks/equipment.json +50 -50
  56. package/dist/web/playground/seed/core/manifest.json +27 -27
  57. package/dist/web/playground/seed/core/markdown/canvas/ai-first/README.json +1 -1
  58. package/dist/web/playground/seed/core/markdown/canvas/guide/README.json +4 -4
  59. package/dist/web/playground/seed/core/markdown/canvas/guide/clock.json +1 -1
  60. package/dist/web/playground/seed/core/markdown/canvas/guide/dashboards.json +1 -1
  61. package/dist/web/playground/seed/core/markdown/canvas/guide/metrics-summaries.json +2 -2
  62. package/dist/web/playground/seed/core/markdown/canvas/guide/metrics.json +12 -12
  63. package/dist/web/playground/seed/core/markdown/canvas/guide/protocols.json +20 -20
  64. package/dist/web/playground/seed/core/markdown/canvas/guide/sessions.json +33 -33
  65. package/dist/web/playground/seed/core/markdown/canvas/guide/start.json +11 -11
  66. package/dist/web/playground/seed/core/markdown/canvas/guide/structure.json +25 -25
  67. package/dist/web/playground/seed/core/markdown/canvas/guide/wql.json +5 -5
  68. package/dist/web/playground/seed/core/markdown/canvas/home/sample-script.json +4 -4
  69. package/dist/web/playground/seed/core/markdown/canvas/home/welcome-1.json +2 -2
  70. package/dist/web/playground/seed/core/markdown/canvas/syntax/actions-comments.json +4 -4
  71. package/dist/web/playground/seed/core/markdown/canvas/syntax/alternating-emom.json +5 -5
  72. package/dist/web/playground/seed/core/markdown/canvas/syntax/basic-emom.json +4 -4
  73. package/dist/web/playground/seed/core/markdown/canvas/syntax/calculated-metrics.json +4 -4
  74. package/dist/web/playground/seed/core/markdown/canvas/syntax/classic-amrap.json +6 -6
  75. package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-barbell-cycling.json +4 -4
  76. package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-full-session.json +10 -10
  77. package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-nested-protocols.json +7 -7
  78. package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-partner-workout.json +7 -7
  79. package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-swimming.json +5 -5
  80. package/dist/web/playground/seed/core/markdown/canvas/syntax/core-rules.json +4 -4
  81. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-and-calculated-metrics.json +4 -4
  82. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-intervals.json +4 -4
  83. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-1.json +4 -4
  84. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-2.json +5 -5
  85. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-3.json +3 -3
  86. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-4.json +4 -4
  87. package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-5.json +4 -4
  88. package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-climb-bouldering.json +2 -2
  89. package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-climb-hangboard.json +2 -2
  90. package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-climb-sport.json +2 -2
  91. package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-log.json +4 -4
  92. package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-plan.json +8 -8
  93. package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-wod.json +5 -5
  94. package/dist/web/playground/seed/core/markdown/canvas/syntax/distance-intervals.json +3 -3
  95. package/dist/web/playground/seed/core/markdown/canvas/syntax/document-1.json +4 -4
  96. package/dist/web/playground/seed/core/markdown/canvas/syntax/document-2.json +5 -5
  97. package/dist/web/playground/seed/core/markdown/canvas/syntax/document-3.json +10 -10
  98. package/dist/web/playground/seed/core/markdown/canvas/syntax/document-4.json +5 -5
  99. package/dist/web/playground/seed/core/markdown/canvas/syntax/effort-notes.json +5 -5
  100. package/dist/web/playground/seed/core/markdown/canvas/syntax/frontmatter-summaries.json +4 -4
  101. package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-1.json +5 -5
  102. package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-2.json +6 -6
  103. package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-3.json +3 -3
  104. package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-4.json +3 -3
  105. package/dist/web/playground/seed/core/markdown/canvas/syntax/longer-duration.json +4 -4
  106. package/dist/web/playground/seed/core/markdown/canvas/syntax/longer-intervals.json +4 -4
  107. package/dist/web/playground/seed/core/markdown/canvas/syntax/measurements.json +7 -7
  108. package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-1.json +5 -5
  109. package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-2.json +7 -7
  110. package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-3.json +8 -8
  111. package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-4.json +6 -6
  112. package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-5.json +5 -5
  113. package/dist/web/playground/seed/core/markdown/canvas/syntax/mixed-sections.json +10 -10
  114. package/dist/web/playground/seed/core/markdown/canvas/syntax/mixed-timers.json +5 -5
  115. package/dist/web/playground/seed/core/markdown/canvas/syntax/multiple-amrap-windows.json +7 -7
  116. package/dist/web/playground/seed/core/markdown/canvas/syntax/multiple-sets.json +4 -4
  117. package/dist/web/playground/seed/core/markdown/canvas/syntax/named-groups.json +6 -6
  118. package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-1.json +6 -6
  119. package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-2.json +4 -4
  120. package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-3.json +6 -6
  121. package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-4.json +3 -3
  122. package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-5.json +4 -4
  123. package/dist/web/playground/seed/core/markdown/canvas/syntax/single-movement.json +3 -3
  124. package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-1.json +4 -4
  125. package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-2.json +5 -5
  126. package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-3.json +4 -4
  127. package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-4.json +4 -4
  128. package/dist/web/playground/seed/core/markdown/canvas/syntax/time-cap.json +6 -6
  129. package/dist/web/playground/seed/core/markdown/canvas/syntax/timer-modifiers.json +6 -6
  130. package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-1.json +6 -6
  131. package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-2.json +4 -4
  132. package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-3.json +4 -4
  133. package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-4.json +4 -4
  134. package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-5.json +5 -5
  135. package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-rest.json +4 -4
  136. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/aggregate-by-effort.json +2 -2
  137. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/aggregate-by-week.json +2 -2
  138. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/content-fran.json +2 -2
  139. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/filter-combos.json +2 -2
  140. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/pipes-limit.json +2 -2
  141. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/session-rpe.json +2 -2
  142. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/source-journal.json +2 -2
  143. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/tis-trend.json +2 -2
  144. package/dist/web/playground/seed/core/markdown/canvas/wql-presets/where-join.json +2 -2
  145. package/dist/web/playground/seed/core/markdown/dashboards/benchmark-pr-board.json +6 -6
  146. package/dist/web/playground/seed/core/markdown/dashboards/finger-strength-v8.json +5 -5
  147. package/dist/web/playground/seed/core/markdown/dashboards/polarized-base-marathon.json +9 -9
  148. package/dist/web/playground/seed/core/markdown/dashboards/recovery-readiness.json +7 -7
  149. package/dist/web/playground/seed/core/markdown/dashboards/road-to-560-total.json +9 -9
  150. package/dist/web/playground/seed/core/markdown/dashboards/training-block-review.json +11 -11
  151. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/air-squat.json +1 -1
  152. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/box-jump.json +1 -1
  153. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/broad-jump.json +1 -1
  154. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/burpee-box-jump-over.json +1 -1
  155. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/burpee-over-dumbbell.json +1 -1
  156. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/burpee.json +1 -1
  157. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/dumbbell-squat-clean.json +1 -1
  158. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/ghd-sit-up.json +1 -1
  159. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/ground-kong.json +1 -1
  160. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/jumping-jack.json +1 -1
  161. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/kong-walk.json +1 -1
  162. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/lunge.json +1 -1
  163. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/overhead-squat.json +1 -1
  164. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/parkour-roll.json +1 -1
  165. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/parkour-squat.json +1 -1
  166. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/pistol-squat.json +1 -1
  167. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/plank.json +1 -1
  168. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/precision-burpee.json +1 -1
  169. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/precision-jump.json +1 -1
  170. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/quadrupedal-movement.json +1 -1
  171. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/russian-twist.json +1 -1
  172. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/sit-up.json +1 -1
  173. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/squat-clean.json +1 -1
  174. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/squat-hold.json +1 -1
  175. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/squat-snatch.json +1 -1
  176. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/tuck-jump.json +1 -1
  177. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/wall-ball.json +1 -1
  178. package/dist/web/playground/seed/core/markdown/efforts/bodyweight/wall-burpee.json +1 -1
  179. package/dist/web/playground/seed/core/markdown/efforts/cycling/assault-bike.json +1 -1
  180. package/dist/web/playground/seed/core/markdown/efforts/cycling/cycling-moderate.json +1 -1
  181. package/dist/web/playground/seed/core/markdown/efforts/cycling/cycling-vigorous.json +1 -1
  182. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/assisted-pull-up.json +1 -1
  183. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/burpee-pull-up.json +1 -1
  184. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/chest-to-bar-pull-up.json +1 -1
  185. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/dip.json +1 -1
  186. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/double-under.json +1 -1
  187. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/handstand-hold.json +1 -1
  188. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/handstand-push-up.json +1 -1
  189. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/handstand-walk.json +1 -1
  190. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/jump-rope.json +1 -1
  191. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/jumping-pull-up.json +1 -1
  192. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/jumping-push-up.json +1 -1
  193. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/l-sit-pull-up.json +1 -1
  194. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/muscle-up.json +1 -1
  195. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/pull-up.json +1 -1
  196. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/push-up.json +1 -1
  197. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/reverse-wall-dip.json +1 -1
  198. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/rope-climb.json +1 -1
  199. package/dist/web/playground/seed/core/markdown/efforts/gymnastics/toes-to-bar.json +1 -1
  200. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-arm-bar.json +1 -1
  201. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-around-the-world.json +1 -1
  202. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-bent-over-row.json +1 -1
  203. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-jerk.json +1 -1
  204. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-press.json +1 -1
  205. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-clean.json +1 -1
  206. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-deadlift.json +1 -1
  207. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-floor-press.json +1 -1
  208. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-front-squat.json +1 -1
  209. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-goblet-squat.json +1 -1
  210. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-gorilla-row.json +1 -1
  211. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-halo.json +1 -1
  212. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-jerk.json +1 -1
  213. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-overhead-squat.json +1 -1
  214. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-press.json +1 -1
  215. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-snatch.json +1 -1
  216. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-swing.json +1 -1
  217. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-windmill.json +1 -1
  218. package/dist/web/playground/seed/core/markdown/efforts/kettlebell/turkish-get-up.json +1 -1
  219. package/dist/web/playground/seed/core/markdown/efforts/recovery/rest.json +1 -1
  220. package/dist/web/playground/seed/core/markdown/efforts/recovery/stretching.json +1 -1
  221. package/dist/web/playground/seed/core/markdown/efforts/rowing/rowing-sprint.json +1 -1
  222. package/dist/web/playground/seed/core/markdown/efforts/rowing/rowing.json +1 -1
  223. package/dist/web/playground/seed/core/markdown/efforts/rowing/ski-erg.json +1 -1
  224. package/dist/web/playground/seed/core/markdown/efforts/running/backward-running.json +1 -1
  225. package/dist/web/playground/seed/core/markdown/efforts/running/running-6-mph.json +1 -1
  226. package/dist/web/playground/seed/core/markdown/efforts/running/running-8-mph.json +1 -1
  227. package/dist/web/playground/seed/core/markdown/efforts/running/running-sprint.json +1 -1
  228. package/dist/web/playground/seed/core/markdown/efforts/snatch.json +2 -2
  229. package/dist/web/playground/seed/core/markdown/efforts/strength/back-squat.json +1 -1
  230. package/dist/web/playground/seed/core/markdown/efforts/strength/bench-press.json +1 -1
  231. package/dist/web/playground/seed/core/markdown/efforts/strength/box-step-up.json +1 -1
  232. package/dist/web/playground/seed/core/markdown/efforts/strength/carioca.json +1 -1
  233. package/dist/web/playground/seed/core/markdown/efforts/strength/clean-and-jerk.json +1 -1
  234. package/dist/web/playground/seed/core/markdown/efforts/strength/cluster.json +1 -1
  235. package/dist/web/playground/seed/core/markdown/efforts/strength/dead-hang.json +1 -1
  236. package/dist/web/playground/seed/core/markdown/efforts/strength/deadlift.json +1 -1
  237. package/dist/web/playground/seed/core/markdown/efforts/strength/devils-press.json +1 -1
  238. package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-box-step-up.json +1 -1
  239. package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-clean.json +1 -1
  240. package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-fly.json +1 -1
  241. package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-row.json +1 -1
  242. package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-snatch.json +1 -1
  243. package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-thruster.json +1 -1
  244. package/dist/web/playground/seed/core/markdown/efforts/strength/elbows-to-knees.json +1 -1
  245. package/dist/web/playground/seed/core/markdown/efforts/strength/farmer-carry.json +1 -1
  246. package/dist/web/playground/seed/core/markdown/efforts/strength/frog-stand.json +1 -1
  247. package/dist/web/playground/seed/core/markdown/efforts/strength/front-squat.json +1 -1
  248. package/dist/web/playground/seed/core/markdown/efforts/strength/good-morning.json +1 -1
  249. package/dist/web/playground/seed/core/markdown/efforts/strength/hanging-leg-raise.json +1 -1
  250. package/dist/web/playground/seed/core/markdown/efforts/strength/hollow-rock.json +1 -1
  251. package/dist/web/playground/seed/core/markdown/efforts/strength/knees-to-elbows.json +1 -1
  252. package/dist/web/playground/seed/core/markdown/efforts/strength/l-sit.json +1 -1
  253. package/dist/web/playground/seed/core/markdown/efforts/strength/man-maker.json +1 -1
  254. package/dist/web/playground/seed/core/markdown/efforts/strength/medicine-ball-clean.json +1 -1
  255. package/dist/web/playground/seed/core/markdown/efforts/strength/overhead-press.json +1 -1
  256. package/dist/web/playground/seed/core/markdown/efforts/strength/parkour-vault.json +1 -1
  257. package/dist/web/playground/seed/core/markdown/efforts/strength/pig-flip.json +1 -1
  258. package/dist/web/playground/seed/core/markdown/efforts/strength/power-clean.json +1 -1
  259. package/dist/web/playground/seed/core/markdown/efforts/strength/power-snatch.json +1 -1
  260. package/dist/web/playground/seed/core/markdown/efforts/strength/push-jerk.json +1 -1
  261. package/dist/web/playground/seed/core/markdown/efforts/strength/push-press.json +1 -1
  262. package/dist/web/playground/seed/core/markdown/efforts/strength/romanian-deadlift.json +1 -1
  263. package/dist/web/playground/seed/core/markdown/efforts/strength/single-leg-deadlift.json +1 -1
  264. package/dist/web/playground/seed/core/markdown/efforts/strength/skull-crusher.json +1 -1
  265. package/dist/web/playground/seed/core/markdown/efforts/strength/slam-ball.json +1 -1
  266. package/dist/web/playground/seed/core/markdown/efforts/strength/sled-pull.json +1 -1
  267. package/dist/web/playground/seed/core/markdown/efforts/strength/sled-push.json +1 -1
  268. package/dist/web/playground/seed/core/markdown/efforts/strength/sumo-deadlift.json +1 -1
  269. package/dist/web/playground/seed/core/markdown/efforts/strength/thruster.json +1 -1
  270. package/dist/web/playground/seed/core/markdown/efforts/strength/triceps-extension.json +1 -1
  271. package/dist/web/playground/seed/core/markdown/efforts/strength/v-sit-hold.json +1 -1
  272. package/dist/web/playground/seed/core/markdown/efforts/strength/wall-walk.json +1 -1
  273. package/dist/web/playground/seed/core/markdown/efforts/strength/yoga-sun-salutation.json +1 -1
  274. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-assisted-sprint.json +1 -1
  275. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-backstroke.json +1 -1
  276. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-breaststroke-kick.json +1 -1
  277. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-breaststroke.json +1 -1
  278. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-butterfly.json +1 -1
  279. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-catch-up-drill.json +1 -1
  280. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-choice-stroke.json +1 -1
  281. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-dive-start.json +1 -1
  282. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-dolphin-kick.json +1 -1
  283. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-drafting.json +1 -1
  284. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-fingertip-drag.json +1 -1
  285. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-freestyle.json +1 -1
  286. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-individual-medley.json +1 -1
  287. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-kick.json +1 -1
  288. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-pull.json +1 -1
  289. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-resisted-sprint.json +1 -1
  290. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-rotation-drill.json +1 -1
  291. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-sighting.json +1 -1
  292. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-single-arm-drill.json +1 -1
  293. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-stroke-transition.json +1 -1
  294. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-two-kick-one-pull.json +1 -1
  295. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-vigorous.json +1 -1
  296. package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming.json +1 -1
  297. package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-arm-cast.json +1 -1
  298. package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-circles.json +1 -1
  299. package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-mill.json +1 -1
  300. package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-reverse-mill.json +1 -1
  301. package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-shield-cast.json +1 -1
  302. package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-10-to-2-swing.json +1 -1
  303. package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-360-swing.json +1 -1
  304. package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-barbarian-squat.json +1 -1
  305. package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-flow.json +1 -1
  306. package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-gravedigger.json +1 -1
  307. package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-touchdown.json +1 -1
  308. package/dist/web/playground/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-carry.json +1 -1
  309. package/dist/web/playground/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-extension.json +1 -1
  310. package/dist/web/playground/seed/core/markdown/efforts/unconventional/sandbag-over-shoulder.json +1 -1
  311. package/dist/web/playground/seed/core/markdown/efforts/walking/walking-3-mph.json +1 -1
  312. package/dist/web/playground/seed/core/markdown/equipment/air-bike.json +1 -1
  313. package/dist/web/playground/seed/core/markdown/equipment/barbell.json +1 -1
  314. package/dist/web/playground/seed/core/markdown/equipment/bench.json +1 -1
  315. package/dist/web/playground/seed/core/markdown/equipment/bike-erg.json +1 -1
  316. package/dist/web/playground/seed/core/markdown/equipment/climbing-rope.json +1 -1
  317. package/dist/web/playground/seed/core/markdown/equipment/clubs.json +1 -1
  318. package/dist/web/playground/seed/core/markdown/equipment/dumbbell.json +1 -1
  319. package/dist/web/playground/seed/core/markdown/equipment/ghd.json +1 -1
  320. package/dist/web/playground/seed/core/markdown/equipment/gymnastic-rings.json +1 -1
  321. package/dist/web/playground/seed/core/markdown/equipment/jump-rope.json +1 -1
  322. package/dist/web/playground/seed/core/markdown/equipment/kettlebell.json +1 -1
  323. package/dist/web/playground/seed/core/markdown/equipment/macebell.json +1 -1
  324. package/dist/web/playground/seed/core/markdown/equipment/medicine-ball.json +1 -1
  325. package/dist/web/playground/seed/core/markdown/equipment/parallettes.json +1 -1
  326. package/dist/web/playground/seed/core/markdown/equipment/plyo-box.json +1 -1
  327. package/dist/web/playground/seed/core/markdown/equipment/pull-up-bar.json +1 -1
  328. package/dist/web/playground/seed/core/markdown/equipment/rower.json +1 -1
  329. package/dist/web/playground/seed/core/markdown/equipment/sandbag.json +1 -1
  330. package/dist/web/playground/seed/core/markdown/equipment/ski-erg.json +1 -1
  331. package/dist/web/playground/seed/core/markdown/equipment/slam-ball.json +1 -1
  332. package/dist/web/playground/seed/core/markdown/equipment/sled.json +1 -1
  333. package/dist/web/playground/seed/core/markdown/equipment/sledgehammer.json +1 -1
  334. package/dist/web/playground/seed/core/markdown/equipment/weight-vest.json +1 -1
  335. package/dist/web/playground/seed/core/report.html +13 -13
  336. package/dist/web/server/ai-skills/agent-parity.md +41 -0
  337. package/dist/web/server/ai-skills/cli.md +127 -0
  338. package/dist/web/server/ai-skills/wql.md +63 -0
  339. package/dist/web/{playground/assets/feedSync.worker-O4TGLEj3.js → server/assets/feedSync.worker-CJyLPLAX.js} +2 -2
  340. package/dist/web/server/assets/main-DJQ7VwVX.js +1160 -0
  341. package/dist/web/server/assets/main-DedlsEjf.css +2 -0
  342. package/dist/web/server/assets/{statementBuilderFlow-C7x-7JGx.js → statementBuilderFlow-4p9d-7VX.js} +2 -2
  343. package/dist/web/server/assets/vendor-BUlwHBNF.js +255 -0
  344. package/dist/web/{playground/assets/vendor-codemirror-B4BeZarI.js → server/assets/vendor-codemirror-Bh6hyz5v.js} +11 -11
  345. package/dist/web/server/index.html +4 -4
  346. package/dist/web/server/llms-full.txt +1444 -0
  347. package/dist/web/server/llms.txt +67 -0
  348. package/dist/web/{playground/seed/core/chunks/canvas.deac64e3.json → server/seed/core/chunks/canvas.6cf875a1.json} +1 -1
  349. package/dist/web/server/seed/core/chunks/{dashboards.08301ab4.json → dashboards.277192c5.json} +1 -1
  350. package/dist/web/server/seed/core/chunks/{efforts.47f650fe.json → efforts.b943edc6.json} +1 -1
  351. package/dist/web/server/seed/core/chunks/{equipment.79146d31.json → equipment.3cc3e02c.json} +1 -1
  352. package/dist/web/server/seed/core/indexes/notebooks/canvas.json +180 -180
  353. package/dist/web/server/seed/core/indexes/notebooks/dashboards.json +16 -16
  354. package/dist/web/server/seed/core/indexes/notebooks/efforts.json +326 -326
  355. package/dist/web/server/seed/core/indexes/notebooks/equipment.json +50 -50
  356. package/dist/web/server/seed/core/manifest.json +27 -27
  357. package/dist/web/server/seed/core/markdown/canvas/ai-first/README.json +1 -1
  358. package/dist/web/server/seed/core/markdown/canvas/guide/README.json +4 -4
  359. package/dist/web/server/seed/core/markdown/canvas/guide/clock.json +1 -1
  360. package/dist/web/server/seed/core/markdown/canvas/guide/dashboards.json +1 -1
  361. package/dist/web/server/seed/core/markdown/canvas/guide/metrics-summaries.json +2 -2
  362. package/dist/web/server/seed/core/markdown/canvas/guide/metrics.json +12 -12
  363. package/dist/web/server/seed/core/markdown/canvas/guide/protocols.json +20 -20
  364. package/dist/web/server/seed/core/markdown/canvas/guide/sessions.json +33 -33
  365. package/dist/web/server/seed/core/markdown/canvas/guide/start.json +11 -11
  366. package/dist/web/server/seed/core/markdown/canvas/guide/structure.json +25 -25
  367. package/dist/web/server/seed/core/markdown/canvas/guide/wql.json +5 -5
  368. package/dist/web/server/seed/core/markdown/canvas/home/sample-script.json +4 -4
  369. package/dist/web/server/seed/core/markdown/canvas/home/welcome-1.json +2 -2
  370. package/dist/web/server/seed/core/markdown/canvas/syntax/actions-comments.json +4 -4
  371. package/dist/web/server/seed/core/markdown/canvas/syntax/alternating-emom.json +5 -5
  372. package/dist/web/server/seed/core/markdown/canvas/syntax/basic-emom.json +4 -4
  373. package/dist/web/server/seed/core/markdown/canvas/syntax/calculated-metrics.json +4 -4
  374. package/dist/web/server/seed/core/markdown/canvas/syntax/classic-amrap.json +6 -6
  375. package/dist/web/server/seed/core/markdown/canvas/syntax/complex-barbell-cycling.json +4 -4
  376. package/dist/web/server/seed/core/markdown/canvas/syntax/complex-full-session.json +10 -10
  377. package/dist/web/server/seed/core/markdown/canvas/syntax/complex-nested-protocols.json +7 -7
  378. package/dist/web/server/seed/core/markdown/canvas/syntax/complex-partner-workout.json +7 -7
  379. package/dist/web/server/seed/core/markdown/canvas/syntax/complex-swimming.json +5 -5
  380. package/dist/web/server/seed/core/markdown/canvas/syntax/core-rules.json +4 -4
  381. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-and-calculated-metrics.json +4 -4
  382. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-intervals.json +4 -4
  383. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-1.json +4 -4
  384. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-2.json +5 -5
  385. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-3.json +3 -3
  386. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-4.json +4 -4
  387. package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-5.json +4 -4
  388. package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-climb-bouldering.json +2 -2
  389. package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-climb-hangboard.json +2 -2
  390. package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-climb-sport.json +2 -2
  391. package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-log.json +4 -4
  392. package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-plan.json +8 -8
  393. package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-wod.json +5 -5
  394. package/dist/web/server/seed/core/markdown/canvas/syntax/distance-intervals.json +3 -3
  395. package/dist/web/server/seed/core/markdown/canvas/syntax/document-1.json +4 -4
  396. package/dist/web/server/seed/core/markdown/canvas/syntax/document-2.json +5 -5
  397. package/dist/web/server/seed/core/markdown/canvas/syntax/document-3.json +10 -10
  398. package/dist/web/server/seed/core/markdown/canvas/syntax/document-4.json +5 -5
  399. package/dist/web/server/seed/core/markdown/canvas/syntax/effort-notes.json +5 -5
  400. package/dist/web/server/seed/core/markdown/canvas/syntax/frontmatter-summaries.json +4 -4
  401. package/dist/web/server/seed/core/markdown/canvas/syntax/groups-1.json +5 -5
  402. package/dist/web/server/seed/core/markdown/canvas/syntax/groups-2.json +6 -6
  403. package/dist/web/server/seed/core/markdown/canvas/syntax/groups-3.json +3 -3
  404. package/dist/web/server/seed/core/markdown/canvas/syntax/groups-4.json +3 -3
  405. package/dist/web/server/seed/core/markdown/canvas/syntax/longer-duration.json +4 -4
  406. package/dist/web/server/seed/core/markdown/canvas/syntax/longer-intervals.json +4 -4
  407. package/dist/web/server/seed/core/markdown/canvas/syntax/measurements.json +7 -7
  408. package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-1.json +5 -5
  409. package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-2.json +7 -7
  410. package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-3.json +8 -8
  411. package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-4.json +6 -6
  412. package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-5.json +5 -5
  413. package/dist/web/server/seed/core/markdown/canvas/syntax/mixed-sections.json +10 -10
  414. package/dist/web/server/seed/core/markdown/canvas/syntax/mixed-timers.json +5 -5
  415. package/dist/web/server/seed/core/markdown/canvas/syntax/multiple-amrap-windows.json +7 -7
  416. package/dist/web/server/seed/core/markdown/canvas/syntax/multiple-sets.json +4 -4
  417. package/dist/web/server/seed/core/markdown/canvas/syntax/named-groups.json +6 -6
  418. package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-1.json +6 -6
  419. package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-2.json +4 -4
  420. package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-3.json +6 -6
  421. package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-4.json +3 -3
  422. package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-5.json +4 -4
  423. package/dist/web/server/seed/core/markdown/canvas/syntax/single-movement.json +3 -3
  424. package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-1.json +4 -4
  425. package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-2.json +5 -5
  426. package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-3.json +4 -4
  427. package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-4.json +4 -4
  428. package/dist/web/server/seed/core/markdown/canvas/syntax/time-cap.json +6 -6
  429. package/dist/web/server/seed/core/markdown/canvas/syntax/timer-modifiers.json +6 -6
  430. package/dist/web/server/seed/core/markdown/canvas/syntax/timers-1.json +6 -6
  431. package/dist/web/server/seed/core/markdown/canvas/syntax/timers-2.json +4 -4
  432. package/dist/web/server/seed/core/markdown/canvas/syntax/timers-3.json +4 -4
  433. package/dist/web/server/seed/core/markdown/canvas/syntax/timers-4.json +4 -4
  434. package/dist/web/server/seed/core/markdown/canvas/syntax/timers-5.json +5 -5
  435. package/dist/web/server/seed/core/markdown/canvas/syntax/timers-rest.json +4 -4
  436. package/dist/web/server/seed/core/markdown/canvas/wql-presets/aggregate-by-effort.json +2 -2
  437. package/dist/web/server/seed/core/markdown/canvas/wql-presets/aggregate-by-week.json +2 -2
  438. package/dist/web/server/seed/core/markdown/canvas/wql-presets/content-fran.json +2 -2
  439. package/dist/web/server/seed/core/markdown/canvas/wql-presets/filter-combos.json +2 -2
  440. package/dist/web/server/seed/core/markdown/canvas/wql-presets/pipes-limit.json +2 -2
  441. package/dist/web/server/seed/core/markdown/canvas/wql-presets/session-rpe.json +2 -2
  442. package/dist/web/server/seed/core/markdown/canvas/wql-presets/source-journal.json +2 -2
  443. package/dist/web/server/seed/core/markdown/canvas/wql-presets/tis-trend.json +2 -2
  444. package/dist/web/server/seed/core/markdown/canvas/wql-presets/where-join.json +2 -2
  445. package/dist/web/server/seed/core/markdown/dashboards/benchmark-pr-board.json +6 -6
  446. package/dist/web/server/seed/core/markdown/dashboards/finger-strength-v8.json +5 -5
  447. package/dist/web/server/seed/core/markdown/dashboards/polarized-base-marathon.json +9 -9
  448. package/dist/web/server/seed/core/markdown/dashboards/recovery-readiness.json +7 -7
  449. package/dist/web/server/seed/core/markdown/dashboards/road-to-560-total.json +9 -9
  450. package/dist/web/server/seed/core/markdown/dashboards/training-block-review.json +11 -11
  451. package/dist/web/server/seed/core/markdown/efforts/bodyweight/air-squat.json +1 -1
  452. package/dist/web/server/seed/core/markdown/efforts/bodyweight/box-jump.json +1 -1
  453. package/dist/web/server/seed/core/markdown/efforts/bodyweight/broad-jump.json +1 -1
  454. package/dist/web/server/seed/core/markdown/efforts/bodyweight/burpee-box-jump-over.json +1 -1
  455. package/dist/web/server/seed/core/markdown/efforts/bodyweight/burpee-over-dumbbell.json +1 -1
  456. package/dist/web/server/seed/core/markdown/efforts/bodyweight/burpee.json +1 -1
  457. package/dist/web/server/seed/core/markdown/efforts/bodyweight/dumbbell-squat-clean.json +1 -1
  458. package/dist/web/server/seed/core/markdown/efforts/bodyweight/ghd-sit-up.json +1 -1
  459. package/dist/web/server/seed/core/markdown/efforts/bodyweight/ground-kong.json +1 -1
  460. package/dist/web/server/seed/core/markdown/efforts/bodyweight/jumping-jack.json +1 -1
  461. package/dist/web/server/seed/core/markdown/efforts/bodyweight/kong-walk.json +1 -1
  462. package/dist/web/server/seed/core/markdown/efforts/bodyweight/lunge.json +1 -1
  463. package/dist/web/server/seed/core/markdown/efforts/bodyweight/overhead-squat.json +1 -1
  464. package/dist/web/server/seed/core/markdown/efforts/bodyweight/parkour-roll.json +1 -1
  465. package/dist/web/server/seed/core/markdown/efforts/bodyweight/parkour-squat.json +1 -1
  466. package/dist/web/server/seed/core/markdown/efforts/bodyweight/pistol-squat.json +1 -1
  467. package/dist/web/server/seed/core/markdown/efforts/bodyweight/plank.json +1 -1
  468. package/dist/web/server/seed/core/markdown/efforts/bodyweight/precision-burpee.json +1 -1
  469. package/dist/web/server/seed/core/markdown/efforts/bodyweight/precision-jump.json +1 -1
  470. package/dist/web/server/seed/core/markdown/efforts/bodyweight/quadrupedal-movement.json +1 -1
  471. package/dist/web/server/seed/core/markdown/efforts/bodyweight/russian-twist.json +1 -1
  472. package/dist/web/server/seed/core/markdown/efforts/bodyweight/sit-up.json +1 -1
  473. package/dist/web/server/seed/core/markdown/efforts/bodyweight/squat-clean.json +1 -1
  474. package/dist/web/server/seed/core/markdown/efforts/bodyweight/squat-hold.json +1 -1
  475. package/dist/web/server/seed/core/markdown/efforts/bodyweight/squat-snatch.json +1 -1
  476. package/dist/web/server/seed/core/markdown/efforts/bodyweight/tuck-jump.json +1 -1
  477. package/dist/web/server/seed/core/markdown/efforts/bodyweight/wall-ball.json +1 -1
  478. package/dist/web/server/seed/core/markdown/efforts/bodyweight/wall-burpee.json +1 -1
  479. package/dist/web/server/seed/core/markdown/efforts/cycling/assault-bike.json +1 -1
  480. package/dist/web/server/seed/core/markdown/efforts/cycling/cycling-moderate.json +1 -1
  481. package/dist/web/server/seed/core/markdown/efforts/cycling/cycling-vigorous.json +1 -1
  482. package/dist/web/server/seed/core/markdown/efforts/gymnastics/assisted-pull-up.json +1 -1
  483. package/dist/web/server/seed/core/markdown/efforts/gymnastics/burpee-pull-up.json +1 -1
  484. package/dist/web/server/seed/core/markdown/efforts/gymnastics/chest-to-bar-pull-up.json +1 -1
  485. package/dist/web/server/seed/core/markdown/efforts/gymnastics/dip.json +1 -1
  486. package/dist/web/server/seed/core/markdown/efforts/gymnastics/double-under.json +1 -1
  487. package/dist/web/server/seed/core/markdown/efforts/gymnastics/handstand-hold.json +1 -1
  488. package/dist/web/server/seed/core/markdown/efforts/gymnastics/handstand-push-up.json +1 -1
  489. package/dist/web/server/seed/core/markdown/efforts/gymnastics/handstand-walk.json +1 -1
  490. package/dist/web/server/seed/core/markdown/efforts/gymnastics/jump-rope.json +1 -1
  491. package/dist/web/server/seed/core/markdown/efforts/gymnastics/jumping-pull-up.json +1 -1
  492. package/dist/web/server/seed/core/markdown/efforts/gymnastics/jumping-push-up.json +1 -1
  493. package/dist/web/server/seed/core/markdown/efforts/gymnastics/l-sit-pull-up.json +1 -1
  494. package/dist/web/server/seed/core/markdown/efforts/gymnastics/muscle-up.json +1 -1
  495. package/dist/web/server/seed/core/markdown/efforts/gymnastics/pull-up.json +1 -1
  496. package/dist/web/server/seed/core/markdown/efforts/gymnastics/push-up.json +1 -1
  497. package/dist/web/server/seed/core/markdown/efforts/gymnastics/reverse-wall-dip.json +1 -1
  498. package/dist/web/server/seed/core/markdown/efforts/gymnastics/rope-climb.json +1 -1
  499. package/dist/web/server/seed/core/markdown/efforts/gymnastics/toes-to-bar.json +1 -1
  500. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-arm-bar.json +1 -1
  501. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-around-the-world.json +1 -1
  502. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-bent-over-row.json +1 -1
  503. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-jerk.json +1 -1
  504. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-press.json +1 -1
  505. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-clean.json +1 -1
  506. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-deadlift.json +1 -1
  507. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-floor-press.json +1 -1
  508. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-front-squat.json +1 -1
  509. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-goblet-squat.json +1 -1
  510. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-gorilla-row.json +1 -1
  511. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-halo.json +1 -1
  512. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-jerk.json +1 -1
  513. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-overhead-squat.json +1 -1
  514. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-press.json +1 -1
  515. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-snatch.json +1 -1
  516. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-swing.json +1 -1
  517. package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-windmill.json +1 -1
  518. package/dist/web/server/seed/core/markdown/efforts/kettlebell/turkish-get-up.json +1 -1
  519. package/dist/web/server/seed/core/markdown/efforts/recovery/rest.json +1 -1
  520. package/dist/web/server/seed/core/markdown/efforts/recovery/stretching.json +1 -1
  521. package/dist/web/server/seed/core/markdown/efforts/rowing/rowing-sprint.json +1 -1
  522. package/dist/web/server/seed/core/markdown/efforts/rowing/rowing.json +1 -1
  523. package/dist/web/server/seed/core/markdown/efforts/rowing/ski-erg.json +1 -1
  524. package/dist/web/server/seed/core/markdown/efforts/running/backward-running.json +1 -1
  525. package/dist/web/server/seed/core/markdown/efforts/running/running-6-mph.json +1 -1
  526. package/dist/web/server/seed/core/markdown/efforts/running/running-8-mph.json +1 -1
  527. package/dist/web/server/seed/core/markdown/efforts/running/running-sprint.json +1 -1
  528. package/dist/web/server/seed/core/markdown/efforts/snatch.json +2 -2
  529. package/dist/web/server/seed/core/markdown/efforts/strength/back-squat.json +1 -1
  530. package/dist/web/server/seed/core/markdown/efforts/strength/bench-press.json +1 -1
  531. package/dist/web/server/seed/core/markdown/efforts/strength/box-step-up.json +1 -1
  532. package/dist/web/server/seed/core/markdown/efforts/strength/carioca.json +1 -1
  533. package/dist/web/server/seed/core/markdown/efforts/strength/clean-and-jerk.json +1 -1
  534. package/dist/web/server/seed/core/markdown/efforts/strength/cluster.json +1 -1
  535. package/dist/web/server/seed/core/markdown/efforts/strength/dead-hang.json +1 -1
  536. package/dist/web/server/seed/core/markdown/efforts/strength/deadlift.json +1 -1
  537. package/dist/web/server/seed/core/markdown/efforts/strength/devils-press.json +1 -1
  538. package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-box-step-up.json +1 -1
  539. package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-clean.json +1 -1
  540. package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-fly.json +1 -1
  541. package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-row.json +1 -1
  542. package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-snatch.json +1 -1
  543. package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-thruster.json +1 -1
  544. package/dist/web/server/seed/core/markdown/efforts/strength/elbows-to-knees.json +1 -1
  545. package/dist/web/server/seed/core/markdown/efforts/strength/farmer-carry.json +1 -1
  546. package/dist/web/server/seed/core/markdown/efforts/strength/frog-stand.json +1 -1
  547. package/dist/web/server/seed/core/markdown/efforts/strength/front-squat.json +1 -1
  548. package/dist/web/server/seed/core/markdown/efforts/strength/good-morning.json +1 -1
  549. package/dist/web/server/seed/core/markdown/efforts/strength/hanging-leg-raise.json +1 -1
  550. package/dist/web/server/seed/core/markdown/efforts/strength/hollow-rock.json +1 -1
  551. package/dist/web/server/seed/core/markdown/efforts/strength/knees-to-elbows.json +1 -1
  552. package/dist/web/server/seed/core/markdown/efforts/strength/l-sit.json +1 -1
  553. package/dist/web/server/seed/core/markdown/efforts/strength/man-maker.json +1 -1
  554. package/dist/web/server/seed/core/markdown/efforts/strength/medicine-ball-clean.json +1 -1
  555. package/dist/web/server/seed/core/markdown/efforts/strength/overhead-press.json +1 -1
  556. package/dist/web/server/seed/core/markdown/efforts/strength/parkour-vault.json +1 -1
  557. package/dist/web/server/seed/core/markdown/efforts/strength/pig-flip.json +1 -1
  558. package/dist/web/server/seed/core/markdown/efforts/strength/power-clean.json +1 -1
  559. package/dist/web/server/seed/core/markdown/efforts/strength/power-snatch.json +1 -1
  560. package/dist/web/server/seed/core/markdown/efforts/strength/push-jerk.json +1 -1
  561. package/dist/web/server/seed/core/markdown/efforts/strength/push-press.json +1 -1
  562. package/dist/web/server/seed/core/markdown/efforts/strength/romanian-deadlift.json +1 -1
  563. package/dist/web/server/seed/core/markdown/efforts/strength/single-leg-deadlift.json +1 -1
  564. package/dist/web/server/seed/core/markdown/efforts/strength/skull-crusher.json +1 -1
  565. package/dist/web/server/seed/core/markdown/efforts/strength/slam-ball.json +1 -1
  566. package/dist/web/server/seed/core/markdown/efforts/strength/sled-pull.json +1 -1
  567. package/dist/web/server/seed/core/markdown/efforts/strength/sled-push.json +1 -1
  568. package/dist/web/server/seed/core/markdown/efforts/strength/sumo-deadlift.json +1 -1
  569. package/dist/web/server/seed/core/markdown/efforts/strength/thruster.json +1 -1
  570. package/dist/web/server/seed/core/markdown/efforts/strength/triceps-extension.json +1 -1
  571. package/dist/web/server/seed/core/markdown/efforts/strength/v-sit-hold.json +1 -1
  572. package/dist/web/server/seed/core/markdown/efforts/strength/wall-walk.json +1 -1
  573. package/dist/web/server/seed/core/markdown/efforts/strength/yoga-sun-salutation.json +1 -1
  574. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-assisted-sprint.json +1 -1
  575. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-backstroke.json +1 -1
  576. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-breaststroke-kick.json +1 -1
  577. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-breaststroke.json +1 -1
  578. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-butterfly.json +1 -1
  579. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-catch-up-drill.json +1 -1
  580. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-choice-stroke.json +1 -1
  581. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-dive-start.json +1 -1
  582. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-dolphin-kick.json +1 -1
  583. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-drafting.json +1 -1
  584. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-fingertip-drag.json +1 -1
  585. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-freestyle.json +1 -1
  586. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-individual-medley.json +1 -1
  587. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-kick.json +1 -1
  588. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-pull.json +1 -1
  589. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-resisted-sprint.json +1 -1
  590. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-rotation-drill.json +1 -1
  591. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-sighting.json +1 -1
  592. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-single-arm-drill.json +1 -1
  593. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-stroke-transition.json +1 -1
  594. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-two-kick-one-pull.json +1 -1
  595. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-vigorous.json +1 -1
  596. package/dist/web/server/seed/core/markdown/efforts/swimming/swimming.json +1 -1
  597. package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-arm-cast.json +1 -1
  598. package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-circles.json +1 -1
  599. package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-mill.json +1 -1
  600. package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-reverse-mill.json +1 -1
  601. package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-shield-cast.json +1 -1
  602. package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-10-to-2-swing.json +1 -1
  603. package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-360-swing.json +1 -1
  604. package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-barbarian-squat.json +1 -1
  605. package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-flow.json +1 -1
  606. package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-gravedigger.json +1 -1
  607. package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-touchdown.json +1 -1
  608. package/dist/web/server/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-carry.json +1 -1
  609. package/dist/web/server/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-extension.json +1 -1
  610. package/dist/web/server/seed/core/markdown/efforts/unconventional/sandbag-over-shoulder.json +1 -1
  611. package/dist/web/server/seed/core/markdown/efforts/walking/walking-3-mph.json +1 -1
  612. package/dist/web/server/seed/core/markdown/equipment/air-bike.json +1 -1
  613. package/dist/web/server/seed/core/markdown/equipment/barbell.json +1 -1
  614. package/dist/web/server/seed/core/markdown/equipment/bench.json +1 -1
  615. package/dist/web/server/seed/core/markdown/equipment/bike-erg.json +1 -1
  616. package/dist/web/server/seed/core/markdown/equipment/climbing-rope.json +1 -1
  617. package/dist/web/server/seed/core/markdown/equipment/clubs.json +1 -1
  618. package/dist/web/server/seed/core/markdown/equipment/dumbbell.json +1 -1
  619. package/dist/web/server/seed/core/markdown/equipment/ghd.json +1 -1
  620. package/dist/web/server/seed/core/markdown/equipment/gymnastic-rings.json +1 -1
  621. package/dist/web/server/seed/core/markdown/equipment/jump-rope.json +1 -1
  622. package/dist/web/server/seed/core/markdown/equipment/kettlebell.json +1 -1
  623. package/dist/web/server/seed/core/markdown/equipment/macebell.json +1 -1
  624. package/dist/web/server/seed/core/markdown/equipment/medicine-ball.json +1 -1
  625. package/dist/web/server/seed/core/markdown/equipment/parallettes.json +1 -1
  626. package/dist/web/server/seed/core/markdown/equipment/plyo-box.json +1 -1
  627. package/dist/web/server/seed/core/markdown/equipment/pull-up-bar.json +1 -1
  628. package/dist/web/server/seed/core/markdown/equipment/rower.json +1 -1
  629. package/dist/web/server/seed/core/markdown/equipment/sandbag.json +1 -1
  630. package/dist/web/server/seed/core/markdown/equipment/ski-erg.json +1 -1
  631. package/dist/web/server/seed/core/markdown/equipment/slam-ball.json +1 -1
  632. package/dist/web/server/seed/core/markdown/equipment/sled.json +1 -1
  633. package/dist/web/server/seed/core/markdown/equipment/sledgehammer.json +1 -1
  634. package/dist/web/server/seed/core/markdown/equipment/weight-vest.json +1 -1
  635. package/dist/web/server/seed/core/report.html +13 -13
  636. package/package.json +10 -8
  637. package/dist/chunk-2EWCEE6N.mjs.map +0 -1
  638. package/dist/chunk-5NNSHRMZ.mjs.map +0 -1
  639. package/dist/chunk-LNBKPHEP.mjs.map +0 -1
  640. package/dist/chunk-SLCRIGUR.mjs.map +0 -1
  641. package/dist/server-SHNWCIIM.mjs +0 -11
  642. package/dist/web/playground/assets/main-DGz9PHS_.css +0 -2
  643. package/dist/web/playground/assets/main-DfHqNhwO.js +0 -1149
  644. package/dist/web/playground/assets/vendor-Dz-Azkoq.js +0 -198
  645. package/dist/web/server/assets/main-DGz9PHS_.css +0 -2
  646. package/dist/web/server/assets/main-VXFEU44Q.js +0 -1149
  647. package/dist/web/server/assets/vendor-Dz-Azkoq.js +0 -198
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/errors.ts","../../src/cli/db.ts","../../src/cli/nodeFeedTree.ts","../../src/server/app.ts"],"names":["normalizeFeedTreePath","FeedTreeError","sha256HexAsync","Readable","createReadStream","storeDefinition","keyFromValue","realpath","join","sep","stat","resolve","getRow","listRows","countRows","refreshDomain","SqlStorage","checkUnpublishedFeedChanges","publishFeedFromStorage","wipeRows","wipeDomain","MAX_BODY","handleDomainQuery","realpathSync","MemoryFeedTree","StorageError"],"mappings":"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","file":"app.cjs","sourcesContent":["/**\n * errors.ts — the single HTTP error type every layer throws; app.ts maps it\n * to the wire's { error, code? } JSON with the matching status.\n */\nexport class HttpError extends Error {\n constructor(readonly status: number, message: string, readonly code?: string) {\n super(message);\n this.name = 'HttpError';\n }\n}\n","/**\n * Local SQLite seam for the `wod` CLI.\n *\n * Opens a libsql `file:` database, initializes the shared storage schema\n * (KV store tables + domain projections), and adapts the rows into the WQL\n * store interfaces — the same shape the playground builds over IndexedDB.\n *\n * Everything heavy is loaded lazily (`@libsql/client`,\n * `@bitcobblers/wod-wiki-storage/sql`, node `fs`/`crypto`) so browser\n * bundles that import the engine index never pull native drivers; the\n * dynamic specifiers stay external in the CLI bundle.\n */\n\nimport type { EventRecord } from '@bitcobblers/wod-wiki-core';\nimport type { IStorage, KeyDTO, Note, Session } from '@bitcobblers/wod-wiki-storage';\nimport type { RangeDTO, StoreDef } from '@bitcobblers/wod-wiki-storage';\nimport type {\n Database,\n LibsqlClient,\n SqlConnection,\n} from '@bitcobblers/wod-wiki-storage/sql';\nimport type { CliDatabaseConfig } from './config';\nimport type {\n BlockQueryStore,\n EventStore,\n EffortQueryStore,\n NoteQueryStore,\n WqlDomainReadResult,\n} from '@bitcobblers/wod-wiki-wql';\nimport { bundledEfforts } from '@bitcobblers/wod-wiki-lang';\n\n/** Structural CJS require — avoids the deprecated NodeJS namespace type. */\ntype CjsRequire = (id: string) => unknown;\n\n/** Minimal node builtin surfaces the CLI uses (kept out of browser bundles). */\nexport interface PathShim { resolve(...parts: string[]): string; join(...parts: string[]): string; dirname(p: string): string; basename(p: string): string }\nexport interface FsShim {\n mkdirSync(p: string, opts: { recursive: boolean }): void;\n existsSync(p: string): boolean;\n unlinkSync(p: string): void;\n readFileSync(p: string, encoding: string): string;\n writeFileSync(p: string, data: string, encoding: string): void;\n}\nexport interface HashShim { update(data: string): HashShim; digest(): Uint8Array }\nexport interface CryptoShim {\n createHash(algorithm: string): HashShim;\n randomUUID(): string;\n}\nexport const nodePath = (): PathShim => nodeRequire()('node:path') as PathShim;\nexport const nodeFs = (): FsShim => nodeRequire()('node:fs') as FsShim;\nexport const nodeCrypto = (): CryptoShim => nodeRequire()('node:crypto') as CryptoShim;\n\n/** Lazy CJS require — keeps node builtins out of browser bundles. */\nfunction nodeRequire(): CjsRequire {\n const g = globalThis as { process?: { versions?: Record<string, string> }; Bun?: unknown; require?: CjsRequire };\n if (typeof g.process?.versions?.node === 'undefined' && typeof g.Bun === 'undefined') {\n throw new Error('SQLite operations are only supported in Node / Bun environments');\n }\n const req = g.require ?? (typeof require === 'function' ? require : undefined);\n if (!req) throw new Error('SQLite operations require a CJS require shim (missing tsup banner?)');\n return req;\n}\n\n/** The storage/sql surface the CLI uses — structural mirror so the lazy import types check. */\nexport interface SqlApi {\n libsqlDatabase(client: LibsqlClient): Database;\n SqlStorage: new (db: Database) => IStorage;\n initializeStore(db: Database): Promise<void>;\n initializeDomain(db: Database): Promise<void>;\n verifyReadiness(db: Database): Promise<void>;\n storeDefinition(name: string): StoreDef;\n listRows(conn: SqlConnection, def: StoreDef, range?: RangeDTO, count?: number, indexName?: string): Promise<unknown[]>;\n getRow(conn: SqlConnection, def: StoreDef, key: KeyDTO): Promise<unknown | undefined>;\n getRows(conn: SqlConnection, def: StoreDef, keys: KeyDTO[]): Promise<(unknown | undefined)[]>;\n putRow(conn: SqlConnection, def: StoreDef, value: unknown): Promise<unknown>;\n deleteRows(conn: SqlConnection, def: StoreDef, keyOrRange: unknown): Promise<void>;\n refreshDomain(conn: SqlConnection, ops: unknown[]): Promise<unknown>;\n handleDomainQuery(db: Database, body: unknown): Promise<unknown>;\n}\n\nlet sqlModulePromise: Promise<SqlApi> | undefined;\n\n/** Lazily import the storage SQL subpath (kept external in the CLI bundle). */\nexport function loadSql(): Promise<SqlApi> {\n sqlModulePromise ??= import(/* @vite-ignore */ '@bitcobblers/wod-wiki-storage/sql') as Promise<SqlApi>;\n return sqlModulePromise;\n}\n\nexport interface CliDb {\n db: Database;\n storage: IStorage;\n /** Absolute path of the underlying .sqlite file — or the sanitized display\n * label (URL without credentials) for remote backends. */\n path: string;\n close(): Promise<void>;\n}\n\n/**\n * Resolve the effective database path: explicit flag wins, then\n * WOD_WIKI_DB, then ./wodwiki.db in the current working directory.\n */\nexport function resolveDbPath(dbPath?: string): string {\n const chosen = dbPath ?? process.env.WOD_WIKI_DB ?? './wodwiki.db';\n return nodePath().resolve(process.cwd(), chosen);\n}\n\n/**\n * Open the CLI database: a legacy local sqlite path (internal callers,\n * created/initialized as before) or a resolved backend config from ./config.\n *\n * opts.initialize (default true): run the schema + projection\n * initialization. false → verify the schema/projection guards only: a\n * missing local sqlite file is NOT created and yields an actionable\n * `wod init` error; remote targets are only probed, never created.\n *\n * opts.create (explicit init requests only, postgres): when the configured\n * PostgreSQL database is missing, openDatabase creates it through the admin\n * \"postgres\" database before initializing. Turso has no management API —\n * its hosted target must already exist.\n */\nexport async function openCliDb(\n target?: string | CliDatabaseConfig,\n opts?: { initialize?: boolean; create?: boolean },\n): Promise<CliDb> {\n if (target === undefined || typeof target === 'string') {\n return openSqliteDb(resolveDbPath(target), opts);\n }\n switch (target.kind) {\n case 'sqlite':\n return openSqliteDb(target.path, opts);\n case 'turso':\n return openRemoteDb(\n { DB_DRIVER: 'turso', DATABASE_URL: target.url, LIBSQL_AUTH_TOKEN: target.authToken },\n target.label,\n opts,\n );\n case 'postgres':\n return openRemoteDb({ DB_DRIVER: 'postgres', DATABASE_URL: target.url }, target.label, opts);\n }\n}\n\nasync function openSqliteDb(resolved: string, opts?: { initialize?: boolean; create?: boolean }): Promise<CliDb> {\n const [{ createClient }, sql] = await Promise.all([\n import(/* @vite-ignore */ '@libsql/client') as Promise<{ createClient: (config: { url: string }) => LibsqlClient }>,\n loadSql(),\n ]);\n const initialize = opts?.initialize ?? true;\n if (!initialize && !nodeFs().existsSync(resolved)) {\n throw new Error(`[wod] no database at ${resolved} — run \\`wod init\\` to create and initialize it`);\n }\n if (initialize) nodeFs().mkdirSync(nodePath().dirname(resolved), { recursive: true });\n const db = sql.libsqlDatabase(createClient({ url: `file:${resolved}` }));\n try {\n if (initialize) {\n await sql.initializeStore(db);\n await sql.initializeDomain(db);\n } else {\n // Guards only — no schema creation on an existing file either.\n await sql.verifyReadiness(db).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`${message} — run \\`wod init\\` to initialize it`, { cause: error });\n });\n }\n return { db, storage: new sql.SqlStorage(db), path: resolved, close: () => db.close() };\n } catch (error) {\n await db.close();\n throw error;\n }\n}\n\n/** Open a postgres/turso/remote-sqlite backend through the extracted server\n * adapter (dynamic on purpose: node-only subpath kept out of browser\n * bundles and external in the CLI bundle). Never falls back locally. */\nasync function openRemoteDb(\n env: Record<string, string | undefined>,\n label: string,\n opts?: { initialize?: boolean; create?: boolean },\n): Promise<CliDb> {\n const [{ openDatabase }, sql] = await Promise.all([\n import(/* @vite-ignore */ '@bitcobblers/wod-wiki-storage/sql/node') as Promise<{\n openDatabase: (env?: Record<string, string | undefined>, opts?: { create?: boolean }) => Promise<Database>;\n }>,\n loadSql(),\n ]);\n let db: Database | undefined;\n try {\n db = await openDatabase(env, { create: opts?.create });\n if (opts?.initialize === false) {\n await sql.verifyReadiness(db);\n } else {\n await sql.initializeStore(db);\n await sql.initializeDomain(db);\n }\n } catch (error) {\n await db?.close().catch(() => {});\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `[wod] ${label}: ${message}${opts?.initialize === false ? ' — run `wod init` to initialize it' : ''}`,\n { cause: error },\n );\n }\n return { db, storage: new sql.SqlStorage(db), path: label, close: () => db.close() };\n}\n\n// ---------------------------------------------------------------------------\n// Identity helpers\n// ---------------------------------------------------------------------------\n\n/** RFC-4122 byte munging + formatting over a 16-byte digest slice. */\nexport function formatV5Digest(digest: Uint8Array): string {\n const bytes = digest.slice(0, 16);\n bytes[6] = (bytes[6] & 0x0f) | 0x50; // version 5\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // RFC-4122 variant\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0'));\n return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10, 16).join('')}`;\n}\n\n/** RFC-4122 v5 (SHA-1) name-based UUID — deterministic seed/note identity. */\nexport function uuid5(namespace: string, name: string): string {\n return formatV5Digest(nodeCrypto().createHash('sha1').update(namespace).update(name).digest());\n}\n\n/** Local namespace for wod-CLI derived identities (not shared with seed ids). */\nexport const CLI_UUID_NAMESPACE = 'c0ffee00-8b1a-4e2c-9d3f-5a6b7c8d9e0f';\n\n/**\n * Stable note identity for a parsed/run source: the same file always maps\n * to the same note, so re-parsing updates instead of duplicating. Stdin\n * sources content-address (no stable path exists).\n */\nexport function stableNoteId(sourceLabel: string, content: string): string {\n if (sourceLabel && sourceLabel !== '-') {\n return uuid5(CLI_UUID_NAMESPACE, `wod-cli:${nodePath().resolve(process.cwd(), sourceLabel)}`);\n }\n return uuid5(CLI_UUID_NAMESPACE, `wod-cli:stdin:${content.length}:${content.slice(0, 256)}`);\n}\n\nexport function randomId(): string {\n return nodeCrypto().randomUUID();\n}\n\n// ---------------------------------------------------------------------------\n// WQL store adapters over the sqlite rows\n// ---------------------------------------------------------------------------\n\nasync function allRows(sql: SqlApi, db: Database, store: string): Promise<unknown[]> {\n return sql.listRows(db, sql.storeDefinition(store));\n}\n\nasync function rowsByIndex(sql: SqlApi, db: Database, store: string, index: string, only: string): Promise<unknown[]> {\n return sql.listRows(db, sql.storeDefinition(store), { only }, undefined, index);\n}\n\n/** EventStore over the `events` table — whole-table reads, keyed writes. */\nexport function sqliteEventStore(db: Database): EventStore {\n const all = async (): Promise<EventRecord[]> => (await allRows(await loadSql(), db, 'events')) as EventRecord[];\n return {\n getEventsByTimeRange: async (start, end) => (await all()).filter((r) => r.timestamp >= start && r.timestamp <= end),\n getEventsByResult: async (resultId) => (await all()).filter((r) => r.resultId === resultId),\n getEventsForNote: async (noteId) => (await all()).filter((r) => r.noteId === noteId),\n getEventsByContent: async (blockContentId) => (await all()).filter((r) => r.blockContentId === blockContentId),\n scanAll: all,\n appendEvents: async (appended) => {\n const sql = await loadSql();\n await db.transaction(async (tx) => {\n const eventsDef = sql.storeDefinition('events');\n for (const row of appended) await sql.putRow(tx, eventsDef, row);\n });\n },\n finalizeSummaries: async (resultId, finals) => {\n const sql = await loadSql();\n await db.transaction(async (tx) => {\n const eventsDef = sql.storeDefinition('events');\n const existing = ((await sql.listRows(tx, eventsDef)) as EventRecord[]).filter(\n (r) => r.resultId === resultId && r.grain === 'summary' && r.origin !== 'user',\n );\n for (const row of existing) await sql.deleteRows(tx, eventsDef, row.id);\n for (const row of finals) await sql.putRow(tx, eventsDef, row);\n });\n },\n deleteEvents: async (ids) => {\n const sql = await loadSql();\n await db.transaction(async (tx) => {\n const eventsDef = sql.storeDefinition('events');\n for (const id of ids) await sql.deleteRows(tx, eventsDef, id);\n });\n },\n };\n}\n\ninterface StoredTag { id: string; label: string; type?: string }\ninterface StoredNoteTag { id: string; noteId: string; tagId: string }\n\n/** NoteQueryStore over the notes/tags/note_tags rows + domain projection reads. */\nexport function sqliteNoteStore(db: Database): NoteQueryStore {\n return {\n getAllNotes: async () => (await allRows(await loadSql(), db, 'notes')) as never,\n getNotesByIds: async (noteIds) => {\n const sql = await loadSql();\n const rows = await sql.getRows(db, sql.storeDefinition('notes'), [...noteIds]) as Array<Note | undefined>;\n return rows.filter((row): row is Note => row !== undefined);\n },\n getNoteIdsForTag: async (label) => {\n const sql = await loadSql();\n const tags = ((await allRows(sql, db, 'tags')) as StoredTag[]).filter((t) => t.label === label);\n const ids: Record<string, true> = {};\n for (const tag of tags) {\n for (const row of await rowsByIndex(sql, db, 'note_tags', 'by-tag', tag.id)) {\n ids[(row as StoredNoteTag).noteId] = true;\n }\n }\n return new Set(Object.keys(ids));\n },\n getNoteTagLabels: async (noteId) => {\n const sql = await loadSql();\n const tagRows = (await allRows(sql, db, 'tags')) as StoredTag[];\n const labelById: Record<string, string> = {};\n for (const t of tagRows) labelById[t.id] = t.label;\n const links = (await rowsByIndex(sql, db, 'note_tags', 'by-note', noteId)) as StoredNoteTag[];\n return links.map((l) => labelById[l.tagId]).filter((l): l is string => typeof l === 'string');\n },\n queryDomain: async (request) => {\n // WQL's domain wire is a structural mirror of the storage DomainQuery.\n const result = await (await loadSql()).handleDomainQuery(db, request as never);\n return result as WqlDomainReadResult;\n },\n };\n}\n\n/** BlockQueryStore over the block_index rows + domain projection reads. */\nexport function sqliteBlockStore(db: Database): BlockQueryStore {\n return {\n getAllBlocks: async () => (await allRows(await loadSql(), db, 'block_index')) as never,\n queryDomain: async (request) => {\n const result = await (await loadSql()).handleDomainQuery(db, { ...request, plan: 'blocks' } as never);\n return result as WqlDomainReadResult;\n },\n };\n}\n\ninterface Slugged { slug: string }\n\n/**\n * EffortQueryStore: rows the seed wrote into the `efforts` registry win by\n * slug; the lang-bundled registry fills the rest (same fallback the\n * playground's RegistryEffortStore performs).\n */\nexport function sqliteEffortStore(db: Database): EffortQueryStore {\n return {\n getAllEfforts: async () => {\n const stored = (await allRows(await loadSql(), db, 'efforts')) as Slugged[];\n const bySlug: Record<string, unknown> = {};\n for (const effort of stored) bySlug[effort.slug] = effort;\n for (const effort of bundledEfforts as unknown as Slugged[]) {\n bySlug[effort.slug] ??= effort;\n }\n return Object.values(bySlug) as never;\n },\n };\n}\n\n/** Generic by-index reader over a store table — the QueryService seam shape. */\nexport interface IndexStore { getAllFromIndex(index: string, key: string): Promise<unknown[]> }\n\n/** Indexed reads over `block_efforts` / `tags` / `note_tags` rows. */\nexport function sqliteIndexStore(db: Database, store: 'block_efforts' | 'tags' | 'note_tags'): IndexStore {\n return {\n getAllFromIndex: async (index, key) => rowsByIndex(await loadSql(), db, store, index, key),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Download bundles (exchange feedstock)\n// ---------------------------------------------------------------------------\n\nexport interface NoteBundle {\n note: Note | undefined;\n}\n\nexport interface SessionBundle {\n session: Session;\n events: EventRecord[];\n}\n\n/** Fetch the whole authored Note. */\nexport async function getNoteBundle(db: Database, noteId: string): Promise<NoteBundle> {\n const sql = await loadSql();\n const note = await sql.getRow(db, sql.storeDefinition('notes'), noteId) as Note | undefined;\n return { note };\n}\n\n/** Fetch a session + its event/summary rows. */\nexport async function getSessionBundle(db: Database, resultId: string): Promise<SessionBundle | undefined> {\n const sql = await loadSql();\n const session = await sql.getRow(db, sql.storeDefinition('sessions'), resultId) as Session | undefined;\n if (!session) return undefined;\n const events = await sql.listRows(db, sql.storeDefinition('events'), { only: resultId }, undefined, 'by-result-grain') as EventRecord[];\n return { session, events };\n}\n\n/** Fetch one effort registry row by slug. */\nexport async function getEffortBySlug(db: Database, slug: string): Promise<Record<string, unknown> | undefined> {\n const sql = await loadSql();\n const efforts = (await allRows(sql, db, 'efforts')) as Array<{ slug: string } & Record<string, unknown>>;\n return efforts.find((e) => e.slug === slug);\n}\n\n/** Fetch one equipment registry row by slug. */\nexport async function getEquipmentBySlug(db: Database, slug: string): Promise<Record<string, unknown> | undefined> {\n const sql = await loadSql();\n const equipment = (await allRows(sql, db, 'equipment')) as Array<{ slug: string } & Record<string, unknown>>;\n return equipment.find((e) => e.slug === slug);\n}\n\n/** Fetch tag rows of one type (e.g. 'equipment'). */\nexport async function listTagsByType(db: Database, type: string): Promise<Array<{ id: string; label: string; type?: string }>> {\n const sql = await loadSql();\n const tags = (await allRows(sql, db, 'tags')) as Array<{ id: string; label: string; type?: string }>;\n return tags.filter((t) => t.type === type);\n}\n","import {\n FeedTreeError,\n normalizeFeedTreePath,\n sha256HexAsync,\n type FeedFileStat,\n type FeedPath,\n type FeedTree,\n} from '@bitcobblers/wod-wiki-engine';\nimport { nodeFs, nodePath } from './db';\n\n/**\n * Node/Bun filesystem adapter for `FeedTree`.\n * Uses lazy `nodeFs()`/`nodePath()` shims so browser bundles never pull `node:fs`.\n */\nexport class NodeFsFeedTree implements FeedTree {\n private readonly rootDir: string;\n\n constructor(rootDir: string) {\n this.rootDir = nodePath().resolve(rootDir);\n }\n\n get root(): string {\n return this.rootDir;\n }\n\n private absPath(relPath: FeedPath): string {\n const clean = normalizeFeedTreePath(relPath);\n const resolved = nodePath().resolve(this.rootDir, clean);\n if (resolved !== this.rootDir && !resolved.startsWith(this.rootDir + '/') && !resolved.startsWith(this.rootDir + '\\\\')) {\n throw new FeedTreeError('layout', `Path '${relPath}' escapes root '${this.rootDir}'`);\n }\n return resolved;\n }\n\n async read(path: FeedPath): Promise<Uint8Array> {\n const abs = this.absPath(path);\n const fs = nodeFs() as unknown as {\n existsSync(p: string): boolean;\n readFileSync(p: string): Uint8Array;\n };\n if (!fs.existsSync(abs)) {\n throw new FeedTreeError('not-found', `File not found: ${path}`);\n }\n return new Uint8Array(fs.readFileSync(abs));\n }\n\n async stat(path: FeedPath): Promise<FeedFileStat | undefined> {\n try {\n const bytes = await this.read(path);\n return {\n bytes: bytes.byteLength,\n sha256: await sha256HexAsync(bytes),\n };\n } catch (err) {\n if (err instanceof FeedTreeError && err.code === 'not-found') return undefined;\n throw err;\n }\n }\n\n async write(path: FeedPath, bytes: Uint8Array): Promise<void> {\n const abs = this.absPath(path);\n const p = nodePath();\n const fs = nodeFs() as unknown as {\n mkdirSync(dir: string, opts: { recursive: boolean }): void;\n writeFileSync(file: string, data: Uint8Array): void;\n };\n fs.mkdirSync(p.dirname(abs), { recursive: true });\n fs.writeFileSync(abs, bytes);\n }\n\n async delete(path: FeedPath): Promise<void> {\n const abs = this.absPath(path);\n const fs = nodeFs();\n if (fs.existsSync(abs)) {\n fs.unlinkSync(abs);\n }\n }\n}\n","/**\n * app.ts — one native fetch handler for the whole surface:\n * GET /api/health\n * GET /api/v1/:store/get?key= GET /api/v1/:store/all?range=&count=\n * GET /api/v1/:store/index/:idx?range=&count=\n * GET /api/v1/:store/count?range=&index=\n * PUT /api/v1/:store {value} DELETE /api/v1/:store?key=\n * POST /api/v1/:store/clear POST /api/v1/tx {ops}\n * POST /api/v1/wipe POST /api/v1/query\n * everything else: static SPA serving from playgroundDist (asset miss with an\n * extension → 404; extensionless → index.html; traversal/symlink escapes →\n * 403; /api never falls through to the SPA).\n *\n * `db` may be null for the CLI playground mode: static SPA serving only, every\n * /api request answers 404 — the playground never touches a server database.\n */\n\nimport { join, resolve, sep } from 'node:path';\nimport { stat, realpath } from 'node:fs/promises';\nimport { realpathSync, createReadStream } from 'node:fs';\nimport { Readable } from 'node:stream';\nimport { HttpError } from './errors';\nimport {\n SqlStorage,\n handleDomainQuery,\n refreshDomain,\n wipeDomain,\n MAX_BODY,\n StorageError,\n storeDefinition,\n getRow,\n listRows,\n countRows,\n wipeRows,\n type Database,\n} from '@bitcobblers/wod-wiki-storage/sql';\nimport { keyFromValue, type KeyDTO, type RangeDTO, type TxOp } from '@bitcobblers/wod-wiki-storage';\nimport {\n FeedTreeError,\n MemoryFeedTree,\n checkUnpublishedFeedChanges,\n publishFeedFromStorage,\n type FeedTree,\n} from '@bitcobblers/wod-wiki-engine';\nimport { NodeFsFeedTree } from '../cli/nodeFeedTree';\nconst json = (value: unknown, status: number): Response =>\n new Response(JSON.stringify(value), { status, headers: { 'content-type': 'application/json' } });\n\nfunction streamFile(path: string): BodyInit {\n const bun = (globalThis as { Bun?: { file(p: string): BodyInit } }).Bun;\n if (bun?.file) return bun.file(path);\n // ponytail: node:fs Readable.toWeb streams files in pure Node.js (v18+) without dependencies\n return Readable.toWeb(createReadStream(path)) as unknown as BodyInit;\n}\n\nconst plain = (body: string, status: number): Response =>\n new Response(body, { status, headers: { 'content-type': 'text/plain; charset=utf-8' } });\n\nconst notFound = (): Response => json({ error: 'not found' }, 404);\nconst methodNotAllowed = (): Response => json({ error: 'method not allowed' }, 405);\n\nconst noContent = (): Response => new Response(null, { status: 204 });\n\n/** URLSearchParams already applies the form-urlencoded '+' → space then %XX\n * decoding the wire contract relies on. */\nconst qget = (url: URL, name: string): string | undefined => url.searchParams.get(name) ?? undefined;\n\nfunction jsonParam(url: URL, name: string): unknown {\n const raw = qget(url, name);\n if (raw === undefined) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new HttpError(400, `invalid JSON in ?${name}`);\n }\n}\n\n/** ?range accepts a RangeDTO object or a bare key (scalar/tuple → {only}). */\nfunction rangeParam(url: URL): RangeDTO | undefined {\n const v = jsonParam(url, 'range');\n if (v === undefined) return undefined;\n if (v !== null && typeof v === 'object' && !Array.isArray(v)) return v as RangeDTO;\n return { only: v as KeyDTO };\n}\n\nfunction countParam(url: URL): number | undefined {\n const raw = qget(url, 'count');\n if (raw === undefined) return undefined;\n const n = Number(raw); // Number('') === 0, matching the wire contract\n if (!Number.isFinite(n) || n < 0) throw new HttpError(400, 'invalid ?count');\n return Math.trunc(n);\n}\n\nasync function readJsonBody(req: Request, maxBytes?: number): Promise<unknown> {\n const body = await req.text();\n if (maxBytes !== undefined && body.length > maxBytes) {\n throw new HttpError(413, `domain query body exceeds ${maxBytes} bytes`);\n }\n try {\n return JSON.parse(body) as unknown;\n } catch {\n throw new HttpError(400, 'body must be valid JSON');\n }\n}\n\nfunction txOps(value: unknown): TxOp[] {\n if (!Array.isArray(value)) throw new HttpError(400, 'tx body must be {ops: []}');\n return value.map((op: unknown): TxOp => {\n if (op === null || typeof op !== 'object' || Array.isArray(op) || !('store' in op) || typeof op.store !== 'string' || !('op' in op)) {\n throw new HttpError(400, 'tx op must have a store and operation');\n }\n const def = storeDefinition(op.store);\n const store = def.name;\n switch (op.op) {\n case 'put':\n if (!('value' in op)) throw new HttpError(400, 'put requires value');\n return { op: 'put', store, value: op.value };\n case 'delete':\n if (!('key' in op)) throw new HttpError(400, 'delete requires key');\n return { op: 'delete', store, key: op.key as KeyDTO };\n case 'clear':\n return { op: 'clear', store };\n case 'check': {\n if (!('key' in op) || !('value' in op)) throw new HttpError(400, 'check requires key and value');\n const scalar = (key: unknown): key is string | number => typeof key === 'string' || (typeof key === 'number' && Number.isFinite(key));\n if (!scalar(op.key) && !(Array.isArray(op.key) && op.key.length > 0 && op.key.every(scalar))) {\n throw new HttpError(400, 'check requires a scalar key or non-empty scalar tuple');\n }\n if (op.value !== null && (typeof op.value !== 'object' || Array.isArray(op.value))) {\n throw new HttpError(400, 'check value must be a row or null');\n }\n const parts = Array.isArray(op.key) ? op.key : [op.key];\n if (parts.length !== def.keyPath.length) throw new HttpError(400, 'check key arity must match the store');\n if (op.value !== null) {\n let rowKey: KeyDTO;\n try { rowKey = keyFromValue(def, op.value); }\n catch { throw new HttpError(400, 'check row must have its primary key'); }\n if (JSON.stringify(rowKey) !== JSON.stringify(op.key)) throw new HttpError(400, 'check row primary key must match key');\n }\n return { op: 'check', store, key: op.key, value: op.value };\n }\n default:\n throw new HttpError(400, 'tx op must be put | delete | clear | check');\n }\n });\n}\n\n// ── Static SPA serving ───────────────────────────────────────────────────────\n\nconst MIME: Record<string, string> = {\n html: 'text/html; charset=utf-8',\n js: 'text/javascript; charset=utf-8',\n mjs: 'text/javascript; charset=utf-8',\n css: 'text/css; charset=utf-8',\n json: 'application/json; charset=utf-8',\n map: 'application/json; charset=utf-8',\n svg: 'image/svg+xml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n webp: 'image/webp',\n ico: 'image/x-icon',\n woff: 'font/woff',\n woff2: 'font/woff2',\n ttf: 'font/ttf',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n webmanifest: 'application/manifest+json',\n xml: 'application/xml',\n txt: 'text/plain; charset=utf-8',\n md: 'text/markdown; charset=utf-8',\n jsonl: 'application/x-ndjson; charset=utf-8',\n csv: 'text/csv; charset=utf-8',\n};\n\nasync function realpathSafe(path: string): Promise<string | undefined> {\n try {\n return await realpath(path);\n } catch {\n return undefined;\n }\n}\n\nasync function serveFile(real: string, rel: string): Promise<Response> {\n // Seed chunks are content-hashed; everything else revalidates.\n const cache = rel.includes('seed/chunks/')\n ? 'public, max-age=31536000, immutable'\n : 'no-cache';\n const ext = rel.slice(rel.lastIndexOf('.') + 1).toLowerCase();\n return new Response(streamFile(real), {\n headers: { 'content-type': MIME[ext] ?? 'application/octet-stream', 'cache-control': cache },\n });\n}\n\nasync function serveSpaShell(distRoot: string): Promise<Response | undefined> {\n const index = await realpathSafe(join(distRoot, 'index.html'));\n // Same symlink confinement as assets: a dist/index.html symlink pointing\n // outside must not become the shell.\n if (index && (index === distRoot || index.startsWith(distRoot + sep))\n && (await stat(index).then((s) => s.isFile(), () => false))) {\n return new Response(streamFile(index), {\n headers: { 'content-type': MIME.html, 'cache-control': 'no-cache' },\n });\n }\n return undefined;\n}\n\nasync function staticResponse(distRoot: string | undefined, method: string, pathname: string): Promise<Response> {\n if (method !== 'GET') return plain('method not allowed', 405);\n if (!distRoot) {\n return plain('wod-wiki-api: playground dist not found. Set PLAYGROUND_DIST or run the playground server build.', 503);\n }\n let rel: string;\n try {\n rel = decodeURIComponent(pathname).replace(/^\\/+/, '');\n } catch {\n return plain('bad request', 400);\n }\n if (rel === '') rel = 'index.html';\n const parts = rel.split('/');\n if (parts.some((p) => p === '..')) return plain('forbidden', 403);\n const base = parts[parts.length - 1] ?? '';\n const hasExtension = base.includes('.');\n\n const abs = resolve(distRoot, ...parts);\n const real = await realpathSafe(abs);\n // Symlink confinement: serve only paths that really live under the dist root.\n if (real && (real === distRoot || real.startsWith(distRoot + sep))) {\n const info = await stat(real).then((s) => s.isFile(), () => false);\n if (info) return serveFile(real, rel);\n }\n // SPA fallback: extensionless paths render the app shell.\n if (!hasExtension) {\n const shell = await serveSpaShell(distRoot);\n if (shell) return shell;\n }\n return plain('not found', 404);\n}\n\n// ── API routing ──────────────────────────────────────────────────────────────\n\nasync function storeRoutes(db: Database, method: string, sub: string, url: URL, req: Request): Promise<Response> {\n let inner = sub.slice('/v1/'.length);\n if (inner.endsWith('/')) inner = inner.slice(0, -1);\n if (inner === '') return notFound();\n const segments = inner.split('/');\n let name: string;\n let action: string | undefined;\n if (segments.length === 1) {\n name = segments[0];\n } else if (segments.length === 2) {\n [name, action] = segments;\n } else if (segments.length === 3 && segments[1] === 'index' && segments[2] !== '') {\n [name, , action] = segments;\n action = `index/${action}`;\n } else {\n return notFound();\n }\n const def = storeDefinition(name); // 404 for unknown stores\n\n const range = rangeParam(url);\n const count = countParam(url);\n\n if (action === 'get' && method === 'GET') {\n const key = jsonParam(url, 'key');\n if (key === undefined) throw new HttpError(400, 'missing ?key');\n const row = await getRow(db, def, key as KeyDTO);\n return row === undefined ? notFound() : json(row, 200);\n }\n if (action === 'all' && method === 'GET') {\n return json(await listRows(db, def, range, count), 200);\n }\n if (action === 'count' && method === 'GET') {\n const indexName = qget(url, 'index');\n const n = indexName\n ? await countRows(db, def, range, indexName)\n : await countRows(db, def, range);\n return json({ count: Number(n) }, 200);\n }\n if (action === 'clear' && method === 'POST') {\n await db.transaction((tx) => refreshDomain(tx, [{ op: 'clear', store: def.name }]));\n return noContent();\n }\n if (action?.startsWith('index/') && method === 'GET') {\n return json(await listRows(db, def, range, count, action.slice('index/'.length)), 200);\n }\n if (action === undefined && method === 'PUT') {\n const parsed = await readJsonBody(req);\n const value = typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) && 'value' in parsed\n ? parsed.value\n : undefined;\n if (value === undefined) throw new HttpError(400, 'body must be {value: ...}');\n const [key] = await db.transaction((tx) => refreshDomain(tx, [{ op: 'put', store: def.name, value }]));\n return json({ key }, 200);\n }\n if (action === undefined && method === 'DELETE') {\n const keyParam = jsonParam(url, 'key');\n const target = keyParam !== undefined ? keyParam : range;\n if (target === undefined || target === null) throw new HttpError(400, 'DELETE requires ?key or ?range');\n // Wire DELETE accepts a key or a range; the TxOp delete variant types the\n // narrower KeyDTO even though deleteRows honours both.\n await db.transaction((tx) => refreshDomain(tx, [{ op: 'delete', store: def.name, key: target as KeyDTO }]));\n return noContent();\n }\n return methodNotAllowed();\n}\n\nfunction isPublishedFeedAssetPath(pathname: string): string | null {\n if (pathname === '/feed' || pathname === '/feed/') return 'index.html';\n if (!pathname.startsWith('/feed/')) return null;\n const sub = pathname.slice('/feed/'.length);\n if (\n sub === 'index.html' ||\n sub === 'manifest.json' ||\n sub === 'report.html' ||\n sub.startsWith('chunks/') ||\n sub.startsWith('indexes/') ||\n sub.startsWith('markdown/')\n ) {\n return sub;\n }\n return null;\n}\n\nasync function servePublishedFeed(feedTree: FeedTree, method: string, relPath: string): Promise<Response> {\n if (method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, HEAD, OPTIONS',\n },\n });\n }\n if (method !== 'GET') return methodNotAllowed();\n try {\n const decoded = decodeURIComponent(relPath);\n const bytes = await feedTree.read(decoded);\n const ext = decoded.includes('.') ? decoded.slice(decoded.lastIndexOf('.') + 1).toLowerCase() : 'html';\n const cache = decoded.startsWith('chunks/')\n ? 'public, max-age=31536000, immutable'\n : 'no-cache';\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return new Response(copy.buffer, {\n status: 200,\n headers: {\n 'content-type': MIME[ext] ?? 'application/octet-stream',\n 'cache-control': cache,\n 'access-control-allow-origin': '*',\n },\n });\n } catch (err) {\n if (err instanceof FeedTreeError && err.code === 'not-found') return notFound();\n if (err instanceof FeedTreeError && err.code === 'layout') return plain('forbidden', 403);\n throw err;\n }\n}\n\nasync function apiRoutes(\n db: Database,\n feedTree: FeedTree,\n req: Request,\n method: string,\n sub: string,\n url: URL,\n): Promise<Response> {\n if (sub === '/health') {\n return json({ ok: true, driver: db.dialect }, 200);\n }\n if (sub === '/v1/feed/status' && method === 'GET') {\n const storage = new SqlStorage(db);\n const status = await checkUnpublishedFeedChanges(storage, feedTree);\n return json({ ...status, feedUrl: `${url.origin}/feed/` }, 200);\n }\n if (sub === '/v1/feed/publish' && method === 'POST') {\n const body = req.headers.get('content-length') === '0' ? {} : await readJsonBody(req).catch(() => ({}));\n const opts = typeof body === 'object' && body !== null ? (body as Record<string, unknown>) : {};\n const storage = new SqlStorage(db);\n const report = await publishFeedFromStorage(storage, feedTree, {\n layout: 'feed',\n ...(typeof opts.name === 'string' ? { name: opts.name } : {}),\n ...(typeof opts.description === 'string' ? { description: opts.description } : {}),\n ...(typeof opts.repositoryUrl === 'string' ? { repositoryUrl: opts.repositoryUrl } : {}),\n ...(typeof opts.notebookSlug === 'string' ? { notebookSlug: opts.notebookSlug } : {}),\n });\n return json({\n manifest: report.manifest,\n notebooks: report.notebooks,\n totalNotes: report.totalNotes,\n totalPublicSessions: report.totalPublicSessions,\n feedUrl: `${url.origin}/feed/`,\n }, 200);\n }\n if (sub === '/v1/wipe' && method === 'POST') {\n await db.transaction(async (tx) => {\n // System memberships survive; derived projections follow (empty is consistent).\n await wipeRows(tx);\n await wipeDomain(tx);\n });\n return noContent();\n }\n if (sub === '/v1/tx' && method === 'POST') {\n const parsed = await readJsonBody(req);\n const ops = typeof parsed === 'object' && parsed !== null && 'ops' in parsed ? parsed.ops : undefined;\n const parsedOps = txOps(ops);\n const results = await db.transaction((tx) => refreshDomain(tx, parsedOps));\n return json({ results }, 200);\n }\n if (sub === '/v1/query') {\n if (method !== 'POST') return methodNotAllowed();\n const body = await readJsonBody(req, MAX_BODY);\n return json(await handleDomainQuery(db, body), 200);\n }\n if (sub.startsWith('/v1/')) return storeRoutes(db, method, sub, url, req);\n return notFound();\n}\n\n// ── Handler factory ──────────────────────────────────────────────────────────\n\nfunction distRootOf(playgroundDist: string | undefined): string | undefined {\n if (!playgroundDist) return undefined;\n try {\n return realpathSync(playgroundDist);\n } catch {\n return undefined;\n }\n}\n\nexport function createHandler(\n db: Database | null,\n options: { playgroundDist: string; feedDir?: string; feedTree?: FeedTree },\n): (request: Request) => Promise<Response> {\n const distRoot = distRootOf(options.playgroundDist);\n const feedTree: FeedTree =\n options.feedTree ??\n (options.feedDir ? new NodeFsFeedTree(options.feedDir) : new MemoryFeedTree());\n return async (request: Request): Promise<Response> => {\n try {\n const url = new URL(request.url);\n const method = request.method === 'HEAD' ? 'GET' : request.method; // Bun strips HEAD bodies\n const path = url.pathname;\n if (path === '/api' || path.startsWith('/api/')) {\n return db\n ? await apiRoutes(db, feedTree, request, method, path.slice('/api'.length) || '/', url)\n : notFound();\n }\n if (db) {\n const feedAsset = isPublishedFeedAssetPath(path);\n if (feedAsset !== null) {\n return await servePublishedFeed(feedTree, request.method === 'OPTIONS' ? 'OPTIONS' : method, feedAsset);\n }\n }\n return await staticResponse(distRoot, method, path);\n } catch (e) {\n if (e instanceof HttpError || e instanceof StorageError) {\n const status = e.status;\n if (status >= 500) console.error('[wod-wiki-api]', e.message);\n const body: { error: string; code?: string } = { error: status >= 500 ? 'internal error' : e.message };\n if (e.code) body.code = e.code;\n return json(body, status);\n }\n console.error('[wod-wiki-api]', e);\n return json({ error: 'internal error' }, 500);\n }\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/server/errors.ts","../../src/cli/db.ts","../../src/cli/nodeFeedTree.ts","../../src/version.ts","../../src/mcp/createWodMcpServer.ts","../../src/mcp/httpHandler.ts","../../src/server/app.ts"],"names":["normalizeFeedTreePath","FeedTreeError","sha256HexAsync","McpServer","DOMAIN_AGENT_TOOLS","AGENT_STATIC_RESOURCES","readAgentResource","AGENT_RESOURCE_TEMPLATES","ResourceTemplate","AGENT_PROMPTS","z","renderAgentPrompt","SqlStorage","WebStandardStreamableHTTPServerTransport","Readable","createReadStream","storeDefinition","keyFromValue","realpath","join","sep","stat","resolve","getRow","listRows","countRows","refreshDomain","checkUnpublishedFeedChanges","publishFeedFromStorage","wipeRows","wipeDomain","MAX_BODY","handleDomainQuery","realpathSync","MemoryFeedTree","exportAgentCapabilitiesManifest","StorageError"],"mappings":"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","file":"app.cjs","sourcesContent":["/**\n * errors.ts — the single HTTP error type every layer throws; app.ts maps it\n * to the wire's { error, code? } JSON with the matching status.\n */\nexport class HttpError extends Error {\n constructor(readonly status: number, message: string, readonly code?: string) {\n super(message);\n this.name = 'HttpError';\n }\n}\n","/**\n * Local SQLite seam for the `wod` CLI.\n *\n * Opens a libsql `file:` database, initializes the shared storage schema\n * (KV store tables + domain projections), and adapts the rows into the WQL\n * store interfaces — the same shape the playground builds over IndexedDB.\n *\n * Everything heavy is loaded lazily (`@libsql/client`,\n * `@bitcobblers/wod-wiki-storage/sql`, node `fs`/`crypto`) so browser\n * bundles that import the engine index never pull native drivers; the\n * dynamic specifiers stay external in the CLI bundle.\n */\n\nimport type { EventRecord } from '@bitcobblers/wod-wiki-core';\nimport type { IStorage, KeyDTO, Note, Session } from '@bitcobblers/wod-wiki-storage';\nimport type { RangeDTO, StoreDef } from '@bitcobblers/wod-wiki-storage';\nimport type {\n Database,\n LibsqlClient,\n SqlConnection,\n} from '@bitcobblers/wod-wiki-storage/sql';\nimport type { CliDatabaseConfig } from './config';\nimport type {\n BlockQueryStore,\n EventStore,\n EffortQueryStore,\n NoteQueryStore,\n WqlDomainReadResult,\n} from '@bitcobblers/wod-wiki-wql';\nimport { bundledEfforts } from '@bitcobblers/wod-wiki-lang';\n\n/** Structural CJS require — avoids the deprecated NodeJS namespace type. */\ntype CjsRequire = (id: string) => unknown;\n\n/** Minimal node builtin surfaces the CLI uses (kept out of browser bundles). */\nexport interface PathShim { resolve(...parts: string[]): string; join(...parts: string[]): string; dirname(p: string): string; basename(p: string): string }\nexport interface FsShim {\n mkdirSync(p: string, opts: { recursive: boolean }): void;\n existsSync(p: string): boolean;\n unlinkSync(p: string): void;\n readFileSync(p: string, encoding: string): string;\n writeFileSync(p: string, data: string, encoding: string): void;\n}\nexport interface HashShim { update(data: string): HashShim; digest(): Uint8Array }\nexport interface CryptoShim {\n createHash(algorithm: string): HashShim;\n randomUUID(): string;\n}\nexport const nodePath = (): PathShim => nodeRequire()('node:path') as PathShim;\nexport const nodeFs = (): FsShim => nodeRequire()('node:fs') as FsShim;\nexport const nodeCrypto = (): CryptoShim => nodeRequire()('node:crypto') as CryptoShim;\n\n/** Lazy CJS require — keeps node builtins out of browser bundles. */\nfunction nodeRequire(): CjsRequire {\n const g = globalThis as { process?: { versions?: Record<string, string> }; Bun?: unknown; require?: CjsRequire };\n if (typeof g.process?.versions?.node === 'undefined' && typeof g.Bun === 'undefined') {\n throw new Error('SQLite operations are only supported in Node / Bun environments');\n }\n const req = g.require ?? (typeof require === 'function' ? require : undefined);\n if (!req) throw new Error('SQLite operations require a CJS require shim (missing tsup banner?)');\n return req;\n}\n\n/** The storage/sql surface the CLI uses — structural mirror so the lazy import types check. */\nexport interface SqlApi {\n libsqlDatabase(client: LibsqlClient): Database;\n SqlStorage: new (db: Database) => IStorage;\n initializeStore(db: Database): Promise<void>;\n initializeDomain(db: Database): Promise<void>;\n verifyReadiness(db: Database): Promise<void>;\n storeDefinition(name: string): StoreDef;\n listRows(conn: SqlConnection, def: StoreDef, range?: RangeDTO, count?: number, indexName?: string): Promise<unknown[]>;\n getRow(conn: SqlConnection, def: StoreDef, key: KeyDTO): Promise<unknown | undefined>;\n getRows(conn: SqlConnection, def: StoreDef, keys: KeyDTO[]): Promise<(unknown | undefined)[]>;\n putRow(conn: SqlConnection, def: StoreDef, value: unknown): Promise<unknown>;\n deleteRows(conn: SqlConnection, def: StoreDef, keyOrRange: unknown): Promise<void>;\n refreshDomain(conn: SqlConnection, ops: unknown[]): Promise<unknown>;\n handleDomainQuery(db: Database, body: unknown): Promise<unknown>;\n}\n\nlet sqlModulePromise: Promise<SqlApi> | undefined;\n\n/** Lazily import the storage SQL subpath (kept external in the CLI bundle). */\nexport function loadSql(): Promise<SqlApi> {\n sqlModulePromise ??= import(/* @vite-ignore */ '@bitcobblers/wod-wiki-storage/sql') as Promise<SqlApi>;\n return sqlModulePromise;\n}\n\nexport interface CliDb {\n db: Database;\n storage: IStorage;\n /** Absolute path of the underlying .sqlite file — or the sanitized display\n * label (URL without credentials) for remote backends. */\n path: string;\n close(): Promise<void>;\n}\n\n/**\n * Resolve the effective database path: explicit flag wins, then\n * WOD_WIKI_DB, then ./wodwiki.db in the current working directory.\n */\nexport function resolveDbPath(dbPath?: string): string {\n const chosen = dbPath ?? process.env.WOD_WIKI_DB ?? './wodwiki.db';\n return nodePath().resolve(process.cwd(), chosen);\n}\n\n/**\n * Open the CLI database: a legacy local sqlite path (internal callers,\n * created/initialized as before) or a resolved backend config from ./config.\n *\n * opts.initialize (default true): run the schema + projection\n * initialization. false → verify the schema/projection guards only: a\n * missing local sqlite file is NOT created and yields an actionable\n * `wod init` error; remote targets are only probed, never created.\n *\n * opts.create (explicit init requests only, postgres): when the configured\n * PostgreSQL database is missing, openDatabase creates it through the admin\n * \"postgres\" database before initializing. Turso has no management API —\n * its hosted target must already exist.\n */\nexport async function openCliDb(\n target?: string | CliDatabaseConfig,\n opts?: { initialize?: boolean; create?: boolean },\n): Promise<CliDb> {\n if (target === undefined || typeof target === 'string') {\n return openSqliteDb(resolveDbPath(target), opts);\n }\n switch (target.kind) {\n case 'sqlite':\n return openSqliteDb(target.path, opts);\n case 'turso':\n return openRemoteDb(\n { DB_DRIVER: 'turso', DATABASE_URL: target.url, LIBSQL_AUTH_TOKEN: target.authToken },\n target.label,\n opts,\n );\n case 'postgres':\n return openRemoteDb({ DB_DRIVER: 'postgres', DATABASE_URL: target.url }, target.label, opts);\n }\n}\n\nasync function openSqliteDb(resolved: string, opts?: { initialize?: boolean; create?: boolean }): Promise<CliDb> {\n const [{ createClient }, sql] = await Promise.all([\n import(/* @vite-ignore */ '@libsql/client') as Promise<{ createClient: (config: { url: string }) => LibsqlClient }>,\n loadSql(),\n ]);\n const initialize = opts?.initialize ?? true;\n if (!initialize && !nodeFs().existsSync(resolved)) {\n throw new Error(`[wod] no database at ${resolved} — run \\`wod init\\` to create and initialize it`);\n }\n if (initialize) nodeFs().mkdirSync(nodePath().dirname(resolved), { recursive: true });\n const db = sql.libsqlDatabase(createClient({ url: `file:${resolved}` }));\n try {\n if (initialize) {\n await sql.initializeStore(db);\n await sql.initializeDomain(db);\n } else {\n // Guards only — no schema creation on an existing file either.\n await sql.verifyReadiness(db).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`${message} — run \\`wod init\\` to initialize it`, { cause: error });\n });\n }\n return { db, storage: new sql.SqlStorage(db), path: resolved, close: () => db.close() };\n } catch (error) {\n await db.close();\n throw error;\n }\n}\n\n/** Open a postgres/turso/remote-sqlite backend through the extracted server\n * adapter (dynamic on purpose: node-only subpath kept out of browser\n * bundles and external in the CLI bundle). Never falls back locally. */\nasync function openRemoteDb(\n env: Record<string, string | undefined>,\n label: string,\n opts?: { initialize?: boolean; create?: boolean },\n): Promise<CliDb> {\n const [{ openDatabase }, sql] = await Promise.all([\n import(/* @vite-ignore */ '@bitcobblers/wod-wiki-storage/sql/node') as Promise<{\n openDatabase: (env?: Record<string, string | undefined>, opts?: { create?: boolean }) => Promise<Database>;\n }>,\n loadSql(),\n ]);\n let db: Database | undefined;\n try {\n db = await openDatabase(env, { create: opts?.create });\n if (opts?.initialize === false) {\n await sql.verifyReadiness(db);\n } else {\n await sql.initializeStore(db);\n await sql.initializeDomain(db);\n }\n } catch (error) {\n await db?.close().catch(() => {});\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `[wod] ${label}: ${message}${opts?.initialize === false ? ' — run `wod init` to initialize it' : ''}`,\n { cause: error },\n );\n }\n return { db, storage: new sql.SqlStorage(db), path: label, close: () => db.close() };\n}\n\n// ---------------------------------------------------------------------------\n// Identity helpers\n// ---------------------------------------------------------------------------\n\n/** RFC-4122 byte munging + formatting over a 16-byte digest slice. */\nexport function formatV5Digest(digest: Uint8Array): string {\n const bytes = digest.slice(0, 16);\n bytes[6] = (bytes[6] & 0x0f) | 0x50; // version 5\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // RFC-4122 variant\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0'));\n return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10, 16).join('')}`;\n}\n\n/** RFC-4122 v5 (SHA-1) name-based UUID — deterministic seed/note identity. */\nexport function uuid5(namespace: string, name: string): string {\n return formatV5Digest(nodeCrypto().createHash('sha1').update(namespace).update(name).digest());\n}\n\n/** Local namespace for wod-CLI derived identities (not shared with seed ids). */\nexport const CLI_UUID_NAMESPACE = 'c0ffee00-8b1a-4e2c-9d3f-5a6b7c8d9e0f';\n\n/**\n * Stable note identity for a parsed/run source: the same file always maps\n * to the same note, so re-parsing updates instead of duplicating. Stdin\n * sources content-address (no stable path exists).\n */\nexport function stableNoteId(sourceLabel: string, content: string): string {\n if (sourceLabel && sourceLabel !== '-') {\n return uuid5(CLI_UUID_NAMESPACE, `wod-cli:${nodePath().resolve(process.cwd(), sourceLabel)}`);\n }\n return uuid5(CLI_UUID_NAMESPACE, `wod-cli:stdin:${content.length}:${content.slice(0, 256)}`);\n}\n\nexport function randomId(): string {\n return nodeCrypto().randomUUID();\n}\n\n// ---------------------------------------------------------------------------\n// WQL store adapters over the sqlite rows\n// ---------------------------------------------------------------------------\n\nasync function allRows(sql: SqlApi, db: Database, store: string): Promise<unknown[]> {\n return sql.listRows(db, sql.storeDefinition(store));\n}\n\nasync function rowsByIndex(sql: SqlApi, db: Database, store: string, index: string, only: string): Promise<unknown[]> {\n return sql.listRows(db, sql.storeDefinition(store), { only }, undefined, index);\n}\n\n/** EventStore over the `events` table — whole-table reads, keyed writes. */\nexport function sqliteEventStore(db: Database): EventStore {\n const all = async (): Promise<EventRecord[]> => (await allRows(await loadSql(), db, 'events')) as EventRecord[];\n return {\n getEventsByTimeRange: async (start, end) => (await all()).filter((r) => r.timestamp >= start && r.timestamp <= end),\n getEventsByResult: async (resultId) => (await all()).filter((r) => r.resultId === resultId),\n getEventsForNote: async (noteId) => (await all()).filter((r) => r.noteId === noteId),\n getEventsByContent: async (blockContentId) => (await all()).filter((r) => r.blockContentId === blockContentId),\n scanAll: all,\n appendEvents: async (appended) => {\n const sql = await loadSql();\n await db.transaction(async (tx) => {\n const eventsDef = sql.storeDefinition('events');\n for (const row of appended) await sql.putRow(tx, eventsDef, row);\n });\n },\n finalizeSummaries: async (resultId, finals) => {\n const sql = await loadSql();\n await db.transaction(async (tx) => {\n const eventsDef = sql.storeDefinition('events');\n const existing = ((await sql.listRows(tx, eventsDef)) as EventRecord[]).filter(\n (r) => r.resultId === resultId && r.grain === 'summary' && r.origin !== 'user',\n );\n for (const row of existing) await sql.deleteRows(tx, eventsDef, row.id);\n for (const row of finals) await sql.putRow(tx, eventsDef, row);\n });\n },\n deleteEvents: async (ids) => {\n const sql = await loadSql();\n await db.transaction(async (tx) => {\n const eventsDef = sql.storeDefinition('events');\n for (const id of ids) await sql.deleteRows(tx, eventsDef, id);\n });\n },\n };\n}\n\ninterface StoredTag { id: string; label: string; type?: string }\ninterface StoredNoteTag { id: string; noteId: string; tagId: string }\n\n/** NoteQueryStore over the notes/tags/note_tags rows + domain projection reads. */\nexport function sqliteNoteStore(db: Database): NoteQueryStore {\n return {\n getAllNotes: async () => (await allRows(await loadSql(), db, 'notes')) as never,\n getNotesByIds: async (noteIds) => {\n const sql = await loadSql();\n const rows = await sql.getRows(db, sql.storeDefinition('notes'), [...noteIds]) as Array<Note | undefined>;\n return rows.filter((row): row is Note => row !== undefined);\n },\n getNoteIdsForTag: async (label) => {\n const sql = await loadSql();\n const tags = ((await allRows(sql, db, 'tags')) as StoredTag[]).filter((t) => t.label === label);\n const ids: Record<string, true> = {};\n for (const tag of tags) {\n for (const row of await rowsByIndex(sql, db, 'note_tags', 'by-tag', tag.id)) {\n ids[(row as StoredNoteTag).noteId] = true;\n }\n }\n return new Set(Object.keys(ids));\n },\n getNoteTagLabels: async (noteId) => {\n const sql = await loadSql();\n const tagRows = (await allRows(sql, db, 'tags')) as StoredTag[];\n const labelById: Record<string, string> = {};\n for (const t of tagRows) labelById[t.id] = t.label;\n const links = (await rowsByIndex(sql, db, 'note_tags', 'by-note', noteId)) as StoredNoteTag[];\n return links.map((l) => labelById[l.tagId]).filter((l): l is string => typeof l === 'string');\n },\n queryDomain: async (request) => {\n // WQL's domain wire is a structural mirror of the storage DomainQuery.\n const result = await (await loadSql()).handleDomainQuery(db, request as never);\n return result as WqlDomainReadResult;\n },\n };\n}\n\n/** BlockQueryStore over the block_index rows + domain projection reads. */\nexport function sqliteBlockStore(db: Database): BlockQueryStore {\n return {\n getAllBlocks: async () => (await allRows(await loadSql(), db, 'block_index')) as never,\n queryDomain: async (request) => {\n const result = await (await loadSql()).handleDomainQuery(db, { ...request, plan: 'blocks' } as never);\n return result as WqlDomainReadResult;\n },\n };\n}\n\ninterface Slugged { slug: string }\n\n/**\n * EffortQueryStore: rows the seed wrote into the `efforts` registry win by\n * slug; the lang-bundled registry fills the rest (same fallback the\n * playground's RegistryEffortStore performs).\n */\nexport function sqliteEffortStore(db: Database): EffortQueryStore {\n return {\n getAllEfforts: async () => {\n const stored = (await allRows(await loadSql(), db, 'efforts')) as Slugged[];\n const bySlug: Record<string, unknown> = {};\n for (const effort of stored) bySlug[effort.slug] = effort;\n for (const effort of bundledEfforts as unknown as Slugged[]) {\n bySlug[effort.slug] ??= effort;\n }\n return Object.values(bySlug) as never;\n },\n };\n}\n\n/** Generic by-index reader over a store table — the QueryService seam shape. */\nexport interface IndexStore { getAllFromIndex(index: string, key: string): Promise<unknown[]> }\n\n/** Indexed reads over `block_efforts` / `tags` / `note_tags` rows. */\nexport function sqliteIndexStore(db: Database, store: 'block_efforts' | 'tags' | 'note_tags'): IndexStore {\n return {\n getAllFromIndex: async (index, key) => rowsByIndex(await loadSql(), db, store, index, key),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Download bundles (exchange feedstock)\n// ---------------------------------------------------------------------------\n\nexport interface NoteBundle {\n note: Note | undefined;\n}\n\nexport interface SessionBundle {\n session: Session;\n events: EventRecord[];\n}\n\n/** Fetch the whole authored Note. */\nexport async function getNoteBundle(db: Database, noteId: string): Promise<NoteBundle> {\n const sql = await loadSql();\n const note = await sql.getRow(db, sql.storeDefinition('notes'), noteId) as Note | undefined;\n return { note };\n}\n\n/** Fetch a session + its event/summary rows. */\nexport async function getSessionBundle(db: Database, resultId: string): Promise<SessionBundle | undefined> {\n const sql = await loadSql();\n const session = await sql.getRow(db, sql.storeDefinition('sessions'), resultId) as Session | undefined;\n if (!session) return undefined;\n const events = await sql.listRows(db, sql.storeDefinition('events'), { only: resultId }, undefined, 'by-result-grain') as EventRecord[];\n return { session, events };\n}\n\n/** Fetch one effort registry row by slug. */\nexport async function getEffortBySlug(db: Database, slug: string): Promise<Record<string, unknown> | undefined> {\n const sql = await loadSql();\n const efforts = (await allRows(sql, db, 'efforts')) as Array<{ slug: string } & Record<string, unknown>>;\n return efforts.find((e) => e.slug === slug);\n}\n\n/** Fetch one equipment registry row by slug. */\nexport async function getEquipmentBySlug(db: Database, slug: string): Promise<Record<string, unknown> | undefined> {\n const sql = await loadSql();\n const equipment = (await allRows(sql, db, 'equipment')) as Array<{ slug: string } & Record<string, unknown>>;\n return equipment.find((e) => e.slug === slug);\n}\n\n/** Fetch tag rows of one type (e.g. 'equipment'). */\nexport async function listTagsByType(db: Database, type: string): Promise<Array<{ id: string; label: string; type?: string }>> {\n const sql = await loadSql();\n const tags = (await allRows(sql, db, 'tags')) as Array<{ id: string; label: string; type?: string }>;\n return tags.filter((t) => t.type === type);\n}\n","import {\n FeedTreeError,\n normalizeFeedTreePath,\n sha256HexAsync,\n type FeedFileStat,\n type FeedPath,\n type FeedTree,\n} from '@bitcobblers/wod-wiki-engine';\nimport { nodeFs, nodePath } from './db';\n\n/**\n * Node/Bun filesystem adapter for `FeedTree`.\n * Uses lazy `nodeFs()`/`nodePath()` shims so browser bundles never pull `node:fs`.\n */\nexport class NodeFsFeedTree implements FeedTree {\n private readonly rootDir: string;\n\n constructor(rootDir: string) {\n this.rootDir = nodePath().resolve(rootDir);\n }\n\n get root(): string {\n return this.rootDir;\n }\n\n private absPath(relPath: FeedPath): string {\n const clean = normalizeFeedTreePath(relPath);\n const resolved = nodePath().resolve(this.rootDir, clean);\n if (resolved !== this.rootDir && !resolved.startsWith(this.rootDir + '/') && !resolved.startsWith(this.rootDir + '\\\\')) {\n throw new FeedTreeError('layout', `Path '${relPath}' escapes root '${this.rootDir}'`);\n }\n return resolved;\n }\n\n async read(path: FeedPath): Promise<Uint8Array> {\n const abs = this.absPath(path);\n const fs = nodeFs() as unknown as {\n existsSync(p: string): boolean;\n readFileSync(p: string): Uint8Array;\n };\n if (!fs.existsSync(abs)) {\n throw new FeedTreeError('not-found', `File not found: ${path}`);\n }\n return new Uint8Array(fs.readFileSync(abs));\n }\n\n async stat(path: FeedPath): Promise<FeedFileStat | undefined> {\n try {\n const bytes = await this.read(path);\n return {\n bytes: bytes.byteLength,\n sha256: await sha256HexAsync(bytes),\n };\n } catch (err) {\n if (err instanceof FeedTreeError && err.code === 'not-found') return undefined;\n throw err;\n }\n }\n\n async write(path: FeedPath, bytes: Uint8Array): Promise<void> {\n const abs = this.absPath(path);\n const p = nodePath();\n const fs = nodeFs() as unknown as {\n mkdirSync(dir: string, opts: { recursive: boolean }): void;\n writeFileSync(file: string, data: Uint8Array): void;\n };\n fs.mkdirSync(p.dirname(abs), { recursive: true });\n fs.writeFileSync(abs, bytes);\n }\n\n async delete(path: FeedPath): Promise<void> {\n const abs = this.absPath(path);\n const fs = nodeFs();\n if (fs.existsSync(abs)) {\n fs.unlinkSync(abs);\n }\n }\n}\n","/**\n * Auto-generated build version metadata.\n * Do not edit directly; updated by scripts/stamp-version.ts\n */\nexport const VERSION = '0.55.2206';\nexport const GIT_SHA = '5735d1c';\nexport const BUILD_TIME = '2026-11-12T04:20:12.798Z';\nexport const SEMVER = {\n version: '0.55.2206',\n gitSha: '5735d1c',\n buildTime: '2026-11-12T04:20:12.798Z',\n} as const;\n","import { z } from 'zod';\nimport { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { IStorage } from '@bitcobblers/wod-wiki-storage';\nimport type { FeedTree } from '@bitcobblers/wod-wiki-engine';\nimport {\n AGENT_PROMPTS,\n AGENT_RESOURCE_TEMPLATES,\n AGENT_STATIC_RESOURCES,\n DOMAIN_AGENT_TOOLS,\n readAgentResource,\n renderAgentPrompt,\n type AgentDomainContext,\n} from '@bitcobblers/wod-wiki-engine/agent';\nimport { VERSION } from '../version';\n\nexport interface CreateWodMcpServerOptions {\n storage: IStorage;\n feedTree?: FeedTree;\n baseUrl?: string;\n readonly?: boolean;\n onMutated?: () => Promise<void> | void;\n}\n\n/**\n * Creates a configured official `@modelcontextprotocol/sdk` `McpServer`\n * exposing all 22 WOD Wiki domain tools (or read-only Tier 0 tools when\n * `readonly: true`), `wod://*` resources, and guided workout prompts.\n */\nexport function createWodMcpServer(options: CreateWodMcpServerOptions): McpServer {\n const server = new McpServer(\n {\n name: 'wod-wiki',\n version: VERSION,\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n prompts: {},\n },\n },\n );\n\n const ctx: AgentDomainContext = {\n storage: options.storage,\n feedTree: options.feedTree,\n baseUrl: options.baseUrl,\n onMutated: options.onMutated,\n // Over MCP HTTP/stdio, explicit confirm=\"<targetId>\" inside tool arguments\n // satisfies Tier 2 confirmation; when omitted, requireAgentConfirmation throws\n // an actionable error instructing the caller to pass confirm=\"<targetId>\".\n };\n\n for (const spec of DOMAIN_AGENT_TOOLS) {\n if (options.readonly && spec.tier !== 0) {\n continue;\n }\n\n server.registerTool(\n spec.name,\n {\n title: spec.title,\n description: spec.description,\n inputSchema: spec.inputSchema,\n annotations: spec.annotations,\n },\n async (args: unknown) => {\n try {\n const parsed = spec.inputSchema.parse(args ?? {});\n const result = await spec.execute(parsed, ctx);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n structuredContent: result as Record<string, unknown>,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [\n {\n type: 'text' as const,\n text: message,\n },\n ],\n };\n }\n },\n );\n }\n\n for (const resource of AGENT_STATIC_RESOURCES) {\n server.registerResource(\n resource.name,\n resource.uri,\n {\n description: resource.description,\n mimeType: resource.mimeType,\n },\n async (uri) => {\n const res = await readAgentResource(uri.toString(), ctx);\n return {\n contents: [\n {\n uri: res.uri,\n mimeType: res.mimeType,\n text: res.text,\n },\n ],\n };\n },\n );\n }\n\n for (const tmpl of AGENT_RESOURCE_TEMPLATES) {\n const template = new ResourceTemplate(tmpl.uriTemplate, { list: undefined });\n server.registerResource(\n tmpl.name,\n template,\n {\n description: tmpl.description,\n mimeType: tmpl.mimeType,\n },\n async (uri) => {\n const res = await readAgentResource(uri.toString(), ctx);\n return {\n contents: [\n {\n uri: res.uri,\n mimeType: res.mimeType,\n text: res.text,\n },\n ],\n };\n },\n );\n }\n\n for (const prompt of AGENT_PROMPTS) {\n const argsShape: Record<string, z.ZodType> = {};\n for (const arg of prompt.arguments) {\n argsShape[arg.name] = arg.required\n ? z.string().describe(arg.description)\n : z.string().optional().describe(arg.description);\n }\n\n server.registerPrompt(\n prompt.name,\n {\n title: prompt.title,\n description: prompt.description,\n argsSchema: argsShape,\n },\n async (args) => {\n const rendered = renderAgentPrompt(prompt.name, args as Record<string, string | undefined>);\n return {\n description: rendered.description,\n messages: rendered.messages,\n };\n },\n );\n }\n\n return server;\n}\n","import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';\nimport { SqlStorage, type Database } from '@bitcobblers/wod-wiki-storage/sql';\nimport type { FeedTree } from '@bitcobblers/wod-wiki-engine';\nimport { createWodMcpServer } from './createWodMcpServer';\n\nconst MCP_CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, DELETE, OPTIONS',\n 'access-control-allow-headers': 'Content-Type, Accept, Authorization, Mcp-Session-Id, MCP-Protocol-Version, Last-Event-ID',\n 'access-control-expose-headers': 'Mcp-Session-Id, MCP-Protocol-Version',\n};\n\nfunction withMcpCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(MCP_CORS_HEADERS)) {\n if (!headers.has(k)) {\n headers.set(k, v);\n }\n }\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nfunction normalizeAcceptForPost(request: Request): Request {\n if (request.method !== 'POST') return request;\n const accept = request.headers.get('accept') ?? '';\n if (accept.includes('application/json') && accept.includes('text/event-stream')) {\n return request;\n }\n const headers = new Headers(request.headers);\n headers.set('accept', 'application/json, text/event-stream');\n return new Request(request, { headers });\n}\n\nexport interface HandleMcpHttpOptions {\n db: Database;\n feedTree: FeedTree;\n baseUrl: string;\n readonly?: boolean;\n authToken?: string;\n}\n\n/**\n * Handles Web-Standard Streamable HTTP MCP requests at `/api/mcp`.\n * Uses stateless per-request `WebStandardStreamableHTTPServerTransport` with\n * `enableJsonResponse: true` so both official MCP SDK clients and plain HTTP\n * JSON-RPC clients work out of the box without sticky session requirements.\n */\nexport async function handleMcpHttpRequest(\n request: Request,\n options: HandleMcpHttpOptions,\n): Promise<Response> {\n if (request.method === 'OPTIONS') {\n return new Response(null, { status: 204, headers: MCP_CORS_HEADERS });\n }\n\n const expectedToken = options.authToken ?? process.env.WOD_MCP_TOKEN?.trim();\n if (expectedToken) {\n const authHeader = request.headers.get('authorization') ?? '';\n const bearer = authHeader.startsWith('Bearer ') ? authHeader.slice('Bearer '.length).trim() : '';\n if (bearer !== expectedToken) {\n return withMcpCors(\n new Response(\n JSON.stringify({\n jsonrpc: '2.0',\n error: { code: -32001, message: 'Unauthorized: missing or invalid Bearer token' },\n id: null,\n }),\n { status: 401, headers: { 'content-type': 'application/json' } },\n ),\n );\n }\n }\n\n const storage = new SqlStorage(options.db);\n const server = createWodMcpServer({\n storage,\n feedTree: options.feedTree,\n baseUrl: options.baseUrl,\n readonly: options.readonly ?? process.env.WOD_MCP_READONLY === '1',\n });\n\n const transport = new WebStandardStreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n });\n\n await server.connect(transport);\n try {\n const normalizedReq = normalizeAcceptForPost(request);\n const response = await transport.handleRequest(normalizedReq);\n return withMcpCors(response);\n } finally {\n await transport.close().catch(() => {});\n await server.close().catch(() => {});\n }\n}\n","/**\n * app.ts — one native fetch handler for the whole surface:\n * GET /api/health\n * GET /api/v1/:store/get?key= GET /api/v1/:store/all?range=&count=\n * GET /api/v1/:store/index/:idx?range=&count=\n * GET /api/v1/:store/count?range=&index=\n * PUT /api/v1/:store {value} DELETE /api/v1/:store?key=\n * POST /api/v1/:store/clear POST /api/v1/tx {ops}\n * POST /api/v1/wipe POST /api/v1/query\n * everything else: static SPA serving from playgroundDist (asset miss with an\n * extension → 404; extensionless → index.html; traversal/symlink escapes →\n * 403; /api never falls through to the SPA).\n *\n * `db` may be null for the CLI playground mode: static SPA serving only, every\n * /api request answers 404 — the playground never touches a server database.\n */\n\nimport { join, resolve, sep } from 'node:path';\nimport { stat, realpath } from 'node:fs/promises';\nimport { realpathSync, createReadStream } from 'node:fs';\nimport { Readable } from 'node:stream';\nimport { HttpError } from './errors';\nimport {\n SqlStorage,\n handleDomainQuery,\n refreshDomain,\n wipeDomain,\n MAX_BODY,\n StorageError,\n storeDefinition,\n getRow,\n listRows,\n countRows,\n wipeRows,\n type Database,\n} from '@bitcobblers/wod-wiki-storage/sql';\nimport { keyFromValue, type KeyDTO, type RangeDTO, type TxOp } from '@bitcobblers/wod-wiki-storage';\nimport {\n FeedTreeError,\n MemoryFeedTree,\n checkUnpublishedFeedChanges,\n publishFeedFromStorage,\n type FeedTree,\n} from '@bitcobblers/wod-wiki-engine';\nimport { exportAgentCapabilitiesManifest } from '@bitcobblers/wod-wiki-engine/agent';\nimport { NodeFsFeedTree } from '../cli/nodeFeedTree';\nimport { handleMcpHttpRequest } from '../mcp/httpHandler';\nconst json = (value: unknown, status: number): Response =>\n new Response(JSON.stringify(value), { status, headers: { 'content-type': 'application/json' } });\n\nfunction streamFile(path: string): BodyInit {\n const bun = (globalThis as { Bun?: { file(p: string): BodyInit } }).Bun;\n if (bun?.file) return bun.file(path);\n // ponytail: node:fs Readable.toWeb streams files in pure Node.js (v18+) without dependencies\n return Readable.toWeb(createReadStream(path)) as unknown as BodyInit;\n}\n\nconst plain = (body: string, status: number): Response =>\n new Response(body, { status, headers: { 'content-type': 'text/plain; charset=utf-8' } });\n\nconst notFound = (): Response => json({ error: 'not found' }, 404);\nconst methodNotAllowed = (): Response => json({ error: 'method not allowed' }, 405);\n\nconst noContent = (): Response => new Response(null, { status: 204 });\n\n/** URLSearchParams already applies the form-urlencoded '+' → space then %XX\n * decoding the wire contract relies on. */\nconst qget = (url: URL, name: string): string | undefined => url.searchParams.get(name) ?? undefined;\n\nfunction jsonParam(url: URL, name: string): unknown {\n const raw = qget(url, name);\n if (raw === undefined) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new HttpError(400, `invalid JSON in ?${name}`);\n }\n}\n\n/** ?range accepts a RangeDTO object or a bare key (scalar/tuple → {only}). */\nfunction rangeParam(url: URL): RangeDTO | undefined {\n const v = jsonParam(url, 'range');\n if (v === undefined) return undefined;\n if (v !== null && typeof v === 'object' && !Array.isArray(v)) return v as RangeDTO;\n return { only: v as KeyDTO };\n}\n\nfunction countParam(url: URL): number | undefined {\n const raw = qget(url, 'count');\n if (raw === undefined) return undefined;\n const n = Number(raw); // Number('') === 0, matching the wire contract\n if (!Number.isFinite(n) || n < 0) throw new HttpError(400, 'invalid ?count');\n return Math.trunc(n);\n}\n\nasync function readJsonBody(req: Request, maxBytes?: number): Promise<unknown> {\n const body = await req.text();\n if (maxBytes !== undefined && body.length > maxBytes) {\n throw new HttpError(413, `domain query body exceeds ${maxBytes} bytes`);\n }\n try {\n return JSON.parse(body) as unknown;\n } catch {\n throw new HttpError(400, 'body must be valid JSON');\n }\n}\n\nfunction txOps(value: unknown): TxOp[] {\n if (!Array.isArray(value)) throw new HttpError(400, 'tx body must be {ops: []}');\n return value.map((op: unknown): TxOp => {\n if (op === null || typeof op !== 'object' || Array.isArray(op) || !('store' in op) || typeof op.store !== 'string' || !('op' in op)) {\n throw new HttpError(400, 'tx op must have a store and operation');\n }\n const def = storeDefinition(op.store);\n const store = def.name;\n switch (op.op) {\n case 'put':\n if (!('value' in op)) throw new HttpError(400, 'put requires value');\n return { op: 'put', store, value: op.value };\n case 'delete':\n if (!('key' in op)) throw new HttpError(400, 'delete requires key');\n return { op: 'delete', store, key: op.key as KeyDTO };\n case 'clear':\n return { op: 'clear', store };\n case 'check': {\n if (!('key' in op) || !('value' in op)) throw new HttpError(400, 'check requires key and value');\n const scalar = (key: unknown): key is string | number => typeof key === 'string' || (typeof key === 'number' && Number.isFinite(key));\n if (!scalar(op.key) && !(Array.isArray(op.key) && op.key.length > 0 && op.key.every(scalar))) {\n throw new HttpError(400, 'check requires a scalar key or non-empty scalar tuple');\n }\n if (op.value !== null && (typeof op.value !== 'object' || Array.isArray(op.value))) {\n throw new HttpError(400, 'check value must be a row or null');\n }\n const parts = Array.isArray(op.key) ? op.key : [op.key];\n if (parts.length !== def.keyPath.length) throw new HttpError(400, 'check key arity must match the store');\n if (op.value !== null) {\n let rowKey: KeyDTO;\n try { rowKey = keyFromValue(def, op.value); }\n catch { throw new HttpError(400, 'check row must have its primary key'); }\n if (JSON.stringify(rowKey) !== JSON.stringify(op.key)) throw new HttpError(400, 'check row primary key must match key');\n }\n return { op: 'check', store, key: op.key, value: op.value };\n }\n default:\n throw new HttpError(400, 'tx op must be put | delete | clear | check');\n }\n });\n}\n\n// ── Static SPA serving ───────────────────────────────────────────────────────\n\nconst MIME: Record<string, string> = {\n html: 'text/html; charset=utf-8',\n js: 'text/javascript; charset=utf-8',\n mjs: 'text/javascript; charset=utf-8',\n css: 'text/css; charset=utf-8',\n json: 'application/json; charset=utf-8',\n map: 'application/json; charset=utf-8',\n svg: 'image/svg+xml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n webp: 'image/webp',\n ico: 'image/x-icon',\n woff: 'font/woff',\n woff2: 'font/woff2',\n ttf: 'font/ttf',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n webmanifest: 'application/manifest+json',\n xml: 'application/xml',\n txt: 'text/plain; charset=utf-8',\n md: 'text/markdown; charset=utf-8',\n jsonl: 'application/x-ndjson; charset=utf-8',\n csv: 'text/csv; charset=utf-8',\n};\n\nasync function realpathSafe(path: string): Promise<string | undefined> {\n try {\n return await realpath(path);\n } catch {\n return undefined;\n }\n}\n\nasync function serveFile(real: string, rel: string): Promise<Response> {\n // Seed chunks are content-hashed; everything else revalidates.\n const cache = rel.includes('seed/chunks/')\n ? 'public, max-age=31536000, immutable'\n : 'no-cache';\n const ext = rel.slice(rel.lastIndexOf('.') + 1).toLowerCase();\n return new Response(streamFile(real), {\n headers: { 'content-type': MIME[ext] ?? 'application/octet-stream', 'cache-control': cache },\n });\n}\n\nasync function serveSpaShell(distRoot: string): Promise<Response | undefined> {\n const index = await realpathSafe(join(distRoot, 'index.html'));\n // Same symlink confinement as assets: a dist/index.html symlink pointing\n // outside must not become the shell.\n if (index && (index === distRoot || index.startsWith(distRoot + sep))\n && (await stat(index).then((s) => s.isFile(), () => false))) {\n return new Response(streamFile(index), {\n headers: { 'content-type': MIME.html, 'cache-control': 'no-cache' },\n });\n }\n return undefined;\n}\n\nasync function staticResponse(distRoot: string | undefined, method: string, pathname: string): Promise<Response> {\n if (method !== 'GET') return plain('method not allowed', 405);\n if (!distRoot) {\n return plain('wod-wiki-api: playground dist not found. Set PLAYGROUND_DIST or run the playground server build.', 503);\n }\n let rel: string;\n try {\n rel = decodeURIComponent(pathname).replace(/^\\/+/, '');\n } catch {\n return plain('bad request', 400);\n }\n if (rel === '') rel = 'index.html';\n const parts = rel.split('/');\n if (parts.some((p) => p === '..')) return plain('forbidden', 403);\n const base = parts[parts.length - 1] ?? '';\n const hasExtension = base.includes('.');\n\n const abs = resolve(distRoot, ...parts);\n const real = await realpathSafe(abs);\n // Symlink confinement: serve only paths that really live under the dist root.\n if (real && (real === distRoot || real.startsWith(distRoot + sep))) {\n const info = await stat(real).then((s) => s.isFile(), () => false);\n if (info) return serveFile(real, rel);\n }\n // SPA fallback: extensionless paths render the app shell.\n if (!hasExtension) {\n const shell = await serveSpaShell(distRoot);\n if (shell) return shell;\n }\n return plain('not found', 404);\n}\n\n// ── API routing ──────────────────────────────────────────────────────────────\n\nasync function storeRoutes(db: Database, method: string, sub: string, url: URL, req: Request): Promise<Response> {\n let inner = sub.slice('/v1/'.length);\n if (inner.endsWith('/')) inner = inner.slice(0, -1);\n if (inner === '') return notFound();\n const segments = inner.split('/');\n let name: string;\n let action: string | undefined;\n if (segments.length === 1) {\n name = segments[0];\n } else if (segments.length === 2) {\n [name, action] = segments;\n } else if (segments.length === 3 && segments[1] === 'index' && segments[2] !== '') {\n [name, , action] = segments;\n action = `index/${action}`;\n } else {\n return notFound();\n }\n const def = storeDefinition(name); // 404 for unknown stores\n\n const range = rangeParam(url);\n const count = countParam(url);\n\n if (action === 'get' && method === 'GET') {\n const key = jsonParam(url, 'key');\n if (key === undefined) throw new HttpError(400, 'missing ?key');\n const row = await getRow(db, def, key as KeyDTO);\n return row === undefined ? notFound() : json(row, 200);\n }\n if (action === 'all' && method === 'GET') {\n return json(await listRows(db, def, range, count), 200);\n }\n if (action === 'count' && method === 'GET') {\n const indexName = qget(url, 'index');\n const n = indexName\n ? await countRows(db, def, range, indexName)\n : await countRows(db, def, range);\n return json({ count: Number(n) }, 200);\n }\n if (action === 'clear' && method === 'POST') {\n await db.transaction((tx) => refreshDomain(tx, [{ op: 'clear', store: def.name }]));\n return noContent();\n }\n if (action?.startsWith('index/') && method === 'GET') {\n return json(await listRows(db, def, range, count, action.slice('index/'.length)), 200);\n }\n if (action === undefined && method === 'PUT') {\n const parsed = await readJsonBody(req);\n const value = typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) && 'value' in parsed\n ? parsed.value\n : undefined;\n if (value === undefined) throw new HttpError(400, 'body must be {value: ...}');\n const [key] = await db.transaction((tx) => refreshDomain(tx, [{ op: 'put', store: def.name, value }]));\n return json({ key }, 200);\n }\n if (action === undefined && method === 'DELETE') {\n const keyParam = jsonParam(url, 'key');\n const target = keyParam !== undefined ? keyParam : range;\n if (target === undefined || target === null) throw new HttpError(400, 'DELETE requires ?key or ?range');\n // Wire DELETE accepts a key or a range; the TxOp delete variant types the\n // narrower KeyDTO even though deleteRows honours both.\n await db.transaction((tx) => refreshDomain(tx, [{ op: 'delete', store: def.name, key: target as KeyDTO }]));\n return noContent();\n }\n return methodNotAllowed();\n}\n\nfunction isPublishedFeedAssetPath(pathname: string): string | null {\n if (pathname === '/feed' || pathname === '/feed/') return 'index.html';\n if (!pathname.startsWith('/feed/')) return null;\n const sub = pathname.slice('/feed/'.length);\n if (\n sub === 'index.html' ||\n sub === 'manifest.json' ||\n sub === 'report.html' ||\n sub.startsWith('chunks/') ||\n sub.startsWith('indexes/') ||\n sub.startsWith('markdown/')\n ) {\n return sub;\n }\n return null;\n}\n\nasync function servePublishedFeed(feedTree: FeedTree, method: string, relPath: string): Promise<Response> {\n if (method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, HEAD, OPTIONS',\n },\n });\n }\n if (method !== 'GET') return methodNotAllowed();\n try {\n const decoded = decodeURIComponent(relPath);\n const bytes = await feedTree.read(decoded);\n const ext = decoded.includes('.') ? decoded.slice(decoded.lastIndexOf('.') + 1).toLowerCase() : 'html';\n const cache = decoded.startsWith('chunks/')\n ? 'public, max-age=31536000, immutable'\n : 'no-cache';\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return new Response(copy.buffer, {\n status: 200,\n headers: {\n 'content-type': MIME[ext] ?? 'application/octet-stream',\n 'cache-control': cache,\n 'access-control-allow-origin': '*',\n },\n });\n } catch (err) {\n if (err instanceof FeedTreeError && err.code === 'not-found') return notFound();\n if (err instanceof FeedTreeError && err.code === 'layout') return plain('forbidden', 403);\n throw err;\n }\n}\n\nasync function apiRoutes(\n db: Database,\n feedTree: FeedTree,\n req: Request,\n method: string,\n sub: string,\n url: URL,\n mcpOptions?: { readonly?: boolean; authToken?: string },\n): Promise<Response> {\n if (sub === '/health') {\n return json({ ok: true, driver: db.dialect }, 200);\n }\n if (sub === '/mcp') {\n return handleMcpHttpRequest(req, {\n db,\n feedTree,\n baseUrl: url.origin,\n readonly: mcpOptions?.readonly,\n authToken: mcpOptions?.authToken,\n });\n }\n if (sub === '/v1/feed/status' && method === 'GET') {\n const storage = new SqlStorage(db);\n const status = await checkUnpublishedFeedChanges(storage, feedTree);\n return json({ ...status, feedUrl: `${url.origin}/feed/` }, 200);\n }\n if (sub === '/v1/feed/publish' && method === 'POST') {\n const body = req.headers.get('content-length') === '0' ? {} : await readJsonBody(req).catch(() => ({}));\n const opts = typeof body === 'object' && body !== null ? (body as Record<string, unknown>) : {};\n const storage = new SqlStorage(db);\n const report = await publishFeedFromStorage(storage, feedTree, {\n layout: 'feed',\n ...(typeof opts.name === 'string' ? { name: opts.name } : {}),\n ...(typeof opts.description === 'string' ? { description: opts.description } : {}),\n ...(typeof opts.repositoryUrl === 'string' ? { repositoryUrl: opts.repositoryUrl } : {}),\n ...(typeof opts.notebookSlug === 'string' ? { notebookSlug: opts.notebookSlug } : {}),\n });\n return json({\n manifest: report.manifest,\n notebooks: report.notebooks,\n totalNotes: report.totalNotes,\n totalPublicSessions: report.totalPublicSessions,\n feedUrl: `${url.origin}/feed/`,\n }, 200);\n }\n if (sub === '/v1/wipe' && method === 'POST') {\n await db.transaction(async (tx) => {\n // System memberships survive; derived projections follow (empty is consistent).\n await wipeRows(tx);\n await wipeDomain(tx);\n });\n return noContent();\n }\n if (sub === '/v1/tx' && method === 'POST') {\n const parsed = await readJsonBody(req);\n const ops = typeof parsed === 'object' && parsed !== null && 'ops' in parsed ? parsed.ops : undefined;\n const parsedOps = txOps(ops);\n const results = await db.transaction((tx) => refreshDomain(tx, parsedOps));\n return json({ results }, 200);\n }\n if (sub === '/v1/query') {\n if (method !== 'POST') return methodNotAllowed();\n const body = await readJsonBody(req, MAX_BODY);\n return json(await handleDomainQuery(db, body), 200);\n }\n if (sub.startsWith('/v1/')) return storeRoutes(db, method, sub, url, req);\n return notFound();\n}\n\n// ── Handler factory ──────────────────────────────────────────────────────────\n\nfunction distRootOf(playgroundDist: string | undefined): string | undefined {\n if (!playgroundDist) return undefined;\n try {\n return realpathSync(playgroundDist);\n } catch {\n return undefined;\n }\n}\n\nexport function createHandler(\n db: Database | null,\n options: {\n playgroundDist: string;\n feedDir?: string;\n feedTree?: FeedTree;\n mcpReadonly?: boolean;\n mcpToken?: string;\n },\n): (request: Request) => Promise<Response> {\n const distRoot = distRootOf(options.playgroundDist);\n const feedTree: FeedTree =\n options.feedTree ??\n (options.feedDir ? new NodeFsFeedTree(options.feedDir) : new MemoryFeedTree());\n return async (request: Request): Promise<Response> => {\n try {\n const url = new URL(request.url);\n const method = request.method === 'HEAD' ? 'GET' : request.method; // Bun strips HEAD bodies\n const path = url.pathname;\n if (path === '/api' || path.startsWith('/api/')) {\n return db\n ? await apiRoutes(\n db,\n feedTree,\n request,\n request.method === 'OPTIONS' ? 'OPTIONS' : method,\n path.slice('/api'.length) || '/',\n url,\n { readonly: options.mcpReadonly, authToken: options.mcpToken },\n )\n : notFound();\n }\n if (db && path === '/.well-known/agent-capabilities.json' && method === 'GET') {\n const res = await staticResponse(distRoot, method, path);\n if (res.status === 200) return res;\n return json(exportAgentCapabilitiesManifest(), 200);\n }\n if (db) {\n const feedAsset = isPublishedFeedAssetPath(path);\n if (feedAsset !== null) {\n return await servePublishedFeed(feedTree, request.method === 'OPTIONS' ? 'OPTIONS' : method, feedAsset);\n }\n }\n return await staticResponse(distRoot, method, path);\n } catch (e) {\n if (e instanceof HttpError || e instanceof StorageError) {\n const status = e.status;\n if (status >= 500) console.error('[wod-wiki-api]', e.message);\n const body: { error: string; code?: string } = { error: status >= 500 ? 'internal error' : e.message };\n if (e.code) body.code = e.code;\n return json(body, status);\n }\n console.error('[wod-wiki-api]', e);\n return json({ error: 'internal error' }, 500);\n }\n };\n}\n"]}
@@ -22,6 +22,8 @@ declare function createHandler(db: Database | null, options: {
22
22
  playgroundDist: string;
23
23
  feedDir?: string;
24
24
  feedTree?: FeedTree;
25
+ mcpReadonly?: boolean;
26
+ mcpToken?: string;
25
27
  }): (request: Request) => Promise<Response>;
26
28
 
27
29
  export { createHandler };
@@ -22,6 +22,8 @@ declare function createHandler(db: Database | null, options: {
22
22
  playgroundDist: string;
23
23
  feedDir?: string;
24
24
  feedTree?: FeedTree;
25
+ mcpReadonly?: boolean;
26
+ mcpToken?: string;
25
27
  }): (request: Request) => Promise<Response>;
26
28
 
27
29
  export { createHandler };
@@ -1,6 +1,8 @@
1
1
  import { createRequire } from 'module';
2
- export { createHandler } from '../chunk-2EWCEE6N.mjs';
2
+ export { createHandler } from '../chunk-FNEN33GQ.mjs';
3
+ import '../chunk-67JAEWEF.mjs';
3
4
  import '../chunk-FUISPA7A.mjs';
5
+ import '../chunk-WKU3MRQI.mjs';
4
6
  import '../chunk-QUUX6NX2.mjs';
5
7
 
6
8
  if (typeof globalThis.require === 'undefined') {
@@ -0,0 +1,13 @@
1
+ import { createRequire } from 'module';
2
+ export { runCliServer } from './chunk-RVQB3DYE.mjs';
3
+ import './chunk-FNEN33GQ.mjs';
4
+ import './chunk-67JAEWEF.mjs';
5
+ import './chunk-FUISPA7A.mjs';
6
+ import './chunk-WKU3MRQI.mjs';
7
+ import './chunk-QUUX6NX2.mjs';
8
+
9
+ if (typeof globalThis.require === 'undefined') {
10
+ try { globalThis.require = createRequire(import.meta.url); } catch {}
11
+ }
12
+ //# sourceMappingURL=server-HQJMA7BU.mjs.map
13
+ //# sourceMappingURL=server-HQJMA7BU.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"server-SHNWCIIM.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"server-HQJMA7BU.mjs"}
@@ -7,6 +7,9 @@ skills/<name>/SKILL.md # frontmatter: name, description (agentskills.io for
7
7
  ```
8
8
 
9
9
  - `wod-extraction` — the parsing skill: teaches an agent to read a workout description in any form and write Whiteboard Script (which metrics a workout implies, the collectible `?` placeholders, statement structure).
10
+ - `wod-cli` — the CLI & MCP execution skill: teaches an agent to drive `wod --json`, `wod mcp`, and `/api/mcp` across notes, journal scheduling, notebooks, headless sessions, catalog/tags, feeds, and Tier 2 `--yes` confirmation gates.
11
+ - `wod-wql` — the WQL query skill: teaches an agent to write, validate, and run WQL `find` and `aggregate` queries across all three surfaces.
12
+ - `wod-agent-parity` — the repository feature-parity skill: enforces action parity across `@bitcobblers/wod-wiki-engine/agent`, Playground WebMCP (`@mcp-b/react-webmcp`), `wod server` `/api/mcp`, and `wod --json` whenever new UI or domain features are developed.
10
13
  - `wod-wiki-testing` — the 3-tier repo testing skill: routes agents across Tier 1 domain scenarios (`@bitcobblers/wod-wiki-core/testing` + `DomainScenarioHarness`), Tier 2 Storybook `parameters.domainState` + `storyActions` and Playground `@/testing/host`, and Tier 3 two-level Markdown specs (`e2e/specs/`) + Playwright `PlaygroundTestActor` (`e2e/fixtures/playgroundActor.ts`), mirrored into `.agents/skills/wod-wiki-testing/`.
11
14
  ## Install
12
15
 
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: wod-agent-parity
3
+ description: 'Enforce First-Class Agent Readiness & Action Parity whenever adding or modifying WOD Wiki features, routes, UI actions, domain services, or CLI commands across Playground WebMCP, wod server MCP, and the wod CLI.'
4
+ license: MIT
5
+ ---
6
+
7
+ # First-Class Agent Readiness & Action Parity (`wod-agent-parity`)
8
+
9
+ ## Core Mandate
10
+
11
+ Every user-facing capability in WOD Wiki MUST maintain **Action Parity** between human-driven UI actions and AI-agent-driven actions across all applicable surfaces:
12
+
13
+ 1. **Portable Domain Mutations & Queries (`@bitcobblers/wod-wiki-engine/agent`)**:
14
+ - Any new domain read or write (Notes, Journal, Notebooks, Sessions, Catalog/Tags, WQL, Feeds, Portability) MUST be defined once as a typed `AgentToolSpec` in `packages/engine/src/agent/tools/` and exported in `packages/engine/src/agent/manifest.ts` (`DOMAIN_AGENT_TOOLS`).
15
+ - Because `PlaygroundAgentProvider` (`apps/playground/app/agent/PlaygroundAgentProvider.tsx`) and `createWodMcpServer` (`packages/tools/src/mcp/createWodMcpServer.ts`) both consume `DOMAIN_AGENT_TOOLS`, registering a domain tool there automatically exposes it to **Browser WebMCP (`navigator.modelContext`)** and **HTTP/Stdio MCP (`/api/mcp` & `wod mcp`)**.
16
+ - Wire the matching noun-verb CLI subcommand in `packages/tools/src/cli/agentCommands.ts` and `packages/tools/src/cli/runner.ts` (`--json` + `--server <url>`), and record the exact `cliEquivalent` on the `AgentToolSpec`.
17
+
18
+ 2. **Playground Live UI & Co-Driving Actions (`apps/playground/app/agent/`)**:
19
+ - Any interactive UI state in `apps/playground` that has no headless equivalent (new routes, view/layout toggles, live editor buffer controls, live workout clock commands, modals/drawers, Cast controls) MUST be exposed to browser agents via `@mcp-b/react-webmcp` (`useWebMCP()`):
20
+ - **Dynamic Lifecycle**: Register route- or surface-scoped UI tools inside a component that mounts *only* when that UI surface is active (e.g. `StreamAgentTools.tsx`, `EditorAgentTools.tsx`, `LiveClockAgentTools.tsx`) using the zero-dependency bridge in `apps/playground/src/agent/surfaceBridges.ts` so Storybook and the Chromecast receiver bundle (`apps/playground/app/receiver-rpc.tsx`) stay completely free of `@mcp-b/*`.
21
+ - **Post-Commit Synchronization**: Every UI-mutating WebMCP `execute` handler MUST `await waitForUiCommit()` (`apps/playground/app/agent/uiCommit.ts`) before returning so browser agents never read stale React state.
22
+ - **Manifest Registration**: Add the schema and `mountScope` entry to `apps/playground/app/agent/uiToolSpecs.ts` (`exportPlaygroundUiToolsManifest()`).
23
+
24
+ 3. **Safety & Risk Tier Discipline**:
25
+ - **Tier 0 (Read-only)**: Set `tier: 0` and `annotations: { readOnlyHint: true, destructiveHint: false, ... }`. Automatically allowed in `--mcp-readonly` mode.
26
+ - **Tier 1 (Reversible / Additive)**: Set `tier: 1` and `destructiveHint: false`.
27
+ - **Tier 2 (Irreversible / Destructive)**: Set `tier: 2` and `destructiveHint: true`, and gate execution with `requireDestructiveConfirmation(ctx, { action, targetId, summary }, args.confirmId)`:
28
+ - In **Playground WebMCP**, `AgentConfirmHost.tsx` automatically opens the Radix human-in-the-loop confirmation dialog (`data-testid="agent-confirm-dialog"`).
29
+ - In **CLI**, omitting `--yes <targetId>` automatically exits with code `4` (`CONFIRMATION_REQUIRED`).
30
+ - In **MCP**, omitting `confirmId` returns a structured confirmation error prompting explicit confirmation.
31
+
32
+ 4. **Deterministic DOM, URL State & Accessibility (Playground Layers 2–4)**:
33
+ - **Semantic Controls**: Interactive elements MUST be real `<button type="button">` / `<a>` / labeled `<input>` controls (never click-only `<div>`/`<span>` without `role`, `tabIndex`, and `Enter`/`Space` keyboard handlers) and carry `TEST_IDS` (`apps/playground/src/lib/testIds.ts`).
34
+ - **Loading & View State**: Async routes and streams MUST signal busy transitions via `setSurfaceBusy(loading)` (`apps/playground/src/agent/surfaceBridges.ts`) so `<main data-agent-status="loading|ready" aria-busy>` and `<script id="agent-view-state" type="application/json">` (`apps/playground/app/agent/AgentStateScript.tsx`) stay accurate.
35
+ - **URL Survival**: New routes go in `apps/playground/src/lib/routes.ts` (`ROUTE_PATTERNS`); meaningful view modes (e.g. `?layout=`, `?q=`, `?note=`) should survive page reload via URL search params.
36
+ - **Regenerate Discovery Files**: Whenever tools or routes change, run:
37
+ ```bash
38
+ bun run sync:agent-manifest
39
+ bun run sync:skills
40
+ bun run check:agent-parity
41
+ ```
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: wod-cli
3
+ description: 'Drive WOD Wiki locally or against a running wod server using the wod CLI (--json), wod mcp (stdio), or /api/mcp (HTTP). Covers notes, journal scheduling, notebooks, headless workout sessions, WQL queries, catalog management, and exit code 4 confirmation gates.'
4
+ license: MIT
5
+ ---
6
+
7
+ # WOD CLI & MCP Agent Guide (`wod`)
8
+
9
+ ## Overview
10
+
11
+ The `wod` CLI exposes every WOD Wiki domain capability with structured `--json` output, deterministic exit codes, and 1:1 parity with the `wod mcp` stdio server and `/api/mcp` HTTP MCP endpoint.
12
+
13
+ ## Quick Diagnostics
14
+
15
+ ```bash
16
+ wod doctor --json
17
+ wod tools list --json
18
+ ```
19
+
20
+ If the local SQLite database is not initialized yet:
21
+ ```bash
22
+ wod init --db ./wodwiki.db
23
+ ```
24
+
25
+ To target a running `wod server` instance instead of a local database file, pass `--server <url>` to any noun-verb command:
26
+ ```bash
27
+ wod note list --server http://127.0.0.1:3000 --json
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Core Workflows
33
+
34
+ ### 1. Parse & Verify Whiteboard Script (Dry Run)
35
+ Always validate authored workout syntax before saving when drafting from unstructured text:
36
+ ```bash
37
+ printf "(21-15-9)\n Thrusters @95lb\n Pull-ups\n" | wod parse - --no-save --json
38
+ ```
39
+
40
+ ### 2. Author, Read, Clone, and Delete Notes
41
+ ```bash
42
+ # List notes (optional filters: --notebook, --tag, --search, --limit)
43
+ wod note list --limit 20 --json
44
+
45
+ # Create a note from inline Markdown or stdin
46
+ wod note create --title "Fran" --tags "benchmark,girl" --markdown $'# Fran\n\n```time\n(21-15-9)\n Thrusters @95lb\n Pull-ups\n```' --json
47
+
48
+ # Read full note Markdown, blocks, and recent sessions
49
+ wod note get <noteId> --json
50
+
51
+ # Clone a template note onto a calendar date
52
+ wod note clone <sourceNoteId> --date 2026-11-11 --notebook journal --json
53
+
54
+ # Delete a note (Tier 2 — requires --yes <noteId>, exits 4 if omitted)
55
+ wod note delete <noteId> --yes <noteId> --json
56
+ ```
57
+
58
+ ### 3. Schedule & Inspect the Daily Journal
59
+ ```bash
60
+ # Read scheduled workouts + logged sessions for a date (YYYY-MM-DD or today)
61
+ wod journal day today --json
62
+
63
+ # Schedule a new workout or clone a template onto a date
64
+ wod journal add today --source-note <templateNoteId> --json
65
+ wod journal add 2026-11-12 --title "Morning 5K" --markdown $'```time\n5000m Run :?\n```' --json
66
+ ```
67
+
68
+ ### 4. Manage Notebooks
69
+ ```bash
70
+ wod notebook list --json
71
+ wod notebook save strength-cycle --title "Strength Cycle" --description "8-week squat block" --json
72
+ wod notebook delete strength-cycle --yes strength-cycle --json
73
+ ```
74
+
75
+ ### 5. Execute Headless Sessions & Inspect Ledgers
76
+ ```bash
77
+ # Run a saved note's workout block headlessly and record session + events
78
+ wod session run --note <noteId> --json
79
+ # Equivalent shorthand on legacy verb:
80
+ wod run --note <noteId> --json
81
+
82
+ # List and inspect recorded sessions
83
+ wod session list --limit 10 --json
84
+ wod session get <sessionId> --json
85
+
86
+ # Delete a recorded session (Tier 2 — requires --yes <sessionId>)
87
+ wod session delete <sessionId> --yes <sessionId> --json
88
+ ```
89
+
90
+ ### 6. Catalog & Tag Management
91
+ ```bash
92
+ wod catalog lookup effort --search thruster --json
93
+ wod catalog upsert effort "Dumbbell Snatch" --category weightlifting --tags dumbbell --json
94
+ wod tag list --type equipment --json
95
+ wod tag upsert kettlebell --type equipment --json
96
+ ```
97
+
98
+ ### 7. Feeds & Portability
99
+ ```bash
100
+ wod feed list --json
101
+ wod feed status --json
102
+ wod export note <noteId> -o -
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Exit Codes & Confirmation Safety
108
+
109
+ | Exit Code | Meaning | Agent Recovery Action |
110
+ |---|---|---|
111
+ | `0` | Success | Parse JSON stdout (`{ "ok": true, "tool": "...", "data": ... }`). |
112
+ | `1` | Runtime / IO / Missing Target | Inspect `error` field and verify IDs via `list` / `lookup`. |
113
+ | `2` | Syntax Error (Whiteboard Script or WQL) | Fix script or query syntax using `wod parse --no-save` or `wod query --validate-only`. |
114
+ | `3` | Language Pack Load Error | Check `--pack` module specifier. |
115
+ | `4` | Tier 2 Confirmation Required | Destructive command lacked `--yes <targetId>`. Confirm intent with the user before re-running with `--yes <targetId>`. |
116
+
117
+ ---
118
+
119
+ ## Starting the Official MCP Server
120
+
121
+ - **Stdio (Claude Code / Cursor / Codex)**:
122
+ ```bash
123
+ wod mcp --db ./wodwiki.db
124
+ wod mcp --readonly --db ./wodwiki.db
125
+ ```
126
+ - **HTTP Streamable MCP**:
127
+ `wod server` automatically mounts `/api/mcp` (`POST`, `GET`, `DELETE`) and `/.well-known/agent-capabilities.json`. Set `WOD_MCP_READONLY=1` or `--mcp-readonly` to expose only Tier 0 read-only tools, and `WOD_MCP_TOKEN=<secret>` to require `Authorization: Bearer <secret>`.