Domain · Specifications

Shakti Domain — Technical Specifications

five modules: types.ts, schemas.ts, db-schema.ts, events.ts, auth.ts.

9sections23 minread

On this page

Shakti — Physical Discipline and Movement Intelligence Platform

This document specifies what is implemented in libs/shakti/*. Shakti is a pure library domain: 28 Nx library projects, no apps/shakti and no services/shakti. Every library is a self-contained TypeScript package with an empty dependencies map — there are no runtime npm dependencies and no cross-domain imports anywhere in libs/shakti/. @shakti/core is the only library other Shakti libraries would build on; in the current source even that coupling is not yet wired (libraries re-declare their own local types).

The dominant implementation pattern is a knowledge-base / configuration registry: each source module declares typed, domain-specific records (e.g. heart-rate zones, periodization presets, asana taxonomy, API endpoint configurations), registers them into module-level Map stores, and exposes getAll*(), get*ById(), search*(), count*(), and reset*Store() accessors plus pure calculation helpers. This specification documents the parts of that surface that are stable and load-bearing.


1. Core Foundation (@shakti/core)#

@shakti/core is the foundation library. Its barrel (src/index.ts) re-exports five modules: types.ts, schemas.ts, db-schema.ts, events.ts, auth.ts. Each section below documents one of these modules in detail.

1.1 Result<T, E> (types.ts)#

Shakti uses a discriminated-union outcome type for domain operations instead of throwing exceptions. This allows callers to handle domain errors without try/catch, and keeps the error handling surface explicit and type-safe.

Member Shape Meaning
Ok<T> { ok: true; value: T } Success
Err<E> { ok: false; error: E } Failure
Result<T, E = Error> Ok<T> | Err<E> Union

Constructors and combinators: ok, err, isOk, isErr, unwrap, unwrapOr, mapResult, mapError, flatMap, tryCatch, tryCatchAsync.

Domain error type ShaktiError carries { code, message, details? }. The SHAKTI_ERROR_CODES constant enumerates twelve codes: INVALID_INPUT, NOT_FOUND, UNAUTHORIZED, FORBIDDEN, CONFLICT, EXERCISE_UNSAFE, INJURY_RESTRICTION, PROGRAM_INVALID, SESSION_EXPIRED, EQUIPMENT_MISSING, PREREQUISITE_UNMET, OVERTRAINING_RISK. ShaktiResult<T> aliases Result<T, ShaktiError>.

1.2 Movement and anatomy taxonomy (types.ts)#

The movement and anatomy taxonomy is the shared vocabulary used throughout the domain. Every exercise, technique, and form-analysis result references these types — they are the conceptual atoms of the Shakti type system.

Type Values
MovementPattern push, pull, hinge, squat, lunge, rotate, gait, carry, brace, anti_rotation, crawl, climb, throw, strike (14)
BodyRegion upper_body, lower_body, core, full_body
UpperBodySubRegion chest, upper_back, lower_back, shoulders, biceps, triceps, forearms, neck, traps
LowerBodySubRegion quadriceps, hamstrings, glutes, calves, hip_flexors, adductors, abductors, tibialis
CoreSubRegion rectus_abdominis, obliques, transverse_abdominis, erector_spinae, pelvic_floor, diaphragm
MuscleGroup 76 individually-named muscles (chest, shoulders, back, arms, forearms, core, glutes, quads, hamstrings, adductors, calves, neck), exported as ALL_MUSCLE_GROUPS
JointType shoulder, elbow, wrist, hip, knee, ankle, spine_cervical, spine_thoracic, spine_lumbar, sacroiliac, metacarpophalangeal, interphalangeal, temporomandibular (13)

BODY_REGION_MAP maps each region to its sub-regions; getBodyRegionForSubRegion resolves the reverse. JOINT_ROM_NORMS holds normative range-of-motion data (flexion / extension and optional abduction, adduction, rotation, lateral flexion, internal/external rotation) per joint; getJointROM(joint) looks one up.

1.3 Training value objects (types.ts)#

Training value objects model the building blocks of how exercise is prescribed. Rather than embedding raw numbers in workout records, these types carry semantic meaning — a Tempo is not just four integers but a named set of eccentric, pause, concentric, and pause phases with helpers to format and compute total time. This prevents ambiguity when workouts are serialized, shared, or analysed.

  • DifficultyScalebeginner, intermediate, advanced, elite, master. Ordered via DIFFICULTY_ORDER; compared with compareDifficulty and isDifficultyAtLeast.
  • IntensityLevellow, moderate, high, very_high, maximal. getIntensityHRPercent(level) returns a heart-rate % band.
  • Duration{ seconds } value object with durationFromSeconds/Minutes/Hours, durationToMinutes/Hours, formatDuration, addDurations.
  • Tempo{ eccentric, pauseBottom, concentric, pauseTop }. Helpers: createTempo, tempoTotalSeconds, formatTempo. Seven TEMPO_PRESETS (controlled, explosive, time_under_tension, isometric, normal, eccentric_focus, speed).
  • RepRange{ min, max, target } with createRepRange and five REP_RANGE_PRESETS (strength, power, hypertrophy, muscular_endurance, endurance).
  • SetTypestraight, drop, super, giant, cluster, rest_pause, myo_rep, pyramid, reverse_pyramid, amrap, emom, tabata (12). SetConfiguration bundles { type, sets, repRange, restBetweenSets }.
  • RestPeriod{ duration, mode, activity? } with RestMode of active / passive; five REST_PRESETS.
  • EquipmentCategory — 14 categories (barbell, dumbbell, kettlebell, machine, cable, band, bodyweight, cardio, yoga, martial_arts, recovery, specialty, outdoor, home). EQUIPMENT_CATALOG holds 75 EquipmentItem records (id, name, category, portability, spaceRequired); getEquipmentByCategory and getPortableEquipment filter it.
  • PhysicalAttributes — height, weight, optional wingspan, body-fat, resting/max HR, VO2max, measurement system. Helpers: estimateMaxHR(age) (220 − age), calculateBMI, getBMICategory.
  • FitnessAssessment — eight scored qualities (cardiovascular, strength, flexibility, balance, power, endurance, agility, coordination). computeOverallFitness averages them; getFitnessLevel(score) maps a 0–100 score to a DifficultyScale.
  • InjuryStatus{ id, bodyPart, severity, phase, description, dateReported, restrictions }. InjurySeverity ∈ {minor, moderate, severe, critical}; InjuryPhase ∈ {acute, subacute, chronic, rehabilitation, return_to_sport}.
  • MovementRestrictionRestrictionType ∈ {avoid, reduce_load, reduce_rom, modify_tempo, use_alternative}, with affected patterns / joints and optional load/ROM caps. isExerciseSafe(patterns, joints, restrictions) returns whether an exercise clears the avoid restrictions.
  • EnergySystemphosphagen, glycolytic, oxidative. ENERGY_SYSTEMS documents duration and intensity ranges; dominantEnergySystem(durationSeconds) selects one.
  • TrainingGoal — 20 goal values, exported as ALL_TRAINING_GOALS.
  • Lateralityunilateral, bilateral, alternating, ipsilateral, contralateral. PlaneOfMotionsagittal, frontal, transverse, multiplanar (with PLANE_DESCRIPTIONS). ForceVector — six values with FORCE_VECTOR_EXAMPLES.
  • LoadTypeabsolute, relative, bodyweight_percentage, rpe, rir, percentage_1rm. LoadPrescription builders: createAbsoluteLoad, createRelativeLoad, createRPELoad (validates 1–10), createRIRLoad. rpeToRIR / rirToRPE convert between RPE and reps-in-reserve.
  • ProgressionModelTypelinear, undulating, block, conjugate, step_loading, autoregulated. PROGRESSION_PRESETS provides a ProgressionModel per type with weekly increment, deload frequency, and deload percentage.

1.4 Validation schemas (schemas.ts)#

schemas.ts defines TypeScript interfaces plus hand-written validate* functions that return readonly string[] of error messages (empty = valid). Validation is plain TypeScript — there is no Zod, Yup, or Joi in this domain.

The foundational enums define the platform's disciplinary vocabulary. These values appear throughout the rest of the codebase — in technique records, session logs, program schemas, and the database schema — so knowing them is essential context:

Type Values (count)
Discipline yoga, martial_arts, strength_training, combat_sports, calisthenics, cardio, mobility, dance, pilates, crossfit, functional_training, olympic_weightlifting, powerlifting, strongman, gymnastics, swimming, running, cycling, rowing, climbing (20) — exported as ALL_DISCIPLINES
YogaStyle hatha, vinyasa, ashtanga, iyengar, bikram, yin, restorative, kundalini, power, jivamukti, anusara, sivananda, forrest, rocket, aerial (15)
MartialArtStyle 28 styles (BJJ, judo, three karate variants, two taekwondo variants, Muay Thai, boxing, kickboxing, wing chun, aikido, krav maga, hapkido, capoeira, sambo, three wrestling variants, two kung fu variants, tai chi, MMA, kendo, fencing, savate, lethwei, sanda, pencak silat)
DifficultyLevel beginner, intermediate, advanced, elite, master
MeasurementSystem metric, imperial
Gender male, female, non_binary, prefer_not_to_say

The schema interfaces and their validation functions cover the complete data surface of the platform. Each interface has a paired validate* function that returns an array of error strings — an empty array means the record is valid:

  • TechniqueSchema / validateTechnique — id, name, discipline, optional style, difficulty, description, instruction steps, common mistakes, target + synergy muscles, optional breathing pattern, contraindications, prerequisites, media URLs.
  • ExerciseSchema / validateExerciseExerciseCategory ∈ {compound, isolation, plyometric, isometric, ballistic, flexibility, balance, cardio, core, corrective}; movement patterns, planes, primary/secondary/stabilizer muscles, joints, required/optional equipment, laterality, force vector, instructions, cues, common mistakes, regressions, progressions, alternatives, contraindications, media.
  • WorkoutSchema + WorkoutBlockSchema + WorkoutExerciseSchema / validateWorkoutWorkoutType has 16 values (strength, hypertrophy, endurance, hiit, circuit, yoga_flow, martial_arts_drill, sparring, technique, mobility, recovery, sport_specific, competition, assessment, warmup, cooldown). A workout has an optional warmup block, one-or-more main blocks, and an optional cooldown block.
  • ProgramSchema + ProgramPhaseSchema / validateProgramProgramGoal (10 values), PeriodizationType ∈ {linear, undulating, block, conjugate, concurrent, reverse_linear}; duration weeks, days per week (1–7), and one-or-more phases each with a week range, focus, intensity range, volume multiplier, deload flag, and workout IDs.
  • SessionSchema + SessionExerciseData + SessionSetData / validateSessionSessionStatus ∈ {planned, in_progress, completed, paused, skipped, cancelled}. A session records practitioner, optional workout/program, discipline, type, start/end times, planned/actual duration, per-exercise set data, totals (volume, sets, reps), optional calories, heart rates, perceived exertion (1–10), mood (1–10), and energy level.
  • PractitionerSchema / validatePractitioner — user id, display name, optional demographics, measurement system, disciplines, goals, fitness level, experience years, available equipment, available days/week, session duration preference, injuries, restrictions, timezone, timestamps.
  • BeltRankSchema / validateBeltRankBeltColor ∈ {white, yellow, orange, green, blue, purple, brown, red, black, coral, red_white}; style, optional degree, order, minimum time in months, requirements.
  • AchievementSchema + AchievementCondition / validateAchievementAchievementCategory (10 values), AchievementRarity ∈ {common, uncommon, rare, epic, legendary}; xp reward, one-or-more conditions (metric / operator / value), secret flag.
  • ChallengeSchema / validateChallengeChallengeType ∈ {streak, volume, consistency, skill, competition, team, seasonal}; duration, date window, target value/metric, optional participant cap, rewards, rules.
  • InstructorSchema + CertificationSchema / validateInstructor — bio, disciplines, styles, certifications, years of experience, specializations, rating (0–5), student/class counts, verification flag, languages.
  • ClassSchema / validateClassClassFormat ∈ {in_person, virtual, hybrid, on_demand}; instructor, discipline, difficulty, duration, capacity, enrollment, scheduled time, optional recurrence, location, virtual meeting URL, equipment, price/currency.
  • GoalSchema + GoalMilestoneSchema / validateGoal — title, target / current value, unit, optional deadline, milestones, completion flag.

schemas.ts also provides standalone calculation helpers that derive numeric results from schema data: checkEquipmentAvailability, calculateVolume, calculateOneRepMax (Brzycki formula w · 36/(37−reps)), calculateWeightForReps, calculateTotalSessionVolume, calculateSessionDensity, calculateFormScore, calculateTrainingAge.

1.5 Authorization (auth.ts)#

Role-based access control is implemented as static permission tables evaluated at call time. There is no middleware framework or runtime token-signing — this module is pure logic that any application layer can call to enforce access rules.

  • ShaktiRolepractitioner, instructor, studio_owner, admin, moderator, content_creator, guest. ROLE_HIERARCHY assigns numeric ranks (guest 0 → admin 100); isRoleAtLeast / compareRoles order them.
  • ResourceType — 16 resources (exercise, technique, workout, program, session, practitioner_profile, class, achievement, challenge, instructor_profile, studio, certification, belt_rank, comment, media, analytics).
  • Actioncreate, read, update, delete, publish, enroll, manage.
  • Permission{ resource, action, scope } with scope ∈ {own, assigned, all}. PermissionKey is the templated string `${resource}:${action}:${scope}`.
  • Per-role permission arrays are defined for all seven roles; getPermissionsForRole(role) returns them.
  • checkPermission(ctx, resource, action, resourceOwnerId?) evaluates an AuthContext against the permission set, checking all then own then assigned scope, and returns an AuthorizationResult ({ allowed, reason?, matchedPermission? }).
  • Token helpers: TokenClaims, isTokenExpired, getTokenRemainingSeconds, tokenClaimsToAuthContext. API-key helpers: ApiKeyConfig, validateApiKeyAccess (checks expiry, allowed resources, then permission).

This is a pure authorization-logic library; it performs no token signing, network calls, or session storage.


2. Discipline Domain Objects#

Each discipline library is a knowledge base of typed records. The common pattern across all five disciplines is: typed record interfaces declared locally, records registered into module-level Map stores at module initialization, and getAll* / get*ById / search* accessors exported for querying. Field and enum definitions are local to each module — they share no cross-library imports.

2.1 @shakti/yoga#

Six modules (asanas, pranayama, sequences, styles, meditation, ayurveda). Asana taxonomy includes AsanaCategory (11 values: standing, seated, prone, supine, inversion, balance, twist, backbend, forward fold, arm balance, hip opener), and yoga-specific concepts modelled as types:

  • Chakra — 7 energy centres
  • Doshavata / pitta / kapha (Ayurvedic constitutions)
  • Drishti — 8 traditional gaze points used during asana practice
  • Bandhamula, uddiyana, jalandhara, maha (energy locks)
  • PropType — 9 supported yoga props (blocks, straps, bolsters, etc.)
  • EngagementLevelprimary, secondary, stabilizer, stretched

pranayama covers breathwork techniques; sequences covers sequence construction; ayurveda covers dosha-based personalization.

2.2 @shakti/strength#

Eight modules: exercises, compounds, olympic, calisthenics, programs, powerlifting, hypertrophy, programs. programs.ts ships 15 complete program templates plus 5 deload protocols spanning linear progression, undulating, block, and conjugate periodization. These are fully specified multi-week templates — not just parameter ranges, but complete program structures with phases, loading schemes, and deload triggers.

2.3 @shakti/martial-arts#

Eight modules: techniques, striking, grappling, mma, traditional, weapons, ranks, sparring.

  • weapons.ts covers bo staff, nunchaku, sword, kendo, kali, and HEMA (Historical European Martial Arts)
  • ranks.ts covers belt/rank progression across multiple martial art styles
  • sparring.ts covers sparring and competition formats with scoring and matchmaking

2.4 @shakti/combat-sports#

Five modules: boxing, kickboxing, muay-thai, wrestling, mma-training. Boxing alone covers stances, footwork, shadowboxing, bag and pad work, conditioning, rulesets, training camps, and weight-cutting protocols — showing the depth of coverage: each module models the full sport preparation lifecycle, not just a technique list.

2.5 @shakti/mobility#

Six modules: stretching, joint-mobility, smr (self-myofascial release), recovery, injury-prevention, rehabilitation. The rehabilitation module includes graduated return-to-training protocols with clearance checkpoints, making the library useful for practitioners coming back from injury as well as healthy practitioners maintaining movement quality.


3. Intelligence Libraries#

The intelligence libraries work across all disciplines. They consume the shared anatomy taxonomy and exercise vocabulary from @shakti/core (and from their own local type re-declarations) to provide analysis, adaptation, and advanced feature modules that are not tied to any single discipline.

3.1 @shakti/biometrics#

Five modules: heart-rate, hrv (within heart-rate), body-composition, performance-metrics, recovery-metrics, device-integrations.

heart-rate.ts exposes the following types and calculators:

  • Types: HRZoneNumber (1–5), MaxHRMethod, HRVMetric (rmssd, sdnn, pnn50, lf_hf_ratio, ln_rmssd, hrv_score), ThresholdType, CardiacDriftCategory, RecoverySpeed.
  • Record types: HeartRateZone, MaxHRFormula, HRVAnalysisConfig, RestingHRBenchmark, CardiacDriftConfig, HRRecoveryBenchmark, ThresholdEstimation, HRTrackingConfig.
  • Calculations: calculateMaxHR, calculateHRR, calculateTargetHR.
  • Registry accessors: getAll*, get*, searchHeartRate, getHeartRateCount, resetHeartRateStore.

device-integrations.ts provides a catalog of named wearable and sensor integrations as descriptive configuration records — not live SDK clients. Each record documents how to connect and what data the platform provides, so application code can use the catalog to guide integration implementation:

  • Types: PlatformType, ConnectionType (bluetooth_le, ant_plus, wifi, usb, api_rest, api_oauth2, nfc), DeviceCategory (10), DataType (15), SyncFrequency.
  • Documented platforms: Apple HealthKit, Google Health Connect, Samsung Health SDK, Garmin Connect, Whoop 4.0, Oura Ring Gen3, Fitbit, Polar Vantage V3, COROS PACE 3, Wahoo TICKR, Stages power meters, the Bluetooth GATT services (Heart Rate, Cycling Power, Cycling/Running Speed and Cadence), ANT+ profiles, Tonal, and PUSH Band 2.0. Each record carries prose-level setup and rate-limit metadata.

3.2 @shakti/form-analysis#

Five modules: motion-capture, form-scoring, technique-analysis, real-time-feedback, video-analysis.

form-scoring.ts is the domain's fault taxonomy and scoring knowledge base. It defines:

  • FormCategory — 10 exercise categories, each with different evaluation criteria
  • DeviationType — 14 fault patterns: knee_valgus, butt_wink, forward_lean, bar_drift, lockout_incomplete, elbow_flare, and 8 others
  • SeverityLevel — fault severity on a graded scale
  • ScoreGrade — letter grades A through F rolled up from severity scores

motion-capture.ts documents pose-estimation approaches (MediaPipe / TensorFlow.js are referenced as descriptive options). All pose math is self-contained — there is no @aja dependency in this library.

3.3 @shakti/personalization#

Five modules: practitioner-profiling, adaptive-programming, ai-workout-generation, recommendation-engine, goal-management. Together these modules model the full lifecycle of a personalized training relationship — from initial profiling through adaptive adjustments to goal tracking.

3.4 @shakti/gamification#

Six modules: achievement-system, streak-system, xp-leveling, challenges, leaderboards, rewards-virtual-items. The gamification library is designed to listen to domain events rather than be called directly from session-logging code — this keeps the two concerns decoupled and ensures gamification enrichment adds no latency to the core training flow.

3.5 @shakti/sota-critical#

@shakti/sota-critical contains 16 modules. These modules represent production-near capabilities that need special hardware or research-grade data sources, and so are kept separate from the main platform to allow independent deployment and validation:

  • mental-health-mood, readiness-scheduling, velocity-based-training
  • dynamic-sequence-generation, virtual-world-gamification, longevity-healthspan
  • genetic-biomarker, vr-fitness, smart-gym-intelligence, health-ai-coach
  • advanced-social-live, edge-ai-offline, voice-first-handsfree
  • data-privacy-control, enterprise-b2b, v2-combat-style-classifier

voice-first-handsfree.ts is the canonical home of the Hey Shakti wake-word phrase definition. The V2 combat-style classifier module is described in detail in §5.4.

3.6 @shakti/sota-advanced#

@shakti/sota-advanced contains 10 modules for differentiating next-generation capabilities that sit further along the research-to-production spectrum than sota-critical:

  • accessibility-inclusion, advanced-equipment-integration
  • advanced-motion-analysis, ai-coach-personal-trainer
  • global-cultural-features, nutrition-holistic-health
  • predictive-analytics, research-science-integration
  • social-competitive-features, wearable-deep-integration

3.7 Operations, delivery, and platform libraries#

The remaining libraries handle the operational and delivery surfaces of the platform. Each follows the same knowledge-base pattern: typed records, Map stores, and getAll* accessors. Module counts are listed for orientation:

  • @shakti/community — 5 modules: social profiles/feed, training groups, accountability partners, messaging
  • @shakti/audio — 3 modules: audio content, music integration, voice commands
  • @shakti/video — 4 modules: content management, follow-along workouts, live streaming, instructional library
  • @shakti/visualization — 5 modules: movement/anatomy visualization, AR, VR, avatar
  • @shakti/studio — 5 modules: class/equipment/facility/membership/staff management
  • @shakti/events — 5 modules: calendar, class scheduling, competitions, live class delivery, workshops
  • @shakti/certifications — 4 modules: credential management, continuing education, licensing/insurance, the Shakti certification program
  • @shakti/instructor-sdk — 5 modules: assessment tools, business analytics, client management, content creation, program builder
  • @shakti/sdk — 3 modules: SDK core, resources, utilities
  • @shakti/web — 6 portal page-spec modules
  • @shakti/mobile — 7 mobile feature-spec modules
  • @shakti/testing — 5 modules: unit, integration, e2e, performance, security testing utilities
  • @shakti/documentation — 3 documentation-spec modules
  • @shakti/deployment — 5 modules: CI/CD, containerization, GPU/ML infrastructure, infrastructure setup, monitoring/observability

4. API Configuration Layer (@shakti/api)#

@shakti/api is not a running HTTP server and not a per-resource REST contract. It is a configuration-and-metadata registry: each module declares typed configuration records describing API building blocks and registers them into Map stores. It exposes getAll*() accessors over those records. There are no /api/v1/users, /api/v1/workouts/{id}-style per-resource routes in the source.

The purpose of this library is to give applications and integrators a machine-readable description of the API surface they will build — endpoint behaviours, auth strategies, rate-limit tiers, error-handling patterns — without coupling to any specific HTTP framework.

Six modules (re-exported from src/index.ts):

  • core-api.ts — declares ten record categories: 7 generic RestEndpoint configs, 7 GraphQLSchema configs, 7 AuthMiddleware configs, 7 RateLimit tier configs, 7 ApiVersion configs, 7 ValidationSchema configs, 7 ErrorHandler configs, 7 ApiDoc configs, 7 CorsConfig configs, 6 ApiMonitor configs. The seven RestEndpoint records use generic paths (/api/v1/resources, /api/v1/resources/:id, /api/v1/search, /api/v1/batch) and carry httpMethod, authRequired, rateLimitPerMinute, responseFormat, cacheDuration, and endpointType ∈ {resource-listing, resource-detail, resource-create, resource-update, resource-delete, search, batch-operation}.
  • exercise-workout-endpoints.ts — endpoint configuration records for exercise listing/detail/search, workout listing/creation/update, AI workout generation, and program listing/enrollment. Records carry behavioural fields (e.g. WorkoutCreation has creationMethod, maxExercises, templateBased, validationStrict, draftSupport, collaborativeEditing) — not literal URL paths.
  • session-tracking-endpoints.ts — configs for session start/update, exercise logging, session completion, history, and progress summaries.
  • social-community-endpoints.ts — configs for activity feeds, posts, likes, comments, user profiles, follow systems.
  • instructor-business-endpoints.ts — configs for client lists, program assignment, class schedules/creation, business analytics, content uploads.
  • form-analysis-endpoints.ts — configs for video upload, analysis status/results, real-time analysis, WebSocket feedback, analysis history.

Consumers query this registry to understand intended API shape; an actual HTTP server would be built in a separate application.


5. Fighting-Ruleset Bridge#

@shakti/fighting-ruleset-bridge is a fully-implemented, deterministic transform library. It takes real combat-sport biomechanics measurements and converts them into fighting-game frame data appropriate for a specific ruleset. The bridge's barrel re-exports fighting-ruleset-bridge.ts and profiles/launch-profiles.ts.

5.1 Constants and identifiers#

Three constants anchor the bridge's identity and versioning:

  • SHAKTI_FIGHTING_RULESET_BRIDGE_PACKAGE_NAME = '@shakti/fighting-ruleset-bridge'
  • SHAKTI_FIGHTING_RULESET_BRIDGE_SCHEMA_VERSION = 1
  • SHAKTI_RULESET_IDS = ['mk', 'sf', 'tekken', 'wwe', 'ufc', 'sc', 'dj']ShaktiRulesetId

5.2 ShaktiRulesetProfile#

A ruleset profile is the key configuration object: it maps real-sport reference numerics onto the game-feel constants that a specific fighting game demands. Each of the seven launch profiles holds a distinct set of scaling factors and rule flags corresponding to that game's design language.

Field Type Meaning
rulesetId ShaktiRulesetId Which ruleset
displayName string Human-readable name
tickRate number Game tick (60 in all launch profiles)
startupScale number Multiplier on real-sport startup frames
recoveryScale number Multiplier on real-sport recovery frames
activeFrames ShaktiActiveFrameModel real, extended, or compressed
reachScale number Multiplier on real-sport reach
meterModel ShaktiMeterModel super-bar, drive, heat, rage, soul-charge, fatal-blow, blazin
staminaModel ShaktiStaminaModel none, ufc-cardiac, wwe-exhaustion, dj-rush
damageScaling ShaktiRulesetDamageScaling { juggle, combo, counterHit } multipliers
ringOut boolean Ring-out enabled
weightDetection boolean Weight-class detection enabled
pinSubmissionMiniGame boolean Pin/submission mini-game enabled
environmentalFinishers boolean Environmental finishers enabled
guardImpact ShaktiGuardImpactModel parry, guard-impact, drive-impact, none

profiles/launch-profiles.ts exports the seven launch profiles (SHAKTI_MK_RULESET_PROFILE, SHAKTI_SF_RULESET_PROFILE, …) and the SHAKTI_LAUNCH_RULESET_PROFILES array. getAllShaktiRulesetProfiles() returns them; getShaktiRulesetProfile(id) looks one up (throwing ShaktiRulesetBridgeError for an unknown id).

5.3 Move biomechanics → frame data#

The bridge's core operation is a three-step pipeline:

  1. Describe the real-sport antecedent. A ShaktiMoveBiomechanicsInput record captures everything known about a move's real-world origin: moveId, fighterId, rulesetId, optional gameOnly flag, sourceSport (ShaktiCombatSport: boxing, kickboxing, muay-thai, wrestling, mma, bjj, karate, taekwondo, weapon-forms, game-only), shaktiTechnique, energyClass (light/medium/heavy/super), rangeClass (point-blank/close/mid/far/weapon), the three real durations (realStartupMs, realActiveMs, realRecoveryMs), forceNewtons, reachMeters, and optional rotationDegrees, balanceCost, staminaCost, cancelComplexity, notes, tags.

  2. Validate and stamp a reference card. buildShaktiMoveReferenceCard(input) returns a ShaktiMoveReferenceCard after enforcing the authoring rule via validateBiomechanicsInput: non-game-only moves must supply a real sourceSport and shaktiTechnique; the five numeric duration/force/reach fields must be positive and finite. The reference-card id is the caller's id or a stable SHA-256 hash of fighter/move/ruleset/sport/technique.

  3. Transform to frame data. transformBiomechanicsToFrameData(input) returns a ShaktiRulesetFrameDataRow by deterministically converting real durations to frames (tickRate-scaled), applying the ruleset profile's startup/recovery scales and active-frame model, computing hitstop, reach in Unreal units, damage, and on-hit / on-block advantage from force, energy class, range class, and the profile's damage-scaling and guard-impact settings. transformBiomechanicsCatalogToFrameData(inputs) maps over a catalog.

5.4 V2 combat-style classifier (@shakti/sota-critical)#

v2-combat-style-classifier.ts implements per-player style classification, used by the V2 AI director to matchup players with appropriate opponents.

  • Constants: V2_STYLE_CLASSIFICATION_EVENT_TOPIC = 'shakti.player.style.updated', V2_STYLE_CLASSIFICATION_SCHEMA_VERSION = 1.
  • V2CombatStyle — the five classifiable play styles: boxer, kickboxer, striker, grappler, submission-specialist.
  • V2CombatStyleTelemetryEvent — observed combat actions with range, strike kind, grappling kind, success, normalized damage, frame data, cancel usage, and pressure state.
  • classifyV2CombatStyle consumes a V2CombatStyleClassifierInput (player, match, ruleset, telemetry events) and returns a V2CombatStyleClassification carrying primaryStyle, secondaryStyle, confidence, rangePreference (point-blank/close/mid/far), pressureTolerance, cancelConfidence, a per-style scoreVector, a per-ruleset styleAffinityVector, scoring evidence, and offRollback: true.

5.5 Sister-monorepo consumption (planned, external)#

The integration boundary between Shakti and the V2 fighting-game project is a documented contract only — no Shakti source file imports any @v2 package. The V2 project documents how it consumes these libraries in V2/docs/integration/shakti-ruleset-bridge.md and V2/docs/integration/shakti-style-classification.md:

  • V2 wraps the bridge in @v2/shakti-ruleset-bridge, which serializes deterministic CSV rows for V2BalanceImporter. The wrapper preserves the ruleset-specific table differences across the MK / SF / Tekken / SC / DJ launch profiles — Tekken's extended actives, Street Fighter's drive-impact guard model, Soul Calibur's weapon reach and ring-out, and Def Jam's dj-rush stamina each survive the transform intact instead of being averaged into one generic table. The bridge RPC is off-rollback and is rejected inside rollback frames; game-only reference cards are allowed (they need no real-sport antecedent).
  • V2 wraps the classifier in @v2/shakti-style-classification, which turns the @shakti/sota-critical style buckets (boxer, kickboxer, striker, grappler, submission-specialist) into AI Director matchup hints via buildV2ShaktiAIDirectorMatchupPlan. Each hint carries preferredOpponentStyles and the pairwiseMatchups table the AI Director uses to pick opponents. Because the underlying classification is offRollback: true, the wrapper downgrades any rollback-enabled session to a next-match-only snapshot so style data never influences a live deterministic frame.

Those @v2/* adapters live in the V2 monorepo, not in libs/shakti/. The per-move reference-card corpus authoring for the full V2 launch roster is planned work tracked outside this domain.

5.6 Frame-data output format#

The bridge's final output is a CSV row ready for downstream import. Each ShaktiRulesetFrameDataRow carries all the information needed to drive a fighting game's balance system:

  • Startup / active / recovery frames
  • On-hit and on-block advantage values
  • Gap-to-followup, damage, hitstop
  • Reach in Unreal units
  • Juggle / combo / counter-hit scaling
  • The profile's meter and stamina model references
  • Special-rule flags
  • The real-sport reference numerics the row was derived from

serializeShaktiFrameDataCsv(rows) serializes a batch of rows to a 26-column CSV using the SHAKTI_FRAME_DATA_CSV_COLUMNS header.


6. Persistence Model#

Shakti defines its database schema as data rather than using a mainstream ORM. This fits the library-domain model: there is no running service to apply migrations, so the schema definition serves as a source of truth that can emit DDL when a deployment pipeline needs it.

@shakti/core/db-schema.ts uses a custom declarative TableDef model — not Drizzle ORM, not Prisma. A hand-written SQL generator turns those definitions into DDL.

  • SHAKTI_SCHEMA = 'shakti' — the target PostgreSQL schema name.
  • Type model: ColumnType (14 values: uuid, text, varchar, integer, bigint, decimal, float, boolean, timestamp, date, json, jsonb, enum, array), ColumnDef, ForeignKeyRef, IndexDef, TableDef.

The 11 tables exported as ALL_SHAKTI_TABLES cover the data that must survive across requests. In-memory knowledge-base content (asana taxonomies, exercise libraries, API configuration records) does not need table rows — it lives in the module-level Map stores:

Table Purpose
practitioners Core practitioner profiles
disciplines Physical disciplines
discipline_styles Styles within a discipline
techniques Techniques within a discipline/style
exercises Exercise library
programs Multi-week training programs
sessions Logged training sessions
personal_records Per-exercise PRs
achievements Achievement definitions
belt_ranks Martial-arts belt/rank systems
streaks Consistency / training streaks

Each TableDef carries columns (with nullability, defaults, foreign keys, enum value lists, check constraints) and indexes (including gin trigram / JSONB indexes). Utilities: getTableByName, getTableColumns, getRequiredColumns, getForeignKeys, getTableIndexes, generateCreateTableSQL, generateAllTablesSQL, countTotalColumns, countTotalIndexes.

There is no migration runner, ORM, or live database client in this domain — the schema module produces DDL strings only.


7. Event System#

@shakti/core/events.ts implements an in-process, synchronous event bus. It is not Redis-backed and not a network broker. Its purpose is cross-module decoupling within a single process — specifically, letting @shakti/gamification react to training events without the session-logging code knowing gamification exists.

7.1 Event envelope#

Every event in the system carries a standard metadata header for traceability. Applications can correlate events back to their originating request using correlationId, and understand causal chains using causationId:

  • ShaktiEventMetadataeventId, correlationId, optional causationId, timestamp, version, source, optional userId / practitionerId.
  • ShaktiEvent<T>{ type, metadata, payload }.
  • generateEventId() produces monotonically-suffixed evt_<ts>_<n> ids; createEventMetadata(...) builds metadata.

7.2 Event types#

ShaktiEventMap keys the 20 supported event types (also exported as ALL_EVENT_TYPES). Each event type has a strongly-typed payload interface, preventing consumers from having to cast or check payload shape at runtime:

Event type Payload interface
session.started SessionStartedPayload
session.completed SessionCompletedPayload
session.paused SessionPausedPayload
session.resumed SessionResumedPayload
exercise.performed ExercisePerformedPayload
technique.attempted TechniqueAttemptedPayload
personal_record.achieved PersonalRecordPayload
program.enrolled ProgramEnrolledPayload
program.completed ProgramCompletedPayload
workout.generated WorkoutGeneratedPayload
form_analysis.completed FormAnalysisPayload
achievement.unlocked AchievementUnlockedPayload
streak.milestone StreakMilestonePayload
challenge.joined ChallengeJoinedPayload
challenge.completed ChallengeCompletedPayload
certification.earned CertificationEarnedPayload
belt.promotion BeltPromotionPayload
injury.reported InjuryReportedPayload
recovery.updated RecoveryStatusPayload
biometric.synced BiometricSyncedPayload

FormAnalysisPayload carries a corrections array of FormCorrection ({ cue, severity, description }, severity ∈ info/warning/critical).

The separate @shakti/sota-critical V2 classifier publishes off-rollback under the topic string shakti.player.style.updated (defined as its own constant, independent of ShaktiEventMap).

7.3 Bus operations#

The bus API covers the full lifecycle of event-driven communication, including batching for performance, dead-letter handling for fault tolerance, and replay for debugging and testing:

  • subscribe(type, handler) → returns an unsubscribe function.
  • publish(type, payload, meta?) → builds an event, appends it to the in-memory eventLog, dispatches synchronously to all handlers, and routes handler exceptions to a dead-letter queue.
  • publishBatched(...) / flushBatch() — batches events, flushing on a 100 ms timer or at 50 events (BATCH_INTERVAL_MS = 100, MAX_BATCH_SIZE = 50).
  • Dead-letter handling: getDeadLetterQueue(), retryDeadLetterEvents() (MAX_RETRY = 3).
  • Replay / inspection: replayEvents(from, to?), getEventLog().
  • Serialization / versioning: serializeEvent, deserializeEvent, migrateEventVersion.
  • Monitoring: getEventMetrics()EventMetrics (published, handled, failed, batched, deadLetterSize, logSize, subscriberCount).
  • resetEventSystem() clears all bus state for test isolation.

8. Technology Stack and Build#

The following table summarizes the technology decisions for the Shakti domain. The most notable choices are the deliberate absence of runtime dependencies (every library ships with an empty dependencies map) and the custom validation and persistence layers that avoid third-party frameworks.

Layer Technology
Language TypeScript, ESM ("type": "module")
Runtime dependencies None — every libs/shakti/* package.json has an empty dependencies map
Validation Hand-written validate* functions returning string[] (no Zod/Yup/Joi)
Persistence model Custom declarative TableDef + SQL string generator targeting PostgreSQL schema shakti (no ORM)
Events In-process synchronous bus in @shakti/core
Hashing Node node:crypto (createHash) — used by the fighting-ruleset bridge and V2 classifier
Build executor @nx/js:tsc (most libraries); nx:run-commands for @shakti/fighting-ruleset-bridge
Test executor @nx/vite:test / Vitest; nx:run-commands running Vitest for fighting-ruleset-bridge
Nx tags scope:shakti, layer:domain, type:lib (the bridge adds domain:combat)

Each library co-locates *.spec.ts Vitest suites next to its source. Direct invocation when Nx is unavailable: cd libs/shakti/<library> && npx tsc --noEmit and npx vitest run.

Note: the libs/shakti/README.md quick-start examples (e.g. createShaktiClient, shakti.workouts.generate) describe an aspirational client surface and an API port. They are illustrative; the implemented sdk and api libraries are configuration/utility modules, and no Shakti library binds an HTTP port.


9. Acceptance Criteria#

A change to the Shakti domain is acceptable when all of the following conditions hold. These criteria exist to prevent the domain from drifting toward stubs — each criterion is designed to be independently verifiable.

  1. No fabricated surface. Every type, enum value, function, table, and event documented or added is present in libs/shakti/* source.
  2. Knowledge-base coherence. New registry records are typed against the module's declared interfaces and reachable through that module's getAll* / get* / search* / count* accessors.
  3. Domain correctness. Calculation helpers compute real domain formulas (e.g. Brzycki 1RM, heart-rate reserve, frame conversion) and tests assert specific computed values, not just shape or truthiness.
  4. Validation parity. Each schema interface that needs validation has a matching validate* function returning a string[] of messages.
  5. Bridge determinism. transformBiomechanicsToFrameData produces identical output for identical input; non-game-only moves are rejected without a real sourceSport and shaktiTechnique.
  6. Self-containment. Libraries add no runtime npm dependencies and no cross-domain imports; the standalone-library model is preserved.
  7. Build and lint. npx tsc --noEmit and the library's Vitest suite pass.