merlina 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. merlina-2.2.0/.env.example +165 -0
  2. merlina-2.2.0/.github/workflows/README.md +144 -0
  3. merlina-2.2.0/.gitignore +234 -0
  4. merlina-2.2.0/API.md +1819 -0
  5. merlina-2.2.0/CHANGELOG.md +495 -0
  6. merlina-2.2.0/LICENSE +21 -0
  7. merlina-2.2.0/PKG-INFO +462 -0
  8. merlina-2.2.0/README.md +394 -0
  9. merlina-2.2.0/bump_version.py +310 -0
  10. merlina-2.2.0/config.py +273 -0
  11. merlina-2.2.0/dataset_handlers/__init__.py +62 -0
  12. merlina-2.2.0/dataset_handlers/base.py +465 -0
  13. merlina-2.2.0/dataset_handlers/deduplication.py +168 -0
  14. merlina-2.2.0/dataset_handlers/factory.py +229 -0
  15. merlina-2.2.0/dataset_handlers/formatters.py +637 -0
  16. merlina-2.2.0/dataset_handlers/loaders.py +449 -0
  17. merlina-2.2.0/dataset_handlers/messages_converter.py +162 -0
  18. merlina-2.2.0/dataset_handlers/validators.py +124 -0
  19. merlina-2.2.0/docs/README.md +43 -0
  20. merlina-2.2.0/docs/dev/dataset-implementation.md +183 -0
  21. merlina-2.2.0/docs/dev/implementation-notes.md +246 -0
  22. merlina-2.2.0/docs/dev/preview-feature.md +213 -0
  23. merlina-2.2.0/docs/dev/tokenizer-implementation.md +132 -0
  24. merlina-2.2.0/docs/user/CONFIG_MANAGEMENT.md +268 -0
  25. merlina-2.2.0/docs/user/dataset-guide.md +343 -0
  26. merlina-2.2.0/docs/user/mcp.md +149 -0
  27. merlina-2.2.0/docs/user/new-features.md +429 -0
  28. merlina-2.2.0/docs/user/quick-start.md +171 -0
  29. merlina-2.2.0/docs/user/runpod.md +70 -0
  30. merlina-2.2.0/docs/user/tokenizer-format.md +223 -0
  31. merlina-2.2.0/examples/README.md +93 -0
  32. merlina-2.2.0/examples/basic-training.json +24 -0
  33. merlina-2.2.0/examples/custom-format.json +28 -0
  34. merlina-2.2.0/examples/datasets/sample-dpo-dataset.json +25 -0
  35. merlina-2.2.0/examples/example_messages_format.py +99 -0
  36. merlina-2.2.0/examples/example_messages_format_with_toggle.py +140 -0
  37. merlina-2.2.0/examples/huggingface-dataset.json +29 -0
  38. merlina-2.2.0/examples/job_history.py +252 -0
  39. merlina-2.2.0/examples/local-dataset.json +22 -0
  40. merlina-2.2.0/examples/manage_configs.py +283 -0
  41. merlina-2.2.0/examples/tokenizer-format.json +31 -0
  42. merlina-2.2.0/examples/validate_and_train.py +158 -0
  43. merlina-2.2.0/examples/websocket_monitor.py +189 -0
  44. merlina-2.2.0/frontend/css/animations.css +245 -0
  45. merlina-2.2.0/frontend/css/base.css +145 -0
  46. merlina-2.2.0/frontend/css/components.css +1294 -0
  47. merlina-2.2.0/frontend/css/layout.css +330 -0
  48. merlina-2.2.0/frontend/css/utilities.css +446 -0
  49. merlina-2.2.0/frontend/css/variables.css +147 -0
  50. merlina-2.2.0/frontend/favicon.ico +0 -0
  51. merlina-2.2.0/frontend/index.html +2048 -0
  52. merlina-2.2.0/frontend/js/api.js +723 -0
  53. merlina-2.2.0/frontend/js/app.js +1195 -0
  54. merlina-2.2.0/frontend/js/config.js +800 -0
  55. merlina-2.2.0/frontend/js/dataset.js +904 -0
  56. merlina-2.2.0/frontend/js/diffusion.js +676 -0
  57. merlina-2.2.0/frontend/js/disk.js +577 -0
  58. merlina-2.2.0/frontend/js/export.js +514 -0
  59. merlina-2.2.0/frontend/js/form_config.js +364 -0
  60. merlina-2.2.0/frontend/js/gpu.js +143 -0
  61. merlina-2.2.0/frontend/js/hf_namespaces.js +136 -0
  62. merlina-2.2.0/frontend/js/inference.js +444 -0
  63. merlina-2.2.0/frontend/js/jobs.js +793 -0
  64. merlina-2.2.0/frontend/js/model.js +198 -0
  65. merlina-2.2.0/frontend/js/package.json +3 -0
  66. merlina-2.2.0/frontend/js/theme.js +151 -0
  67. merlina-2.2.0/frontend/js/ui.js +956 -0
  68. merlina-2.2.0/frontend/js/validation.js +342 -0
  69. merlina-2.2.0/frontend/madewithmerlina_smol.png +0 -0
  70. merlina-2.2.0/frontend/merlina.png +0 -0
  71. merlina-2.2.0/frontend/styles.css +20 -0
  72. merlina-2.2.0/mcp_server.py +605 -0
  73. merlina-2.2.0/merlina.py +5150 -0
  74. merlina-2.2.0/merlina_cli.py +82 -0
  75. merlina-2.2.0/pyproject.toml +155 -0
  76. merlina-2.2.0/pytest.ini +47 -0
  77. merlina-2.2.0/requirements.txt +66 -0
  78. merlina-2.2.0/scripts/cleanup_checkpoints.py +101 -0
  79. merlina-2.2.0/scripts/generate_diffusion_samples.py +146 -0
  80. merlina-2.2.0/scripts/runpod_setup.sh +50 -0
  81. merlina-2.2.0/src/__init__.py +105 -0
  82. merlina-2.2.0/src/checkpoint_policy.py +72 -0
  83. merlina-2.2.0/src/checkpoint_rescue.py +181 -0
  84. merlina-2.2.0/src/config_image.py +263 -0
  85. merlina-2.2.0/src/config_manager.py +364 -0
  86. merlina-2.2.0/src/constants.py +223 -0
  87. merlina-2.2.0/src/disk_manager.py +596 -0
  88. merlina-2.2.0/src/exceptions.py +276 -0
  89. merlina-2.2.0/src/gguf_exporter.py +650 -0
  90. merlina-2.2.0/src/gpu_utils.py +244 -0
  91. merlina-2.2.0/src/hf_namespaces.py +180 -0
  92. merlina-2.2.0/src/job_manager.py +580 -0
  93. merlina-2.2.0/src/job_queue.py +505 -0
  94. merlina-2.2.0/src/llama_cpp_resolver.py +310 -0
  95. merlina-2.2.0/src/llama_server.py +335 -0
  96. merlina-2.2.0/src/local_models.py +141 -0
  97. merlina-2.2.0/src/memory_guard.py +694 -0
  98. merlina-2.2.0/src/merge_artifact.py +60 -0
  99. merlina-2.2.0/src/model_artifacts.py +239 -0
  100. merlina-2.2.0/src/model_card.py +684 -0
  101. merlina-2.2.0/src/preflight_checks.py +961 -0
  102. merlina-2.2.0/src/presets.py +181 -0
  103. merlina-2.2.0/src/train_worker.py +909 -0
  104. merlina-2.2.0/src/training_runner.py +2095 -0
  105. merlina-2.2.0/src/training_runner_diffusion.py +602 -0
  106. merlina-2.2.0/src/training_runner_vlm.py +604 -0
  107. merlina-2.2.0/src/upload_state.py +195 -0
  108. merlina-2.2.0/src/utils.py +399 -0
  109. merlina-2.2.0/src/vram_estimator.py +619 -0
  110. merlina-2.2.0/src/websocket_manager.py +367 -0
  111. merlina-2.2.0/src/worker_reattach.py +316 -0
  112. merlina-2.2.0/tests/README.md +308 -0
  113. merlina-2.2.0/tests/TEST_SUMMARY.md +322 -0
  114. merlina-2.2.0/tests/conftest.py +223 -0
  115. merlina-2.2.0/tests/fixtures/test_dataset.json +25 -0
  116. merlina-2.2.0/tests/fixtures/test_messages_dataset.json +74 -0
  117. merlina-2.2.0/tests/frontend/playwright.config.mjs +57 -0
  118. merlina-2.2.0/tests/frontend/serve_for_tests.py +61 -0
  119. merlina-2.2.0/tests/frontend/test_api.mjs +348 -0
  120. merlina-2.2.0/tests/frontend/test_form_config.mjs +601 -0
  121. merlina-2.2.0/tests/frontend/test_integration.spec.mjs +770 -0
  122. merlina-2.2.0/tests/frontend/test_theme.mjs +269 -0
  123. merlina-2.2.0/tests/frontend/test_ui.mjs +447 -0
  124. merlina-2.2.0/tests/frontend/test_validation.mjs +602 -0
  125. merlina-2.2.0/tests/requirements-test.txt +26 -0
  126. merlina-2.2.0/tests/test_api_comprehensive.py +1354 -0
  127. merlina-2.2.0/tests/test_api_endpoints.py +105 -0
  128. merlina-2.2.0/tests/test_artemis_runner.py +189 -0
  129. merlina-2.2.0/tests/test_attention_settings.py +153 -0
  130. merlina-2.2.0/tests/test_build_grimoire_config.py +190 -0
  131. merlina-2.2.0/tests/test_centralized_config_save.py +469 -0
  132. merlina-2.2.0/tests/test_chat_template_embedding.py +194 -0
  133. merlina-2.2.0/tests/test_checkpoint_policy.py +68 -0
  134. merlina-2.2.0/tests/test_cleanup.py +288 -0
  135. merlina-2.2.0/tests/test_config_field_names.py +303 -0
  136. merlina-2.2.0/tests/test_config_image.py +241 -0
  137. merlina-2.2.0/tests/test_config_manager.py +190 -0
  138. merlina-2.2.0/tests/test_config_only.py +91 -0
  139. merlina-2.2.0/tests/test_dataset_config_bugs.py +393 -0
  140. merlina-2.2.0/tests/test_dataset_config_name.py +127 -0
  141. merlina-2.2.0/tests/test_dataset_loaders.py +70 -0
  142. merlina-2.2.0/tests/test_deduplication.py +258 -0
  143. merlina-2.2.0/tests/test_diffusion_dispatch.py +461 -0
  144. merlina-2.2.0/tests/test_disk_manager.py +441 -0
  145. merlina-2.2.0/tests/test_event_loop_blocking.py +224 -0
  146. merlina-2.2.0/tests/test_frontend_wb_changes.py +118 -0
  147. merlina-2.2.0/tests/test_gguf_exporter.py +411 -0
  148. merlina-2.2.0/tests/test_hf_hub_private.py +144 -0
  149. merlina-2.2.0/tests/test_hf_hub_private_simple.py +122 -0
  150. merlina-2.2.0/tests/test_hf_namespace_api.py +188 -0
  151. merlina-2.2.0/tests/test_hf_namespaces.py +191 -0
  152. merlina-2.2.0/tests/test_job_deletion.py +168 -0
  153. merlina-2.2.0/tests/test_linear_attention_kernels.py +117 -0
  154. merlina-2.2.0/tests/test_llama_cpp_resolver.py +183 -0
  155. merlina-2.2.0/tests/test_local_models.py +202 -0
  156. merlina-2.2.0/tests/test_mcp_server.py +370 -0
  157. merlina-2.2.0/tests/test_memory_guard.py +491 -0
  158. merlina-2.2.0/tests/test_merge_artifact.py +107 -0
  159. merlina-2.2.0/tests/test_messages_format.py +225 -0
  160. merlina-2.2.0/tests/test_messages_format_toggle.py +89 -0
  161. merlina-2.2.0/tests/test_model_artifacts.py +166 -0
  162. merlina-2.2.0/tests/test_model_loading_integration.py +200 -0
  163. merlina-2.2.0/tests/test_model_path_detection.py +65 -0
  164. merlina-2.2.0/tests/test_model_readme.py +600 -0
  165. merlina-2.2.0/tests/test_multi_dataset.py +218 -0
  166. merlina-2.2.0/tests/test_new_settings.py +150 -0
  167. merlina-2.2.0/tests/test_optimizer_settings.py +151 -0
  168. merlina-2.2.0/tests/test_pipeline.py +93 -0
  169. merlina-2.2.0/tests/test_presets.py +231 -0
  170. merlina-2.2.0/tests/test_queue.py +461 -0
  171. merlina-2.2.0/tests/test_raw_formatter.py +95 -0
  172. merlina-2.2.0/tests/test_share_config_readme.py +378 -0
  173. merlina-2.2.0/tests/test_streaming_loader.py +329 -0
  174. merlina-2.2.0/tests/test_tokenizer_formatter.py +105 -0
  175. merlina-2.2.0/tests/test_upload_state.py +193 -0
  176. merlina-2.2.0/tests/test_v1_1_features.py +345 -0
  177. merlina-2.2.0/tests/test_vlm_model_type.py +312 -0
  178. merlina-2.2.0/tests/test_vlm_processor_saving.py +427 -0
  179. merlina-2.2.0/tests/test_vram_estimator.py +306 -0
  180. merlina-2.2.0/tests/test_wandb_missing_key.py +45 -0
  181. merlina-2.2.0/tests/test_wandb_settings.py +224 -0
  182. merlina-2.2.0/tests/test_wandb_standalone.py +226 -0
  183. merlina-2.2.0/version.py +39 -0
@@ -0,0 +1,165 @@
1
+ # Merlina Configuration Template
2
+ # Copy this file to .env and customize for your environment
3
+
4
+ # ==========================================
5
+ # Server Configuration
6
+ # ==========================================
7
+
8
+ # Server host (0.0.0.0 allows external connections, 127.0.0.1 is localhost only)
9
+ HOST=0.0.0.0
10
+
11
+ # Server port
12
+ PORT=8000
13
+
14
+ # Production domain (leave empty for development)
15
+ # Examples:
16
+ # http://localhost:8000
17
+ # https://merlina.example.com
18
+ # http://192.168.1.100:8000
19
+ # DOMAIN=
20
+
21
+ # ==========================================
22
+ # Directory Paths (Optional)
23
+ # ==========================================
24
+
25
+ # Uncomment to customize data directories
26
+ # DATA_DIR=./data
27
+ # MODELS_DIR=./models
28
+ # RESULTS_DIR=./results
29
+ # UPLOADS_DIR=./data/uploads
30
+ # FRONTEND_DIR=./frontend
31
+
32
+ # Database location
33
+ # DATABASE_PATH=./data/jobs.db
34
+
35
+ # ==========================================
36
+ # External Services — API Secrets
37
+ # ==========================================
38
+ # Setting these here means clients don't need to send the tokens in HTTP
39
+ # requests. The server will automatically fall back to these values for
40
+ # any training/upload/preload/inference request that omits them. A token
41
+ # sent in a request still overrides the env value.
42
+ #
43
+ # The GET /env/secrets endpoint reports which of these are configured
44
+ # (booleans only — never the values themselves) so the frontend can hide
45
+ # token fields when the server already has them.
46
+
47
+ # Weights & Biases API Key
48
+ # Get your key from: https://wandb.ai/authorize
49
+ # WANDB_API_KEY=
50
+
51
+ # HuggingFace Token (required for gated models like Llama, and for Hub uploads)
52
+ # Get your token from: https://huggingface.co/settings/tokens
53
+ # HF_TOKEN=
54
+
55
+ # ==========================================
56
+ # Training Defaults (Optional)
57
+ # ==========================================
58
+
59
+ # Default LoRA settings
60
+ # DEFAULT_LORA_R=64
61
+ # DEFAULT_LORA_ALPHA=32
62
+
63
+ # Default training hyperparameters
64
+ # DEFAULT_LEARNING_RATE=0.000005
65
+ # DEFAULT_BATCH_SIZE=1
66
+ # DEFAULT_GRADIENT_ACCUMULATION_STEPS=16
67
+ # DEFAULT_NUM_EPOCHS=2
68
+
69
+ # ==========================================
70
+ # Job Queue Configuration
71
+ # ==========================================
72
+
73
+ # Maximum number of training jobs to run simultaneously
74
+ # Set to 1 for safety (prevents OOM on single GPU)
75
+ # Increase if you have multiple GPUs with sufficient VRAM
76
+ # MAX_CONCURRENT_JOBS=1
77
+
78
+ # ==========================================
79
+ # System Configuration
80
+ # ==========================================
81
+
82
+ # GPU selection (comma-separated GPU IDs)
83
+ # Examples:
84
+ # CUDA_VISIBLE_DEVICES=0 # Use only GPU 0
85
+ # CUDA_VISIBLE_DEVICES=0,1 # Use GPUs 0 and 1
86
+ # CUDA_VISIBLE_DEVICES=1,2,3 # Use GPUs 1, 2, and 3
87
+ # CUDA_VISIBLE_DEVICES=
88
+
89
+ # Logging level (DEBUG, INFO, WARNING, ERROR)
90
+ LOG_LEVEL=INFO
91
+
92
+ # Offline mode: never contact the HuggingFace Hub. Models and datasets are
93
+ # loaded from the local HF cache or local paths only (sets HF_HUB_OFFLINE
94
+ # and TRANSFORMERS_OFFLINE). Use GET /models/local or the "Local Models"
95
+ # picker in the UI to see what's available offline.
96
+ OFFLINE_MODE=false
97
+
98
+ # ==========================================
99
+ # Unified-Memory Protection (DGX Spark / Grace-Blackwell)
100
+ # ==========================================
101
+ # On unified-memory machines (NVIDIA GB10 "DGX Spark", GH200/GB200, Jetson)
102
+ # the GPU and system RAM share one physical pool. A training memory spike
103
+ # there doesn't raise a clean CUDA OOM — it can starve the OS and take the
104
+ # whole machine down. Merlina's memory guard detects these systems, caps
105
+ # the CUDA allocator so spikes fail as ordinary OOMs, and runs a watchdog
106
+ # that gracefully stops (or, as a last resort, aborts) training before the
107
+ # OS runs out of RAM. It also writes an fsync'd forensic log to
108
+ # data/memory_guard.log so post-crash investigation has a memory timeline.
109
+ #
110
+ # The guard is a no-op on discrete-GPU systems. Defaults are tuned for a
111
+ # 128GB GB10; you rarely need to change anything.
112
+
113
+ # Master switch for the guard
114
+ # MEMORY_GUARD_ENABLED=true
115
+
116
+ # Detection override: auto (default) | true (force on) | false (force off)
117
+ # UNIFIED_MEMORY=auto
118
+
119
+ # RAM kept off-limits to the CUDA allocator (GB). Capped at 25% of the pool
120
+ # on small boards.
121
+ # MEMORY_GUARD_RESERVE_GB=12
122
+
123
+ # Free-RAM floors for the watchdog (GB): below the soft floor training is
124
+ # gracefully stopped (checkpoint saved); below the hard floor the job is
125
+ # aborted to keep the machine alive. Scaled down automatically on systems
126
+ # with less total RAM.
127
+ # MEMORY_GUARD_SOFT_FREE_GB=8
128
+ # MEMORY_GUARD_HARD_FREE_GB=3
129
+
130
+ # Watchdog sampling interval (seconds) and forensic log switch
131
+ # MEMORY_GUARD_POLL_SECONDS=5
132
+ # MEMORY_GUARD_LOG_ENABLED=true
133
+
134
+ # At the soft floor the watchdog first releases the CUDA allocator's idle
135
+ # cache (e.g. eval leftovers) and only stops training if free RAM is still
136
+ # below the floor — or if pressure returns within this cooldown (seconds).
137
+ # MEMORY_GUARD_RECLAIM_COOLDOWN_SECONDS=60
138
+
139
+ # ==========================================
140
+ # Security & Limits
141
+ # ==========================================
142
+
143
+ # CORS origins (comma-separated list or "*" for all)
144
+ # CORS_ORIGINS=*
145
+
146
+ # Maximum upload file size in MB
147
+ # MAX_UPLOAD_SIZE_MB=500
148
+
149
+ # ==========================================
150
+ # llama.cpp Integration (Optional)
151
+ # ==========================================
152
+ # Merlina uses llama.cpp for GGUF export/quantization and (optionally)
153
+ # spinning up llama-server for synthetic rejected-response generation.
154
+ #
155
+ # Resolution precedence (first hit wins):
156
+ # 1. LLAMA_CPP_DIR — path to a llama.cpp checkout (contains
157
+ # convert_hf_to_gguf.py and build/bin/)
158
+ # 2. LLAMA_CPP_BIN_DIR — path to a directory of built binaries only
159
+ # 3. System PATH — llama-quantize, llama-server, etc. on PATH
160
+ # 4. ./vendor/llama.cpp — conventional local clone
161
+ #
162
+ # If none of the above are present, llama.cpp-backed features stay disabled
163
+ # in the UI and pre-flight surfaces a warning (never an error).
164
+ # LLAMA_CPP_DIR=/opt/llama.cpp
165
+ # LLAMA_CPP_BIN_DIR=/opt/llama.cpp/build/bin
@@ -0,0 +1,144 @@
1
+ # GitHub Actions Workflows
2
+
3
+ This directory contains CI/CD workflows for automated testing and quality checks.
4
+
5
+ ## Workflows
6
+
7
+ ### 1. Tests (`tests.yml`)
8
+
9
+ **Triggers**: Push to main/master/develop, Pull Requests
10
+
11
+ **What it does**:
12
+ - Runs on Python 3.10 and 3.11 (matrix testing)
13
+ - Installs all dependencies
14
+ - Runs comprehensive API test suite
15
+ - Generates coverage reports
16
+ - Uploads coverage to Codecov
17
+ - Runs code quality checks (ruff, black, mypy)
18
+
19
+ **Jobs**:
20
+ - `test`: Runs all tests with coverage
21
+ - `lint`: Code quality checks
22
+ - `test-summary`: Posts summary to GitHub
23
+
24
+ **Duration**: ~3-5 minutes
25
+
26
+ ### 2. Quick Tests (`quick-test.yml`)
27
+
28
+ **Triggers**: Push to any branch
29
+
30
+ **What it does**:
31
+ - Fast feedback on every commit
32
+ - Runs only comprehensive API tests
33
+ - Times out after 5 minutes
34
+ - Comments on PR if tests fail
35
+
36
+ **Duration**: ~2-3 minutes
37
+
38
+ ## Status Badges
39
+
40
+ Add these badges to your README:
41
+
42
+ ```markdown
43
+ [![Tests](https://github.com/Schneewolf-Labs/Merlina/actions/workflows/tests.yml/badge.svg)](https://github.com/Schneewolf-Labs/Merlina/actions/workflows/tests.yml)
44
+ [![Quick Tests](https://github.com/Schneewolf-Labs/Merlina/actions/workflows/quick-test.yml/badge.svg)](https://github.com/Schneewolf-Labs/Merlina/actions/workflows/quick-test.yml)
45
+ [![codecov](https://codecov.io/gh/Schneewolf-Labs/Merlina/branch/main/graph/badge.svg)](https://codecov.io/gh/Schneewolf-Labs/Merlina)
46
+ ```
47
+
48
+ ## Configuration
49
+
50
+ ### Required Secrets
51
+
52
+ None required for basic testing. Optional:
53
+
54
+ - `CODECOV_TOKEN`: For private repo coverage reports
55
+ - `HF_TOKEN`: For testing with gated models
56
+
57
+ ### Permissions
58
+
59
+ Default permissions are sufficient. The workflows need:
60
+ - Read access to repository
61
+ - Write access to checks (automatic)
62
+
63
+ ## Running Locally
64
+
65
+ To run the same tests locally:
66
+
67
+ ```bash
68
+ # Run all tests
69
+ pytest tests/test_api_comprehensive.py -v
70
+
71
+ # Run with coverage
72
+ pytest --cov=src --cov=merlina --cov-report=html
73
+
74
+ # Quick test (matches quick-test.yml)
75
+ pytest tests/test_api_comprehensive.py -v --tb=short -x
76
+ ```
77
+
78
+ ## Customization
79
+
80
+ ### Change Python Versions
81
+
82
+ Edit `tests.yml`:
83
+
84
+ ```yaml
85
+ strategy:
86
+ matrix:
87
+ python-version: ['3.10', '3.11', '3.12']
88
+ ```
89
+
90
+ ### Add More Tests
91
+
92
+ Edit the test step:
93
+
94
+ ```yaml
95
+ - name: Run all tests
96
+ run: |
97
+ pytest tests/ -v
98
+ ```
99
+
100
+ ### Disable Lint Checks
101
+
102
+ Remove or comment out the `lint` job in `tests.yml`.
103
+
104
+ ## Troubleshooting
105
+
106
+ ### Tests Fail Locally but Pass in CI
107
+
108
+ - Check Python version: `python --version`
109
+ - Clear pytest cache: `pytest --cache-clear`
110
+ - Install exact dependencies: `pip install -r requirements.txt -r tests/requirements-test.txt`
111
+
112
+ ### Slow Tests
113
+
114
+ - Use `quick-test.yml` for fast feedback
115
+ - Run specific tests: `pytest tests/test_api_comprehensive.py::TestTrainingEndpoints`
116
+ - Enable parallel testing: `pytest -n auto`
117
+
118
+ ### Coverage Not Uploading
119
+
120
+ - Check Codecov token (for private repos)
121
+ - Verify coverage.xml is generated
122
+ - Check Codecov action logs
123
+
124
+ ## Best Practices
125
+
126
+ 1. **Keep tests fast**: Use mocking to avoid slow operations
127
+ 2. **Fail fast**: Use `-x` flag to stop on first failure
128
+ 3. **Matrix testing**: Test multiple Python versions
129
+ 4. **Branch protection**: Require tests to pass before merge
130
+ 5. **Coverage goals**: Maintain >80% coverage
131
+
132
+ ## Maintenance
133
+
134
+ These workflows are automatically maintained and updated with the test suite. No manual updates needed unless:
135
+
136
+ - Adding new Python versions
137
+ - Changing test structure
138
+ - Adding new dependencies
139
+ - Modifying coverage requirements
140
+
141
+ ---
142
+
143
+ **Last Updated**: 2025-11-16
144
+ **Maintained by**: Merlina Development Team
@@ -0,0 +1,234 @@
1
+ .env
2
+
3
+ # Node.js (installed by CI for Playwright tests). Anchored to repo root
4
+ # so legitimate sub-package.json files (e.g. frontend/js/package.json,
5
+ # which marks that directory as ESM for older Node versions) stay tracked.
6
+ node_modules/
7
+ /package.json
8
+ /package-lock.json
9
+
10
+ # Playwright test artifacts
11
+ test-results/
12
+ playwright-report/
13
+
14
+ # ML stuff
15
+ wandb/
16
+
17
+ # Merlina app outputs
18
+ models/
19
+ results/
20
+ data/
21
+ uploads/
22
+ *.safetensors
23
+ *.bin
24
+
25
+ # Byte-compiled / optimized / DLL files
26
+ __pycache__/
27
+ *.py[codz]
28
+ *$py.class
29
+
30
+ # C extensions
31
+ *.so
32
+
33
+ # Distribution / packaging
34
+ .Python
35
+ build/
36
+ develop-eggs/
37
+ dist/
38
+ downloads/
39
+ eggs/
40
+ .eggs/
41
+ lib/
42
+ lib64/
43
+ parts/
44
+ sdist/
45
+ var/
46
+ wheels/
47
+ share/python-wheels/
48
+ *.egg-info/
49
+ .installed.cfg
50
+ *.egg
51
+ MANIFEST
52
+
53
+ # PyInstaller
54
+ # Usually these files are written by a python script from a template
55
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
56
+ *.manifest
57
+ *.spec
58
+
59
+ # Installer logs
60
+ pip-log.txt
61
+ pip-delete-this-directory.txt
62
+
63
+ # Unit test / coverage reports
64
+ htmlcov/
65
+ .tox/
66
+ .nox/
67
+ .coverage
68
+ .coverage.*
69
+ .cache
70
+ nosetests.xml
71
+ coverage.xml
72
+ *.cover
73
+ *.py.cover
74
+ .hypothesis/
75
+ .pytest_cache/
76
+ cover/
77
+
78
+ # Translations
79
+ *.mo
80
+ *.pot
81
+
82
+ # Django stuff:
83
+ *.log
84
+ local_settings.py
85
+ db.sqlite3
86
+ db.sqlite3-journal
87
+
88
+ # Flask stuff:
89
+ instance/
90
+ .webassets-cache
91
+
92
+ # Scrapy stuff:
93
+ .scrapy
94
+
95
+ # Sphinx documentation
96
+ docs/_build/
97
+
98
+ # PyBuilder
99
+ .pybuilder/
100
+ target/
101
+
102
+ # Jupyter Notebook
103
+ .ipynb_checkpoints
104
+
105
+ # IPython
106
+ profile_default/
107
+ ipython_config.py
108
+
109
+ # pyenv
110
+ # For a library or package, you might want to ignore these files since the code is
111
+ # intended to run in multiple environments; otherwise, check them in:
112
+ # .python-version
113
+
114
+ # pipenv
115
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
116
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
117
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
118
+ # install all needed dependencies.
119
+ #Pipfile.lock
120
+
121
+ # UV
122
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
123
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
124
+ # commonly ignored for libraries.
125
+ #uv.lock
126
+
127
+ # poetry
128
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
129
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
130
+ # commonly ignored for libraries.
131
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
132
+ #poetry.lock
133
+ #poetry.toml
134
+
135
+ # pdm
136
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
137
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
138
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
139
+ #pdm.lock
140
+ #pdm.toml
141
+ .pdm-python
142
+ .pdm-build/
143
+
144
+ # pixi
145
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
146
+ #pixi.lock
147
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
148
+ # in the .venv directory. It is recommended not to include this directory in version control.
149
+ .pixi
150
+
151
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
152
+ __pypackages__/
153
+
154
+ # Celery stuff
155
+ celerybeat-schedule
156
+ celerybeat.pid
157
+
158
+ # SageMath parsed files
159
+ *.sage.py
160
+
161
+ # Environments
162
+ .env # Merlina configuration (API keys, secrets)
163
+ .env.* # Environment-specific configs (.env.production, etc.)
164
+ !.env.example # Keep example config template
165
+ .envrc
166
+ .venv
167
+ env/
168
+ venv/
169
+ ENV/
170
+ env.bak/
171
+ venv.bak/
172
+
173
+ # Spyder project settings
174
+ .spyderproject
175
+ .spyproject
176
+
177
+ # Rope project settings
178
+ .ropeproject
179
+
180
+ # mkdocs documentation
181
+ /site
182
+
183
+ # mypy
184
+ .mypy_cache/
185
+ .dmypy.json
186
+ dmypy.json
187
+
188
+ # Pyre type checker
189
+ .pyre/
190
+
191
+ # pytype static type analyzer
192
+ .pytype/
193
+
194
+ # Cython debug symbols
195
+ cython_debug/
196
+
197
+ # PyCharm
198
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
199
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
200
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
201
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
202
+ #.idea/
203
+
204
+ # Abstra
205
+ # Abstra is an AI-powered process automation framework.
206
+ # Ignore directories containing user credentials, local state, and settings.
207
+ # Learn more at https://abstra.io/docs
208
+ .abstra/
209
+
210
+ # Visual Studio Code
211
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
212
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
213
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
214
+ # you could uncomment the following to ignore the entire vscode folder
215
+ # .vscode/
216
+
217
+ # Ruff stuff:
218
+ .ruff_cache/
219
+
220
+ # PyPI configuration file
221
+ .pypirc
222
+
223
+ # Cursor
224
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
225
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
226
+ # refer to https://docs.cursor.com/context/ignore-files
227
+ .cursorignore
228
+ .cursorindexingignore
229
+
230
+ # Marimo
231
+ marimo/_static/
232
+ marimo/_lsp/
233
+ __marimo__/
234
+ .test-venv/