@bitcobblers/wod-wiki-tools 0.51.2196 → 0.53.2203
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.
- package/dist/bin/wod.cjs +964 -806
- package/dist/bin/wod.cjs.map +1 -1
- package/dist/bin/wod.mjs +4 -4
- package/dist/{chunk-V23POHG2.mjs → chunk-2EWCEE6N.mjs} +86 -7
- package/dist/chunk-2EWCEE6N.mjs.map +1 -0
- package/dist/{chunk-QE5CK3QT.mjs → chunk-ES4ZZ447.mjs} +3 -3
- package/dist/chunk-ES4ZZ447.mjs.map +1 -0
- package/dist/{chunk-ZUZMRH3G.mjs → chunk-FUISPA7A.mjs} +55 -3
- package/dist/chunk-FUISPA7A.mjs.map +1 -0
- package/dist/chunk-KGP6STLY.mjs +69 -0
- package/dist/chunk-KGP6STLY.mjs.map +1 -0
- package/dist/{chunk-Z2IQPTDI.mjs → chunk-LNBKPHEP.mjs} +6 -5
- package/dist/chunk-LNBKPHEP.mjs.map +1 -0
- package/dist/{chunk-TDYC2FCK.mjs → chunk-LWW4HK4G.mjs} +69 -148
- package/dist/chunk-LWW4HK4G.mjs.map +1 -0
- package/dist/{chunk-L5S7PXAB.mjs → compiler-WNZ455VL.mjs} +152 -105
- package/dist/compiler-WNZ455VL.mjs.map +1 -0
- package/dist/index.cjs +964 -806
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +6 -6
- package/dist/{scaffoldFeed-MROAPAAP.mjs → scaffoldFeed-OS5HGYG4.mjs} +3 -3
- package/dist/{scaffoldFeed-MROAPAAP.mjs.map → scaffoldFeed-OS5HGYG4.mjs.map} +1 -1
- package/dist/server/app.cjs +155 -5
- package/dist/server/app.cjs.map +1 -1
- package/dist/server/app.d.cts +3 -0
- package/dist/server/app.d.ts +3 -0
- package/dist/server/app.mjs +2 -1
- package/dist/server-SHNWCIIM.mjs +11 -0
- package/dist/{server-QK2CXCDJ.mjs.map → server-SHNWCIIM.mjs.map} +1 -1
- package/dist/skills/wod-extraction/SKILL.md +40 -0
- package/dist/web/playground/ai-skills/parse.md +40 -0
- package/dist/web/playground/assets/{feedSync.worker-ftP9nOAl.js → feedSync.worker-O4TGLEj3.js} +7 -7
- package/dist/web/playground/assets/main-BChtcigM.js +1149 -0
- package/dist/web/playground/assets/main-DGz9PHS_.css +2 -0
- package/dist/web/playground/assets/{statementBuilderFlow-CNz2Wkh9.js → statementBuilderFlow-BHGR9gIs.js} +2 -2
- package/dist/web/playground/assets/{vendor-BiwvmytJ.js → vendor-Dz-Azkoq.js} +69 -69
- package/dist/web/{server/assets/vendor-codemirror-B461LMkB.js → playground/assets/vendor-codemirror-B4BeZarI.js} +11 -11
- package/dist/web/playground/index.html +4 -4
- package/dist/web/playground/seed/core/chunks/canvas.28c523ac.json +1 -0
- package/dist/web/playground/seed/core/chunks/dashboards.dc521d4e.json +1 -0
- package/dist/web/playground/seed/core/chunks/{efforts.f2875ac9.json → efforts.cc1d51a5.json} +1 -1
- package/dist/web/playground/seed/core/chunks/{equipment.a56f9b72.json → equipment.3c479de5.json} +1 -1
- package/dist/web/playground/seed/core/indexes/notebooks/canvas.json +181 -181
- package/dist/web/playground/seed/core/indexes/notebooks/dashboards.json +17 -17
- package/dist/web/playground/seed/core/indexes/notebooks/efforts.json +326 -326
- package/dist/web/playground/seed/core/indexes/notebooks/equipment.json +50 -50
- package/dist/web/playground/seed/core/manifest.json +31 -31
- package/dist/web/playground/seed/core/markdown/canvas/ai-first/README.json +1 -1
- package/dist/web/playground/seed/core/markdown/canvas/guide/README.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/guide/clock.json +1 -1
- package/dist/web/playground/seed/core/markdown/canvas/guide/dashboards.json +4 -32
- package/dist/web/playground/seed/core/markdown/canvas/guide/metrics-summaries.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/guide/metrics.json +16 -16
- package/dist/web/playground/seed/core/markdown/canvas/guide/protocols.json +20 -20
- package/dist/web/playground/seed/core/markdown/canvas/guide/sessions.json +33 -33
- package/dist/web/playground/seed/core/markdown/canvas/guide/start.json +11 -11
- package/dist/web/playground/seed/core/markdown/canvas/guide/structure.json +25 -25
- package/dist/web/playground/seed/core/markdown/canvas/guide/wql.json +22 -22
- package/dist/web/playground/seed/core/markdown/canvas/home/sample-script.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/home/welcome-1.json +2 -2
- package/dist/web/playground/seed/core/markdown/canvas/syntax/actions-comments.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/alternating-emom.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/basic-emom.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/calculated-metrics.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/classic-amrap.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-barbell-cycling.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-full-session.json +10 -10
- package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-nested-protocols.json +7 -7
- package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-partner-workout.json +7 -7
- package/dist/web/playground/seed/core/markdown/canvas/syntax/complex-swimming.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/core-rules.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-and-calculated-metrics.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-intervals.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-1.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-2.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-3.json +3 -3
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-4.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/custom-metrics-5.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-climb-bouldering.json +2 -2
- package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-climb-hangboard.json +2 -2
- package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-climb-sport.json +2 -2
- package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-log.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-plan.json +8 -8
- package/dist/web/playground/seed/core/markdown/canvas/syntax/dialect-wod.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/distance-intervals.json +3 -3
- package/dist/web/playground/seed/core/markdown/canvas/syntax/document-1.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/document-2.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/document-3.json +10 -10
- package/dist/web/playground/seed/core/markdown/canvas/syntax/document-4.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/effort-notes.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/frontmatter-summaries.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-1.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-2.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-3.json +3 -3
- package/dist/web/playground/seed/core/markdown/canvas/syntax/groups-4.json +3 -3
- package/dist/web/playground/seed/core/markdown/canvas/syntax/longer-duration.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/longer-intervals.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/measurements.json +7 -7
- package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-1.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-2.json +7 -7
- package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-3.json +8 -8
- package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-4.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/metrics-5.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/mixed-sections.json +10 -10
- package/dist/web/playground/seed/core/markdown/canvas/syntax/mixed-timers.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/multiple-amrap-windows.json +7 -7
- package/dist/web/playground/seed/core/markdown/canvas/syntax/multiple-sets.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/named-groups.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-1.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-2.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-3.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-4.json +3 -3
- package/dist/web/playground/seed/core/markdown/canvas/syntax/protocols-5.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/single-movement.json +3 -3
- package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-1.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-2.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-3.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/supplemental-4.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/time-cap.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timer-modifiers.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-1.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-2.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-3.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-4.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-5.json +5 -5
- package/dist/web/playground/seed/core/markdown/canvas/syntax/timers-rest.json +4 -4
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/aggregate-by-effort.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/aggregate-by-week.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/content-fran.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/filter-combos.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/pipes-limit.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/session-rpe.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/source-journal.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/tis-trend.json +6 -6
- package/dist/web/playground/seed/core/markdown/canvas/wql-presets/where-join.json +6 -6
- package/dist/web/playground/seed/core/markdown/dashboards/benchmark-pr-board.json +32 -32
- package/dist/web/playground/seed/core/markdown/dashboards/finger-strength-v8.json +26 -26
- package/dist/web/playground/seed/core/markdown/dashboards/polarized-base-marathon.json +50 -50
- package/dist/web/playground/seed/core/markdown/dashboards/recovery-readiness.json +38 -38
- package/dist/web/playground/seed/core/markdown/dashboards/road-to-560-total.json +50 -50
- package/dist/web/playground/seed/core/markdown/dashboards/training-block-review.json +62 -62
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/air-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/box-jump.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/broad-jump.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/burpee-box-jump-over.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/burpee-over-dumbbell.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/burpee.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/dumbbell-squat-clean.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/ghd-sit-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/ground-kong.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/jumping-jack.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/kong-walk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/lunge.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/overhead-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/parkour-roll.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/parkour-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/pistol-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/plank.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/precision-burpee.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/precision-jump.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/quadrupedal-movement.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/russian-twist.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/sit-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/squat-clean.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/squat-hold.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/squat-snatch.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/tuck-jump.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/wall-ball.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/bodyweight/wall-burpee.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/cycling/assault-bike.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/cycling/cycling-moderate.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/cycling/cycling-vigorous.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/assisted-pull-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/burpee-pull-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/chest-to-bar-pull-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/dip.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/double-under.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/handstand-hold.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/handstand-push-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/handstand-walk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/jump-rope.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/jumping-pull-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/jumping-push-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/l-sit-pull-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/muscle-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/pull-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/push-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/reverse-wall-dip.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/rope-climb.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/gymnastics/toes-to-bar.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-arm-bar.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-around-the-world.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-bent-over-row.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-jerk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-clean.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-deadlift.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-floor-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-front-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-goblet-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-gorilla-row.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-halo.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-jerk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-overhead-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-snatch.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-swing.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/kettlebell-windmill.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/kettlebell/turkish-get-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/recovery/rest.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/recovery/stretching.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/rowing/rowing-sprint.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/rowing/rowing.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/rowing/ski-erg.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/running/backward-running.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/running/running-6-mph.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/running/running-8-mph.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/running/running-sprint.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/snatch.json +2 -2
- package/dist/web/playground/seed/core/markdown/efforts/strength/back-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/bench-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/box-step-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/carioca.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/clean-and-jerk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/cluster.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dead-hang.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/deadlift.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/devils-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-box-step-up.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-clean.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-fly.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-row.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-snatch.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/dumbbell-thruster.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/elbows-to-knees.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/farmer-carry.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/frog-stand.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/front-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/good-morning.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/hanging-leg-raise.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/hollow-rock.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/knees-to-elbows.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/l-sit.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/man-maker.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/medicine-ball-clean.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/overhead-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/parkour-vault.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/pig-flip.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/power-clean.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/power-snatch.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/push-jerk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/push-press.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/romanian-deadlift.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/single-leg-deadlift.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/skull-crusher.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/slam-ball.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/sled-pull.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/sled-push.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/sumo-deadlift.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/thruster.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/triceps-extension.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/v-sit-hold.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/wall-walk.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/strength/yoga-sun-salutation.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-assisted-sprint.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-backstroke.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-breaststroke-kick.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-breaststroke.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-butterfly.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-catch-up-drill.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-choice-stroke.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-dive-start.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-dolphin-kick.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-drafting.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-fingertip-drag.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-freestyle.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-individual-medley.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-kick.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-pull.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-resisted-sprint.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-rotation-drill.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-sighting.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-single-arm-drill.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-stroke-transition.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-two-kick-one-pull.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming-vigorous.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/swimming/swimming.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-arm-cast.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-circles.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-mill.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-reverse-mill.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/clubbell-shield-cast.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-10-to-2-swing.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-360-swing.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-barbarian-squat.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-flow.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-gravedigger.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/macebell-touchdown.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-carry.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-extension.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/unconventional/sandbag-over-shoulder.json +1 -1
- package/dist/web/playground/seed/core/markdown/efforts/walking/walking-3-mph.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/air-bike.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/barbell.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/bench.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/bike-erg.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/climbing-rope.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/clubs.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/dumbbell.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/ghd.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/gymnastic-rings.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/jump-rope.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/kettlebell.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/macebell.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/medicine-ball.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/parallettes.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/plyo-box.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/pull-up-bar.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/rower.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/sandbag.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/ski-erg.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/slam-ball.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/sled.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/sledgehammer.json +1 -1
- package/dist/web/playground/seed/core/markdown/equipment/weight-vest.json +1 -1
- package/dist/web/playground/seed/core/report.html +14 -14
- package/dist/web/server/ai-skills/parse.md +40 -0
- package/dist/web/server/assets/{feedSync.worker-ftP9nOAl.js → feedSync.worker-O4TGLEj3.js} +7 -7
- package/dist/web/server/assets/main-BT4Llg8k.js +1149 -0
- package/dist/web/server/assets/main-DGz9PHS_.css +2 -0
- package/dist/web/server/assets/{statementBuilderFlow-BgrBt6FL.js → statementBuilderFlow-C7ob6Wnu.js} +2 -2
- package/dist/web/server/assets/{vendor-BiwvmytJ.js → vendor-Dz-Azkoq.js} +69 -69
- package/dist/web/{playground/assets/vendor-codemirror-B461LMkB.js → server/assets/vendor-codemirror-B4BeZarI.js} +11 -11
- package/dist/web/server/index.html +4 -4
- package/dist/web/server/seed/core/chunks/canvas.28c523ac.json +1 -0
- package/dist/web/server/seed/core/chunks/dashboards.dc521d4e.json +1 -0
- package/dist/web/server/seed/core/chunks/{efforts.f2875ac9.json → efforts.cc1d51a5.json} +1 -1
- package/dist/web/server/seed/core/chunks/{equipment.a56f9b72.json → equipment.3c479de5.json} +1 -1
- package/dist/web/server/seed/core/indexes/notebooks/canvas.json +181 -181
- package/dist/web/server/seed/core/indexes/notebooks/dashboards.json +17 -17
- package/dist/web/server/seed/core/indexes/notebooks/efforts.json +326 -326
- package/dist/web/server/seed/core/indexes/notebooks/equipment.json +50 -50
- package/dist/web/server/seed/core/manifest.json +31 -31
- package/dist/web/server/seed/core/markdown/canvas/ai-first/README.json +1 -1
- package/dist/web/server/seed/core/markdown/canvas/guide/README.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/guide/clock.json +1 -1
- package/dist/web/server/seed/core/markdown/canvas/guide/dashboards.json +4 -32
- package/dist/web/server/seed/core/markdown/canvas/guide/metrics-summaries.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/guide/metrics.json +16 -16
- package/dist/web/server/seed/core/markdown/canvas/guide/protocols.json +20 -20
- package/dist/web/server/seed/core/markdown/canvas/guide/sessions.json +33 -33
- package/dist/web/server/seed/core/markdown/canvas/guide/start.json +11 -11
- package/dist/web/server/seed/core/markdown/canvas/guide/structure.json +25 -25
- package/dist/web/server/seed/core/markdown/canvas/guide/wql.json +22 -22
- package/dist/web/server/seed/core/markdown/canvas/home/sample-script.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/home/welcome-1.json +2 -2
- package/dist/web/server/seed/core/markdown/canvas/syntax/actions-comments.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/alternating-emom.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/basic-emom.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/calculated-metrics.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/classic-amrap.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/complex-barbell-cycling.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/complex-full-session.json +10 -10
- package/dist/web/server/seed/core/markdown/canvas/syntax/complex-nested-protocols.json +7 -7
- package/dist/web/server/seed/core/markdown/canvas/syntax/complex-partner-workout.json +7 -7
- package/dist/web/server/seed/core/markdown/canvas/syntax/complex-swimming.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/core-rules.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-and-calculated-metrics.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-intervals.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-1.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-2.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-3.json +3 -3
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-4.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/custom-metrics-5.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-climb-bouldering.json +2 -2
- package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-climb-hangboard.json +2 -2
- package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-climb-sport.json +2 -2
- package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-log.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-plan.json +8 -8
- package/dist/web/server/seed/core/markdown/canvas/syntax/dialect-wod.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/distance-intervals.json +3 -3
- package/dist/web/server/seed/core/markdown/canvas/syntax/document-1.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/document-2.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/document-3.json +10 -10
- package/dist/web/server/seed/core/markdown/canvas/syntax/document-4.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/effort-notes.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/frontmatter-summaries.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/groups-1.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/groups-2.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/groups-3.json +3 -3
- package/dist/web/server/seed/core/markdown/canvas/syntax/groups-4.json +3 -3
- package/dist/web/server/seed/core/markdown/canvas/syntax/longer-duration.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/longer-intervals.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/measurements.json +7 -7
- package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-1.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-2.json +7 -7
- package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-3.json +8 -8
- package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-4.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/metrics-5.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/mixed-sections.json +10 -10
- package/dist/web/server/seed/core/markdown/canvas/syntax/mixed-timers.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/multiple-amrap-windows.json +7 -7
- package/dist/web/server/seed/core/markdown/canvas/syntax/multiple-sets.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/named-groups.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-1.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-2.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-3.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-4.json +3 -3
- package/dist/web/server/seed/core/markdown/canvas/syntax/protocols-5.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/single-movement.json +3 -3
- package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-1.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-2.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-3.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/supplemental-4.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/time-cap.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/timer-modifiers.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/timers-1.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/syntax/timers-2.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/timers-3.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/timers-4.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/syntax/timers-5.json +5 -5
- package/dist/web/server/seed/core/markdown/canvas/syntax/timers-rest.json +4 -4
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/aggregate-by-effort.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/aggregate-by-week.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/content-fran.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/filter-combos.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/pipes-limit.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/session-rpe.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/source-journal.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/tis-trend.json +6 -6
- package/dist/web/server/seed/core/markdown/canvas/wql-presets/where-join.json +6 -6
- package/dist/web/server/seed/core/markdown/dashboards/benchmark-pr-board.json +32 -32
- package/dist/web/server/seed/core/markdown/dashboards/finger-strength-v8.json +26 -26
- package/dist/web/server/seed/core/markdown/dashboards/polarized-base-marathon.json +50 -50
- package/dist/web/server/seed/core/markdown/dashboards/recovery-readiness.json +38 -38
- package/dist/web/server/seed/core/markdown/dashboards/road-to-560-total.json +50 -50
- package/dist/web/server/seed/core/markdown/dashboards/training-block-review.json +62 -62
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/air-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/box-jump.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/broad-jump.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/burpee-box-jump-over.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/burpee-over-dumbbell.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/burpee.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/dumbbell-squat-clean.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/ghd-sit-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/ground-kong.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/jumping-jack.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/kong-walk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/lunge.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/overhead-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/parkour-roll.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/parkour-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/pistol-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/plank.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/precision-burpee.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/precision-jump.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/quadrupedal-movement.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/russian-twist.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/sit-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/squat-clean.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/squat-hold.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/squat-snatch.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/tuck-jump.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/wall-ball.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/bodyweight/wall-burpee.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/cycling/assault-bike.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/cycling/cycling-moderate.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/cycling/cycling-vigorous.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/assisted-pull-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/burpee-pull-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/chest-to-bar-pull-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/dip.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/double-under.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/handstand-hold.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/handstand-push-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/handstand-walk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/jump-rope.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/jumping-pull-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/jumping-push-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/l-sit-pull-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/muscle-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/pull-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/push-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/reverse-wall-dip.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/rope-climb.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/gymnastics/toes-to-bar.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-arm-bar.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-around-the-world.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-bent-over-row.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-jerk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-clean-and-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-clean.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-deadlift.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-floor-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-front-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-goblet-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-gorilla-row.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-halo.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-jerk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-overhead-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-snatch.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-swing.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/kettlebell-windmill.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/kettlebell/turkish-get-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/recovery/rest.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/recovery/stretching.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/rowing/rowing-sprint.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/rowing/rowing.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/rowing/ski-erg.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/running/backward-running.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/running/running-6-mph.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/running/running-8-mph.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/running/running-sprint.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/snatch.json +2 -2
- package/dist/web/server/seed/core/markdown/efforts/strength/back-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/bench-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/box-step-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/carioca.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/clean-and-jerk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/cluster.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dead-hang.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/deadlift.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/devils-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-box-step-up.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-clean.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-fly.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-row.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-snatch.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/dumbbell-thruster.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/elbows-to-knees.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/farmer-carry.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/frog-stand.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/front-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/good-morning.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/hanging-leg-raise.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/hollow-rock.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/knees-to-elbows.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/l-sit.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/man-maker.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/medicine-ball-clean.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/overhead-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/parkour-vault.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/pig-flip.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/power-clean.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/power-snatch.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/push-jerk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/push-press.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/romanian-deadlift.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/single-leg-deadlift.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/skull-crusher.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/slam-ball.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/sled-pull.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/sled-push.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/sumo-deadlift.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/thruster.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/triceps-extension.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/v-sit-hold.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/wall-walk.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/strength/yoga-sun-salutation.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-assisted-sprint.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-backstroke.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-breaststroke-kick.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-breaststroke.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-butterfly.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-catch-up-drill.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-choice-stroke.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-dive-start.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-dolphin-kick.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-drafting.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-fingertip-drag.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-freestyle.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-individual-medley.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-kick.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-pull.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-resisted-sprint.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-rotation-drill.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-sighting.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-single-arm-drill.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-stroke-transition.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-two-kick-one-pull.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming-vigorous.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/swimming/swimming.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-arm-cast.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-circles.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-mill.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-reverse-mill.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/clubbell-shield-cast.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-10-to-2-swing.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-360-swing.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-barbarian-squat.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-flow.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-gravedigger.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/macebell-touchdown.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-carry.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/sandbag-bear-hug-extension.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/unconventional/sandbag-over-shoulder.json +1 -1
- package/dist/web/server/seed/core/markdown/efforts/walking/walking-3-mph.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/air-bike.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/barbell.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/bench.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/bike-erg.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/climbing-rope.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/clubs.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/dumbbell.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/ghd.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/gymnastic-rings.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/jump-rope.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/kettlebell.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/macebell.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/medicine-ball.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/parallettes.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/plyo-box.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/pull-up-bar.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/rower.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/sandbag.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/ski-erg.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/slam-ball.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/sled.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/sledgehammer.json +1 -1
- package/dist/web/server/seed/core/markdown/equipment/weight-vest.json +1 -1
- package/dist/web/server/seed/core/report.html +14 -14
- package/package.json +6 -6
- package/dist/chunk-L5S7PXAB.mjs.map +0 -1
- package/dist/chunk-QE5CK3QT.mjs.map +0 -1
- package/dist/chunk-TDYC2FCK.mjs.map +0 -1
- package/dist/chunk-V23POHG2.mjs.map +0 -1
- package/dist/chunk-Z2IQPTDI.mjs.map +0 -1
- package/dist/chunk-ZUZMRH3G.mjs.map +0 -1
- package/dist/compiler-TOM2S2RL.mjs +0 -9
- package/dist/compiler-TOM2S2RL.mjs.map +0 -1
- package/dist/server-QK2CXCDJ.mjs +0 -11
- package/dist/web/playground/assets/main-Dq1wHl4y.css +0 -2
- package/dist/web/playground/assets/main-lF0MJ7yl.js +0 -499
- package/dist/web/playground/seed/core/chunks/canvas.499930d3.json +0 -1
- package/dist/web/playground/seed/core/chunks/dashboards.91cae756.json +0 -1
- package/dist/web/server/assets/main-4y8Q5pTh.js +0 -499
- package/dist/web/server/assets/main-Dq1wHl4y.css +0 -2
- package/dist/web/server/seed/core/chunks/canvas.499930d3.json +0 -1
- package/dist/web/server/seed/core/chunks/dashboards.91cae756.json +0 -1
package/dist/index.cjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var wodWikiLang = require('@bitcobblers/wod-wiki-lang');
|
|
4
4
|
var wod_wiki_engine_star = require('@bitcobblers/wod-wiki-engine');
|
|
5
|
-
var child_process = require('child_process');
|
|
6
5
|
var fs = require('fs');
|
|
7
6
|
var path = require('path');
|
|
7
|
+
var child_process = require('child_process');
|
|
8
8
|
var wodWikiCore = require('@bitcobblers/wod-wiki-core');
|
|
9
9
|
var wodWikiWql = require('@bitcobblers/wod-wiki-wql');
|
|
10
10
|
var crypto = require('crypto');
|
|
@@ -315,82 +315,60 @@ var init_db = __esm({
|
|
|
315
315
|
CLI_UUID_NAMESPACE = "c0ffee00-8b1a-4e2c-9d3f-5a6b7c8d9e0f";
|
|
316
316
|
}
|
|
317
317
|
});
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
function resolveGitVersion(repoRoot) {
|
|
373
|
-
try {
|
|
374
|
-
const run = (args) => child_process.execSync(`git ${args}`, { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
375
|
-
const count = Number(run("rev-list --count HEAD"));
|
|
376
|
-
return {
|
|
377
|
-
version: Number.isFinite(count) && count > 0 ? count : 0,
|
|
378
|
-
versionLabel: run("describe --tags --long --always --dirty"),
|
|
379
|
-
commit: run("rev-parse HEAD"),
|
|
380
|
-
dirty: run("status --porcelain") !== ""
|
|
381
|
-
};
|
|
382
|
-
} catch {
|
|
383
|
-
return UNKNOWN_GIT_VERSION;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
var UNKNOWN_GIT_VERSION;
|
|
387
|
-
var init_git_version = __esm({
|
|
388
|
-
"src/seedbuild/git-version.ts"() {
|
|
389
|
-
UNKNOWN_GIT_VERSION = {
|
|
390
|
-
version: 0,
|
|
391
|
-
versionLabel: "unknown",
|
|
392
|
-
commit: "",
|
|
393
|
-
dirty: false
|
|
318
|
+
var NodeFsFeedTree;
|
|
319
|
+
var init_nodeFeedTree = __esm({
|
|
320
|
+
"src/cli/nodeFeedTree.ts"() {
|
|
321
|
+
init_db();
|
|
322
|
+
NodeFsFeedTree = class {
|
|
323
|
+
rootDir;
|
|
324
|
+
constructor(rootDir) {
|
|
325
|
+
this.rootDir = nodePath().resolve(rootDir);
|
|
326
|
+
}
|
|
327
|
+
get root() {
|
|
328
|
+
return this.rootDir;
|
|
329
|
+
}
|
|
330
|
+
absPath(relPath) {
|
|
331
|
+
const clean = wod_wiki_engine_star.normalizeFeedTreePath(relPath);
|
|
332
|
+
const resolved = nodePath().resolve(this.rootDir, clean);
|
|
333
|
+
if (resolved !== this.rootDir && !resolved.startsWith(this.rootDir + "/") && !resolved.startsWith(this.rootDir + "\\")) {
|
|
334
|
+
throw new wod_wiki_engine_star.FeedTreeError("layout", `Path '${relPath}' escapes root '${this.rootDir}'`);
|
|
335
|
+
}
|
|
336
|
+
return resolved;
|
|
337
|
+
}
|
|
338
|
+
async read(path) {
|
|
339
|
+
const abs = this.absPath(path);
|
|
340
|
+
const fs = nodeFs();
|
|
341
|
+
if (!fs.existsSync(abs)) {
|
|
342
|
+
throw new wod_wiki_engine_star.FeedTreeError("not-found", `File not found: ${path}`);
|
|
343
|
+
}
|
|
344
|
+
return new Uint8Array(fs.readFileSync(abs));
|
|
345
|
+
}
|
|
346
|
+
async stat(path) {
|
|
347
|
+
try {
|
|
348
|
+
const bytes = await this.read(path);
|
|
349
|
+
return {
|
|
350
|
+
bytes: bytes.byteLength,
|
|
351
|
+
sha256: await wod_wiki_engine_star.sha256HexAsync(bytes)
|
|
352
|
+
};
|
|
353
|
+
} catch (err) {
|
|
354
|
+
if (err instanceof wod_wiki_engine_star.FeedTreeError && err.code === "not-found") return void 0;
|
|
355
|
+
throw err;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
async write(path, bytes) {
|
|
359
|
+
const abs = this.absPath(path);
|
|
360
|
+
const p = nodePath();
|
|
361
|
+
const fs = nodeFs();
|
|
362
|
+
fs.mkdirSync(p.dirname(abs), { recursive: true });
|
|
363
|
+
fs.writeFileSync(abs, bytes);
|
|
364
|
+
}
|
|
365
|
+
async delete(path) {
|
|
366
|
+
const abs = this.absPath(path);
|
|
367
|
+
const fs = nodeFs();
|
|
368
|
+
if (fs.existsSync(abs)) {
|
|
369
|
+
fs.unlinkSync(abs);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
394
372
|
};
|
|
395
373
|
}
|
|
396
374
|
});
|
|
@@ -456,188 +434,609 @@ var init_report = __esm({
|
|
|
456
434
|
"src/seedbuild/report.ts"() {
|
|
457
435
|
}
|
|
458
436
|
});
|
|
459
|
-
var init_frontmatter = __esm({
|
|
460
|
-
"src/seedbuild/frontmatter.ts"() {
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
437
|
|
|
464
|
-
// src/
|
|
465
|
-
var
|
|
466
|
-
var
|
|
467
|
-
"src/
|
|
468
|
-
|
|
438
|
+
// src/version.ts
|
|
439
|
+
var VERSION;
|
|
440
|
+
var init_version = __esm({
|
|
441
|
+
"src/version.ts"() {
|
|
442
|
+
VERSION = "0.53.2203";
|
|
469
443
|
}
|
|
470
444
|
});
|
|
471
445
|
|
|
472
|
-
// src/
|
|
473
|
-
var
|
|
474
|
-
__export(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
buildBlockIndexRows: () => buildBlockIndexRows,
|
|
478
|
-
chunkIdFor: () => chunkIdFor,
|
|
479
|
-
collectCorpusMarkdown: () => collectCorpusMarkdown,
|
|
480
|
-
compileSeedRow: () => compileSeedRow,
|
|
481
|
-
dateKeyToCreatedAt: () => dateKeyToCreatedAt,
|
|
482
|
-
discoverUncatalogedEfforts: () => discoverUncatalogedEfforts,
|
|
483
|
-
frontmatterDateToCreatedAt: () => frontmatterDateToCreatedAt,
|
|
484
|
-
generateSeed: () => generateSeed,
|
|
485
|
-
getFileCommit: () => getFileCommit,
|
|
486
|
-
getFileVersion: () => getFileVersion,
|
|
487
|
-
getPathCommit: () => getPathCommit,
|
|
488
|
-
getPathUpdatedAt: () => getPathUpdatedAt,
|
|
489
|
-
getPathVersion: () => getPathVersion,
|
|
490
|
-
groupCorpusPath: () => groupCorpusPath,
|
|
491
|
-
loadCorpusReferenceCatalog: () => loadCorpusReferenceCatalog,
|
|
492
|
-
partitionIntoChunks: () => partitionIntoChunks,
|
|
493
|
-
scaffoldDiscoveredEfforts: () => scaffoldDiscoveredEfforts,
|
|
494
|
-
seedNoteIdSync: () => seedNoteIdSync,
|
|
495
|
-
validateDashboardNote: () => validateDashboardNote,
|
|
496
|
-
validateWodBlockSyntax: () => validateWodBlockSyntax
|
|
446
|
+
// src/cli/scaffoldFeed.ts
|
|
447
|
+
var scaffoldFeed_exports = {};
|
|
448
|
+
__export(scaffoldFeed_exports, {
|
|
449
|
+
scaffoldFeed: () => scaffoldFeed,
|
|
450
|
+
validateFeedName: () => validateFeedName
|
|
497
451
|
});
|
|
498
|
-
function
|
|
499
|
-
if (
|
|
500
|
-
|
|
501
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
502
|
-
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
503
|
-
if (entry.isDirectory()) out.push(...listMarkdownFiles(path.join(dir, entry.name), rel));
|
|
504
|
-
else if (entry.isFile() && entry.name.endsWith(".md")) out.push(rel);
|
|
452
|
+
function validateFeedName(name) {
|
|
453
|
+
if (name.length === 0 || name === "." || name === "..") {
|
|
454
|
+
throw new Error("Feed name must be a single non-empty directory name");
|
|
505
455
|
}
|
|
506
|
-
|
|
507
|
-
}
|
|
508
|
-
function chunkIdFor(relPath) {
|
|
509
|
-
const parts = relPath.split("/");
|
|
510
|
-
if (parts[0] !== "markdown" || parts.length < 2) return null;
|
|
511
|
-
const corpus = parts[1];
|
|
512
|
-
if (parts.length === 2) return null;
|
|
513
|
-
const slug = parts[2]?.replace(/\.md$/, "");
|
|
514
|
-
switch (corpus) {
|
|
515
|
-
case "canvas":
|
|
516
|
-
case "dashboards":
|
|
517
|
-
case "efforts":
|
|
518
|
-
case "equipment":
|
|
519
|
-
return corpus;
|
|
520
|
-
case "notebooks":
|
|
521
|
-
return parts.length === 3 ? `notebook._root` : `notebook.${slug}`;
|
|
522
|
-
default:
|
|
523
|
-
return null;
|
|
456
|
+
if (name.includes("/") || name.includes("\\") || name.includes("\0")) {
|
|
457
|
+
throw new Error(`Invalid feed name '${name}': must be a single directory name (no path separators or traversal)`);
|
|
524
458
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
const excluded = new Set(excludePaths);
|
|
528
|
-
return listMarkdownFiles(markdownDir).map((p) => `markdown/${p}`).filter((path) => !excluded.has(path));
|
|
529
|
-
}
|
|
530
|
-
function partitionIntoChunks(paths) {
|
|
531
|
-
const byId = /* @__PURE__ */ new Map();
|
|
532
|
-
for (const p of paths) {
|
|
533
|
-
const id = chunkIdFor(p);
|
|
534
|
-
if (id === null) {
|
|
535
|
-
throw new Error(
|
|
536
|
-
`[generate-seed] Parity failure: '${p}' is not part of any known corpus (canvas | dashboards | efforts | equipment | notebooks). Extend chunkIdFor() if this is a new corpus.`
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
const list = byId.get(id);
|
|
540
|
-
if (list) list.push(p);
|
|
541
|
-
else byId.set(id, [p]);
|
|
459
|
+
if (/^(?:[A-Za-z]:)?[/\\]/.test(name)) {
|
|
460
|
+
throw new Error(`Invalid feed name '${name}': absolute paths are not allowed`);
|
|
542
461
|
}
|
|
543
|
-
|
|
462
|
+
if (name.length > 214 || !/^[a-z0-9][a-z0-9._-]*$/.test(name)) {
|
|
463
|
+
throw new Error(
|
|
464
|
+
`Invalid feed name '${name}': must be a valid npm package name (lowercase letters, digits, dots, hyphens, underscores; no leading dot/hyphen)`
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
return name;
|
|
544
468
|
}
|
|
545
|
-
function
|
|
546
|
-
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const declared = new Set(doc.tokens.map((t) => t.name));
|
|
554
|
-
for (const widget of doc.widgets) {
|
|
555
|
-
const where = `widget '${widget.title ?? widget.body.slice(0, 40)}'`;
|
|
556
|
-
if (widget.title === void 0) problems.push(`${where}: missing title`);
|
|
557
|
-
if (!wodWikiWql.isDashboardWidgetType(wodWikiWql.resolveWidgetType(widget.type))) {
|
|
558
|
-
problems.push(`${where}: unknown widget type '${widget.type}'`);
|
|
469
|
+
function scaffoldFeed(name, opts = {}) {
|
|
470
|
+
validateFeedName(name);
|
|
471
|
+
const dir = path.resolve(opts.cwd ?? process.cwd(), name);
|
|
472
|
+
try {
|
|
473
|
+
fs.mkdirSync(dir);
|
|
474
|
+
} catch (error) {
|
|
475
|
+
if (error.code === "EEXIST") {
|
|
476
|
+
throw new Error(`Refusing to overwrite '${dir}': destination already exists`, { cause: error });
|
|
559
477
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
478
|
+
throw error;
|
|
479
|
+
}
|
|
480
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
481
|
+
const files = [
|
|
482
|
+
["package.json", `${JSON.stringify(
|
|
483
|
+
{
|
|
484
|
+
name,
|
|
485
|
+
version: "0.1.0",
|
|
486
|
+
private: true,
|
|
487
|
+
type: "module",
|
|
488
|
+
description: `WOD Wiki workout feed: ${name}`,
|
|
489
|
+
scripts: {
|
|
490
|
+
build: "wod build . --output dist"
|
|
491
|
+
},
|
|
492
|
+
devDependencies: {
|
|
493
|
+
"@bitcobblers/wod-wiki-tools": `^${VERSION}`
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
null,
|
|
497
|
+
2
|
|
498
|
+
)}
|
|
499
|
+
`],
|
|
500
|
+
[".gitignore", "node_modules/\ndist/\n"],
|
|
501
|
+
[".github/workflows/publish-feed.yml", publishWorkflow()],
|
|
502
|
+
["markdown/notebooks/example/README.md", feedReadme(name)],
|
|
503
|
+
[`markdown/notebooks/example/morning-session.md`, exampleWorkout(date)],
|
|
504
|
+
["README.md", repoReadme(name)]
|
|
505
|
+
];
|
|
506
|
+
try {
|
|
507
|
+
for (const [rel, content] of files) {
|
|
508
|
+
const target = path.join(dir, rel);
|
|
509
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
510
|
+
fs.writeFileSync(target, content, "utf-8");
|
|
567
511
|
}
|
|
512
|
+
} catch (error) {
|
|
513
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
514
|
+
throw error;
|
|
568
515
|
}
|
|
569
|
-
return
|
|
516
|
+
return { dir, files: files.map(([rel]) => rel) };
|
|
570
517
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
518
|
+
var publishWorkflow, feedReadme, exampleWorkout, repoReadme;
|
|
519
|
+
var init_scaffoldFeed = __esm({
|
|
520
|
+
"src/cli/scaffoldFeed.ts"() {
|
|
521
|
+
init_version();
|
|
522
|
+
publishWorkflow = () => `name: Publish feed
|
|
523
|
+
|
|
524
|
+
# Compile the feed with the wod CLI and deploy dist/ to GitHub Pages.
|
|
525
|
+
# Requires Pages enabled: repo Settings \u2192 Pages \u2192 Source: "GitHub Actions".
|
|
526
|
+
|
|
527
|
+
on:
|
|
528
|
+
push:
|
|
529
|
+
branches: [main]
|
|
530
|
+
workflow_dispatch:
|
|
531
|
+
|
|
532
|
+
permissions:
|
|
533
|
+
contents: read
|
|
534
|
+
pages: write
|
|
535
|
+
id-token: write
|
|
536
|
+
|
|
537
|
+
concurrency:
|
|
538
|
+
group: pages
|
|
539
|
+
cancel-in-progress: true
|
|
540
|
+
|
|
541
|
+
jobs:
|
|
542
|
+
publish:
|
|
543
|
+
runs-on: ubuntu-latest
|
|
544
|
+
environment:
|
|
545
|
+
name: github-pages
|
|
546
|
+
url: \${{ steps.deployment.outputs.page_url }}
|
|
547
|
+
steps:
|
|
548
|
+
- uses: actions/checkout@v4
|
|
549
|
+
with:
|
|
550
|
+
# Full history: seed manifest version stamps derive from git commit count.
|
|
551
|
+
fetch-depth: 0
|
|
552
|
+
|
|
553
|
+
- name: Set up Bun
|
|
554
|
+
uses: oven-sh/setup-bun@v2
|
|
555
|
+
with:
|
|
556
|
+
bun-version: 1.4.x
|
|
557
|
+
|
|
558
|
+
- name: Install dependencies
|
|
559
|
+
run: bun install
|
|
560
|
+
|
|
561
|
+
- name: Build seed
|
|
562
|
+
run: bunx wod build . --output dist
|
|
563
|
+
|
|
564
|
+
- uses: actions/configure-pages@v5
|
|
565
|
+
|
|
566
|
+
- name: Upload dist
|
|
567
|
+
uses: actions/upload-pages-artifact@v3
|
|
568
|
+
with:
|
|
569
|
+
path: dist
|
|
570
|
+
|
|
571
|
+
- id: deployment
|
|
572
|
+
uses: actions/deploy-pages@v4
|
|
573
|
+
`;
|
|
574
|
+
feedReadme = (name) => `# ${name}
|
|
575
|
+
|
|
576
|
+
Example benchmark notebook. Each \`.md\` file in this directory becomes part of
|
|
577
|
+
the \`example\` notebook chunk; \`README.md\` is the notebook's landing page.
|
|
578
|
+
|
|
579
|
+
Add one file per workout:
|
|
580
|
+
|
|
581
|
+
\`\`\`\`markdown
|
|
582
|
+
---
|
|
583
|
+
title: My workout
|
|
584
|
+
date: 2026-01-01
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
# My workout
|
|
588
|
+
|
|
589
|
+
\`\`\`time
|
|
590
|
+
(21-15-9)
|
|
591
|
+
Thrusters @95lb
|
|
592
|
+
Pull-ups
|
|
593
|
+
\`\`\`
|
|
594
|
+
\`\`\`\`
|
|
595
|
+
|
|
596
|
+
The \`date:\` frontmatter field sets the workout's chronological placement
|
|
597
|
+
(regardless of filename or directory).
|
|
598
|
+
`;
|
|
599
|
+
exampleWorkout = (date) => `---
|
|
600
|
+
title: Morning session
|
|
601
|
+
date: ${date}
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
# Morning session
|
|
605
|
+
|
|
606
|
+
\`\`\`time
|
|
607
|
+
(21-15-9)
|
|
608
|
+
Thrusters @95lb
|
|
609
|
+
Pull-ups
|
|
610
|
+
\`\`\`
|
|
611
|
+
`;
|
|
612
|
+
repoReadme = (name) => `# ${name}
|
|
613
|
+
|
|
614
|
+
A [WOD Wiki](https://github.com/bitcobblers/wod-wiki) workout feed: plain
|
|
615
|
+
Markdown workouts compiled to static, version-stamped seed chunks and published
|
|
616
|
+
via GitHub Pages.
|
|
617
|
+
|
|
618
|
+
## Develop
|
|
619
|
+
|
|
620
|
+
\`\`\`sh
|
|
621
|
+
bun install
|
|
622
|
+
bunx wod build . --output dist
|
|
623
|
+
\`\`\`
|
|
624
|
+
|
|
625
|
+
Workouts live under \`markdown/\` \u2014 this scaffold starts with one example
|
|
626
|
+
feed. Validate everything with \`bunx wod build\`: it gates every file on
|
|
627
|
+
the Whiteboard grammar and corpus layout before writing \`dist/\`.
|
|
628
|
+
|
|
629
|
+
## Publish
|
|
630
|
+
|
|
631
|
+
Push to GitHub and enable Pages (**Settings \u2192 Pages \u2192 Source: GitHub
|
|
632
|
+
Actions**). The bundled workflow (\`.github/workflows/publish-feed.yml\`)
|
|
633
|
+
builds the feed on every push to \`main\` and deploys \`dist/\`.
|
|
634
|
+
|
|
635
|
+
## Share
|
|
636
|
+
|
|
637
|
+
Once published, anyone can subscribe to this feed from a WOD Wiki instance
|
|
638
|
+
at:
|
|
639
|
+
|
|
640
|
+
\`\`\`
|
|
641
|
+
<app-url>/subscribe?source=<url-encoded published feed URL>
|
|
642
|
+
\`\`\`
|
|
643
|
+
|
|
644
|
+
For \`owner\`/\`repo\` on GitHub Pages the feed URL is the deployed
|
|
645
|
+
directory, \`https://owner.github.io/repo/\`, e.g.
|
|
646
|
+
\`/subscribe?source=https%3A%2F%2Fowner.github.io%2Frepo%2F\`.
|
|
647
|
+
`;
|
|
581
648
|
}
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
// src/cli/skills.ts
|
|
652
|
+
var skills_exports = {};
|
|
653
|
+
__export(skills_exports, {
|
|
654
|
+
bundledSkillsRoot: () => bundledSkillsRoot,
|
|
655
|
+
installSkills: () => installSkills,
|
|
656
|
+
listBundledSkills: () => listBundledSkills
|
|
657
|
+
});
|
|
658
|
+
function frontmatterField(source, key) {
|
|
659
|
+
const match = source.match(new RegExp(`^${key}:[ ]*(.*)$`, "m"));
|
|
660
|
+
return match?.[1].trim().replace(/^(['"])(.*)\1$/, "$2") || void 0;
|
|
582
661
|
}
|
|
583
|
-
function
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
const
|
|
587
|
-
return
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
662
|
+
function listBundledSkills(root) {
|
|
663
|
+
if (!fs.existsSync(root)) return [];
|
|
664
|
+
return fs.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory() && fs.existsSync(path.join(root, entry.name, "SKILL.md"))).sort((a, b) => a.name.localeCompare(b.name)).map((entry) => {
|
|
665
|
+
const source = fs.readFileSync(path.join(root, entry.name, "SKILL.md"), "utf-8");
|
|
666
|
+
return {
|
|
667
|
+
name: entry.name,
|
|
668
|
+
description: frontmatterField(source, "description") ?? "",
|
|
669
|
+
path: path.join(root, entry.name)
|
|
670
|
+
};
|
|
671
|
+
});
|
|
591
672
|
}
|
|
592
|
-
function
|
|
593
|
-
const
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
return
|
|
673
|
+
function bundledSkillsRoot() {
|
|
674
|
+
const scriptDir = path.dirname(fs.realpathSync(process.argv[1] ?? process.cwd()));
|
|
675
|
+
const candidates = ["skills", "../skills", "../../skills", "../../../skills", "../../../../skills"].map(
|
|
676
|
+
(rel) => path.resolve(scriptDir, rel)
|
|
677
|
+
);
|
|
678
|
+
return candidates.find((candidate) => listBundledSkills(candidate).length > 0);
|
|
598
679
|
}
|
|
599
|
-
function
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
return "";
|
|
680
|
+
function installSkills(options = {}) {
|
|
681
|
+
const root = options.root ?? bundledSkillsRoot();
|
|
682
|
+
if (!root) {
|
|
683
|
+
throw new Error("no bundled skills found next to this CLI \u2014 reinstall the package or run from the wod-wiki checkout");
|
|
604
684
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
685
|
+
const skills = listBundledSkills(root);
|
|
686
|
+
if (skills.length === 0) throw new Error(`no skills under ${root}`);
|
|
687
|
+
const target = path.join(path.resolve(options.dir ?? process.cwd()), ".agents", "skills");
|
|
688
|
+
const installed = [];
|
|
689
|
+
const skipped = [];
|
|
690
|
+
for (const skill of skills) {
|
|
691
|
+
const destination = path.join(target, skill.name);
|
|
692
|
+
if (fs.existsSync(destination) && options.force !== true) {
|
|
693
|
+
skipped.push(skill.name);
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
fs.rmSync(destination, { recursive: true, force: true });
|
|
697
|
+
fs.mkdirSync(target, { recursive: true });
|
|
698
|
+
fs.cpSync(skill.path, destination, { recursive: true });
|
|
699
|
+
installed.push(skill.name);
|
|
613
700
|
}
|
|
701
|
+
return { root, target, installed, skipped };
|
|
614
702
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
const out = child_process.execFileSync("git", ["rev-list", "--count", "HEAD", "--", targetPath], { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
618
|
-
const count = Number(out);
|
|
619
|
-
return Number.isFinite(count) && count > 0 ? count : 1;
|
|
620
|
-
} catch {
|
|
621
|
-
return 1;
|
|
703
|
+
var init_skills = __esm({
|
|
704
|
+
"src/cli/skills.ts"() {
|
|
622
705
|
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
// src/seedbuild/contract.ts
|
|
709
|
+
var contract_exports = {};
|
|
710
|
+
var init_contract = __esm({
|
|
711
|
+
"src/seedbuild/contract.ts"() {
|
|
712
|
+
__reExport(contract_exports, wod_wiki_engine_star__namespace);
|
|
629
713
|
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
// src/seedbuild/filename.ts
|
|
717
|
+
function fileToDisplayName(filename) {
|
|
718
|
+
const base = filename.replace(/\.md$/, "");
|
|
719
|
+
if (base.toUpperCase() === "README") return "Overview";
|
|
720
|
+
const cleaned = base.replace(/^day-\d+-/, "");
|
|
721
|
+
const tokens = cleaned.split(/[-_]/);
|
|
722
|
+
const titled = [];
|
|
723
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
724
|
+
const token = tokens[i];
|
|
725
|
+
const next = tokens[i + 1];
|
|
726
|
+
const after = tokens[i + 2];
|
|
727
|
+
const prev = tokens[i - 1];
|
|
728
|
+
if (/^\d{1,2}$/.test(token) && /^\d{1,2}$/.test(next ?? "") && !/^\d+$/.test(prev ?? "") && !/^\d+$/.test(after ?? "")) {
|
|
729
|
+
titled.push(`${token}.${next}`);
|
|
730
|
+
i++;
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (titled.length > 0 && FILE_TITLE_STOP_WORDS[token.toLowerCase()]) {
|
|
734
|
+
titled.push(token.toLowerCase());
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
titled.push(token.charAt(0).toUpperCase() + token.slice(1));
|
|
637
738
|
}
|
|
739
|
+
return titled.join(" ");
|
|
638
740
|
}
|
|
639
|
-
|
|
640
|
-
|
|
741
|
+
var FILE_TITLE_STOP_WORDS;
|
|
742
|
+
var init_filename = __esm({
|
|
743
|
+
"src/seedbuild/filename.ts"() {
|
|
744
|
+
FILE_TITLE_STOP_WORDS = {
|
|
745
|
+
and: true,
|
|
746
|
+
or: true,
|
|
747
|
+
of: true,
|
|
748
|
+
for: true,
|
|
749
|
+
to: true,
|
|
750
|
+
in: true,
|
|
751
|
+
on: true,
|
|
752
|
+
at: true,
|
|
753
|
+
by: true,
|
|
754
|
+
with: true,
|
|
755
|
+
the: true,
|
|
756
|
+
a: true,
|
|
757
|
+
an: true
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
function resolveGitVersion(repoRoot) {
|
|
762
|
+
try {
|
|
763
|
+
const run = (args) => child_process.execSync(`git ${args}`, { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
764
|
+
const count = Number(run("rev-list --count HEAD"));
|
|
765
|
+
return {
|
|
766
|
+
version: Number.isFinite(count) && count > 0 ? count : 0,
|
|
767
|
+
versionLabel: run("describe --tags --long --always --dirty"),
|
|
768
|
+
commit: run("rev-parse HEAD"),
|
|
769
|
+
dirty: run("status --porcelain") !== ""
|
|
770
|
+
};
|
|
771
|
+
} catch {
|
|
772
|
+
return UNKNOWN_GIT_VERSION;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
var UNKNOWN_GIT_VERSION;
|
|
776
|
+
var init_git_version = __esm({
|
|
777
|
+
"src/seedbuild/git-version.ts"() {
|
|
778
|
+
UNKNOWN_GIT_VERSION = {
|
|
779
|
+
version: 0,
|
|
780
|
+
versionLabel: "unknown",
|
|
781
|
+
commit: "",
|
|
782
|
+
dirty: false
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
var init_frontmatter = __esm({
|
|
787
|
+
"src/seedbuild/frontmatter.ts"() {
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
// src/seedbuild/validation.ts
|
|
792
|
+
var validation_exports = {};
|
|
793
|
+
var init_validation = __esm({
|
|
794
|
+
"src/seedbuild/validation.ts"() {
|
|
795
|
+
__reExport(validation_exports, wod_wiki_engine_star__namespace);
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
// src/seedbuild/compiler.ts
|
|
800
|
+
var compiler_exports = {};
|
|
801
|
+
__export(compiler_exports, {
|
|
802
|
+
buildBlockEffortRows: () => buildBlockEffortRows,
|
|
803
|
+
buildBlockEquipmentRows: () => buildBlockEquipmentRows,
|
|
804
|
+
buildBlockIndexRows: () => buildBlockIndexRows,
|
|
805
|
+
chunkIdFor: () => chunkIdFor,
|
|
806
|
+
collectCorpusMarkdown: () => collectCorpusMarkdown,
|
|
807
|
+
compileSeedRow: () => compileSeedRow,
|
|
808
|
+
dateKeyToCreatedAt: () => dateKeyToCreatedAt,
|
|
809
|
+
discoverUncatalogedEfforts: () => discoverUncatalogedEfforts,
|
|
810
|
+
frontmatterDateToCreatedAt: () => frontmatterDateToCreatedAt,
|
|
811
|
+
generateSeed: () => generateSeed,
|
|
812
|
+
getFileCommit: () => getFileCommit,
|
|
813
|
+
getFileVersion: () => getFileVersion,
|
|
814
|
+
getPathCommit: () => getPathCommit,
|
|
815
|
+
getPathUpdatedAt: () => getPathUpdatedAt,
|
|
816
|
+
getPathVersion: () => getPathVersion,
|
|
817
|
+
groupCorpusPath: () => groupCorpusPath,
|
|
818
|
+
loadCorpusReferenceCatalog: () => loadCorpusReferenceCatalog,
|
|
819
|
+
partitionIntoChunks: () => partitionIntoChunks,
|
|
820
|
+
scaffoldDiscoveredEfforts: () => scaffoldDiscoveredEfforts,
|
|
821
|
+
seedNoteIdSync: () => seedNoteIdSync,
|
|
822
|
+
validateDashboardNote: () => validateDashboardNote,
|
|
823
|
+
validateWodBlockSyntax: () => validateWodBlockSyntax
|
|
824
|
+
});
|
|
825
|
+
function listMarkdownFiles(dir, prefix = "") {
|
|
826
|
+
if (!fs.existsSync(dir)) return [];
|
|
827
|
+
const out = [];
|
|
828
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
829
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
830
|
+
if (entry.isDirectory()) out.push(...listMarkdownFiles(path.join(dir, entry.name), rel));
|
|
831
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) out.push(rel);
|
|
832
|
+
}
|
|
833
|
+
return out.sort();
|
|
834
|
+
}
|
|
835
|
+
function chunkIdFor(relPath) {
|
|
836
|
+
const parts = relPath.split("/");
|
|
837
|
+
if (parts[0] !== "markdown" || parts.length < 2) return null;
|
|
838
|
+
const corpus = parts[1];
|
|
839
|
+
if (parts.length === 2) return null;
|
|
840
|
+
const slug = parts[2]?.replace(/\.md$/, "");
|
|
841
|
+
switch (corpus) {
|
|
842
|
+
case "canvas":
|
|
843
|
+
case "dashboards":
|
|
844
|
+
case "efforts":
|
|
845
|
+
case "equipment":
|
|
846
|
+
return corpus;
|
|
847
|
+
case "notebooks":
|
|
848
|
+
return parts.length === 3 ? `notebook._root` : `notebook.${slug}`;
|
|
849
|
+
default:
|
|
850
|
+
return null;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
function collectCorpusMarkdown(markdownDir, excludePaths = []) {
|
|
854
|
+
const excluded = new Set(excludePaths);
|
|
855
|
+
return listMarkdownFiles(markdownDir).map((p) => `markdown/${p}`).filter((path) => !excluded.has(path));
|
|
856
|
+
}
|
|
857
|
+
function partitionIntoChunks(paths) {
|
|
858
|
+
const byId = /* @__PURE__ */ new Map();
|
|
859
|
+
for (const p of paths) {
|
|
860
|
+
const id = chunkIdFor(p);
|
|
861
|
+
if (id === null) {
|
|
862
|
+
throw new Error(
|
|
863
|
+
`[generate-seed] Parity failure: '${p}' is not part of any known corpus (canvas | dashboards | efforts | equipment | notebooks). Extend chunkIdFor() if this is a new corpus.`
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
const list = byId.get(id);
|
|
867
|
+
if (list) list.push(p);
|
|
868
|
+
else byId.set(id, [p]);
|
|
869
|
+
}
|
|
870
|
+
return [...byId.entries()].sort(([a], [b]) => a < b ? -1 : 1).map(([id, files]) => ({ id, files }));
|
|
871
|
+
}
|
|
872
|
+
function validateDashboardNote(raw) {
|
|
873
|
+
const problems = [];
|
|
874
|
+
const { meta } = wodWikiCore.parseFrontmatter(raw);
|
|
875
|
+
const { sections } = wodWikiWql.parseDashboardNote(raw);
|
|
876
|
+
const doc = wodWikiWql.buildDashboardDocument(sections, meta);
|
|
877
|
+
if (!doc.isDashboard) return ["file is not a dashboard note (missing dashboard frontmatter)"];
|
|
878
|
+
if (doc.title === void 0) problems.push("dashboard has no title");
|
|
879
|
+
if (doc.widgets.length < 3) problems.push(`dashboard has only ${doc.widgets.length} widgets (the locked format has \u2265 3)`);
|
|
880
|
+
const declared = new Set(doc.tokens.map((t) => t.name));
|
|
881
|
+
for (const widget of doc.widgets) {
|
|
882
|
+
const where = `widget '${widget.title ?? widget.body.slice(0, 40)}'`;
|
|
883
|
+
if (widget.title === void 0) problems.push(`${where}: missing title`);
|
|
884
|
+
if (!wodWikiWql.isDashboardWidgetType(wodWikiWql.resolveWidgetType(widget.type))) {
|
|
885
|
+
problems.push(`${where}: unknown widget type '${widget.type}'`);
|
|
886
|
+
}
|
|
887
|
+
if (widget.body.includes("\n")) {
|
|
888
|
+
const docParsed = wodWikiWql.parseDocument(widget.body);
|
|
889
|
+
if (docParsed.diagnostics.length > 0) {
|
|
890
|
+
problems.push(`${where}: QueryDocument error: ${docParsed.diagnostics[0]}`);
|
|
891
|
+
}
|
|
892
|
+
} else {
|
|
893
|
+
const parsed = wodWikiWql.parseQuery(widget.body);
|
|
894
|
+
if (parsed.error !== void 0) problems.push(`${where}: WQL parse error: ${parsed.error}`);
|
|
895
|
+
}
|
|
896
|
+
for (const ref of [
|
|
897
|
+
...widget.body.matchAll(/\$([A-Za-z][\w-]*)/g),
|
|
898
|
+
...Object.values(widget.attributes).flatMap((v) => [...String(v).matchAll(/\$([A-Za-z][\w-]*)/g)])
|
|
899
|
+
]) {
|
|
900
|
+
if (!declared.has(ref[1])) problems.push(`${where}: undeclared token $${ref[1]}`);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return problems;
|
|
904
|
+
}
|
|
905
|
+
function gateDashboards(groups, corpusRoot) {
|
|
906
|
+
for (const group of groups) {
|
|
907
|
+
if (group.id !== contract_exports.DASHBOARDS_CHUNK_ID) continue;
|
|
908
|
+
for (const p of group.files) {
|
|
909
|
+
const problems = validateDashboardNote(fs.readFileSync(path.join(corpusRoot, p), "utf8"));
|
|
910
|
+
if (problems.length > 0) {
|
|
911
|
+
throw new Error(`[generate-seed] Dashboard validation failed for '${p}':
|
|
912
|
+
- ${problems.join("\n - ")}`);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
function normalizeRelGitPath(p) {
|
|
918
|
+
return p.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/+|\/+$/g, "");
|
|
919
|
+
}
|
|
920
|
+
function getGitHistoryIndex(repoRoot, targetRelPath) {
|
|
921
|
+
const normTarget = targetRelPath ? normalizeRelGitPath(targetRelPath) : "";
|
|
922
|
+
const topSegment = normTarget.split("/")[0] ?? "";
|
|
923
|
+
const scopeArg = topSegment && fs.existsSync(path.join(repoRoot, topSegment)) ? topSegment : ".";
|
|
924
|
+
let prefix;
|
|
925
|
+
let headSha;
|
|
926
|
+
try {
|
|
927
|
+
const rev = child_process.execFileSync("git", ["rev-parse", "--show-prefix", "HEAD"], {
|
|
928
|
+
cwd: repoRoot,
|
|
929
|
+
encoding: "utf8",
|
|
930
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
931
|
+
});
|
|
932
|
+
const lines = rev.split("\n");
|
|
933
|
+
prefix = lines[0] ?? "";
|
|
934
|
+
headSha = (lines[1] ?? "").trim();
|
|
935
|
+
} catch {
|
|
936
|
+
return EMPTY_GIT_INDEX;
|
|
937
|
+
}
|
|
938
|
+
if (!headSha) return EMPTY_GIT_INDEX;
|
|
939
|
+
const cacheKey = `${repoRoot}::${prefix}::${scopeArg}::${headSha}`;
|
|
940
|
+
const cached = gitHistoryCache.get(cacheKey);
|
|
941
|
+
if (cached) return cached;
|
|
942
|
+
const files = /* @__PURE__ */ new Map();
|
|
943
|
+
const dirs = /* @__PURE__ */ new Map();
|
|
944
|
+
try {
|
|
945
|
+
const out = child_process.execFileSync(
|
|
946
|
+
"git",
|
|
947
|
+
["log", "--format=%H %ct %cI", "--name-only", "HEAD", "--", scopeArg],
|
|
948
|
+
{
|
|
949
|
+
cwd: repoRoot,
|
|
950
|
+
encoding: "utf8",
|
|
951
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
952
|
+
maxBuffer: 64 * 1024 * 1024
|
|
953
|
+
}
|
|
954
|
+
);
|
|
955
|
+
for (const block of out.split("")) {
|
|
956
|
+
const trimmed = block.trim();
|
|
957
|
+
if (!trimmed) continue;
|
|
958
|
+
const lines = trimmed.split("\n");
|
|
959
|
+
const header = lines[0] ?? "";
|
|
960
|
+
const [commit = "", ctStr = "0", cI = ""] = header.split(" ");
|
|
961
|
+
const ts = Number(ctStr) * 1e3;
|
|
962
|
+
const ctMs = Number.isFinite(ts) && ts > 0 ? ts : 0;
|
|
963
|
+
const seenDirs = /* @__PURE__ */ new Set();
|
|
964
|
+
for (let i = 1; i < lines.length; i++) {
|
|
965
|
+
let rel = lines[i].trim();
|
|
966
|
+
if (!rel) continue;
|
|
967
|
+
if (prefix) {
|
|
968
|
+
if (!rel.startsWith(prefix)) continue;
|
|
969
|
+
rel = rel.slice(prefix.length);
|
|
970
|
+
}
|
|
971
|
+
rel = normalizeRelGitPath(rel);
|
|
972
|
+
if (!rel) continue;
|
|
973
|
+
const existingFile = files.get(rel);
|
|
974
|
+
if (!existingFile) {
|
|
975
|
+
files.set(rel, { commit, ctMs, cI, count: 1 });
|
|
976
|
+
} else {
|
|
977
|
+
existingFile.count += 1;
|
|
978
|
+
}
|
|
979
|
+
let slash = rel.lastIndexOf("/");
|
|
980
|
+
while (slash > 0) {
|
|
981
|
+
seenDirs.add(rel.slice(0, slash));
|
|
982
|
+
slash = rel.lastIndexOf("/", slash - 1);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
for (const dir of seenDirs) {
|
|
986
|
+
const existingDir = dirs.get(dir);
|
|
987
|
+
if (!existingDir) {
|
|
988
|
+
dirs.set(dir, { commit, ctMs, cI, count: 1 });
|
|
989
|
+
} else {
|
|
990
|
+
existingDir.count += 1;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
} catch {
|
|
995
|
+
return EMPTY_GIT_INDEX;
|
|
996
|
+
}
|
|
997
|
+
if (gitHistoryCache.size >= 8) {
|
|
998
|
+
gitHistoryCache.clear();
|
|
999
|
+
}
|
|
1000
|
+
const built = { files, dirs };
|
|
1001
|
+
gitHistoryCache.set(cacheKey, built);
|
|
1002
|
+
return built;
|
|
1003
|
+
}
|
|
1004
|
+
function getFileCreatedAt(file, repoRoot) {
|
|
1005
|
+
const norm = normalizeRelGitPath(file);
|
|
1006
|
+
return getGitHistoryIndex(repoRoot, norm).files.get(norm)?.ctMs ?? 0;
|
|
1007
|
+
}
|
|
1008
|
+
function seedNoteIdSync(path) {
|
|
1009
|
+
const hash = crypto.createHash("sha1").update(`${contract_exports.SEED_NAMESPACE}:${path}`).digest();
|
|
1010
|
+
const bytes = new Uint8Array(hash.subarray(0, 16));
|
|
1011
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
1012
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
1013
|
+
return [...bytes].map((b, i) => [4, 6, 8, 10].includes(i) ? `-${b.toString(16).padStart(2, "0")}` : b.toString(16).padStart(2, "0")).join("");
|
|
1014
|
+
}
|
|
1015
|
+
function getFileCommit(file, repoRoot) {
|
|
1016
|
+
const norm = normalizeRelGitPath(file);
|
|
1017
|
+
return getGitHistoryIndex(repoRoot, norm).files.get(norm)?.commit ?? "";
|
|
1018
|
+
}
|
|
1019
|
+
function getFileVersion(file, repoRoot) {
|
|
1020
|
+
const norm = normalizeRelGitPath(file);
|
|
1021
|
+
return getGitHistoryIndex(repoRoot, norm).files.get(norm)?.count ?? 1;
|
|
1022
|
+
}
|
|
1023
|
+
function lookupPathStats(targetPath, repoRoot) {
|
|
1024
|
+
const norm = normalizeRelGitPath(targetPath);
|
|
1025
|
+
const idx = getGitHistoryIndex(repoRoot, norm);
|
|
1026
|
+
return idx.dirs.get(norm) ?? idx.files.get(norm);
|
|
1027
|
+
}
|
|
1028
|
+
function getPathVersion(targetPath, repoRoot) {
|
|
1029
|
+
return lookupPathStats(targetPath, repoRoot)?.count ?? 1;
|
|
1030
|
+
}
|
|
1031
|
+
function getPathCommit(targetPath, repoRoot) {
|
|
1032
|
+
return lookupPathStats(targetPath, repoRoot)?.commit ?? "";
|
|
1033
|
+
}
|
|
1034
|
+
function getPathUpdatedAt(targetPath, repoRoot) {
|
|
1035
|
+
const cI = lookupPathStats(targetPath, repoRoot)?.cI;
|
|
1036
|
+
return cI || void 0;
|
|
1037
|
+
}
|
|
1038
|
+
function groupCorpusPath(id) {
|
|
1039
|
+
if (id.startsWith("notebook.")) {
|
|
641
1040
|
const slug = id.slice("notebook.".length);
|
|
642
1041
|
return slug === "_root" ? "markdown/notebooks" : `markdown/notebooks/${slug}`;
|
|
643
1042
|
}
|
|
@@ -660,6 +1059,29 @@ function dateKeyToCreatedAt(dateKey) {
|
|
|
660
1059
|
const ts = Date.parse(`${dateKey}T00:00:00Z`);
|
|
661
1060
|
return Number.isNaN(ts) ? 0 : ts;
|
|
662
1061
|
}
|
|
1062
|
+
function compileCompanionTelemetry(path, jsonl, blockIndex) {
|
|
1063
|
+
const firstWod = blockIndex.find((block) => block.dataType === "wod");
|
|
1064
|
+
const noteId = seedNoteIdSync(path);
|
|
1065
|
+
const normalized = jsonl.split(/\r?\n/).map((line) => {
|
|
1066
|
+
if (!line.trim()) return line;
|
|
1067
|
+
const parsed2 = JSON.parse(line);
|
|
1068
|
+
if (typeof parsed2 !== "object" || parsed2 === null || Array.isArray(parsed2)) return line;
|
|
1069
|
+
const record = { ...parsed2, noteId };
|
|
1070
|
+
if (record.kind === "session" || record.kind === "event") {
|
|
1071
|
+
if (!firstWod) throw new Error(`Telemetry for '${path}' requires a wod block`);
|
|
1072
|
+
if (record.blockId === void 0 || record.blockId === "@first-wod") record.blockId = firstWod.blockId;
|
|
1073
|
+
if (record.blockVersion === void 0 || record.blockVersion === "@first-wod") record.blockVersion = firstWod.blockVersion;
|
|
1074
|
+
if (record.blockContentId === void 0 || record.blockContentId === "@first-wod") record.blockContentId = firstWod.blockContentId;
|
|
1075
|
+
}
|
|
1076
|
+
return JSON.stringify(record);
|
|
1077
|
+
}).join("\n");
|
|
1078
|
+
const parsed = wodWikiCore.parseNoteBundleFromJsonl(normalized);
|
|
1079
|
+
if (parsed.errors.length > 0) throw new Error(`Invalid telemetry companion '${path}': ${parsed.errors.join("; ")}`);
|
|
1080
|
+
return {
|
|
1081
|
+
sessions: parsed.bundles.flatMap((bundle) => bundle.sessions),
|
|
1082
|
+
events: parsed.bundles.flatMap((bundle) => bundle.events)
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
663
1085
|
function compileSeedRow(path, content, metadata = {}) {
|
|
664
1086
|
let ordinal = 0;
|
|
665
1087
|
const blocks = wodWikiCore.reconcileNoteBlocks(content, { sourceRevision: 1, registeredWidgets: contract_exports.SEED_REGISTERED_WIDGETS, createId: () => `seed:${path}:${ordinal++}` });
|
|
@@ -669,7 +1091,8 @@ function compileSeedRow(path, content, metadata = {}) {
|
|
|
669
1091
|
const section = sections.find((section2) => section2.from === block.from && section2.to === block.to);
|
|
670
1092
|
return { id: `${noteId}:${block.id}`, noteId, blockId: block.id, blockVersion: 1, sourceRevision: 1, from: block.from, to: block.to, position, dataType: block.kind, ...block.kind === "wod" ? { blockContentId: wodWikiCore.blockContentId(section?.scriptBlock?.content ?? content.slice(block.from, block.to)) } : {}, rawContent: content.slice(block.from, block.to), noteTitle: metadata.noteTitle ?? fileToDisplayName(path.split("/").at(-1) ?? path), createdAt: metadata.createdAt ?? 0, isStatic: true, sourceId: metadata.sourceId, sourcePath: path, routeId: metadata.routeId };
|
|
671
1093
|
});
|
|
672
|
-
|
|
1094
|
+
const telemetry = metadata.telemetryJsonl === void 0 ? void 0 : compileCompanionTelemetry(path, metadata.telemetryJsonl, blockIndex);
|
|
1095
|
+
return { path, content, blocks, blockIndex, blockEfforts: [], blockEquipment: [], ...telemetry ? { telemetry } : {} };
|
|
673
1096
|
}
|
|
674
1097
|
function buildBlockIndexRows(markdownDir, corpusRoot, excludePaths = []) {
|
|
675
1098
|
const rows = [];
|
|
@@ -911,435 +1334,171 @@ ${shown}${more}`);
|
|
|
911
1334
|
blocksByPath.set(row.sourcePath, rows);
|
|
912
1335
|
}
|
|
913
1336
|
for (const row of effortRows) {
|
|
914
|
-
const rows = effortsByPath.get(row.sourcePath) ?? [];
|
|
915
|
-
rows.push(row);
|
|
916
|
-
effortsByPath.set(row.sourcePath, rows);
|
|
917
|
-
}
|
|
918
|
-
for (const row of equipmentRows) {
|
|
919
|
-
const rows = equipmentByPath.get(row.sourcePath) ?? [];
|
|
920
|
-
rows.push(row);
|
|
921
|
-
equipmentByPath.set(row.sourcePath, rows);
|
|
922
|
-
}
|
|
923
|
-
let totalFiles = 0;
|
|
924
|
-
const manifestNotebooks = [];
|
|
925
|
-
const manifestBuiltAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
926
|
-
const tWrite = Date.now();
|
|
927
|
-
for (const { id, files } of groups) {
|
|
928
|
-
const records = [];
|
|
929
|
-
const rows = files.map((p) => {
|
|
930
|
-
const raw = fs.readFileSync(path.join(corpusRoot, p), "utf8");
|
|
931
|
-
const content = raw;
|
|
932
|
-
const compiled = compileSeedRow(p, content);
|
|
933
|
-
compiled.blockIndex = blocksByPath.get(p) ?? compiled.blockIndex;
|
|
934
|
-
compiled.blockEfforts = effortsByPath.get(p) ?? [];
|
|
935
|
-
compiled.blockEquipment = equipmentByPath.get(p) ?? [];
|
|
936
|
-
const fileCommit = getFileCommit(p, corpusRoot) || gitVersion.commit || "";
|
|
937
|
-
const fileVer = getFileVersion(p, corpusRoot);
|
|
938
|
-
const uuid = seedNoteIdSync(p);
|
|
939
|
-
compiled.commit = fileCommit;
|
|
940
|
-
compiled.uuid = uuid;
|
|
941
|
-
compiled.version = fileVer;
|
|
942
|
-
const recordRelPath = p.replace(/\.md$/, ".json");
|
|
943
|
-
const recordOutFile = path.join(outDir, recordRelPath);
|
|
944
|
-
fs.mkdirSync(path.dirname(recordOutFile), { recursive: true });
|
|
945
|
-
const recordBytes = Buffer.from(JSON.stringify(compiled, null, 2), "utf8");
|
|
946
|
-
fs.writeFileSync(recordOutFile, recordBytes);
|
|
947
|
-
const title = compiled.blockIndex[0]?.noteTitle ?? fileToDisplayName(p.split("/").at(-1) ?? p);
|
|
948
|
-
records.push({
|
|
949
|
-
uuid,
|
|
950
|
-
path: p,
|
|
951
|
-
recordPath: recordRelPath,
|
|
952
|
-
commit: fileCommit,
|
|
953
|
-
version: fileVer,
|
|
954
|
-
sha256: sha256Hex(recordBytes),
|
|
955
|
-
title,
|
|
956
|
-
date: frontmatterDateToCreatedAt(content, p)
|
|
957
|
-
});
|
|
958
|
-
return compiled;
|
|
959
|
-
});
|
|
960
|
-
(0, validation_exports.assertSeedRows)(rows);
|
|
961
|
-
const bytes = Buffer.from(JSON.stringify(rows), "utf8");
|
|
962
|
-
const sha = sha256Hex(bytes);
|
|
963
|
-
const file = `chunks/${id}.${sha.slice(0, 8)}.json`;
|
|
964
|
-
fs.writeFileSync(path.join(outDir, file), bytes);
|
|
965
|
-
manifestChunks.push({ id, path: file, sha256: sha, bytes: bytes.length, count: rows.length });
|
|
966
|
-
totalFiles += rows.length;
|
|
967
|
-
const groupPath = groupCorpusPath(id);
|
|
968
|
-
const groupVersion = getPathVersion(groupPath, corpusRoot);
|
|
969
|
-
const groupCommit = getPathCommit(groupPath, corpusRoot) || gitVersion.commit || "";
|
|
970
|
-
const groupUpdatedAt = getPathUpdatedAt(groupPath, corpusRoot);
|
|
971
|
-
const notebookIndexPath = `indexes/notebooks/${id}.json`;
|
|
972
|
-
const summary = {
|
|
973
|
-
notebookId: id,
|
|
974
|
-
label: fileToDisplayName(id.split(".").at(-1) ?? id),
|
|
975
|
-
category: (0, contract_exports.notebookSlugForChunkId)(id),
|
|
976
|
-
indexPath: notebookIndexPath,
|
|
977
|
-
version: groupVersion,
|
|
978
|
-
commit: groupCommit,
|
|
979
|
-
updatedAt: groupUpdatedAt,
|
|
980
|
-
builtAt: manifestBuiltAt,
|
|
981
|
-
sha256: sha,
|
|
982
|
-
bytes: bytes.length,
|
|
983
|
-
count: rows.length
|
|
984
|
-
};
|
|
985
|
-
const notebookIndex = {
|
|
986
|
-
...summary,
|
|
987
|
-
records
|
|
988
|
-
};
|
|
989
|
-
(0, validation_exports.assertNotebookIndex)(notebookIndex);
|
|
990
|
-
const indexOutFile = path.join(outDir, notebookIndexPath);
|
|
991
|
-
fs.mkdirSync(path.dirname(indexOutFile), { recursive: true });
|
|
992
|
-
fs.writeFileSync(indexOutFile, JSON.stringify(notebookIndex, null, 2) + "\n");
|
|
993
|
-
manifestNotebooks.push(summary);
|
|
994
|
-
}
|
|
995
|
-
passMs.write = Date.now() - tWrite;
|
|
996
|
-
const manifest = {
|
|
997
|
-
name: "name" in metadata && typeof metadata.name === "string" ? metadata.name : void 0,
|
|
998
|
-
description: "description" in metadata && typeof metadata.description === "string" ? metadata.description : void 0,
|
|
999
|
-
repositoryUrl: repositoryLink?.protocol === "https:" && !repositoryLink.username && !repositoryLink.password ? repositoryLink.href : void 0,
|
|
1000
|
-
schema: contract_exports.SEED_SCHEMA,
|
|
1001
|
-
version: gitVersion.version,
|
|
1002
|
-
versionLabel: gitVersion.versionLabel,
|
|
1003
|
-
commit: gitVersion.commit,
|
|
1004
|
-
dirty: gitVersion.dirty,
|
|
1005
|
-
builtAt: manifestBuiltAt,
|
|
1006
|
-
chunks: manifestChunks,
|
|
1007
|
-
notebooks: manifestNotebooks
|
|
1008
|
-
};
|
|
1009
|
-
(0, validation_exports.assertSeedManifest)(manifest);
|
|
1010
|
-
fs.writeFileSync(path.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
1011
|
-
const reportPath = writeBuildReport(outDir, {
|
|
1012
|
-
manifest,
|
|
1013
|
-
totalMs: Date.now() - t0,
|
|
1014
|
-
passMs,
|
|
1015
|
-
fileCount: paths.length});
|
|
1016
|
-
return { manifest, outDir, totalFiles, reportPath, passMs };
|
|
1017
|
-
}
|
|
1018
|
-
var NON_EFFORT_SLUGS;
|
|
1019
|
-
var init_compiler = __esm({
|
|
1020
|
-
"src/seedbuild/compiler.ts"() {
|
|
1021
|
-
init_contract();
|
|
1022
|
-
init_filename();
|
|
1023
|
-
init_git_version();
|
|
1024
|
-
init_report();
|
|
1025
|
-
init_frontmatter();
|
|
1026
|
-
init_validation();
|
|
1027
|
-
NON_EFFORT_SLUGS = {
|
|
1028
|
-
"amrap": true,
|
|
1029
|
-
"emom": true,
|
|
1030
|
-
"tabata": true,
|
|
1031
|
-
"for-time": true,
|
|
1032
|
-
"rounds": true,
|
|
1033
|
-
"sets": true,
|
|
1034
|
-
"repetitions": true,
|
|
1035
|
-
"count-down": true,
|
|
1036
|
-
"total-reps": true,
|
|
1037
|
-
"warmup": true,
|
|
1038
|
-
"cooldown": true,
|
|
1039
|
-
"cool-down": true,
|
|
1040
|
-
"transition": true,
|
|
1041
|
-
"rest": true,
|
|
1042
|
-
"break": true,
|
|
1043
|
-
"work": true,
|
|
1044
|
-
"i-suck-at-this": true,
|
|
1045
|
-
"isuckatthis": true,
|
|
1046
|
-
"movement": true,
|
|
1047
|
-
"movement-you": true,
|
|
1048
|
-
"selected-exercise": true,
|
|
1049
|
-
"training-setup": true,
|
|
1050
|
-
"grade-system": true,
|
|
1051
|
-
"hangs": true,
|
|
1052
|
-
"warm-light-wind": true,
|
|
1053
|
-
"basin": true,
|
|
1054
|
-
"rock-canyon": true,
|
|
1055
|
-
"b-onsight": true,
|
|
1056
|
-
"a-redpoint": true,
|
|
1057
|
-
"d-redpoint": true,
|
|
1058
|
-
"v0-flash": true,
|
|
1059
|
-
"v2-flash": true,
|
|
1060
|
-
"v7-redpoint": true,
|
|
1061
|
-
"avgrpe-mean": true,
|
|
1062
|
-
"calculate": true,
|
|
1063
|
-
"totalload-sum": true,
|
|
1064
|
-
"query": true,
|
|
1065
|
-
"by": true,
|
|
1066
|
-
"": true,
|
|
1067
|
-
"-": true,
|
|
1068
|
-
"...": true,
|
|
1069
|
-
"x": true,
|
|
1070
|
-
"s": true,
|
|
1071
|
-
"bw": true
|
|
1072
|
-
};
|
|
1073
|
-
}
|
|
1074
|
-
});
|
|
1075
|
-
|
|
1076
|
-
// src/version.ts
|
|
1077
|
-
var VERSION;
|
|
1078
|
-
var init_version = __esm({
|
|
1079
|
-
"src/version.ts"() {
|
|
1080
|
-
VERSION = "0.51.2196";
|
|
1081
|
-
}
|
|
1082
|
-
});
|
|
1083
|
-
|
|
1084
|
-
// src/cli/scaffoldFeed.ts
|
|
1085
|
-
var scaffoldFeed_exports = {};
|
|
1086
|
-
__export(scaffoldFeed_exports, {
|
|
1087
|
-
scaffoldFeed: () => scaffoldFeed,
|
|
1088
|
-
validateFeedName: () => validateFeedName
|
|
1089
|
-
});
|
|
1090
|
-
function validateFeedName(name) {
|
|
1091
|
-
if (name.length === 0 || name === "." || name === "..") {
|
|
1092
|
-
throw new Error("Feed name must be a single non-empty directory name");
|
|
1093
|
-
}
|
|
1094
|
-
if (name.includes("/") || name.includes("\\") || name.includes("\0")) {
|
|
1095
|
-
throw new Error(`Invalid feed name '${name}': must be a single directory name (no path separators or traversal)`);
|
|
1096
|
-
}
|
|
1097
|
-
if (/^(?:[A-Za-z]:)?[/\\]/.test(name)) {
|
|
1098
|
-
throw new Error(`Invalid feed name '${name}': absolute paths are not allowed`);
|
|
1099
|
-
}
|
|
1100
|
-
if (name.length > 214 || !/^[a-z0-9][a-z0-9._-]*$/.test(name)) {
|
|
1101
|
-
throw new Error(
|
|
1102
|
-
`Invalid feed name '${name}': must be a valid npm package name (lowercase letters, digits, dots, hyphens, underscores; no leading dot/hyphen)`
|
|
1103
|
-
);
|
|
1104
|
-
}
|
|
1105
|
-
return name;
|
|
1106
|
-
}
|
|
1107
|
-
function scaffoldFeed(name, opts = {}) {
|
|
1108
|
-
validateFeedName(name);
|
|
1109
|
-
const dir = path.resolve(opts.cwd ?? process.cwd(), name);
|
|
1110
|
-
try {
|
|
1111
|
-
fs.mkdirSync(dir);
|
|
1112
|
-
} catch (error) {
|
|
1113
|
-
if (error.code === "EEXIST") {
|
|
1114
|
-
throw new Error(`Refusing to overwrite '${dir}': destination already exists`, { cause: error });
|
|
1115
|
-
}
|
|
1116
|
-
throw error;
|
|
1117
|
-
}
|
|
1118
|
-
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1119
|
-
const files = [
|
|
1120
|
-
["package.json", `${JSON.stringify(
|
|
1121
|
-
{
|
|
1122
|
-
name,
|
|
1123
|
-
version: "0.1.0",
|
|
1124
|
-
private: true,
|
|
1125
|
-
type: "module",
|
|
1126
|
-
description: `WOD Wiki workout feed: ${name}`,
|
|
1127
|
-
scripts: {
|
|
1128
|
-
build: "wod build . --output dist"
|
|
1129
|
-
},
|
|
1130
|
-
devDependencies: {
|
|
1131
|
-
"@bitcobblers/wod-wiki-tools": `^${VERSION}`
|
|
1132
|
-
}
|
|
1133
|
-
},
|
|
1134
|
-
null,
|
|
1135
|
-
2
|
|
1136
|
-
)}
|
|
1137
|
-
`],
|
|
1138
|
-
[".gitignore", "node_modules/\ndist/\n"],
|
|
1139
|
-
[".github/workflows/publish-feed.yml", publishWorkflow()],
|
|
1140
|
-
["markdown/notebooks/example/README.md", feedReadme(name)],
|
|
1141
|
-
[`markdown/notebooks/example/morning-session.md`, exampleWorkout(date)],
|
|
1142
|
-
["README.md", repoReadme(name)]
|
|
1143
|
-
];
|
|
1144
|
-
try {
|
|
1145
|
-
for (const [rel, content] of files) {
|
|
1146
|
-
const target = path.join(dir, rel);
|
|
1147
|
-
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
1148
|
-
fs.writeFileSync(target, content, "utf-8");
|
|
1149
|
-
}
|
|
1150
|
-
} catch (error) {
|
|
1151
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
1152
|
-
throw error;
|
|
1153
|
-
}
|
|
1154
|
-
return { dir, files: files.map(([rel]) => rel) };
|
|
1155
|
-
}
|
|
1156
|
-
var publishWorkflow, feedReadme, exampleWorkout, repoReadme;
|
|
1157
|
-
var init_scaffoldFeed = __esm({
|
|
1158
|
-
"src/cli/scaffoldFeed.ts"() {
|
|
1159
|
-
init_version();
|
|
1160
|
-
publishWorkflow = () => `name: Publish feed
|
|
1161
|
-
|
|
1162
|
-
# Compile the feed with the wod CLI and deploy dist/ to GitHub Pages.
|
|
1163
|
-
# Requires Pages enabled: repo Settings \u2192 Pages \u2192 Source: "GitHub Actions".
|
|
1164
|
-
|
|
1165
|
-
on:
|
|
1166
|
-
push:
|
|
1167
|
-
branches: [main]
|
|
1168
|
-
workflow_dispatch:
|
|
1169
|
-
|
|
1170
|
-
permissions:
|
|
1171
|
-
contents: read
|
|
1172
|
-
pages: write
|
|
1173
|
-
id-token: write
|
|
1174
|
-
|
|
1175
|
-
concurrency:
|
|
1176
|
-
group: pages
|
|
1177
|
-
cancel-in-progress: true
|
|
1178
|
-
|
|
1179
|
-
jobs:
|
|
1180
|
-
publish:
|
|
1181
|
-
runs-on: ubuntu-latest
|
|
1182
|
-
environment:
|
|
1183
|
-
name: github-pages
|
|
1184
|
-
url: \${{ steps.deployment.outputs.page_url }}
|
|
1185
|
-
steps:
|
|
1186
|
-
- uses: actions/checkout@v4
|
|
1187
|
-
with:
|
|
1188
|
-
# Full history: seed manifest version stamps derive from git commit count.
|
|
1189
|
-
fetch-depth: 0
|
|
1190
|
-
|
|
1191
|
-
- name: Set up Bun
|
|
1192
|
-
uses: oven-sh/setup-bun@v2
|
|
1193
|
-
with:
|
|
1194
|
-
bun-version: 1.4.x
|
|
1195
|
-
|
|
1196
|
-
- name: Install dependencies
|
|
1197
|
-
run: bun install
|
|
1198
|
-
|
|
1199
|
-
- name: Build seed
|
|
1200
|
-
run: bunx wod build . --output dist
|
|
1201
|
-
|
|
1202
|
-
- uses: actions/configure-pages@v5
|
|
1203
|
-
|
|
1204
|
-
- name: Upload dist
|
|
1205
|
-
uses: actions/upload-pages-artifact@v3
|
|
1206
|
-
with:
|
|
1207
|
-
path: dist
|
|
1208
|
-
|
|
1209
|
-
- id: deployment
|
|
1210
|
-
uses: actions/deploy-pages@v4
|
|
1211
|
-
`;
|
|
1212
|
-
feedReadme = (name) => `# ${name}
|
|
1213
|
-
|
|
1214
|
-
Example benchmark notebook. Each \`.md\` file in this directory becomes part of
|
|
1215
|
-
the \`example\` notebook chunk; \`README.md\` is the notebook's landing page.
|
|
1216
|
-
|
|
1217
|
-
Add one file per workout:
|
|
1218
|
-
|
|
1219
|
-
\`\`\`\`markdown
|
|
1220
|
-
---
|
|
1221
|
-
title: My workout
|
|
1222
|
-
date: 2026-01-01
|
|
1223
|
-
---
|
|
1224
|
-
|
|
1225
|
-
# My workout
|
|
1226
|
-
|
|
1227
|
-
\`\`\`time
|
|
1228
|
-
(21-15-9)
|
|
1229
|
-
Thrusters @95lb
|
|
1230
|
-
Pull-ups
|
|
1231
|
-
\`\`\`
|
|
1232
|
-
\`\`\`\`
|
|
1233
|
-
|
|
1234
|
-
The \`date:\` frontmatter field sets the workout's chronological placement
|
|
1235
|
-
(regardless of filename or directory).
|
|
1236
|
-
`;
|
|
1237
|
-
exampleWorkout = (date) => `---
|
|
1238
|
-
title: Morning session
|
|
1239
|
-
date: ${date}
|
|
1240
|
-
---
|
|
1241
|
-
|
|
1242
|
-
# Morning session
|
|
1243
|
-
|
|
1244
|
-
\`\`\`time
|
|
1245
|
-
(21-15-9)
|
|
1246
|
-
Thrusters @95lb
|
|
1247
|
-
Pull-ups
|
|
1248
|
-
\`\`\`
|
|
1249
|
-
`;
|
|
1250
|
-
repoReadme = (name) => `# ${name}
|
|
1251
|
-
|
|
1252
|
-
A [WOD Wiki](https://github.com/bitcobblers/wod-wiki) workout feed: plain
|
|
1253
|
-
Markdown workouts compiled to static, version-stamped seed chunks and published
|
|
1254
|
-
via GitHub Pages.
|
|
1255
|
-
|
|
1256
|
-
## Develop
|
|
1257
|
-
|
|
1258
|
-
\`\`\`sh
|
|
1259
|
-
bun install
|
|
1260
|
-
bunx wod build . --output dist
|
|
1261
|
-
\`\`\`
|
|
1262
|
-
|
|
1263
|
-
Workouts live under \`markdown/\` \u2014 this scaffold starts with one example
|
|
1264
|
-
feed. Validate everything with \`bunx wod build\`: it gates every file on
|
|
1265
|
-
the Whiteboard grammar and corpus layout before writing \`dist/\`.
|
|
1266
|
-
|
|
1267
|
-
## Publish
|
|
1268
|
-
|
|
1269
|
-
Push to GitHub and enable Pages (**Settings \u2192 Pages \u2192 Source: GitHub
|
|
1270
|
-
Actions**). The bundled workflow (\`.github/workflows/publish-feed.yml\`)
|
|
1271
|
-
builds the feed on every push to \`main\` and deploys \`dist/\`.
|
|
1272
|
-
|
|
1273
|
-
## Share
|
|
1274
|
-
|
|
1275
|
-
Once published, anyone can subscribe to this feed from a WOD Wiki instance
|
|
1276
|
-
at:
|
|
1277
|
-
|
|
1278
|
-
\`\`\`
|
|
1279
|
-
<app-url>/subscribe?source=<url-encoded published feed URL>
|
|
1280
|
-
\`\`\`
|
|
1281
|
-
|
|
1282
|
-
For \`owner\`/\`repo\` on GitHub Pages the feed URL is the deployed
|
|
1283
|
-
directory, \`https://owner.github.io/repo/\`, e.g.
|
|
1284
|
-
\`/subscribe?source=https%3A%2F%2Fowner.github.io%2Frepo%2F\`.
|
|
1285
|
-
`;
|
|
1337
|
+
const rows = effortsByPath.get(row.sourcePath) ?? [];
|
|
1338
|
+
rows.push(row);
|
|
1339
|
+
effortsByPath.set(row.sourcePath, rows);
|
|
1286
1340
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
__export(skills_exports, {
|
|
1292
|
-
bundledSkillsRoot: () => bundledSkillsRoot,
|
|
1293
|
-
installSkills: () => installSkills,
|
|
1294
|
-
listBundledSkills: () => listBundledSkills
|
|
1295
|
-
});
|
|
1296
|
-
function frontmatterField(source, key) {
|
|
1297
|
-
const match = source.match(new RegExp(`^${key}:[ ]*(.*)$`, "m"));
|
|
1298
|
-
return match?.[1].trim().replace(/^(['"])(.*)\1$/, "$2") || void 0;
|
|
1299
|
-
}
|
|
1300
|
-
function listBundledSkills(root) {
|
|
1301
|
-
if (!fs.existsSync(root)) return [];
|
|
1302
|
-
return fs.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory() && fs.existsSync(path.join(root, entry.name, "SKILL.md"))).sort((a, b) => a.name.localeCompare(b.name)).map((entry) => {
|
|
1303
|
-
const source = fs.readFileSync(path.join(root, entry.name, "SKILL.md"), "utf-8");
|
|
1304
|
-
return {
|
|
1305
|
-
name: entry.name,
|
|
1306
|
-
description: frontmatterField(source, "description") ?? "",
|
|
1307
|
-
path: path.join(root, entry.name)
|
|
1308
|
-
};
|
|
1309
|
-
});
|
|
1310
|
-
}
|
|
1311
|
-
function bundledSkillsRoot() {
|
|
1312
|
-
const scriptDir = path.dirname(fs.realpathSync(process.argv[1] ?? process.cwd()));
|
|
1313
|
-
const candidates = ["skills", "../skills", "../../skills", "../../../skills", "../../../../skills"].map(
|
|
1314
|
-
(rel) => path.resolve(scriptDir, rel)
|
|
1315
|
-
);
|
|
1316
|
-
return candidates.find((candidate) => listBundledSkills(candidate).length > 0);
|
|
1317
|
-
}
|
|
1318
|
-
function installSkills(options = {}) {
|
|
1319
|
-
const root = options.root ?? bundledSkillsRoot();
|
|
1320
|
-
if (!root) {
|
|
1321
|
-
throw new Error("no bundled skills found next to this CLI \u2014 reinstall the package or run from the wod-wiki checkout");
|
|
1341
|
+
for (const row of equipmentRows) {
|
|
1342
|
+
const rows = equipmentByPath.get(row.sourcePath) ?? [];
|
|
1343
|
+
rows.push(row);
|
|
1344
|
+
equipmentByPath.set(row.sourcePath, rows);
|
|
1322
1345
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
const
|
|
1326
|
-
const
|
|
1327
|
-
const
|
|
1328
|
-
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1346
|
+
let totalFiles = 0;
|
|
1347
|
+
const manifestNotebooks = [];
|
|
1348
|
+
const manifestBuiltAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1349
|
+
const tWrite = Date.now();
|
|
1350
|
+
for (const { id, files } of groups) {
|
|
1351
|
+
const records = [];
|
|
1352
|
+
const rows = files.map((p) => {
|
|
1353
|
+
const raw = fs.readFileSync(path.join(corpusRoot, p), "utf8");
|
|
1354
|
+
const content = raw;
|
|
1355
|
+
const companionPath = path.join(corpusRoot, p.replace(/\.md$/, ".jsonl"));
|
|
1356
|
+
const compiled = compileSeedRow(p, content, { telemetryJsonl: fs.existsSync(companionPath) ? fs.readFileSync(companionPath, "utf8") : void 0 });
|
|
1357
|
+
compiled.blockIndex = blocksByPath.get(p) ?? compiled.blockIndex;
|
|
1358
|
+
compiled.blockEfforts = effortsByPath.get(p) ?? [];
|
|
1359
|
+
compiled.blockEquipment = equipmentByPath.get(p) ?? [];
|
|
1360
|
+
const fileCommit = getFileCommit(p, corpusRoot) || gitVersion.commit || "";
|
|
1361
|
+
const fileVer = getFileVersion(p, corpusRoot);
|
|
1362
|
+
const uuid = seedNoteIdSync(p);
|
|
1363
|
+
compiled.commit = fileCommit;
|
|
1364
|
+
compiled.uuid = uuid;
|
|
1365
|
+
compiled.version = fileVer;
|
|
1366
|
+
const recordRelPath = p.replace(/\.md$/, ".json");
|
|
1367
|
+
const recordOutFile = path.join(outDir, recordRelPath);
|
|
1368
|
+
fs.mkdirSync(path.dirname(recordOutFile), { recursive: true });
|
|
1369
|
+
const recordBytes = Buffer.from(JSON.stringify(compiled, null, 2), "utf8");
|
|
1370
|
+
fs.writeFileSync(recordOutFile, recordBytes);
|
|
1371
|
+
if (compiled.telemetry) {
|
|
1372
|
+
fs.writeFileSync(path.join(outDir, p.replace(/\.md$/, ".jsonl")), wodWikiCore.serializeNoteBundleToJsonl(compiled.telemetry) + "\n");
|
|
1373
|
+
}
|
|
1374
|
+
const title = compiled.blockIndex[0]?.noteTitle ?? fileToDisplayName(p.split("/").at(-1) ?? p);
|
|
1375
|
+
records.push({
|
|
1376
|
+
uuid,
|
|
1377
|
+
path: p,
|
|
1378
|
+
recordPath: recordRelPath,
|
|
1379
|
+
commit: fileCommit,
|
|
1380
|
+
version: fileVer,
|
|
1381
|
+
sha256: sha256Hex(recordBytes),
|
|
1382
|
+
title,
|
|
1383
|
+
date: frontmatterDateToCreatedAt(content, p)
|
|
1384
|
+
});
|
|
1385
|
+
return compiled;
|
|
1386
|
+
});
|
|
1387
|
+
(0, validation_exports.assertSeedRows)(rows);
|
|
1388
|
+
const bytes = Buffer.from(JSON.stringify(rows), "utf8");
|
|
1389
|
+
const sha = sha256Hex(bytes);
|
|
1390
|
+
const file = `chunks/${id}.${sha.slice(0, 8)}.json`;
|
|
1391
|
+
fs.writeFileSync(path.join(outDir, file), bytes);
|
|
1392
|
+
manifestChunks.push({ id, path: file, sha256: sha, bytes: bytes.length, count: rows.length });
|
|
1393
|
+
totalFiles += rows.length;
|
|
1394
|
+
const groupPath = groupCorpusPath(id);
|
|
1395
|
+
const groupVersion = getPathVersion(groupPath, corpusRoot);
|
|
1396
|
+
const groupCommit = getPathCommit(groupPath, corpusRoot) || gitVersion.commit || "";
|
|
1397
|
+
const groupUpdatedAt = getPathUpdatedAt(groupPath, corpusRoot);
|
|
1398
|
+
const notebookIndexPath = `indexes/notebooks/${id}.json`;
|
|
1399
|
+
const summary = {
|
|
1400
|
+
notebookId: id,
|
|
1401
|
+
label: fileToDisplayName(id.split(".").at(-1) ?? id),
|
|
1402
|
+
category: (0, contract_exports.notebookSlugForChunkId)(id),
|
|
1403
|
+
indexPath: notebookIndexPath,
|
|
1404
|
+
version: groupVersion,
|
|
1405
|
+
commit: groupCommit,
|
|
1406
|
+
updatedAt: groupUpdatedAt,
|
|
1407
|
+
builtAt: manifestBuiltAt,
|
|
1408
|
+
sha256: sha,
|
|
1409
|
+
bytes: bytes.length,
|
|
1410
|
+
count: rows.length
|
|
1411
|
+
};
|
|
1412
|
+
const notebookIndex = {
|
|
1413
|
+
...summary,
|
|
1414
|
+
records
|
|
1415
|
+
};
|
|
1416
|
+
(0, validation_exports.assertNotebookIndex)(notebookIndex);
|
|
1417
|
+
const indexOutFile = path.join(outDir, notebookIndexPath);
|
|
1418
|
+
fs.mkdirSync(path.dirname(indexOutFile), { recursive: true });
|
|
1419
|
+
fs.writeFileSync(indexOutFile, JSON.stringify(notebookIndex, null, 2) + "\n");
|
|
1420
|
+
manifestNotebooks.push(summary);
|
|
1338
1421
|
}
|
|
1339
|
-
|
|
1422
|
+
passMs.write = Date.now() - tWrite;
|
|
1423
|
+
const manifest = {
|
|
1424
|
+
name: "name" in metadata && typeof metadata.name === "string" ? metadata.name : void 0,
|
|
1425
|
+
description: "description" in metadata && typeof metadata.description === "string" ? metadata.description : void 0,
|
|
1426
|
+
repositoryUrl: repositoryLink?.protocol === "https:" && !repositoryLink.username && !repositoryLink.password ? repositoryLink.href : void 0,
|
|
1427
|
+
schema: contract_exports.SEED_SCHEMA,
|
|
1428
|
+
version: gitVersion.version,
|
|
1429
|
+
versionLabel: gitVersion.versionLabel,
|
|
1430
|
+
commit: gitVersion.commit,
|
|
1431
|
+
dirty: gitVersion.dirty,
|
|
1432
|
+
builtAt: manifestBuiltAt,
|
|
1433
|
+
chunks: manifestChunks,
|
|
1434
|
+
notebooks: manifestNotebooks
|
|
1435
|
+
};
|
|
1436
|
+
(0, validation_exports.assertSeedManifest)(manifest);
|
|
1437
|
+
fs.writeFileSync(path.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
1438
|
+
const reportPath = writeBuildReport(outDir, {
|
|
1439
|
+
manifest,
|
|
1440
|
+
totalMs: Date.now() - t0,
|
|
1441
|
+
passMs,
|
|
1442
|
+
fileCount: paths.length});
|
|
1443
|
+
return { manifest, outDir, totalFiles, reportPath, passMs };
|
|
1340
1444
|
}
|
|
1341
|
-
var
|
|
1342
|
-
|
|
1445
|
+
var EMPTY_GIT_INDEX, gitHistoryCache, NON_EFFORT_SLUGS;
|
|
1446
|
+
var init_compiler = __esm({
|
|
1447
|
+
"src/seedbuild/compiler.ts"() {
|
|
1448
|
+
init_contract();
|
|
1449
|
+
init_filename();
|
|
1450
|
+
init_git_version();
|
|
1451
|
+
init_report();
|
|
1452
|
+
init_frontmatter();
|
|
1453
|
+
init_validation();
|
|
1454
|
+
EMPTY_GIT_INDEX = { files: /* @__PURE__ */ new Map(), dirs: /* @__PURE__ */ new Map() };
|
|
1455
|
+
gitHistoryCache = /* @__PURE__ */ new Map();
|
|
1456
|
+
NON_EFFORT_SLUGS = {
|
|
1457
|
+
"amrap": true,
|
|
1458
|
+
"emom": true,
|
|
1459
|
+
"tabata": true,
|
|
1460
|
+
"for-time": true,
|
|
1461
|
+
"rounds": true,
|
|
1462
|
+
"sets": true,
|
|
1463
|
+
"repetitions": true,
|
|
1464
|
+
"count-down": true,
|
|
1465
|
+
"total-reps": true,
|
|
1466
|
+
"warmup": true,
|
|
1467
|
+
"cooldown": true,
|
|
1468
|
+
"cool-down": true,
|
|
1469
|
+
"transition": true,
|
|
1470
|
+
"rest": true,
|
|
1471
|
+
"break": true,
|
|
1472
|
+
"work": true,
|
|
1473
|
+
"i-suck-at-this": true,
|
|
1474
|
+
"isuckatthis": true,
|
|
1475
|
+
"movement": true,
|
|
1476
|
+
"movement-you": true,
|
|
1477
|
+
"selected-exercise": true,
|
|
1478
|
+
"training-setup": true,
|
|
1479
|
+
"grade-system": true,
|
|
1480
|
+
"hangs": true,
|
|
1481
|
+
"warm-light-wind": true,
|
|
1482
|
+
"basin": true,
|
|
1483
|
+
"rock-canyon": true,
|
|
1484
|
+
"b-onsight": true,
|
|
1485
|
+
"a-redpoint": true,
|
|
1486
|
+
"d-redpoint": true,
|
|
1487
|
+
"v0-flash": true,
|
|
1488
|
+
"v2-flash": true,
|
|
1489
|
+
"v7-redpoint": true,
|
|
1490
|
+
"avgrpe-mean": true,
|
|
1491
|
+
"calculate": true,
|
|
1492
|
+
"totalload-sum": true,
|
|
1493
|
+
"query": true,
|
|
1494
|
+
"by": true,
|
|
1495
|
+
"": true,
|
|
1496
|
+
"-": true,
|
|
1497
|
+
"...": true,
|
|
1498
|
+
"x": true,
|
|
1499
|
+
"s": true,
|
|
1500
|
+
"bw": true
|
|
1501
|
+
};
|
|
1343
1502
|
}
|
|
1344
1503
|
});
|
|
1345
1504
|
|
|
@@ -1549,10 +1708,75 @@ async function storeRoutes(db, method, sub, url, req) {
|
|
|
1549
1708
|
}
|
|
1550
1709
|
return methodNotAllowed();
|
|
1551
1710
|
}
|
|
1552
|
-
|
|
1711
|
+
function isPublishedFeedAssetPath(pathname) {
|
|
1712
|
+
if (pathname === "/feed" || pathname === "/feed/") return "index.html";
|
|
1713
|
+
if (!pathname.startsWith("/feed/")) return null;
|
|
1714
|
+
const sub = pathname.slice("/feed/".length);
|
|
1715
|
+
if (sub === "index.html" || sub === "manifest.json" || sub === "report.html" || sub.startsWith("chunks/") || sub.startsWith("indexes/") || sub.startsWith("markdown/")) {
|
|
1716
|
+
return sub;
|
|
1717
|
+
}
|
|
1718
|
+
return null;
|
|
1719
|
+
}
|
|
1720
|
+
async function servePublishedFeed(feedTree, method, relPath) {
|
|
1721
|
+
if (method === "OPTIONS") {
|
|
1722
|
+
return new Response(null, {
|
|
1723
|
+
status: 204,
|
|
1724
|
+
headers: {
|
|
1725
|
+
"access-control-allow-origin": "*",
|
|
1726
|
+
"access-control-allow-methods": "GET, HEAD, OPTIONS"
|
|
1727
|
+
}
|
|
1728
|
+
});
|
|
1729
|
+
}
|
|
1730
|
+
if (method !== "GET") return methodNotAllowed();
|
|
1731
|
+
try {
|
|
1732
|
+
const decoded = decodeURIComponent(relPath);
|
|
1733
|
+
const bytes = await feedTree.read(decoded);
|
|
1734
|
+
const ext = decoded.includes(".") ? decoded.slice(decoded.lastIndexOf(".") + 1).toLowerCase() : "html";
|
|
1735
|
+
const cache = decoded.startsWith("chunks/") ? "public, max-age=31536000, immutable" : "no-cache";
|
|
1736
|
+
const copy = new Uint8Array(bytes.byteLength);
|
|
1737
|
+
copy.set(bytes);
|
|
1738
|
+
return new Response(copy.buffer, {
|
|
1739
|
+
status: 200,
|
|
1740
|
+
headers: {
|
|
1741
|
+
"content-type": MIME[ext] ?? "application/octet-stream",
|
|
1742
|
+
"cache-control": cache,
|
|
1743
|
+
"access-control-allow-origin": "*"
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
} catch (err) {
|
|
1747
|
+
if (err instanceof wod_wiki_engine_star.FeedTreeError && err.code === "not-found") return notFound();
|
|
1748
|
+
if (err instanceof wod_wiki_engine_star.FeedTreeError && err.code === "layout") return plain("forbidden", 403);
|
|
1749
|
+
throw err;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
async function apiRoutes(db, feedTree, req, method, sub, url) {
|
|
1553
1753
|
if (sub === "/health") {
|
|
1554
1754
|
return json({ ok: true, driver: db.dialect }, 200);
|
|
1555
1755
|
}
|
|
1756
|
+
if (sub === "/v1/feed/status" && method === "GET") {
|
|
1757
|
+
const storage = new sql.SqlStorage(db);
|
|
1758
|
+
const status = await wod_wiki_engine_star.checkUnpublishedFeedChanges(storage, feedTree);
|
|
1759
|
+
return json({ ...status, feedUrl: `${url.origin}/feed/` }, 200);
|
|
1760
|
+
}
|
|
1761
|
+
if (sub === "/v1/feed/publish" && method === "POST") {
|
|
1762
|
+
const body = req.headers.get("content-length") === "0" ? {} : await readJsonBody(req).catch(() => ({}));
|
|
1763
|
+
const opts = typeof body === "object" && body !== null ? body : {};
|
|
1764
|
+
const storage = new sql.SqlStorage(db);
|
|
1765
|
+
const report = await wod_wiki_engine_star.publishFeedFromStorage(storage, feedTree, {
|
|
1766
|
+
layout: "feed",
|
|
1767
|
+
...typeof opts.name === "string" ? { name: opts.name } : {},
|
|
1768
|
+
...typeof opts.description === "string" ? { description: opts.description } : {},
|
|
1769
|
+
...typeof opts.repositoryUrl === "string" ? { repositoryUrl: opts.repositoryUrl } : {},
|
|
1770
|
+
...typeof opts.notebookSlug === "string" ? { notebookSlug: opts.notebookSlug } : {}
|
|
1771
|
+
});
|
|
1772
|
+
return json({
|
|
1773
|
+
manifest: report.manifest,
|
|
1774
|
+
notebooks: report.notebooks,
|
|
1775
|
+
totalNotes: report.totalNotes,
|
|
1776
|
+
totalPublicSessions: report.totalPublicSessions,
|
|
1777
|
+
feedUrl: `${url.origin}/feed/`
|
|
1778
|
+
}, 200);
|
|
1779
|
+
}
|
|
1556
1780
|
if (sub === "/v1/wipe" && method === "POST") {
|
|
1557
1781
|
await db.transaction(async (tx) => {
|
|
1558
1782
|
await sql.wipeRows(tx);
|
|
@@ -1585,13 +1809,22 @@ function distRootOf(playgroundDist) {
|
|
|
1585
1809
|
}
|
|
1586
1810
|
function createHandler(db, options) {
|
|
1587
1811
|
const distRoot = distRootOf(options.playgroundDist);
|
|
1812
|
+
const feedTree = options.feedTree ?? (options.feedDir ? new NodeFsFeedTree(options.feedDir) : new wod_wiki_engine_star.MemoryFeedTree());
|
|
1588
1813
|
return async (request) => {
|
|
1589
1814
|
try {
|
|
1590
1815
|
const url = new URL(request.url);
|
|
1591
1816
|
const method = request.method === "HEAD" ? "GET" : request.method;
|
|
1592
1817
|
const path = url.pathname;
|
|
1593
|
-
|
|
1594
|
-
|
|
1818
|
+
if (path === "/api" || path.startsWith("/api/")) {
|
|
1819
|
+
return db ? await apiRoutes(db, feedTree, request, method, path.slice("/api".length) || "/", url) : notFound();
|
|
1820
|
+
}
|
|
1821
|
+
if (db) {
|
|
1822
|
+
const feedAsset = isPublishedFeedAssetPath(path);
|
|
1823
|
+
if (feedAsset !== null) {
|
|
1824
|
+
return await servePublishedFeed(feedTree, request.method === "OPTIONS" ? "OPTIONS" : method, feedAsset);
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
return await staticResponse(distRoot, method, path);
|
|
1595
1828
|
} catch (e) {
|
|
1596
1829
|
if (e instanceof HttpError || e instanceof sql.StorageError) {
|
|
1597
1830
|
const status = e.status;
|
|
@@ -1609,6 +1842,7 @@ var json, plain, notFound, methodNotAllowed, noContent, qget, MIME;
|
|
|
1609
1842
|
var init_app = __esm({
|
|
1610
1843
|
"src/server/app.ts"() {
|
|
1611
1844
|
init_errors();
|
|
1845
|
+
init_nodeFeedTree();
|
|
1612
1846
|
json = (value, status) => new Response(JSON.stringify(value), { status, headers: { "content-type": "application/json" } });
|
|
1613
1847
|
plain = (body, status) => new Response(body, { status, headers: { "content-type": "text/plain; charset=utf-8" } });
|
|
1614
1848
|
notFound = () => json({ error: "not found" }, 404);
|
|
@@ -1635,7 +1869,10 @@ var init_app = __esm({
|
|
|
1635
1869
|
wav: "audio/wav",
|
|
1636
1870
|
webmanifest: "application/manifest+json",
|
|
1637
1871
|
xml: "application/xml",
|
|
1638
|
-
txt: "text/plain; charset=utf-8"
|
|
1872
|
+
txt: "text/plain; charset=utf-8",
|
|
1873
|
+
md: "text/markdown; charset=utf-8",
|
|
1874
|
+
jsonl: "application/x-ndjson; charset=utf-8",
|
|
1875
|
+
csv: "text/csv; charset=utf-8"
|
|
1639
1876
|
};
|
|
1640
1877
|
}
|
|
1641
1878
|
});
|
|
@@ -1766,7 +2003,8 @@ async function runCliServer(mode, options, writeOut) {
|
|
|
1766
2003
|
let server;
|
|
1767
2004
|
try {
|
|
1768
2005
|
const dist = resolveDist(mode, options);
|
|
1769
|
-
const
|
|
2006
|
+
const feedDir = mode === "server" && options.database?.kind === "sqlite" ? `${options.database.path}.feed` : void 0;
|
|
2007
|
+
const handler = createHandler(db?.db ?? null, { playgroundDist: dist, feedDir });
|
|
1770
2008
|
server = await startHttpServer(handler, host, port);
|
|
1771
2009
|
if (mode === "server") {
|
|
1772
2010
|
writeOut(`wod server: http://${host}:${port} \u2014 ${dbLabel} \xB7 dist ${dist}`);
|
|
@@ -3474,145 +3712,37 @@ function defaultSeedDirs(cwd) {
|
|
|
3474
3712
|
|
|
3475
3713
|
// src/cli/publish.ts
|
|
3476
3714
|
init_db();
|
|
3477
|
-
|
|
3478
|
-
init_compiler();
|
|
3715
|
+
init_nodeFeedTree();
|
|
3479
3716
|
init_report();
|
|
3480
3717
|
async function publishNotebookSeed(db, options) {
|
|
3481
3718
|
const t0 = Date.now();
|
|
3482
|
-
const fs = nodeFs();
|
|
3483
|
-
const path = nodePath();
|
|
3484
3719
|
const allNotes = await db.storage.readonly("notes").getAll();
|
|
3485
3720
|
if (allNotes.length === 0) {
|
|
3486
3721
|
throw new Error(`[wod publish] No notes found in database ${db.path}`);
|
|
3487
3722
|
}
|
|
3488
|
-
const
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
targetNotebooks.set(options.notebook, matching);
|
|
3501
|
-
} else if (notesByNotebook.has("__unassigned__") && notesByNotebook.size === 1) {
|
|
3502
|
-
targetNotebooks.set(options.notebook, notesByNotebook.get("__unassigned__"));
|
|
3503
|
-
} else {
|
|
3504
|
-
const available = [...notesByNotebook.keys()].filter((k) => k !== "__unassigned__");
|
|
3505
|
-
throw new Error(
|
|
3506
|
-
`[wod publish] Notebook "${options.notebook}" not found in ${db.path}.` + (available.length > 0 ? ` Available notebooks: ${available.join(", ")}` : "")
|
|
3507
|
-
);
|
|
3508
|
-
}
|
|
3509
|
-
} else {
|
|
3510
|
-
for (const [slug, notes] of notesByNotebook.entries()) {
|
|
3511
|
-
targetNotebooks.set(slug === "__unassigned__" ? "default" : slug, notes);
|
|
3512
|
-
}
|
|
3513
|
-
}
|
|
3514
|
-
const allIndexRows = await db.storage.readonly("block_index").getAll();
|
|
3515
|
-
const allEffortRows = await db.storage.readonly("block_efforts").getAll();
|
|
3516
|
-
const allEquipmentRows = await db.storage.readonly("block_equipment").getAll();
|
|
3517
|
-
const indexByNote = /* @__PURE__ */ new Map();
|
|
3518
|
-
for (const row of allIndexRows) {
|
|
3519
|
-
const list = indexByNote.get(row.noteId) ?? [];
|
|
3520
|
-
list.push(row);
|
|
3521
|
-
indexByNote.set(row.noteId, list);
|
|
3522
|
-
}
|
|
3523
|
-
const effortsByNote = /* @__PURE__ */ new Map();
|
|
3524
|
-
for (const row of allEffortRows) {
|
|
3525
|
-
const list = effortsByNote.get(row.noteId) ?? [];
|
|
3526
|
-
list.push(row);
|
|
3527
|
-
effortsByNote.set(row.noteId, list);
|
|
3528
|
-
}
|
|
3529
|
-
const equipmentByNote = /* @__PURE__ */ new Map();
|
|
3530
|
-
for (const row of allEquipmentRows) {
|
|
3531
|
-
const list = equipmentByNote.get(row.noteId) ?? [];
|
|
3532
|
-
list.push(row);
|
|
3533
|
-
equipmentByNote.set(row.noteId, list);
|
|
3534
|
-
}
|
|
3535
|
-
const outDir = path.resolve(process.cwd(), options.outDir);
|
|
3536
|
-
const chunksDir = path.join(outDir, "chunks");
|
|
3537
|
-
fs.mkdirSync(chunksDir, { recursive: true });
|
|
3538
|
-
const manifestChunks = [];
|
|
3539
|
-
let totalNotes = 0;
|
|
3540
|
-
const publishedNotebooks = [];
|
|
3541
|
-
for (const [notebookSlug, notes] of targetNotebooks.entries()) {
|
|
3542
|
-
publishedNotebooks.push(notebookSlug);
|
|
3543
|
-
const chunkRows = [];
|
|
3544
|
-
for (const note of notes) {
|
|
3545
|
-
const stem = (note.title || note.id).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") || "note";
|
|
3546
|
-
const notePath = note.sourcePath ?? `markdown/notebooks/${notebookSlug}/${stem}.md`;
|
|
3547
|
-
const noteBlockIndex = indexByNote.get(note.id) ?? [];
|
|
3548
|
-
const noteBlockEfforts = effortsByNote.get(note.id) ?? [];
|
|
3549
|
-
const noteBlockEquipment = equipmentByNote.get(note.id) ?? [];
|
|
3550
|
-
const blockIndex = noteBlockIndex.length > 0 ? noteBlockIndex.map((b) => ({
|
|
3551
|
-
...b,
|
|
3552
|
-
isStatic: true,
|
|
3553
|
-
sourceId: b.sourceId ?? `notebook:${notebookSlug}/${stem}`,
|
|
3554
|
-
sourcePath: b.sourcePath ?? notePath
|
|
3555
|
-
})) : compileSeedRow(notePath, note.rawContent, {
|
|
3556
|
-
routeId: `${notebookSlug}/${stem}`,
|
|
3557
|
-
sourceId: `notebook:${notebookSlug}/${stem}`,
|
|
3558
|
-
// Authored frontmatter date first — exports keep the post's own
|
|
3559
|
-
// day, never the import/publish time.
|
|
3560
|
-
createdAt: note.date ?? note.createdAt,
|
|
3561
|
-
noteTitle: note.title
|
|
3562
|
-
}).blockIndex;
|
|
3563
|
-
const blockEfforts = noteBlockEfforts.map((e) => ({
|
|
3564
|
-
...e,
|
|
3565
|
-
isStatic: true,
|
|
3566
|
-
sourcePath: e.sourcePath ?? notePath
|
|
3567
|
-
}));
|
|
3568
|
-
const blockEquipment = noteBlockEquipment.map((e) => ({
|
|
3569
|
-
...e,
|
|
3570
|
-
isStatic: true,
|
|
3571
|
-
sourcePath: e.sourcePath ?? notePath
|
|
3572
|
-
}));
|
|
3573
|
-
chunkRows.push({
|
|
3574
|
-
path: notePath,
|
|
3575
|
-
content: note.rawContent,
|
|
3576
|
-
blocks: note.blocks,
|
|
3577
|
-
blockIndex,
|
|
3578
|
-
blockEfforts,
|
|
3579
|
-
blockEquipment
|
|
3580
|
-
});
|
|
3581
|
-
}
|
|
3582
|
-
const chunkId = `notebook.${notebookSlug}`;
|
|
3583
|
-
const json2 = JSON.stringify(chunkRows);
|
|
3584
|
-
const digest = nodeCrypto().createHash("sha256").update(json2).digest();
|
|
3585
|
-
const sha = [...digest].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3586
|
-
const chunkFile = `chunks/${chunkId}.${sha.slice(0, 8)}.json`;
|
|
3587
|
-
fs.writeFileSync(path.join(outDir, chunkFile), json2, "utf-8");
|
|
3588
|
-
manifestChunks.push({
|
|
3589
|
-
id: chunkId,
|
|
3590
|
-
path: chunkFile,
|
|
3591
|
-
sha256: sha,
|
|
3592
|
-
bytes: Buffer.byteLength(json2, "utf8"),
|
|
3593
|
-
count: chunkRows.length,
|
|
3594
|
-
kind: "notes"
|
|
3595
|
-
});
|
|
3596
|
-
totalNotes += chunkRows.length;
|
|
3597
|
-
}
|
|
3598
|
-
const manifest = {
|
|
3599
|
-
schema: contract_exports.SEED_SCHEMA,
|
|
3600
|
-
version: options.version ?? 1,
|
|
3601
|
-
versionLabel: `v${options.version ?? 1}`,
|
|
3602
|
-
builtAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3603
|
-
chunks: manifestChunks
|
|
3604
|
-
};
|
|
3605
|
-
fs.writeFileSync(path.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
3723
|
+
const outDir = nodePath().resolve(process.cwd(), options.outDir);
|
|
3724
|
+
const tree = new NodeFsFeedTree(outDir);
|
|
3725
|
+
const report = await wod_wiki_engine_star.publishFeedFromStorage(db.storage, tree, {
|
|
3726
|
+
layout: "feed",
|
|
3727
|
+
notebookSlug: options.notebook,
|
|
3728
|
+
version: options.version,
|
|
3729
|
+
name: options.name,
|
|
3730
|
+
description: options.description,
|
|
3731
|
+
repositoryUrl: options.repositoryUrl,
|
|
3732
|
+
includePrivateWhenFiltered: true
|
|
3733
|
+
});
|
|
3734
|
+
const elapsed = Math.max(1, Date.now() - t0);
|
|
3606
3735
|
writeBuildReport(outDir, {
|
|
3607
|
-
manifest,
|
|
3608
|
-
totalMs:
|
|
3609
|
-
passMs: { scan: 0, blockIndex: 0, parseGate: 0, blockEfforts: 0, write:
|
|
3610
|
-
fileCount: totalNotes});
|
|
3736
|
+
manifest: report.manifest,
|
|
3737
|
+
totalMs: elapsed,
|
|
3738
|
+
passMs: { scan: 0, blockIndex: 0, parseGate: 0, blockEfforts: 0, write: elapsed },
|
|
3739
|
+
fileCount: report.totalNotes});
|
|
3611
3740
|
return {
|
|
3612
|
-
manifest,
|
|
3741
|
+
manifest: report.manifest,
|
|
3613
3742
|
outDir,
|
|
3614
|
-
notebooks:
|
|
3615
|
-
totalNotes
|
|
3743
|
+
notebooks: report.notebooks,
|
|
3744
|
+
totalNotes: report.totalNotes,
|
|
3745
|
+
totalPublicSessions: report.totalPublicSessions
|
|
3616
3746
|
};
|
|
3617
3747
|
}
|
|
3618
3748
|
|
|
@@ -3990,13 +4120,13 @@ function parseCliArgs(args) {
|
|
|
3990
4120
|
i++;
|
|
3991
4121
|
} else if (arg === "--format") {
|
|
3992
4122
|
const fmt = args[++i];
|
|
3993
|
-
if (fmt === "json" || fmt === "table" || fmt === "csv") {
|
|
4123
|
+
if (fmt === "json" || fmt === "table" || fmt === "csv" || fmt === "jsonl") {
|
|
3994
4124
|
result.format = fmt;
|
|
3995
4125
|
}
|
|
3996
4126
|
i++;
|
|
3997
4127
|
} else if (arg.startsWith("--format=")) {
|
|
3998
4128
|
const fmt = arg.slice("--format=".length);
|
|
3999
|
-
if (fmt === "json" || fmt === "table" || fmt === "csv") {
|
|
4129
|
+
if (fmt === "json" || fmt === "table" || fmt === "csv" || fmt === "jsonl") {
|
|
4000
4130
|
result.format = fmt;
|
|
4001
4131
|
}
|
|
4002
4132
|
i++;
|
|
@@ -4623,12 +4753,28 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
|
|
|
4623
4753
|
writeErr(`[wod ${verb}] Session not found in ${db.path}: ${id}`);
|
|
4624
4754
|
return 1;
|
|
4625
4755
|
}
|
|
4626
|
-
const
|
|
4627
|
-
const
|
|
4756
|
+
const wantsJsonl = parsed.format === "jsonl" || parsed.output !== void 0 && /\.jsonl$/i.test(parsed.output);
|
|
4757
|
+
const defaultExt = wantsJsonl ? "jsonl" : "csv";
|
|
4758
|
+
const target = parsed.output && parsed.output !== "-" ? parsed.output : `${id}.${defaultExt}`;
|
|
4759
|
+
let payload;
|
|
4760
|
+
if (wantsJsonl) {
|
|
4761
|
+
const rev = await db.storage.readonly("block_revisions").get([
|
|
4762
|
+
bundle.session.noteId,
|
|
4763
|
+
bundle.session.blockId,
|
|
4764
|
+
bundle.session.blockVersion
|
|
4765
|
+
]);
|
|
4766
|
+
payload = wod_wiki_engine_star.serializeNoteBundleToJsonl({
|
|
4767
|
+
...rev ? { revisions: [rev] } : {},
|
|
4768
|
+
sessions: [bundle.session],
|
|
4769
|
+
events: bundle.events
|
|
4770
|
+
}) + "\n";
|
|
4771
|
+
} else {
|
|
4772
|
+
payload = wod_wiki_engine_star.sessionToCsv(bundle.session, bundle.events);
|
|
4773
|
+
}
|
|
4628
4774
|
if (parsed.output === "-") {
|
|
4629
|
-
writeOut(
|
|
4775
|
+
writeOut(payload.trimEnd());
|
|
4630
4776
|
} else {
|
|
4631
|
-
nodeFs().writeFileSync(target,
|
|
4777
|
+
nodeFs().writeFileSync(target, payload, "utf-8");
|
|
4632
4778
|
}
|
|
4633
4779
|
if (parsed.output !== "-") writeOut(`[wod ${verb}] session ${id} \u2192 ${target} (${bundle.events.length} events)`);
|
|
4634
4780
|
} else if (kind === "effort") {
|
|
@@ -4748,13 +4894,25 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
|
|
|
4748
4894
|
}
|
|
4749
4895
|
return 0;
|
|
4750
4896
|
}
|
|
4751
|
-
const
|
|
4897
|
+
const rawSessionText = fs.readFileSync(file, "utf-8");
|
|
4752
4898
|
const db = await openCliDb(cliDb());
|
|
4753
4899
|
try {
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4900
|
+
if (/\.jsonl$/i.test(file)) {
|
|
4901
|
+
const report = await wod_wiki_engine_star.ingestPortableFilesIntoStorage(db.storage, [{ path: file, content: rawSessionText }]);
|
|
4902
|
+
if (report.errors.length > 0 && report.sessionsImported === 0) {
|
|
4903
|
+
writeErr(`[wod import] ${report.errors.join("; ")}`);
|
|
4904
|
+
return 1;
|
|
4905
|
+
}
|
|
4906
|
+
writeOut(
|
|
4907
|
+
`[wod import] session jsonl \u2014 ${report.sessionsImported} session(s), ${report.eventsImported} events \u2192 ${db.path}`
|
|
4908
|
+
);
|
|
4909
|
+
} else {
|
|
4910
|
+
const { session, events } = wod_wiki_engine_star.csvToSessionRows(rawSessionText);
|
|
4911
|
+
const result = await persistSessionBundle(db, session, events);
|
|
4912
|
+
writeOut(
|
|
4913
|
+
`[wod import] session ${session.id} \u2014 ${result.events} events \u2192 ${db.path}`
|
|
4914
|
+
);
|
|
4915
|
+
}
|
|
4758
4916
|
} finally {
|
|
4759
4917
|
await db.close();
|
|
4760
4918
|
}
|