favlo 0.3.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 (720) hide show
  1. favlo-0.3.0/.cursor/mcp.json +8 -0
  2. favlo-0.3.0/.cursor/rules/commit-precheck.mdc +22 -0
  3. favlo-0.3.0/.cursor/rules/documentation.mdc +43 -0
  4. favlo-0.3.0/.cursor/rules/embeddings-pipeline.mdc +19 -0
  5. favlo-0.3.0/.cursor/rules/favlo-web.mdc +35 -0
  6. favlo-0.3.0/.cursor/rules/harness.mdc +17 -0
  7. favlo-0.3.0/.cursor/rules/language-pipeline.mdc +28 -0
  8. favlo-0.3.0/.cursor/rules/mcp-server.mdc +17 -0
  9. favlo-0.3.0/.cursor/rules/media-pipeline.mdc +36 -0
  10. favlo-0.3.0/.cursor/rules/memory-management.mdc +42 -0
  11. favlo-0.3.0/.cursor/rules/metal-mappings.mdc +44 -0
  12. favlo-0.3.0/.cursor/rules/optimization-image.mdc +8 -0
  13. favlo-0.3.0/.cursor/rules/optimization-llm.mdc +8 -0
  14. favlo-0.3.0/.cursor/rules/pipeline-isolation.mdc +67 -0
  15. favlo-0.3.0/.cursor/rules/public-algorithms.mdc +27 -0
  16. favlo-0.3.0/.cursor/rules/python-file-split.mdc +32 -0
  17. favlo-0.3.0/.cursor/rules/research-evidence.mdc +43 -0
  18. favlo-0.3.0/.cursor/rules/serving-media.mdc +41 -0
  19. favlo-0.3.0/.cursor/skills/bootstrap-new-model/SKILL.md +65 -0
  20. favlo-0.3.0/.cursor/skills/favlo-server/SKILL.md +45 -0
  21. favlo-0.3.0/.cursor/skills/inspect-voice/SKILL.md +18 -0
  22. favlo-0.3.0/.cursor/skills/music-prompting/SKILL.md +38 -0
  23. favlo-0.3.0/.cursor/skills/optimization-image/SKILL.md +58 -0
  24. favlo-0.3.0/.cursor/skills/optimization-loop/SKILL.md +70 -0
  25. favlo-0.3.0/.cursor/skills/optimization-music/SKILL.md +58 -0
  26. favlo-0.3.0/.cursor/skills/prefix-caching/SKILL.md +72 -0
  27. favlo-0.3.0/.cursor/skills/prompting-z-image-turbo/SKILL.md +85 -0
  28. favlo-0.3.0/.cursor/skills/prompting-z-image-turbo/reference.md +48 -0
  29. favlo-0.3.0/.cursor/skills/research-claims/SKILL.md +53 -0
  30. favlo-0.3.0/.cursor/skills/smoke-testing/SKILL.md +72 -0
  31. favlo-0.3.0/.cursor/skills/zonos2-prompting/SKILL.md +41 -0
  32. favlo-0.3.0/.githooks/commit-msg +16 -0
  33. favlo-0.3.0/.github/workflows/workflow.yml +59 -0
  34. favlo-0.3.0/.gitignore +45 -0
  35. favlo-0.3.0/.python-version +1 -0
  36. favlo-0.3.0/AGENTS.md +95 -0
  37. favlo-0.3.0/ARCHITECTURE.md +134 -0
  38. favlo-0.3.0/CITATION.cff +12 -0
  39. favlo-0.3.0/LICENSE.md +202 -0
  40. favlo-0.3.0/MCP.md +253 -0
  41. favlo-0.3.0/NOTICE +5 -0
  42. favlo-0.3.0/PKG-INFO +164 -0
  43. favlo-0.3.0/README.md +126 -0
  44. favlo-0.3.0/REFERENCES.md +104 -0
  45. favlo-0.3.0/RESEARCH.md +35 -0
  46. favlo-0.3.0/bench/synthetic_decode.metal +922 -0
  47. favlo-0.3.0/bench/synthetic_decode.py +477 -0
  48. favlo-0.3.0/docs/README.md +74 -0
  49. favlo-0.3.0/docs/ace-step-15-turbo/README.md +27 -0
  50. favlo-0.3.0/docs/ace-step-15-turbo/SETUP.md +87 -0
  51. favlo-0.3.0/docs/ace-step-15-turbo/long.json +11 -0
  52. favlo-0.3.0/docs/ace-step-15-turbo/research/dit-mlp-fp4-error.md +67 -0
  53. favlo-0.3.0/docs/ace-step-15-turbo/smoke.json +11 -0
  54. favlo-0.3.0/docs/ai-assistance/README.md +57 -0
  55. favlo-0.3.0/docs/bge-m3/README.md +13 -0
  56. favlo-0.3.0/docs/bge-m3/failed/failed.md +11 -0
  57. favlo-0.3.0/docs/bge-m3/references.md +9 -0
  58. favlo-0.3.0/docs/bge-m3/research/recorded-encode.md +40 -0
  59. favlo-0.3.0/docs/coding-primitives.md +104 -0
  60. favlo-0.3.0/docs/console.md +19 -0
  61. favlo-0.3.0/docs/guides/clients.md +23 -0
  62. favlo-0.3.0/docs/guides/history.md +3 -0
  63. favlo-0.3.0/docs/guides/models.md +81 -0
  64. favlo-0.3.0/docs/harness.md +246 -0
  65. favlo-0.3.0/docs/images/favlo-stable.jpg +0 -0
  66. favlo-0.3.0/docs/images/favlo.png +0 -0
  67. favlo-0.3.0/docs/prefix.md +7 -0
  68. favlo-0.3.0/docs/qwen36-35b-a3b/README.md +39 -0
  69. favlo-0.3.0/docs/qwen36-35b-a3b/SETUP.md +126 -0
  70. favlo-0.3.0/docs/qwen36-35b-a3b/benchmarks.md +60 -0
  71. favlo-0.3.0/docs/qwen36-35b-a3b/ceilings.md +173 -0
  72. favlo-0.3.0/docs/qwen36-35b-a3b/performance.md +158 -0
  73. favlo-0.3.0/docs/qwen36-35b-a3b/research/fp16-peak-restore.md +44 -0
  74. favlo-0.3.0/docs/qwen36-35b-a3b/research/kernel-ceilings.md +49 -0
  75. favlo-0.3.0/docs/qwen36-35b-a3b/research/recorded-forward.md +54 -0
  76. favlo-0.3.0/docs/qwen38-27b/README.md +41 -0
  77. favlo-0.3.0/docs/qwen38-27b/SETUP.md +109 -0
  78. favlo-0.3.0/docs/qwen38-27b/benchmarks.md +72 -0
  79. favlo-0.3.0/docs/qwen38-27b/ceilings.md +142 -0
  80. favlo-0.3.0/docs/qwen38-27b/memory-usage.md +22 -0
  81. favlo-0.3.0/docs/qwen38-27b/research/ffn-fp8-budget.md +53 -0
  82. favlo-0.3.0/docs/qwen38-27b/research/int8-prefill.md +36 -0
  83. favlo-0.3.0/docs/qwen38-27b/research/kernel-ceilings.md +47 -0
  84. favlo-0.3.0/docs/qwen38-27b/research/mixed-agent-forward.md +97 -0
  85. favlo-0.3.0/docs/qwen38-27b/research/mtp-window.md +44 -0
  86. favlo-0.3.0/docs/qwen38-27b/research/recorded-forward.md +39 -0
  87. favlo-0.3.0/docs/qwen38-27b/research/span-draft.md +43 -0
  88. favlo-0.3.0/docs/qwen38-flash-next/architecture.md +137 -0
  89. favlo-0.3.0/docs/qwen38-flash-next/benchmarks.md +57 -0
  90. favlo-0.3.0/docs/qwen38-flash-next/ceilings.md +125 -0
  91. favlo-0.3.0/docs/qwen38-flash-next/console.md +15 -0
  92. favlo-0.3.0/docs/qwen38-flash-next/ngram.md +9 -0
  93. favlo-0.3.0/docs/qwen38-flash-next/performance.md +43 -0
  94. favlo-0.3.0/docs/qwen38-flash-next/probe.md +13 -0
  95. favlo-0.3.0/docs/qwen38-flash-next/record.md +43 -0
  96. favlo-0.3.0/docs/qwen38-flash-next/references.md +104 -0
  97. favlo-0.3.0/docs/qwen38-flash-next/research/expert-planes.md +42 -0
  98. favlo-0.3.0/docs/qwen38-flash-next/research/int2-miss.md +62 -0
  99. favlo-0.3.0/docs/qwen38-flash-next/research/kernel-ceilings.md +39 -0
  100. favlo-0.3.0/docs/qwen38-flash-next/research/recorded-forward.md +43 -0
  101. favlo-0.3.0/docs/qwen38-flash-next/schedule.md +28 -0
  102. favlo-0.3.0/docs/serve.md +29 -0
  103. favlo-0.3.0/docs/synthetic-decode.md +81 -0
  104. favlo-0.3.0/docs/synthetic-matmul2d.md +53 -0
  105. favlo-0.3.0/docs/ternary-bonsai-2/README.md +33 -0
  106. favlo-0.3.0/docs/ternary-bonsai-2/references.md +11 -0
  107. favlo-0.3.0/docs/voxcpm2/README.md +26 -0
  108. favlo-0.3.0/docs/voxcpm2/references.md +19 -0
  109. favlo-0.3.0/docs/voxcpm2/smoke.json +7 -0
  110. favlo-0.3.0/docs/wan22-i2v/README.md +29 -0
  111. favlo-0.3.0/docs/wan22-i2v/SETUP.md +123 -0
  112. favlo-0.3.0/docs/wan22-i2v/ceilings.md +98 -0
  113. favlo-0.3.0/docs/wan22-i2v/research/block-fp4-error.md +41 -0
  114. favlo-0.3.0/docs/wan22-i2v/research/clip-ceiling.md +57 -0
  115. favlo-0.3.0/docs/wan22-i2v/research/int8-weight-error.md +38 -0
  116. favlo-0.3.0/docs/wan22-i2v/smoke.json +11 -0
  117. favlo-0.3.0/docs/wan22-ti2v-5b/README.md +81 -0
  118. favlo-0.3.0/docs/wan22-ti2v-5b/SETUP.md +33 -0
  119. favlo-0.3.0/docs/wan22-ti2v-5b/ceilings.md +27 -0
  120. favlo-0.3.0/docs/wan22-ti2v-5b/research/clip-ceiling.md +42 -0
  121. favlo-0.3.0/docs/wan22-ti2v-5b/research/int8-weight-error.md +36 -0
  122. favlo-0.3.0/docs/wan22-ti2v-5b/smoke.json +11 -0
  123. favlo-0.3.0/docs/wan22-ti2v-5b/still.png +0 -0
  124. favlo-0.3.0/docs/z-image-turbo/README.md +59 -0
  125. favlo-0.3.0/docs/z-image-turbo/SETUP.md +99 -0
  126. favlo-0.3.0/docs/z-image-turbo/ceilings.md +51 -0
  127. favlo-0.3.0/docs/z-image-turbo/research/generation-ceiling.md +52 -0
  128. favlo-0.3.0/docs/z-image-turbo/smoke.json +19 -0
  129. favlo-0.3.0/docs/zonos2/README.md +21 -0
  130. favlo-0.3.0/docs/zonos2/references.md +14 -0
  131. favlo-0.3.0/docs/zonos2/research/moe-fp4-error.md +59 -0
  132. favlo-0.3.0/docs/zonos2/smoke.json +4 -0
  133. favlo-0.3.0/harness/__init__.py +1 -0
  134. favlo-0.3.0/harness/__main__.py +3 -0
  135. favlo-0.3.0/harness/benchmarks/__init__.py +4 -0
  136. favlo-0.3.0/harness/benchmarks/__main__.py +539 -0
  137. favlo-0.3.0/harness/benchmarks/data/gsm8k/test.jsonl +1319 -0
  138. favlo-0.3.0/harness/benchmarks/data/gsm8k/train_shots.jsonl +5 -0
  139. favlo-0.3.0/harness/benchmarks/data/humaneval/HumanEval.jsonl.gz +0 -0
  140. favlo-0.3.0/harness/benchmarks/data/ifeval/input_data.jsonl +541 -0
  141. favlo-0.3.0/harness/benchmarks/gsm8k.py +85 -0
  142. favlo-0.3.0/harness/benchmarks/humaneval.py +91 -0
  143. favlo-0.3.0/harness/benchmarks/ifeval.py +68 -0
  144. favlo-0.3.0/harness/benchmarks/serve.py +275 -0
  145. favlo-0.3.0/harness/benchmarks/vendor/human_eval/LICENSE +21 -0
  146. favlo-0.3.0/harness/benchmarks/vendor/human_eval/__init__.py +0 -0
  147. favlo-0.3.0/harness/benchmarks/vendor/human_eval/execution.py +241 -0
  148. favlo-0.3.0/harness/benchmarks/vendor/instruction_following_eval/LICENSE +202 -0
  149. favlo-0.3.0/harness/benchmarks/vendor/instruction_following_eval/__init__.py +0 -0
  150. favlo-0.3.0/harness/benchmarks/vendor/instruction_following_eval/evaluation_lib.py +220 -0
  151. favlo-0.3.0/harness/benchmarks/vendor/instruction_following_eval/instructions.py +1566 -0
  152. favlo-0.3.0/harness/benchmarks/vendor/instruction_following_eval/instructions_registry.py +176 -0
  153. favlo-0.3.0/harness/benchmarks/vendor/instruction_following_eval/instructions_util.py +147 -0
  154. favlo-0.3.0/harness/benchmarks/vendor/nltk_data/tokenizers/punkt_tab/english/abbrev_types.txt +156 -0
  155. favlo-0.3.0/harness/benchmarks/vendor/nltk_data/tokenizers/punkt_tab/english/collocations.tab +37 -0
  156. favlo-0.3.0/harness/benchmarks/vendor/nltk_data/tokenizers/punkt_tab/english/ortho_context.tab +20366 -0
  157. favlo-0.3.0/harness/benchmarks/vendor/nltk_data/tokenizers/punkt_tab/english/sent_starters.txt +39 -0
  158. favlo-0.3.0/harness/chat_agent.py +231 -0
  159. favlo-0.3.0/harness/coding/__init__.py +1 -0
  160. favlo-0.3.0/harness/coding/__main__.py +101 -0
  161. favlo-0.3.0/harness/coding/checks/test_ledger.py +31 -0
  162. favlo-0.3.0/harness/coding/grade.py +23 -0
  163. favlo-0.3.0/harness/coding/loop.py +124 -0
  164. favlo-0.3.0/harness/coding/session.py +105 -0
  165. favlo-0.3.0/harness/coding/tools/__init__.py +1 -0
  166. favlo-0.3.0/harness/coding/tools/args.py +121 -0
  167. favlo-0.3.0/harness/coding/tools/catalog.py +36 -0
  168. favlo-0.3.0/harness/coding/tools/context.py +26 -0
  169. favlo-0.3.0/harness/coding/tools/edit.py +146 -0
  170. favlo-0.3.0/harness/coding/tools/errors.py +23 -0
  171. favlo-0.3.0/harness/coding/tools/glob_files.py +94 -0
  172. favlo-0.3.0/harness/coding/tools/globs.py +44 -0
  173. favlo-0.3.0/harness/coding/tools/grep_search.py +227 -0
  174. favlo-0.3.0/harness/coding/tools/idempotency.py +111 -0
  175. favlo-0.3.0/harness/coding/tools/journal.py +38 -0
  176. favlo-0.3.0/harness/coding/tools/limits.py +19 -0
  177. favlo-0.3.0/harness/coding/tools/mutations.py +48 -0
  178. favlo-0.3.0/harness/coding/tools/paths.py +45 -0
  179. favlo-0.3.0/harness/coding/tools/read_file.py +54 -0
  180. favlo-0.3.0/harness/coding/tools/rg.py +35 -0
  181. favlo-0.3.0/harness/coding/tools/schemas.py +179 -0
  182. favlo-0.3.0/harness/coding/tools/shell.py +546 -0
  183. favlo-0.3.0/harness/coding/tools/textfile.py +37 -0
  184. favlo-0.3.0/harness/coding/tools/write_file.py +125 -0
  185. favlo-0.3.0/harness/coding/workspace.py +109 -0
  186. favlo-0.3.0/harness/coherence.py +346 -0
  187. favlo-0.3.0/harness/embeddings_agent.py +132 -0
  188. favlo-0.3.0/harness/file_agent.py +160 -0
  189. favlo-0.3.0/harness/file_session.py +650 -0
  190. favlo-0.3.0/harness/harness_model.py +12 -0
  191. favlo-0.3.0/harness/image.py +62 -0
  192. favlo-0.3.0/harness/image_attachment.py +159 -0
  193. favlo-0.3.0/harness/image_persona.py +155 -0
  194. favlo-0.3.0/harness/image_smoke_agent.py +183 -0
  195. favlo-0.3.0/harness/inspect_voice.py +159 -0
  196. favlo-0.3.0/harness/inspect_wav.py +630 -0
  197. favlo-0.3.0/harness/language_pipeline.py +116 -0
  198. favlo-0.3.0/harness/mcp_media.py +223 -0
  199. favlo-0.3.0/harness/media_pipeline.py +607 -0
  200. favlo-0.3.0/harness/memory_agent.py +288 -0
  201. favlo-0.3.0/harness/music_long_agent.py +232 -0
  202. favlo-0.3.0/harness/music_smoke_agent.py +133 -0
  203. favlo-0.3.0/harness/music_template.py +146 -0
  204. favlo-0.3.0/harness/server.py +96 -0
  205. favlo-0.3.0/harness/video_mp4.py +116 -0
  206. favlo-0.3.0/harness/video_quality_agent.py +118 -0
  207. favlo-0.3.0/harness/video_smoke_agent.py +277 -0
  208. favlo-0.3.0/harness/video_ti2v_agent.py +263 -0
  209. favlo-0.3.0/harness/voice_smoke_agent.py +135 -0
  210. favlo-0.3.0/harness/worktree.py +509 -0
  211. favlo-0.3.0/pipelines/cuda/.gitkeep +0 -0
  212. favlo-0.3.0/pipelines/failed/ternary-bonsai-2.py +23 -0
  213. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/__init__.py +6 -0
  214. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/attn.py +584 -0
  215. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/budget.py +299 -0
  216. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/cache.py +162 -0
  217. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/chat.py +495 -0
  218. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/checks.py +565 -0
  219. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/commands.py +213 -0
  220. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/convert.py +246 -0
  221. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/fetch.py +193 -0
  222. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/formats.py +444 -0
  223. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/forward.py +1377 -0
  224. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/gguf.py +122 -0
  225. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/layout.py +35 -0
  226. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/prefill.py +471 -0
  227. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/prefix.py +231 -0
  228. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/resident.py +160 -0
  229. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/runtime.py +30 -0
  230. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/sampling.py +62 -0
  231. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/session.py +420 -0
  232. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/shaders/kernels.metal +2452 -0
  233. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/shaders/vision.metal +371 -0
  234. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/tools.py +305 -0
  235. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/tower.py +493 -0
  236. favlo-0.3.0/pipelines/failed/ternary_bonsai_2/vision.py +320 -0
  237. favlo-0.3.0/pipelines/failed/tests/test_ternary_bonsai_2.py +36 -0
  238. favlo-0.3.0/pipelines/failed/tests/test_ternary_bonsai_2_smoke.py +177 -0
  239. favlo-0.3.0/pipelines/failed/tests/test_zonos2.py +357 -0
  240. favlo-0.3.0/pipelines/failed/tests/test_zonos2_emotion_smoke.py +59 -0
  241. favlo-0.3.0/pipelines/failed/tests/test_zonos2_smoke.py +33 -0
  242. favlo-0.3.0/pipelines/failed/zonos2/__init__.py +8 -0
  243. favlo-0.3.0/pipelines/failed/zonos2/audio.py +129 -0
  244. favlo-0.3.0/pipelines/failed/zonos2/checkpoint.py +195 -0
  245. favlo-0.3.0/pipelines/failed/zonos2/checks.py +44 -0
  246. favlo-0.3.0/pipelines/failed/zonos2/codec.py +339 -0
  247. favlo-0.3.0/pipelines/failed/zonos2/commands.py +77 -0
  248. favlo-0.3.0/pipelines/failed/zonos2/delay.py +32 -0
  249. favlo-0.3.0/pipelines/failed/zonos2/emotion.py +165 -0
  250. favlo-0.3.0/pipelines/failed/zonos2/emotions/angry.npy +0 -0
  251. favlo-0.3.0/pipelines/failed/zonos2/emotions/arousal.npy +0 -0
  252. favlo-0.3.0/pipelines/failed/zonos2/emotions/calibration.json +42 -0
  253. favlo-0.3.0/pipelines/failed/zonos2/emotions/happy.npy +0 -0
  254. favlo-0.3.0/pipelines/failed/zonos2/emotions/manifest.json +38 -0
  255. favlo-0.3.0/pipelines/failed/zonos2/emotions/sad.npy +0 -0
  256. favlo-0.3.0/pipelines/failed/zonos2/emotions/surprised.npy +0 -0
  257. favlo-0.3.0/pipelines/failed/zonos2/emotions/valence.npy +0 -0
  258. favlo-0.3.0/pipelines/failed/zonos2/formats.py +174 -0
  259. favlo-0.3.0/pipelines/failed/zonos2/forward.py +252 -0
  260. favlo-0.3.0/pipelines/failed/zonos2/layout.py +54 -0
  261. favlo-0.3.0/pipelines/failed/zonos2/mel.py +92 -0
  262. favlo-0.3.0/pipelines/failed/zonos2/metal.py +164 -0
  263. favlo-0.3.0/pipelines/failed/zonos2/pack.py +200 -0
  264. favlo-0.3.0/pipelines/failed/zonos2/record.py +182 -0
  265. favlo-0.3.0/pipelines/failed/zonos2/runtime.py +124 -0
  266. favlo-0.3.0/pipelines/failed/zonos2/sampling.py +67 -0
  267. favlo-0.3.0/pipelines/failed/zonos2/session.py +369 -0
  268. favlo-0.3.0/pipelines/failed/zonos2/shaders/codec.metal +85 -0
  269. favlo-0.3.0/pipelines/failed/zonos2/shaders/kernels.metal +161 -0
  270. favlo-0.3.0/pipelines/failed/zonos2/signals.py +120 -0
  271. favlo-0.3.0/pipelines/failed/zonos2/speaker.py +162 -0
  272. favlo-0.3.0/pipelines/failed/zonos2/voices/heather-lawrence.npy +0 -0
  273. favlo-0.3.0/pipelines/failed/zonos2/voices/soprano-harmony.npy +0 -0
  274. favlo-0.3.0/pipelines/failed/zonos2/voices.py +41 -0
  275. favlo-0.3.0/pipelines/failed/zonos2.py +23 -0
  276. favlo-0.3.0/pipelines/metal41/ace-step-15-turbo.py +23 -0
  277. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/__init__.py +20 -0
  278. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/commands.py +206 -0
  279. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/graph.py +788 -0
  280. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/hold.py +51 -0
  281. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/measure.py +381 -0
  282. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/metal.py +592 -0
  283. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/pack.py +272 -0
  284. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/pcm.py +50 -0
  285. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/record.py +334 -0
  286. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/request.py +154 -0
  287. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/runtime.py +411 -0
  288. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/sampling.py +16 -0
  289. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/schedule.py +78 -0
  290. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/shaders/kernels.metal +746 -0
  291. favlo-0.3.0/pipelines/metal41/ace_step_15_turbo/tiles.py +85 -0
  292. favlo-0.3.0/pipelines/metal41/bge-m3.py +23 -0
  293. favlo-0.3.0/pipelines/metal41/bge_m3/__init__.py +6 -0
  294. favlo-0.3.0/pipelines/metal41/bge_m3/commands.py +60 -0
  295. favlo-0.3.0/pipelines/metal41/bge_m3/gpu.py +402 -0
  296. favlo-0.3.0/pipelines/metal41/bge_m3/model.py +204 -0
  297. favlo-0.3.0/pipelines/metal41/bge_m3/pack.py +41 -0
  298. favlo-0.3.0/pipelines/metal41/bge_m3/passages.py +27 -0
  299. favlo-0.3.0/pipelines/metal41/bge_m3/quantize.py +261 -0
  300. favlo-0.3.0/pipelines/metal41/bge_m3/runtime.py +172 -0
  301. favlo-0.3.0/pipelines/metal41/bge_m3/sampling.py +27 -0
  302. favlo-0.3.0/pipelines/metal41/bge_m3/shaders/kernels.metal +291 -0
  303. favlo-0.3.0/pipelines/metal41/bge_m3/text.py +130 -0
  304. favlo-0.3.0/pipelines/metal41/qwen36-35b-a3b.py +23 -0
  305. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/__init__.py +7 -0
  306. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/atlas.py +722 -0
  307. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/attn.py +843 -0
  308. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/cache.py +201 -0
  309. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/chat.py +603 -0
  310. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/checks.py +1394 -0
  311. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/commands.py +522 -0
  312. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/convert.py +700 -0
  313. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/fetch.py +213 -0
  314. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/firing.py +336 -0
  315. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/formats.py +339 -0
  316. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/forward.py +2423 -0
  317. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/prefill.py +1148 -0
  318. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/prefix.py +223 -0
  319. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/runtime.py +32 -0
  320. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/sampling.py +70 -0
  321. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/session.py +505 -0
  322. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/shaders/kernels.metal +5177 -0
  323. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/span.py +602 -0
  324. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/speculate.py +281 -0
  325. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/tools.py +326 -0
  326. favlo-0.3.0/pipelines/metal41/qwen36_35b_a3b/vision.py +954 -0
  327. favlo-0.3.0/pipelines/metal41/qwen38-27b.py +23 -0
  328. favlo-0.3.0/pipelines/metal41/qwen38-flash-next.py +23 -0
  329. favlo-0.3.0/pipelines/metal41/qwen38_27b/__init__.py +6 -0
  330. favlo-0.3.0/pipelines/metal41/qwen38_27b/attn.py +599 -0
  331. favlo-0.3.0/pipelines/metal41/qwen38_27b/budget.py +300 -0
  332. favlo-0.3.0/pipelines/metal41/qwen38_27b/cache.py +162 -0
  333. favlo-0.3.0/pipelines/metal41/qwen38_27b/chat.py +574 -0
  334. favlo-0.3.0/pipelines/metal41/qwen38_27b/checks.py +678 -0
  335. favlo-0.3.0/pipelines/metal41/qwen38_27b/commands.py +376 -0
  336. favlo-0.3.0/pipelines/metal41/qwen38_27b/convert.py +489 -0
  337. favlo-0.3.0/pipelines/metal41/qwen38_27b/fetch.py +193 -0
  338. favlo-0.3.0/pipelines/metal41/qwen38_27b/formats.py +351 -0
  339. favlo-0.3.0/pipelines/metal41/qwen38_27b/forward.py +1649 -0
  340. favlo-0.3.0/pipelines/metal41/qwen38_27b/layout.py +35 -0
  341. favlo-0.3.0/pipelines/metal41/qwen38_27b/prefill.py +559 -0
  342. favlo-0.3.0/pipelines/metal41/qwen38_27b/prefix.py +231 -0
  343. favlo-0.3.0/pipelines/metal41/qwen38_27b/resident.py +170 -0
  344. favlo-0.3.0/pipelines/metal41/qwen38_27b/runtime.py +37 -0
  345. favlo-0.3.0/pipelines/metal41/qwen38_27b/sampling.py +62 -0
  346. favlo-0.3.0/pipelines/metal41/qwen38_27b/session.py +451 -0
  347. favlo-0.3.0/pipelines/metal41/qwen38_27b/shaders/kernels.metal +2984 -0
  348. favlo-0.3.0/pipelines/metal41/qwen38_27b/shaders/vision.metal +371 -0
  349. favlo-0.3.0/pipelines/metal41/qwen38_27b/span.py +540 -0
  350. favlo-0.3.0/pipelines/metal41/qwen38_27b/speculate.py +199 -0
  351. favlo-0.3.0/pipelines/metal41/qwen38_27b/tools.py +305 -0
  352. favlo-0.3.0/pipelines/metal41/qwen38_27b/tower.py +506 -0
  353. favlo-0.3.0/pipelines/metal41/qwen38_27b/vision.py +518 -0
  354. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/__init__.py +135 -0
  355. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/adapt.py +365 -0
  356. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/allocate.py +147 -0
  357. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/carrot.py +88 -0
  358. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/checks.py +788 -0
  359. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/commands.py +1094 -0
  360. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/context.py +416 -0
  361. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/convert.py +910 -0
  362. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/eviction.py +317 -0
  363. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/experts.py +400 -0
  364. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/firing.py +393 -0
  365. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/formats.py +784 -0
  366. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/probe.py +665 -0
  367. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/quant_map.json +59 -0
  368. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/record.py +610 -0
  369. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/repack.py +246 -0
  370. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/runtime.py +4705 -0
  371. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/sampling.py +61 -0
  372. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/session.py +2963 -0
  373. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shader_text.py +8 -0
  374. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shaders/act.metal +1332 -0
  375. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shaders/matmul.metal +117 -0
  376. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shaders/moe.metal +1208 -0
  377. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shaders/probe.metal +109 -0
  378. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shaders/scan.metal +1393 -0
  379. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/shaders/vector.metal +137 -0
  380. favlo-0.3.0/pipelines/metal41/qwen38_flash_next/tools.py +374 -0
  381. favlo-0.3.0/pipelines/metal41/voxcpm2/__init__.py +6 -0
  382. favlo-0.3.0/pipelines/metal41/voxcpm2/audio.py +21 -0
  383. favlo-0.3.0/pipelines/metal41/voxcpm2/block.py +87 -0
  384. favlo-0.3.0/pipelines/metal41/voxcpm2/checkpoint.py +31 -0
  385. favlo-0.3.0/pipelines/metal41/voxcpm2/checks.py +196 -0
  386. favlo-0.3.0/pipelines/metal41/voxcpm2/commands.py +155 -0
  387. favlo-0.3.0/pipelines/metal41/voxcpm2/config.py +120 -0
  388. favlo-0.3.0/pipelines/metal41/voxcpm2/dit.py +165 -0
  389. favlo-0.3.0/pipelines/metal41/voxcpm2/fetch.py +67 -0
  390. favlo-0.3.0/pipelines/metal41/voxcpm2/fsq.py +17 -0
  391. favlo-0.3.0/pipelines/metal41/voxcpm2/metal.py +373 -0
  392. favlo-0.3.0/pipelines/metal41/voxcpm2/runtime.py +297 -0
  393. favlo-0.3.0/pipelines/metal41/voxcpm2/sampling.py +25 -0
  394. favlo-0.3.0/pipelines/metal41/voxcpm2/shaders/kernels.metal +219 -0
  395. favlo-0.3.0/pipelines/metal41/voxcpm2/speak.py +175 -0
  396. favlo-0.3.0/pipelines/metal41/voxcpm2/stack.py +144 -0
  397. favlo-0.3.0/pipelines/metal41/voxcpm2/store.py +88 -0
  398. favlo-0.3.0/pipelines/metal41/voxcpm2/text.py +15 -0
  399. favlo-0.3.0/pipelines/metal41/voxcpm2/tokenize.py +22 -0
  400. favlo-0.3.0/pipelines/metal41/voxcpm2/vae.py +206 -0
  401. favlo-0.3.0/pipelines/metal41/voxcpm2.py +23 -0
  402. favlo-0.3.0/pipelines/metal41/wan22-i2v.py +23 -0
  403. favlo-0.3.0/pipelines/metal41/wan22-ti2v-5b.py +23 -0
  404. favlo-0.3.0/pipelines/metal41/wan22_i2v/__init__.py +15 -0
  405. favlo-0.3.0/pipelines/metal41/wan22_i2v/chat.py +362 -0
  406. favlo-0.3.0/pipelines/metal41/wan22_i2v/commands.py +478 -0
  407. favlo-0.3.0/pipelines/metal41/wan22_i2v/dit.py +384 -0
  408. favlo-0.3.0/pipelines/metal41/wan22_i2v/formats.py +324 -0
  409. favlo-0.3.0/pipelines/metal41/wan22_i2v/hold.py +61 -0
  410. favlo-0.3.0/pipelines/metal41/wan22_i2v/latent.py +65 -0
  411. favlo-0.3.0/pipelines/metal41/wan22_i2v/measure.py +214 -0
  412. favlo-0.3.0/pipelines/metal41/wan22_i2v/metal.py +1106 -0
  413. favlo-0.3.0/pipelines/metal41/wan22_i2v/png.py +130 -0
  414. favlo-0.3.0/pipelines/metal41/wan22_i2v/progress.py +347 -0
  415. favlo-0.3.0/pipelines/metal41/wan22_i2v/record.py +437 -0
  416. favlo-0.3.0/pipelines/metal41/wan22_i2v/runtime.py +839 -0
  417. favlo-0.3.0/pipelines/metal41/wan22_i2v/sampling.py +26 -0
  418. favlo-0.3.0/pipelines/metal41/wan22_i2v/schedule.py +248 -0
  419. favlo-0.3.0/pipelines/metal41/wan22_i2v/shaders/kernels.metal +1516 -0
  420. favlo-0.3.0/pipelines/metal41/wan22_i2v/source.py +354 -0
  421. favlo-0.3.0/pipelines/metal41/wan22_i2v/text.py +143 -0
  422. favlo-0.3.0/pipelines/metal41/wan22_i2v/umt5_pack.py +285 -0
  423. favlo-0.3.0/pipelines/metal41/wan22_i2v/vae.py +661 -0
  424. favlo-0.3.0/pipelines/metal41/wan22_i2v/video.py +112 -0
  425. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/__init__.py +14 -0
  426. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/activations.py +125 -0
  427. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/avi.py +91 -0
  428. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/checkpoint.py +184 -0
  429. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/clip.py +146 -0
  430. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/commands.py +440 -0
  431. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/dit.py +192 -0
  432. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/gpu.py +898 -0
  433. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/png.py +121 -0
  434. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/quant.py +171 -0
  435. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/quantize.py +216 -0
  436. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/request.py +185 -0
  437. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/runtime.py +210 -0
  438. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/sampling.py +16 -0
  439. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/schedule.py +146 -0
  440. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/shaders/kernels.metal +1115 -0
  441. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/spec.py +30 -0
  442. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/stream.py +490 -0
  443. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/text.py +117 -0
  444. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/vae.py +577 -0
  445. favlo-0.3.0/pipelines/metal41/wan22_ti2v_5b/weights.py +91 -0
  446. favlo-0.3.0/pipelines/metal41/z-image-turbo.py +23 -0
  447. favlo-0.3.0/pipelines/metal41/z_image_turbo/__init__.py +7 -0
  448. favlo-0.3.0/pipelines/metal41/z_image_turbo/chat.py +419 -0
  449. favlo-0.3.0/pipelines/metal41/z_image_turbo/commands.py +373 -0
  450. favlo-0.3.0/pipelines/metal41/z_image_turbo/dit.py +471 -0
  451. favlo-0.3.0/pipelines/metal41/z_image_turbo/formats.py +146 -0
  452. favlo-0.3.0/pipelines/metal41/z_image_turbo/hold.py +60 -0
  453. favlo-0.3.0/pipelines/metal41/z_image_turbo/metal.py +1022 -0
  454. favlo-0.3.0/pipelines/metal41/z_image_turbo/ops.py +59 -0
  455. favlo-0.3.0/pipelines/metal41/z_image_turbo/png.py +85 -0
  456. favlo-0.3.0/pipelines/metal41/z_image_turbo/progress.py +126 -0
  457. favlo-0.3.0/pipelines/metal41/z_image_turbo/record.py +324 -0
  458. favlo-0.3.0/pipelines/metal41/z_image_turbo/runtime.py +498 -0
  459. favlo-0.3.0/pipelines/metal41/z_image_turbo/sampling.py +27 -0
  460. favlo-0.3.0/pipelines/metal41/z_image_turbo/schedule.py +28 -0
  461. favlo-0.3.0/pipelines/metal41/z_image_turbo/scratch.py +137 -0
  462. favlo-0.3.0/pipelines/metal41/z_image_turbo/shaders/kernels.metal +1296 -0
  463. favlo-0.3.0/pipelines/metal41/z_image_turbo/source.py +97 -0
  464. favlo-0.3.0/pipelines/metal41/z_image_turbo/text.py +242 -0
  465. favlo-0.3.0/pipelines/metal41/z_image_turbo/vae.py +304 -0
  466. favlo-0.3.0/pyproject.toml +64 -0
  467. favlo-0.3.0/skills-global/session-clear/SKILL.md +6 -0
  468. favlo-0.3.0/skills-global/session-remember/SKILL.md +6 -0
  469. favlo-0.3.0/src/favlo/__init__.py +3 -0
  470. favlo-0.3.0/src/favlo/__main__.py +3 -0
  471. favlo-0.3.0/src/favlo/chat_client.py +117 -0
  472. favlo-0.3.0/src/favlo/cli.py +225 -0
  473. favlo-0.3.0/src/favlo/config_tools.py +234 -0
  474. favlo-0.3.0/src/favlo/console.py +1175 -0
  475. favlo-0.3.0/src/favlo/daemon.py +496 -0
  476. favlo-0.3.0/src/favlo/embeddings_pipeline.py +105 -0
  477. favlo-0.3.0/src/favlo/guides.py +49 -0
  478. favlo-0.3.0/src/favlo/hf_cache.py +31 -0
  479. favlo-0.3.0/src/favlo/http_app.py +924 -0
  480. favlo-0.3.0/src/favlo/images.py +130 -0
  481. favlo-0.3.0/src/favlo/language_pipeline.py +86 -0
  482. favlo-0.3.0/src/favlo/listener.py +342 -0
  483. favlo-0.3.0/src/favlo/logs.py +293 -0
  484. favlo-0.3.0/src/favlo/machine.py +237 -0
  485. favlo-0.3.0/src/favlo/mcp_server.py +969 -0
  486. favlo-0.3.0/src/favlo/media_meta.py +118 -0
  487. favlo-0.3.0/src/favlo/media_pipeline.py +454 -0
  488. favlo-0.3.0/src/favlo/media_session.py +67 -0
  489. favlo-0.3.0/src/favlo/memory.py +996 -0
  490. favlo-0.3.0/src/favlo/memory_mcp.py +111 -0
  491. favlo-0.3.0/src/favlo/memory_notes.py +322 -0
  492. favlo-0.3.0/src/favlo/music.py +151 -0
  493. favlo-0.3.0/src/favlo/offset.py +117 -0
  494. favlo-0.3.0/src/favlo/persona.py +17 -0
  495. favlo-0.3.0/src/favlo/pipeline.py +69 -0
  496. favlo-0.3.0/src/favlo/pipeline_worker.py +877 -0
  497. favlo-0.3.0/src/favlo/pipelines.py +565 -0
  498. favlo-0.3.0/src/favlo/prefix.py +695 -0
  499. favlo-0.3.0/src/favlo/registry.py +999 -0
  500. favlo-0.3.0/src/favlo/reply.py +128 -0
  501. favlo-0.3.0/src/favlo/schedule.py +186 -0
  502. favlo-0.3.0/src/favlo/setup.py +75 -0
  503. favlo-0.3.0/src/favlo/setup_run.py +271 -0
  504. favlo-0.3.0/src/favlo/smoke_lock.py +305 -0
  505. favlo-0.3.0/src/favlo/videos.py +223 -0
  506. favlo-0.3.0/src/favlo/voice.py +151 -0
  507. favlo-0.3.0/src/favlo/web_host.py +143 -0
  508. favlo-0.3.0/tests/decode_rate.py +14 -0
  509. favlo-0.3.0/tests/test_acceptance_smoke.py +76 -0
  510. favlo-0.3.0/tests/test_ace_step_15_turbo.py +592 -0
  511. favlo-0.3.0/tests/test_act.py +9 -0
  512. favlo-0.3.0/tests/test_agent_harness.py +63 -0
  513. favlo-0.3.0/tests/test_benchmarks.py +102 -0
  514. favlo-0.3.0/tests/test_bge_m3.py +149 -0
  515. favlo-0.3.0/tests/test_bge_m3_smoke.py +51 -0
  516. favlo-0.3.0/tests/test_chat_agent.py +71 -0
  517. favlo-0.3.0/tests/test_chat_client.py +58 -0
  518. favlo-0.3.0/tests/test_cli.py +92 -0
  519. favlo-0.3.0/tests/test_cli_session.py +18 -0
  520. favlo-0.3.0/tests/test_coding_harness.py +101 -0
  521. favlo-0.3.0/tests/test_coding_tools.py +564 -0
  522. favlo-0.3.0/tests/test_coherence.py +28 -0
  523. favlo-0.3.0/tests/test_console.py +889 -0
  524. favlo-0.3.0/tests/test_context.py +244 -0
  525. favlo-0.3.0/tests/test_daemon.py +242 -0
  526. favlo-0.3.0/tests/test_embeddings_agent.py +75 -0
  527. favlo-0.3.0/tests/test_eviction.py +151 -0
  528. favlo-0.3.0/tests/test_experts.py +14 -0
  529. favlo-0.3.0/tests/test_file_session.py +142 -0
  530. favlo-0.3.0/tests/test_firing.py +261 -0
  531. favlo-0.3.0/tests/test_guides.py +74 -0
  532. favlo-0.3.0/tests/test_harness_server.py +81 -0
  533. favlo-0.3.0/tests/test_harness_video_mp4.py +27 -0
  534. favlo-0.3.0/tests/test_heartbeat.py +113 -0
  535. favlo-0.3.0/tests/test_hf_cache.py +21 -0
  536. favlo-0.3.0/tests/test_image_attachment.py +44 -0
  537. favlo-0.3.0/tests/test_images.py +46 -0
  538. favlo-0.3.0/tests/test_indexer.py +74 -0
  539. favlo-0.3.0/tests/test_inspect_voice.py +25 -0
  540. favlo-0.3.0/tests/test_jobs.py +124 -0
  541. favlo-0.3.0/tests/test_kv_cache.py +159 -0
  542. favlo-0.3.0/tests/test_language_pipeline.py +163 -0
  543. favlo-0.3.0/tests/test_logs.py +117 -0
  544. favlo-0.3.0/tests/test_long_context.py +38 -0
  545. favlo-0.3.0/tests/test_matmul.py +10 -0
  546. favlo-0.3.0/tests/test_mcp_music.py +19 -0
  547. favlo-0.3.0/tests/test_media_meta.py +47 -0
  548. favlo-0.3.0/tests/test_media_pipeline.py +193 -0
  549. favlo-0.3.0/tests/test_media_pipeline_harness.py +127 -0
  550. favlo-0.3.0/tests/test_memory.py +175 -0
  551. favlo-0.3.0/tests/test_memory_agent.py +41 -0
  552. favlo-0.3.0/tests/test_memory_notes.py +160 -0
  553. favlo-0.3.0/tests/test_mtp.py +29 -0
  554. favlo-0.3.0/tests/test_music_long_agent.py +48 -0
  555. favlo-0.3.0/tests/test_music_template.py +77 -0
  556. favlo-0.3.0/tests/test_ngram.py +41 -0
  557. favlo-0.3.0/tests/test_packing.py +106 -0
  558. favlo-0.3.0/tests/test_page_advice.py +154 -0
  559. favlo-0.3.0/tests/test_pipeline_worker.py +179 -0
  560. favlo-0.3.0/tests/test_pipelines.py +215 -0
  561. favlo-0.3.0/tests/test_prefix.py +353 -0
  562. favlo-0.3.0/tests/test_probe.py +28 -0
  563. favlo-0.3.0/tests/test_qwen36_35b_a3b.py +1436 -0
  564. favlo-0.3.0/tests/test_qwen36_35b_a3b_smoke.py +178 -0
  565. favlo-0.3.0/tests/test_qwen36_35b_a3b_smoke_16gb.py +63 -0
  566. favlo-0.3.0/tests/test_qwen36_fetch.py +109 -0
  567. favlo-0.3.0/tests/test_qwen36_firing.py +214 -0
  568. favlo-0.3.0/tests/test_qwen36_vision.py +162 -0
  569. favlo-0.3.0/tests/test_qwen38_27b.py +1676 -0
  570. favlo-0.3.0/tests/test_qwen38_27b_smoke.py +210 -0
  571. favlo-0.3.0/tests/test_registry.py +487 -0
  572. favlo-0.3.0/tests/test_resident_rate.py +98 -0
  573. favlo-0.3.0/tests/test_runtime_quant.py +1397 -0
  574. favlo-0.3.0/tests/test_sampling.py +78 -0
  575. favlo-0.3.0/tests/test_schedule.py +358 -0
  576. favlo-0.3.0/tests/test_server.py +2262 -0
  577. favlo-0.3.0/tests/test_setup.py +61 -0
  578. favlo-0.3.0/tests/test_setup_run.py +199 -0
  579. favlo-0.3.0/tests/test_smoke.py +205 -0
  580. favlo-0.3.0/tests/test_smoke_lock.py +177 -0
  581. favlo-0.3.0/tests/test_tools.py +379 -0
  582. favlo-0.3.0/tests/test_videos.py +73 -0
  583. favlo-0.3.0/tests/test_voice_smoke_agent.py +37 -0
  584. favlo-0.3.0/tests/test_voxcpm2.py +173 -0
  585. favlo-0.3.0/tests/test_voxcpm2_smoke.py +41 -0
  586. favlo-0.3.0/tests/test_wan22_i2v.py +1170 -0
  587. favlo-0.3.0/tests/test_wan22_i2v_smoke.py +55 -0
  588. favlo-0.3.0/tests/test_wan22_ti2v_5b.py +184 -0
  589. favlo-0.3.0/tests/test_web_api.py +1255 -0
  590. favlo-0.3.0/tests/test_web_folder_pick.py +43 -0
  591. favlo-0.3.0/tests/test_web_gallery.py +787 -0
  592. favlo-0.3.0/tests/test_web_heartbeat.py +201 -0
  593. favlo-0.3.0/tests/test_web_host.py +18 -0
  594. favlo-0.3.0/tests/test_web_mcp.py +526 -0
  595. favlo-0.3.0/tests/test_web_media.py +34 -0
  596. favlo-0.3.0/tests/test_worktree_harness.py +130 -0
  597. favlo-0.3.0/tests/test_z_image_turbo.py +1018 -0
  598. favlo-0.3.0/tests/test_z_image_turbo_smoke.py +79 -0
  599. favlo-0.3.0/uv.lock +2572 -0
  600. favlo-0.3.0/web-api/README.md +83 -0
  601. favlo-0.3.0/web-api/app.py +7 -0
  602. favlo-0.3.0/web-api/web_api/__init__.py +1 -0
  603. favlo-0.3.0/web-api/web_api/api.py +156 -0
  604. favlo-0.3.0/web-api/web_api/bus.py +23 -0
  605. favlo-0.3.0/web-api/web_api/chat.py +305 -0
  606. favlo-0.3.0/web-api/web_api/conversation.py +207 -0
  607. favlo-0.3.0/web-api/web_api/cron.py +115 -0
  608. favlo-0.3.0/web-api/web_api/db.py +594 -0
  609. favlo-0.3.0/web-api/web_api/discovery.py +45 -0
  610. favlo-0.3.0/web-api/web_api/events.py +46 -0
  611. favlo-0.3.0/web-api/web_api/folder_pick.py +38 -0
  612. favlo-0.3.0/web-api/web_api/folder_port.py +239 -0
  613. favlo-0.3.0/web-api/web_api/gallery_tools.py +246 -0
  614. favlo-0.3.0/web-api/web_api/global_skill_catalog.py +44 -0
  615. favlo-0.3.0/web-api/web_api/heartbeat_clock.py +54 -0
  616. favlo-0.3.0/web-api/web_api/heartbeat_tools.py +232 -0
  617. favlo-0.3.0/web-api/web_api/http.py +18 -0
  618. favlo-0.3.0/web-api/web_api/ids.py +9 -0
  619. favlo-0.3.0/web-api/web_api/mcp_cache.py +103 -0
  620. favlo-0.3.0/web-api/web_api/mcp_client.py +265 -0
  621. favlo-0.3.0/web-api/web_api/mcp_groups.py +43 -0
  622. favlo-0.3.0/web-api/web_api/mcp_tasks.py +163 -0
  623. favlo-0.3.0/web-api/web_api/mcp_tools.py +227 -0
  624. favlo-0.3.0/web-api/web_api/profile.py +34 -0
  625. favlo-0.3.0/web-api/web_api/routes/__init__.py +1 -0
  626. favlo-0.3.0/web-api/web_api/routes/agents.py +185 -0
  627. favlo-0.3.0/web-api/web_api/routes/channels.py +17 -0
  628. favlo-0.3.0/web-api/web_api/routes/events.py +64 -0
  629. favlo-0.3.0/web-api/web_api/routes/heartbeats.py +71 -0
  630. favlo-0.3.0/web-api/web_api/routes/mcp.py +86 -0
  631. favlo-0.3.0/web-api/web_api/routes/media.py +80 -0
  632. favlo-0.3.0/web-api/web_api/routes/providers.py +122 -0
  633. favlo-0.3.0/web-api/web_api/routes/sessions.py +48 -0
  634. favlo-0.3.0/web-api/web_api/routes/settings.py +29 -0
  635. favlo-0.3.0/web-api/web_api/routes/workspaces.py +354 -0
  636. favlo-0.3.0/web-api/web_api/runs.py +146 -0
  637. favlo-0.3.0/web-api/web_api/schemas.py +190 -0
  638. favlo-0.3.0/web-api/web_api/session_tools.py +68 -0
  639. favlo-0.3.0/web-api/web_api/skills-workspace/gallery/manage-gallery/SKILL.md +26 -0
  640. favlo-0.3.0/web-api/web_api/store.py +3091 -0
  641. favlo-0.3.0/web-api/web_api/tool_names.py +31 -0
  642. favlo-0.3.0/web-api/web_api/workspace.py +42 -0
  643. favlo-0.3.0/web-api/web_api/workspace_skill_catalog.py +20 -0
  644. favlo-0.3.0/web-spa/README.md +70 -0
  645. favlo-0.3.0/web-spa/app.json +20 -0
  646. favlo-0.3.0/web-spa/babel.config.js +6 -0
  647. favlo-0.3.0/web-spa/e2e/agent-create.spec.ts +58 -0
  648. favlo-0.3.0/web-spa/e2e/agent-delete.spec.ts +39 -0
  649. favlo-0.3.0/web-spa/e2e/agent-skills.spec.ts +34 -0
  650. favlo-0.3.0/web-spa/e2e/chat-align.spec.ts +84 -0
  651. favlo-0.3.0/web-spa/e2e/chat.spec.ts +306 -0
  652. favlo-0.3.0/web-spa/e2e/cleanup.ts +83 -0
  653. favlo-0.3.0/web-spa/e2e/empty.spec.ts +75 -0
  654. favlo-0.3.0/web-spa/e2e/gallery.spec.ts +69 -0
  655. favlo-0.3.0/web-spa/e2e/markdown.spec.ts +28 -0
  656. favlo-0.3.0/web-spa/e2e/mcp.spec.ts +74 -0
  657. favlo-0.3.0/web-spa/e2e/media.spec.ts +124 -0
  658. favlo-0.3.0/web-spa/e2e/thinking.spec.ts +35 -0
  659. favlo-0.3.0/web-spa/e2e/web-new-user-e2e-setup/playwright.config.ts +40 -0
  660. favlo-0.3.0/web-spa/e2e/web-new-user-e2e-setup/serve.sh +18 -0
  661. favlo-0.3.0/web-spa/e2e/web-new-user-e2e-setup/setup.spec.ts +93 -0
  662. favlo-0.3.0/web-spa/e2e/working.spec.ts +30 -0
  663. favlo-0.3.0/web-spa/e2e/workspace-skills.spec.ts +42 -0
  664. favlo-0.3.0/web-spa/package-lock.json +17638 -0
  665. favlo-0.3.0/web-spa/package.json +53 -0
  666. favlo-0.3.0/web-spa/playwright.config.ts +19 -0
  667. favlo-0.3.0/web-spa/src/api/client.ts +29 -0
  668. favlo-0.3.0/web-spa/src/app/_layout.tsx +39 -0
  669. favlo-0.3.0/web-spa/src/app/index.tsx +5 -0
  670. favlo-0.3.0/web-spa/src/app/settings.tsx +5 -0
  671. favlo-0.3.0/web-spa/src/components/ChatScreen.tsx +689 -0
  672. favlo-0.3.0/web-spa/src/components/Composer.tsx +97 -0
  673. favlo-0.3.0/web-spa/src/components/Confirmation.tsx +56 -0
  674. favlo-0.3.0/web-spa/src/components/EmptyState.tsx +49 -0
  675. favlo-0.3.0/web-spa/src/components/FeatherIcon.tsx +39 -0
  676. favlo-0.3.0/web-spa/src/components/Frame.tsx +254 -0
  677. favlo-0.3.0/web-spa/src/components/GalleryWorkspace.tsx +1274 -0
  678. favlo-0.3.0/web-spa/src/components/IconButton.tsx +72 -0
  679. favlo-0.3.0/web-spa/src/components/MarkdownText.tsx +194 -0
  680. favlo-0.3.0/web-spa/src/components/MenuRow.tsx +56 -0
  681. favlo-0.3.0/web-spa/src/components/MessageBody.tsx +442 -0
  682. favlo-0.3.0/web-spa/src/components/Modal.tsx +109 -0
  683. favlo-0.3.0/web-spa/src/components/Pressable.tsx +64 -0
  684. favlo-0.3.0/web-spa/src/components/SettingsScreen.tsx +1497 -0
  685. favlo-0.3.0/web-spa/src/components/SkillForm.tsx +141 -0
  686. favlo-0.3.0/web-spa/src/components/Thinking.tsx +46 -0
  687. favlo-0.3.0/web-spa/src/components/WorkspaceSkills.tsx +139 -0
  688. favlo-0.3.0/web-spa/src/components/Workspaces.tsx +54 -0
  689. favlo-0.3.0/web-spa/src/components/chat-transcript.tsx +116 -0
  690. favlo-0.3.0/web-spa/src/components/composer-keys.ts +6 -0
  691. favlo-0.3.0/web-spa/src/components/scrollbar.ts +24 -0
  692. favlo-0.3.0/web-spa/src/components/working.ts +33 -0
  693. favlo-0.3.0/web-spa/src/react-dom.d.ts +5 -0
  694. favlo-0.3.0/web-spa/src/theme/Theme.tsx +64 -0
  695. favlo-0.3.0/web-spa/src/theme/tokens.ts +156 -0
  696. favlo-0.3.0/web-spa/src/theme/type.ts +43 -0
  697. favlo-0.3.0/web-spa/tests/agent-create-test.tsx +176 -0
  698. favlo-0.3.0/web-spa/tests/channels-test.tsx +44 -0
  699. favlo-0.3.0/web-spa/tests/composer-test.ts +15 -0
  700. favlo-0.3.0/web-spa/tests/composer-ui-test.tsx +23 -0
  701. favlo-0.3.0/web-spa/tests/confirmation-test.tsx +20 -0
  702. favlo-0.3.0/web-spa/tests/contrast-test.ts +37 -0
  703. favlo-0.3.0/web-spa/tests/conversation-tools-test.tsx +84 -0
  704. favlo-0.3.0/web-spa/tests/empty-chat-test.tsx +110 -0
  705. favlo-0.3.0/web-spa/tests/frame-test.tsx +53 -0
  706. favlo-0.3.0/web-spa/tests/gallery-workspace-test.tsx +385 -0
  707. favlo-0.3.0/web-spa/tests/heartbeats-test.tsx +82 -0
  708. favlo-0.3.0/web-spa/tests/markdown-test.tsx +63 -0
  709. favlo-0.3.0/web-spa/tests/mcp-test.tsx +82 -0
  710. favlo-0.3.0/web-spa/tests/message-body-test.tsx +48 -0
  711. favlo-0.3.0/web-spa/tests/press-feedback-test.tsx +31 -0
  712. favlo-0.3.0/web-spa/tests/scrollbar-test.ts +16 -0
  713. favlo-0.3.0/web-spa/tests/session-clear-test.tsx +10 -0
  714. favlo-0.3.0/web-spa/tests/setup.js +9 -0
  715. favlo-0.3.0/web-spa/tests/skills-config-test.tsx +87 -0
  716. favlo-0.3.0/web-spa/tests/thinking-test.tsx +47 -0
  717. favlo-0.3.0/web-spa/tests/transcript-scroll-test.tsx +22 -0
  718. favlo-0.3.0/web-spa/tests/working-test.ts +17 -0
  719. favlo-0.3.0/web-spa/tests/workspaces-test.tsx +50 -0
  720. favlo-0.3.0/web-spa/tsconfig.json +18 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "favlo": {
4
+ "type": "http",
5
+ "url": "http://127.0.0.1:8129/mcp"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: Before a commit, check every file for personal data and disallowed content
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Commit precheck
7
+
8
+ Before creating a commit, check every path the commit would add. That includes source, docs, tests, shaders, data, images, and any other file. A clean subset does not excuse an unchecked path.
9
+
10
+ ## Personal data
11
+
12
+ Look for names, email addresses, phone numbers, account handles, home directories, hostnames, serial numbers, local network addresses, tokens, keys, passwords, and private URLs. Logs, screenshots, and sample output count.
13
+
14
+ Placeholders are `~/.favlo`, `127.0.0.1`, and `example-model`. The copyright line already in the repository stays. A new name does not.
15
+
16
+ When a path contains personal data, leave it out of the commit. Name the path and the kind. Do not copy the value into the commit message or the reply.
17
+
18
+ ## NSFW, violent, and racist content
19
+
20
+ Look for sexual, erotic, nude, obscene, violent, racist, hateful, or abusive text, prompts, and images, including instructions to harm a person or an animal. A refusal policy may name the categories it refuses. A test may quote a request only to assert that the refusal leaves it out of the reply.
21
+
22
+ When a path contains that content, leave it out of the commit. Name the path. Do not quote the content.
@@ -0,0 +1,43 @@
1
+ ---
2
+ globs: *.md
3
+ alwaysApply: false
4
+ ---
5
+ # Public documentation
6
+
7
+ This repository is public. Anyone can read the tree, the history, issues, and pull requests. Write docs, commits, comments, and examples as if they will stay public.
8
+
9
+ A block quote is a line that starts with `>`. The author wrote those lines, including the tone and the first person. Leave a block quote unchanged. Do not rephrase it, apply the tone rules to it, or move its wording into the surrounding prose. Update a block quote only when the user explicitly asks for that quote to be changed.
10
+
11
+ ## No personal data
12
+
13
+ Do not commit personal data or secrets. That includes names, email addresses, phone numbers, account handles, home directories, hostnames, serial numbers, local network addresses, tokens, keys, passwords, and private URLs. Logs, screenshots, and sample output follow the same rule.
14
+
15
+ Use a placeholder instead: `~/.favlo`, `127.0.0.1`, `example-model`. If a secret was committed, remove it and rotate it. Deleting the file in a later commit leaves it in history.
16
+
17
+ ## Official base models
18
+
19
+ A pipeline note names the official base model and its Hugging Face model card. A finetune, merge, or other derived checkpoint stays out of `docs/<pipeline>/`, even when this repo quantizes or serves that derived checkpoint.
20
+
21
+ The directory stem in the note is the official repository name plus the weight quants, such as `Qwen3.6-35B-A3B-fp4`. The card link is the publisher's repository, such as `Qwen/Qwen3.6-35B-A3B`.
22
+
23
+ ## Tone and shape
24
+
25
+ Use calm, neutral sentences. State what the project does and what the reader can run. Skip slogans and urgency. A measured time names the machine: an M5 Pro with 48 GB. A hostname, a home directory, a serial number, and a user name stay out.
26
+
27
+ Outside a block quote, a claim by the author is in the third person. Write "the author", not "I", "me", or "my".
28
+
29
+ A public README says what the project is, how to install it, one minimal command, the license, and where to report a problem. Name a pipeline only in the Pipeline table. Keep the as-built detail in linked docs such as ARCHITECTURE.md. Prefer relative links between files in the repo.
30
+
31
+ ## Examples
32
+
33
+ Wrong: "Fixed the crash on the user's M5 at `/Users/user/Models`. Email me at user@example.com."
34
+
35
+ Right: "On an M5 Pro with 48 GB the dispatch measured 15.084 ms. The server listens on `127.0.0.1:8000`. A missing checkpoint path is reported and the process exits."
36
+
37
+ Wrong, outside a block quote: "I admire this work, and I recommend it before trying Favlo."
38
+
39
+ Right, outside a block quote: "The author admires this work and recommends it before trying Favlo." A block quote that already says this in the first person stays as written.
40
+
41
+ Wrong: "Quantize writes `models/Example-Model-Uncensored-fp4` from `ExampleOrg/Example-Model-Uncensored`."
42
+
43
+ Right: "Quantize writes `models/Qwen3.6-35B-A3B-fp4`. The model card is [Qwen/Qwen3.6-35B-A3B](https://huggingface.co/Qwen/Qwen3.6-35B-A3B)."
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: How a served embedding model implements EmbeddingsPipeline.
3
+ globs: src/favlo/embeddings_pipeline.py,src/favlo/pipeline.py,pipelines/metal41/bge_m3/**,docs/bge-m3/**,harness/language_pipeline.py,harness/embeddings_agent.py
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Embedding pipelines
8
+
9
+ A served embedding model inherits `EmbeddingsPipeline` in `src/favlo/embeddings_pipeline.py`. That class extends `Pipeline`. A language model and a media pipeline do not inherit it. The class writes the OpenAI list object. It does not normalize a vector or choose a hidden size.
10
+
11
+ Bind `handle_embed = Pipeline()`. `embed` returns the vector and the token count. `parse` rejects a missing or blank string with `input must be a string` and `param` `input`. A `ValueError` from `embed` is a 400 with `param` `None`. The `model` field is `selection.requested_id`, or `""` when the selection is missing. It does not read `body["model"]`.
12
+
13
+ A new abstract method on `EmbeddingsPipeline` updates every served embedding subclass in that same change.
14
+
15
+ The language harness posts this route. After a change to `embed` or the list object, run `uv run python -m harness.language_pipeline`. That command is in [language-pipeline.mdc](language-pipeline.mdc). `python -m harness.embeddings_agent` remains the direct check of the same six sentences.
16
+
17
+ Wrong: copying the list object into the pipeline package, or catching `ValueError` around the reply builder.
18
+
19
+ Right: `embed` returns `(vector, tokens)` and the class writes `usage.prompt_tokens`.
@@ -0,0 +1,35 @@
1
+ ---
2
+ description: Favlo web UI changes need a Jest unit test and a headless Playwright script against live favlo serve.
3
+ globs: web-spa/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Favlo web completion
8
+
9
+ A change under `web-spa/` that alters what a person can see or do needs both of the checks below, in the same change. A change that does not alter the screen adds neither.
10
+
11
+ ## Unit tests
12
+
13
+ Use Jest with the `jest-expo` preset and `@testing-library/react-native`. Router tests use `expo-router/testing-library` and live outside `app/`. These tests do not start `favlo serve` or a browser.
14
+
15
+ ```bash
16
+ cd web-spa && npx jest <test>
17
+ ```
18
+
19
+ ## End-to-end
20
+
21
+ Playwright simulates the person in headless Chromium. The script is a fixed sequence of clicks, typing, and keys. `favlo web` is running, and it calls a live `favlo serve`. Do not stub the model or a media tool.
22
+
23
+ ```bash
24
+ cd web-spa && npx playwright test e2e/<feature>.spec.ts --project=chromium
25
+ ```
26
+
27
+ The script is `web-spa/e2e/<feature>.spec.ts`. `web-spa/playwright.config.ts` sets `screenshot` to `on`.
28
+
29
+ - Do not use `waitForTimeout` or a retry that ignores the failure. Wait for a selector, a response, or an event.
30
+ - The prompt and the clicks are fixed. Assert the outcome on screen. Assert exact wording only when that wording is not model output.
31
+ - Cover wide at 1280×800. When the feature has a narrow layout, cover 390×844 in the same script.
32
+ - Open `http://127.0.0.1:8012`. Leave the browser on `127.0.0.1`.
33
+ - Playwright writes a screenshot for every script, including a script that passes. The file is under `web-spa/test-results/`. Read that screenshot before treating the run as finished. Leave the screenshot uncommitted.
34
+
35
+ A phase is finished only when every feature script in that phase passes, its unit tests pass, and the passing screenshot shows the outcome on screen.
@@ -0,0 +1,17 @@
1
+ ---
2
+ description: Keep docs/harness.md in sync when harness entry points or shared harness behavior change.
3
+ globs: harness/**,docs/harness.md
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Harness documentation
8
+
9
+ [docs/harness.md](../docs/harness.md) is the catalog of `python -m harness.*` clients and shared listener or lock rules.
10
+
11
+ When you add, remove, or rename a harness module, change what a harness calls on `serve` or `POST /mcp`, change exit criteria or artifact paths, or change whether a harness takes the machine lock or uses `harness.server`, update `docs/harness.md` in the same change.
12
+
13
+ Give each runnable harness its own `###` subsection under the right group (language, image, video, music, voice, media preemption, or helpers). The subsection title is a short descriptive name, not the CLI. Put the command in a fenced `bash` block immediately under the title, then the prose. Mention `pytest` or `tests/test_*` when a harness has a unit test that runs without a listener.
14
+
15
+ Shared infrastructure (`harness.server`, machine lock, default chat model) stays in the opening sections; do not duplicate those paragraphs in every subsection.
16
+
17
+ Follow [documentation.mdc](documentation.mdc) for tone and placeholders.
@@ -0,0 +1,28 @@
1
+ ---
2
+ description: How a served language model implements LanguagePipeline, and when to run the language harness.
3
+ globs: src/favlo/pipeline.py,src/favlo/language_pipeline.py,harness/language_pipeline.py,tests/test_language_pipeline.py,pipelines/metal41/qwen36_35b_a3b/**,pipelines/metal41/qwen38_27b/**,pipelines/metal41/qwen38_flash_next/**,docs/qwen36-35b-a3b/**,docs/qwen38-27b/**,docs/qwen38-flash-next/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Language pipelines
8
+
9
+ A served language model inherits `LanguagePipeline` in `src/favlo/language_pipeline.py`. That class extends `Pipeline`. A media pipeline does not inherit it. A failed pipeline does not. The class is the disconnect shell around one chat completion. It does not encode a prompt, sample a token, or parse a tool call.
10
+
11
+ Bind `handle_chat = Pipeline()`. `complete` is the pipeline's own chat, including its sampler and its stream. `RequestClosed` subclasses `ClientClosed`.
12
+
13
+ `on_open` is the work that already sits outside the try. qwen36 and qwen38-27b reset `_halted` and set `runtime._stop` there. Flash Next only calls `open_request` there. `prepare` is inside the outer try and outside the disconnect try. Only Flash Next uses it, for the tool fields and the sampler. `on_finish` keeps that pipeline's current order and always runs after `prepare`. Hooks are called directly. Do not swallow a hook exception.
14
+
15
+ A new abstract method on `LanguagePipeline` updates every served language subclass in that same change. A new abstract method on `Pipeline` updates every subclass of every seam.
16
+
17
+ After a change to this shell, run:
18
+
19
+ ```text
20
+ uv run pytest tests/test_language_pipeline.py
21
+ uv run python -m harness.language_pipeline
22
+ ```
23
+
24
+ The harness is the one agent for the registry default chat model and `bge-m3-int8`. It does not take the machine lock. It uses one `favlo serve` on `127.0.0.1:8129`. Exit 0 means `check_embeddings` ran and every paraphrase cosine beat every cross-topic cosine. A kernel or quantize edit that leaves `complete`, the disconnect shell, and the reply alone does not run the harness.
25
+
26
+ Wrong: a shared sampler in `LanguagePipeline`, or a second harness per language model.
27
+
28
+ Right: `complete` raises `RequestClosed`, and the shell clears `runtime._stop`.
@@ -0,0 +1,17 @@
1
+ ---
2
+ description: Keep MCP.md in sync when the media MCP server tools, resources, or task behavior change.
3
+ globs: src/favlo/mcp_server.py,src/favlo/memory_mcp.py,tests/test_server.py
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # MCP server documentation
8
+
9
+ `MCP.md` at the repository root is the public catalog of Favlo’s `POST /mcp` tools and `favlo://` resources.
10
+
11
+ When you add, remove, or rename a tool or resource, change tool parameters or defaults, change optional-task behavior, or change what generate tools return (links, inline media, task fields), update `MCP.md` in the same change.
12
+
13
+ `docs/serve.md` stays the listener note: transport, queue, preemption, logging, and client wiring. Do not duplicate the full tool tables there; add or adjust a single pointer to `MCP.md` if the serve note still names tools inline.
14
+
15
+ Do not document chat completion or OpenAI HTTP routes in `MCP.md`. Do not add HTTP `/v1/images`, `/v1/videos`, or `/v1/audio` routes to satisfy MCP clients.
16
+
17
+ Follow [documentation.mdc](documentation.mdc) for tone and placeholders.
@@ -0,0 +1,36 @@
1
+ ---
2
+ description: How a served media pipeline implements MediaPipeline, and when to extend and run the preemption harness.
3
+ globs: src/favlo/media_pipeline.py,src/favlo/pipeline_worker.py,src/favlo/pipelines.py,harness/media_pipeline.py,tests/test_media_pipeline.py,tests/test_media_pipeline_harness.py,pipelines/metal41/z_image_turbo/**,pipelines/metal41/wan22_i2v/**,pipelines/metal41/wan22_ti2v_5b/**,pipelines/metal41/ace_step_15_turbo/**,pipelines/metal41/voxcpm2/**,docs/z-image-turbo/**,docs/wan22-i2v/**,docs/wan22-ti2v-5b/**,docs/ace-step-15-turbo/**,docs/voxcpm2/**,docs/harness.md
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Media pipelines
8
+
9
+ A served image, video, music, or voice pipeline inherits `MediaPipeline` in `src/favlo/media_pipeline.py`. `MediaPipeline` extends `Pipeline`. A language model, an embedding model, and a failed pipeline do not inherit `MediaPipeline`. The class is the listener seam. It does not run a forward, name stages, acquire a scheduler ticket, or free device memory.
10
+
11
+ Bind `handle_<kind> = Pipeline()`. `__call__` is `handle`. The subclass implements `parse`, `generate`, and `pack`. The checkpoint type stays in the pipeline package. `ClipPaused` and `ImagePaused` subclass `MediaPaused`.
12
+
13
+ `generate` calls `stop()` at a stage boundary, after the Metal command already submitted has finished. Preempt raises `MediaPaused("preempt", hold)` with the host values the next stage needs. Cancel raises `MediaPaused("cancel", None)`. Device buffers do not go in the hold. They do not survive `close`. Resume calls `generate` again with that hold and the same job id.
14
+
15
+ Clear a hold with `state[key] = None`. Do not `pop` the key. The exported keys are `image_hold`, `video_hold`, `music_hold`, and `voice_hold`, the same tuple in `pipeline_worker.py` and `pipelines.py`. A new kind adds its key to both tuples in that change.
16
+
17
+ `parse` or `generate` raises `MediaRequestError` for a bad body. That is a 400. Any other exception fails the job with `error` `{"message", "type"}`. `describe` copies the job keys MCP already reads (`size`, `seconds`, `response_format`). `reply.json` runs once with the job before `generate`. Call it again only when `pack` or `working` returns a different dict. A new abstract method updates every subclass in that same change. One pipeline note records that pipeline's checkpoint. Do not describe another pipeline there.
18
+
19
+ ## Preemption harness
20
+
21
+ One agent covers every served media pipeline: `python -m harness.media_pipeline`. The order is `image`, `i2v`, `t2v`, `music`, `voice`. Names after the command run that subset in the same order, as in `python -m harness.media_pipeline i2v`. An omitted list runs every name. Do not add a second preemption agent.
22
+
23
+ A new served media pipeline adds one probe in that module: a name on `_PROBES`, a body in `probes()` taken from that pipeline's `smoke.json` at the shortest length that still reaches a `stop()` check, a file `artifacts/media-preempt-<name>.*`, and a shape check in `accept`. The same change adds the package and its `docs/<pipeline>/` path to this rule's globs, and one sentence in `docs/harness.md`.
24
+
25
+ Run both checks before the change is done when the edit touches `MediaPipeline`, a hold tuple, or a media pipeline's `parse`, `generate`, `pack`, pause, or job dict:
26
+
27
+ ```text
28
+ uv run pytest tests/test_media_pipeline.py tests/test_media_pipeline_harness.py
29
+ uv run python -m harness.media_pipeline
30
+ ```
31
+
32
+ The pytest does not open a listener and does not take the machine lock. The harness uses one `favlo serve` on `127.0.0.1:8129` and does not take the lock. If `artifacts/pipeline-test.lock` is held by a live pid, wait. Exit 0 means every selected probe paused with `task is ongoing` and that same task finished. A kernel, shader, or quantize edit that leaves the request, the checkpoint, and the job dict alone does not run the harness.
33
+
34
+ Wrong: a host matmul standing in for a missing kernel, a popped hold, or one preemption agent per pipeline.
35
+
36
+ Right: `MediaPaused("preempt", hold)` after the command finishes, `state["video_hold"] = None` when the job completes, and one new row in `_PROBES`.
@@ -0,0 +1,42 @@
1
+ ---
2
+ description: Pipeline-agnostic memory ledger. Owner strings, budget, sweep, and the one knob a runtime may shrink.
3
+ globs: **/*.py
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Memory management
8
+
9
+ `src/favlo/memory.py` is the only allocator. `memory` is the process singleton. Device, residency set, and command queues stay process-owned. Heaps are per owner, kind (`resident`, `scratch`, `private`), and storage (`shared` or `private`). A pipeline does not call `newBufferWithLength` or keep a second allocator.
10
+
11
+ ## Owner
12
+
13
+ `open_runtime` accepts `owner` and `max_memory` and forwards both. Stamp `_owner` before the first allocate:
14
+
15
+ ```python
16
+ self._owner = owner or f"{stem}:{id(self)}"
17
+ ```
18
+
19
+ `stem` is the flag stem (`wan22-i2v`, `z-image-turbo`). Every `allocate` and `upload` in that opening uses that string. `sweep` matches the whole string. `close` sweeps it in `finally`, including when `open` fails after a span exists. A missing record raises `FileNotFoundError` before `Gpu()`. The listener passes `mint_owner(stem)` when the signature includes `owner`, records `runtime._owner`, and sweeps that opening after `close`.
20
+
21
+ ## Room
22
+
23
+ `budget()` is reclaimable pages plus `live` plus `pending` plus bytes whose heap was released and which the kernel has not yet reported reclaimable. `live` and `pending` are properties. Room for a new span keeps those just-released bytes:
24
+
25
+ ```python
26
+ ceiling = memory.budget()
27
+ if cap is not None:
28
+ ceiling = min(ceiling, cap)
29
+ room = max(0, ceiling - memory.live - memory.pending)
30
+ ```
31
+
32
+ `max_memory` is the cap: `32GiB`, `512MiB`, `g`/`m`/`gb`/`mb`, or a positive byte count. Empty means uncapped. Copy the parser into the pipeline that reads it. Read the ledger when the job starts and again at `complete`. A step does not re-read it.
33
+
34
+ ## Fit
35
+
36
+ Weights plus the requested working set must fit in `room` before the first commit. The request keeps its resolution, frame count, and duration. Shrink the one knob that pipeline owns, down to the minimum that still runs that request. When the minimum does not fit, raise `RuntimeError` and name the request. Do not drop layers, substitute a host GEMV, or change the packed quant. 16 GB is the product floor. It is not free memory and it is not `budget()`.
37
+
38
+ `release` returns a span the caller has dropped. Leave a buffer a later command or a live local still names. `sweep` waits out tracked command buffers, then frees that owner's spans and idle heaps.
39
+
40
+ ## Release
41
+
42
+ `close` sweeps the owner. The release is done when that owner has no live span and no command still holds a freed span. `memory.wait_released` returns on that check. Pending and returning bytes stay in the budget until the kernel reports them. They do not keep the process alive, and they do not keep the next call queued. A chat preemption runs the check in the process that allocated the spans, before the handler returns. The listener stores the opening report. The daemon does not admit the next call while an allocation or a release is still open. A partial drop uses `memory.confirm_released` for the bytes that sweep freed and blocks until those pages are back.
@@ -0,0 +1,44 @@
1
+ ---
2
+ description: Use when designing a pipeline's Metal data plane or writing its kernels. Tensor types, matmul2d, and the E8M0 scale layout.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Metal data planes
7
+
8
+ Use a Metal 4 tensor op. The type list and `matmul2d` are [WWDC26 session 330](https://developer.apple.com/videos/play/wwdc2026/330/) and `MTLTensorDataType` on macOS 27. The scale and the element encodings are the OCP MX spec, as [REFERENCES.md](REFERENCES.md) records them. A pipeline's `kernels` command is what accepts a dispatch. Another pipeline's probe is not that acceptance.
9
+
10
+ ## Ops
11
+
12
+ `mpp::tensor_ops::matmul2d` dequantizes a quantized right-hand tensor. The left operand is float16. The destination is float32. The descriptor sets the output tile, the K tile, and the two transpose flags so they match the stored major axis. Launch it with `execution_simdgroups<N>` and have every thread in that scope take part. Apple's sample uses four simdgroups.
13
+
14
+ ```metal
15
+ constexpr auto desc = matmul2d_descriptor(
16
+ tile_m, tile_n, static_cast<int>(dynamic_extent),
17
+ transpose_left, transpose_right, false);
18
+ matmul2d<desc, execution_simdgroups<4>> op;
19
+ ```
20
+
21
+ A quantized tensor can also be dequantized into a cooperative tensor and passed back into `matmul2d` when `is_compatible_as_left_input` or `is_compatible_as_right_input` is true. Reductions are the same TensorOps set. A missing kernel stays missing. A host GEMV or a CPU matmul is not a stand-in. A language-model pipeline does not fuse a whole layer. An image, video, music, or voice pipeline may place several kernels of one generation in one command buffer and may fuse those kernels.
22
+
23
+ ## Planes
24
+
25
+ | MSL type | Role |
26
+ |---|---|
27
+ | `metal_fp4_e2m1` | 4-bit float weight. Magnitudes `0, 0.5, 1, 1.5, 2, 3, 4, 6`. Sign is bit 3. Low nibble is element 0 |
28
+ | `metal_fp8_e4m3` | 8-bit float weight or key/value. OCP E4M3FN. Largest finite value is 448. `0x7F` is NaN |
29
+ | `metal_fp8_ue8m0` | Scale plane only. One byte covers 32 values along K. Block factors `{32, 1}` |
30
+ | `half` | Activation, norms, biases, and any matrix that is not a quantized tensor |
31
+ | `float` | `matmul2d` destination and a recurrent or latent state |
32
+
33
+ `MTLTensorDataType` also names bfloat16, fp8 E5M2, and int and uint 2/4/8/16/32. Those stay unused until this pipeline's `kernels` command completes a dispatch of that type.
34
+
35
+ One scale byte is an E8M0 exponent, bias 127. Reconstruct `value × 2^(e − 127)`. Store `e` in `0..254`. `0xFF` is not a scale. A zero block stores 0. There is no zero point. Round the power of two up so the peak fits: fp4 endpoint 6, fp8 E4M3 endpoint 448.
36
+
37
+ For int4, int8, int2, fp8, and E8M0, the innermost stride is 1 and every later stride is a multiple of 128 bytes. The buffer offset is 128-byte aligned. A row's packed bytes are therefore a multiple of 128: fp4 K is a multiple of 256, fp8 K is a multiple of 128, int2 K is a multiple of 512. Extra K columns are zero codes. The scale extent is the data extent divided by `{32, 1}`. The data plane ends on a 128-byte boundary and the scale plane starts there.
38
+
39
+ Pad a batch or an output extent up to the tile and drop the extra rows. A K that is not a multiple of 32 is not a scale block. Pad it to the row alignment above before the pack.
40
+
41
+ ```metal
42
+ // ❌ K 144 on an fp4 tensor — 144 is not a multiple of 32, so the scale plane has no whole block
43
+ // ✅ pad K 144 → 256, pad output rows up to tile_n, drop the extra rows
44
+ ```
@@ -0,0 +1,8 @@
1
+ ---
2
+ description: Use when optimizing an image pipeline's generation time. Do not use for language-model prefill or decode.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Image optimization
7
+
8
+ Load [optimization-image](../skills/optimization-image/SKILL.md) and follow it. The ceiling is seconds for one generation. A shorter time is faster. The 90% test compares the printed generation time with the kernel ceiling. Do not apply this rule to a language model.
@@ -0,0 +1,8 @@
1
+ ---
2
+ description: Use when optimizing a language-model pipeline's prefill or decode rate. Do not use for image generation.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Language-model optimization
7
+
8
+ Load [optimization-loop](../skills/optimization-loop/SKILL.md) and follow it. The ceiling is tok/s for prefill or decode. The 90% test compares the coding agent's printed rate on that phase with the kernel ceiling. Do not run the file agent. Do not apply this rule to an image pipeline.
@@ -0,0 +1,67 @@
1
+ ---
2
+ globs: *.py,*.metal
3
+ alwaysApply: false
4
+ ---
5
+ # Pipeline isolation
6
+
7
+ Edit one runtime. Leave every other runtime's files untouched. Pipeline tests share one machine lock so several agents can edit different pipelines at the same time and only one of them runs on the GPU.
8
+
9
+ `favlo serve` is the entry point for inference. The client selects one model through the OpenAI endpoints: `GET /v1/models` lists the registry, and the `model` field on `POST /v1/chat/completions` loads that row's pipeline. Quantize and the other non-serve commands require `favlo --<pipeline>`. A new runtime keeps that flag.
10
+
11
+ The write set for a runtime is its entry file (`pipelines/metal41/<pipeline>.py`, which sets `PIPELINE` to that stem), its package beside that file, `docs/<pipeline>/`, and tests that import only that package. Flash Next's note is `docs/qwen38-flash-next/`. 27B's note is `docs/qwen38-27b/`.
12
+
13
+ A new runtime adds those files and one row in the runtime table in `ARCHITECTURE.md`. The command discovers the entry. Do not edit `src/favlo/cli.py` to register it.
14
+
15
+ Do not edit another pipeline's package, shaders, tests, or docs. A served media pipeline inherits `MediaPipeline`. A served language model inherits `LanguagePipeline`. A served embedding model inherits `EmbeddingsPipeline`. All three extend `Pipeline` in `src/favlo/pipeline.py`. Those classes are the listener seams. They do not run a forward, name stages, or branch on the pipeline. A failed pipeline inherits none of them. Do not add a kernel that branches on the pipeline. A new abstract method on `Pipeline` updates every subclass of every seam in that same change. A new abstract method on one seam updates every subclass of that seam. A seam migration may edit every served subclass of that seam in one change. Do not change `src/favlo/` unless the task is the listener, the registry, or the console. Registration loads `sampling.py` from the pipeline that owns the row. Do not pass a sampling card into the registry.
16
+
17
+ A pipeline's kernels, records, and cache are described in that pipeline's `docs/<pipeline>/` note. Synthetic `matmul2d` dtype rates are [docs/synthetic-matmul2d.md](../../docs/synthetic-matmul2d.md). Root `ARCHITECTURE.md` is the process and the write set.
18
+
19
+ ## Model switch
20
+
21
+ One chat or media pipeline is resident. A chat or media request that names a different folder or a different pipeline closes that runtime before the next one opens. The same folder and the same pipeline stay resident. An embeddings request does not close the resident runtime. It opens its own process for that request and closes it when the request returns.
22
+
23
+ `close` returns only after that pipeline's device memory is released. That includes its key/value cache, prefill workspace, decode path, command queue, and open record. A prefix flush may finish first. After `close` returns, the previous runtime holds no Metal buffer, and the next runtime is the one that allocates.
24
+
25
+ Spans for one runtime share one owner string. The string is the flag stem, a colon, and `id()` of the object `open_runtime` returns, taken once when that runtime opens:
26
+
27
+ ```text
28
+ qwen38-27b:4317261824
29
+ ```
30
+
31
+ `allocate`, `upload`, and `sweep` use that string. A cache, a codec, or a probe in that pipeline passes the same string. `close` sweeps it. After `close` returns, that owner has no span left. A command outside `favlo serve` uses the same format for the session it opens, and that session's `close` sweeps the string before the command returns.
32
+
33
+ The listener records every owner that gained a span during `open_runtime`, and `runtime._owner` when that attribute is a string. It sweeps those strings after `close`. An `open_runtime` that raises sweeps every owner that appeared during the call. `open_runtime` receives `owner` when its signature includes that parameter. A pipeline that omits the parameter keeps the `id()` string above. `mint_owner` supplies the listener's string. Its token is a process counter.
34
+
35
+ ## Media preemption
36
+
37
+ An image, video, or music pipeline assumes a chat can set `state["preempt"]` while that pipeline holds the GPU. An embeddings request does not set `preempt` and does not close that device. Read the event at each stage boundary, after the Metal command already submitted has finished. On preempt, save the finished stage in a host checkpoint, leave the job `in_progress` with the same id, and return. `close` then releases the device so the chat's model can allocate. The listener calls the same handler again after those chats. The handler loads that checkpoint and continues the unfinished work. Cancel drops the checkpoint and does not resume.
38
+
39
+ Device buffers do not survive `close`. A value the next stage needs is in the host checkpoint. Each pipeline keeps that checkpoint in its own package.
40
+
41
+ ## Machine lock
42
+
43
+ Wait until the machine is free before a test command. That includes `pytest`, `kernels`, `quantize`, `complete`, `bf16`, `probe`, `matmul`, `python -m harness`, and `python -m harness.coding`: any command that compiles shaders, dispatches Metal, loads a checkpoint, quantizes, or starts `favlo serve`. Editing the write set does not wait. Reading another pipeline does not.
44
+
45
+ The machine is busy when `artifacts/pipeline-test.lock` exists and the `pid` in it is still running. A running `favlo serve` is not itself a reason to wait. Take the lock with the smoke script. When the daemon is up and no request is open, the script closes the resident model and holds chat until release. The daemon stays up. Do not kill the server, and do not kill the process that holds the lock.
46
+
47
+ ```text
48
+ uv run python -m favlo.smoke_lock acquire --pipeline <stem> --command <name>
49
+ ```
50
+
51
+ Exit 0 means this shell holds the lock and the GPU is free. Exit 2 means a request is open: the lock was not taken. Wait and run acquire again. Exit 3 means another live pid holds the lock. Wait. A lock whose `pid` is gone is stale. The next acquire removes it. The `favlo serve` a test starts itself is that test's process. The wait is before the test starts.
52
+
53
+ Do not create the lock file by hand. Release it when the testing stretch ends, including when the command fails:
54
+
55
+ ```text
56
+ uv run python -m favlo.smoke_lock release
57
+ ```
58
+
59
+ Release removes the file only when its `pid` is this shell. A chat during the hold receives 503. After release, the next chat loads a model again. The lock is one JSON object and nothing else:
60
+
61
+ ```json
62
+ {"pipeline": "qwen38-27b", "pid": 12345, "command": "kernels"}
63
+ ```
64
+
65
+ `pipeline` is the flag stem. `pid` is the shell that owns the test. `uv` and `python` are skipped when the script records that pid, so `uv run` names the shell that stays up for the stretch. A nested command from that shell leaves the file in place. `command` is the short name of that test. Do not write a name, home directory, hostname, or device path.
66
+
67
+ The file lives under `artifacts/`, which is gitignored. Do not commit it. `pid` is the shell that ran acquire, not the short-lived Python process. Run acquire, the test, and release in that same shell.
@@ -0,0 +1,27 @@
1
+ ---
2
+ globs: *.py,*.metal
3
+ alwaysApply: false
4
+ ---
5
+ # Public algorithms, Metal mapping
6
+
7
+ Every equation in a pipeline comes from a public paper, spec, or vendor document, then mapped onto a Metal op an M5 Pro with 48 GB runs. Another repository's source, tests, comments, or design notes are not a reference. Porting them pulls in that runtime's layout and hides the Metal mapping.
8
+
9
+ Score a formula on this runtime's own forward. An int4 argmax is not evidence the equation is right. Check the BF16 shader dot of the checkpoint values.
10
+
11
+ Record a pipeline citation in that pipeline's references note, and a process citation in REFERENCES.md. The as-built form goes in that pipeline's note, or in ARCHITECTURE.md when the change is the listener, the registry, or the console.
12
+
13
+ ## Memory
14
+
15
+ Allocate the input path and the output path first. The input path is the key/value cache and the prefill workspace. The output path is decode. Other modules, such as the expert atlas, staging buffers, and a scratch buffer that the forward can rebuild, receive what remains.
16
+
17
+ When a formula needs more device memory, leave the key/value cache, the prefill workspace, and the decode path allocated. Name another module to drop, and say which bytes that module returns.
18
+
19
+ ## Examples
20
+
21
+ Wrong: open another runtime's n-gram forward and copy its hash so the tokens match.
22
+
23
+ Right: Cheng et al. eq. (6) for the branch gate, the tech report's `1/n_r` on the residual read, and a Metal float dot of the stored matrix.
24
+
25
+ Wrong: shrink the key/value cache so the atlas stays complete.
26
+
27
+ Right: keep the cache, the prefill workspace, and decode, and drop atlas images that the forward can read again from the record.
@@ -0,0 +1,32 @@
1
+ ---
2
+ description: Split and organize Python files by responsibility, with one-way imports
3
+ globs: **/*.py
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Python file split
8
+
9
+ Split a module when it has more than one job, or when a section is data the rest of the file only reads. Line count is not the trigger. PEP 8 sets no file-length limit. Related classes and functions stay in one module.
10
+
11
+ A package name is an identifier. A hyphenated pipeline entry stays a path-loaded file. The package beside it uses underscores. `qwen38-flash-next.py` loads `qwen38_flash_next`.
12
+
13
+ ## How to cut
14
+
15
+ - One module, one responsibility. Imports point one way: `formats` → `convert` / `session` → `runtime` → `commands`.
16
+ - If two modules need each other, the cut is wrong. Move the shared names into a third module, or leave the pieces together.
17
+ - Keep one class in one file. Do not break a class into mixins to shorten a file.
18
+ - Move large source strings, such as Metal shaders, into files the module reads as text. Compile them the same way as before.
19
+ - Re-export the names callers already use from the package `__init__.py`. A path-loaded entry exposes those names, including `main`.
20
+ - Use a regular package with `__init__.py`. A namespace package is for one name split across distributions.
21
+ - A new model is a new entry file under `pipelines/metal41/`, a new package beside it, and a `PIPELINE` assignment. It does not edit another pipeline. A served media pipeline inherits `MediaPipeline`. A served language model inherits `LanguagePipeline`. A served embedding model inherits `EmbeddingsPipeline`. A failed pipeline inherits none of them. A kernel does not branch on the pipeline.
22
+ - Update that pipeline's `docs/<pipeline>/` note in the same change that moves one of its modules. Update root ARCHITECTURE.md only when the process contract or the runtime table changes.
23
+
24
+ ## Examples
25
+
26
+ Wrong: split `Qwen38Runtime` into `gdn.py`, `qsa.py`, and `moe.py` that import each other.
27
+
28
+ Right: leave the forward in `runtime.py`. Put packing in `formats.py`, which the runtime imports and which does not import the runtime.
29
+
30
+ Wrong: name the package `qwen38-flash-next/` and import it.
31
+
32
+ Right: keep `qwen38-flash-next.py` as the entry. Put the modules in `qwen38_flash_next/`, and read `shaders/act.metal` as text.
@@ -0,0 +1,43 @@
1
+ ---
2
+ description: Bound a research claim to the measured remainder and the search that limits it
3
+ globs: docs/**/*.md,REFERENCES.md,RESEARCH.md
4
+ alwaysApply: false
5
+ ---
6
+ # Research evidence
7
+
8
+ A public commit records an artifact and a date. It does not establish that the idea is original. Write "not found in these sources on this date." Do not write "first," "novel," or "no prior work."
9
+
10
+ Split the proposal into the method, the model or task, the measurement, and the mechanism. Name the closest public predecessor for each part, with a link and one sentence on what that work already did. Papers, model cards, and shipped code all count. The sentence this repo may own is only the remainder.
11
+
12
+ A measured mapping onto one machine is a claim even when the method is already published. A measurement from this repository names that machine as an M5 Pro with 48 GB. The remainder is this implementation's table: the times, the bandwidth ceiling, or the recorded rate for that pipeline's task. Name the closest published implementation of the same task and the figure it reported. The "not found" sentence names this table. A tile or stride the vendor requires is a constraint. An unmeasured mapping stays a plan.
13
+
14
+ ## Citing this software
15
+
16
+ [REFERENCES.md](../../REFERENCES.md) and a pipeline note cite the papers, model cards, and vendor documents the implementation uses. [RESEARCH.md](../../RESEARCH.md) indexes measured remainders. Neither file is a citation of Favlo.
17
+
18
+ The citable software record is [CITATION.cff](../../CITATION.cff) at the repository root. Its version and release date are the release a reader cites. A paper that uses a recorded rate cites that software version and the predecessor papers named in the note. The note does not embed a BibTeX entry for Favlo, and the catalog does not gain a row for the software citation.
19
+
20
+ A release that changes the version updates `CITATION.cff` in that same change. Do not invent a DOI or an ORCID. The repository URL is the identifier until a DOI is archived.
21
+
22
+ ## Where a note lives
23
+
24
+ An idea with no measurement is not committed in this repository.
25
+
26
+ A measured remainder is one Markdown file, `docs/<pipeline>/research/<slug>.md`. A format bound is a measurement of the code points. A per-matrix table is a measurement of the checkout. A dispatch table, a bandwidth ceiling, or a recorded rate is a measurement of this implementation. The file says which one it holds. The pipeline README links it as a measurement. The serving note changes only when that behavior ships.
27
+
28
+ The root catalog is [RESEARCH.md](../../RESEARCH.md). It is an index, not a second copy of the notes. One row per claim, added in the same commit as the note. Columns are slug, pipeline, status, search date, shipped date, benchmark date, the one-sentence remainder, and the note path. Status is `measured` while the serving note is unchanged, `shipped` once that note describes the behavior, and `narrowed` after a correction is appended. A row stays. The shipped date is the date that serving note described the behavior, and it stays empty while status is `measured`. The benchmark date is the date of that pipeline's latest harness scores. It stays empty when that pipeline has no harness scores. The index does not repeat the table, the predecessors, or the command.
29
+
30
+ Sections, in order: Remainder, Predecessors, Rule, Command, Table, Search, Corrections. The command is the one that regenerates the table. Corrections are appended. Earlier sections stay as committed.
31
+
32
+ Ship that remainder in the same commit as the claim:
33
+
34
+ - The formula, the budget or decision rule, and the command that regenerates the result.
35
+ - The measured table. A claim with no numbers stays a plan.
36
+ - The search note: queries, date, and the predecessors above.
37
+ - A license and a readme so a second person can rerun it. This repo's license and readme are the package ones.
38
+
39
+ The git author date is chosen by the committer. The public timestamp is the host's record of the push, or a Software Heritage snapshot of that commit. An ACM artifact badge means the artifact is available, or that another team reran it. The badge does not certify novelty.
40
+
41
+ Wrong: "This is the first fp4-to-fp8 allocation by weight error."
42
+
43
+ Right: "MixQuant scores layers by weight error. This note records the relative error of these feed-forward matrices under this quantizer. A search on 21 October 2026 did not find that table."
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: Save generated media to disk, then return that file. Generate tools are optional MCP tasks.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Serving media
7
+
8
+ When an API returns generated media, write the file first and send that file. The kind does not matter: image, audio, video, or another download.
9
+
10
+ This applies to a new endpoint and to a change in how an existing one returns bytes. A kernel, a quantizer, a CLI `--out` path, and a harness artifact stay where they are.
11
+
12
+ ## Tasks
13
+
14
+ `generate_image`, `generate_video`, and `generate_music` are optional MCP tasks on `io.modelcontextprotocol/tasks`. A client that advertises the extension receives a task (`resultType` `task`, `pollIntervalMs` 2000). The GPU starts when the worker reaches it. Poll `tasks/get` or `media_status` until `completed`, `failed`, or `cancelled`, then `resources/read` the `favlo://` link. A client that does not advertise the extension receives the finished tool result on that same `tools/call`.
15
+
16
+ Leave the mode optional. Required mode returns JSON-RPC `-32021` when the client did not advertise the extension, and the job never starts. Many MCP clients do not advertise it.
17
+
18
+ The inline call ends at that client's tool timeout. An image or a short clip can finish inside it. A long video or a long music clip needs a client that polls. Otherwise the call ends at the timeout while the job is still running. Closing the poll request does not cancel the job. Cancel with `tasks/cancel` or `media_cancel`.
19
+
20
+ Do not add an HTTP media route so a client can skip the extension. Chat stays `POST /v1/chat/completions`.
21
+
22
+ ## Order
23
+
24
+ 1. Save the uncompressed file under `~/.favlo/<kind>/<id>.<ext>`. Write a sibling `.tmp`, then replace the final path. The id is the job id. Refuse an id that contains a path separator, `.`, or `..`.
25
+ 2. Write the served file from that saved file. A compressed download is a second file beside it. The content response reads the served file.
26
+ 3. Stream the served file, with its media type. A missing file is 404.
27
+ 4. The job JSON names the id. It carries no filesystem path and no media bytes.
28
+
29
+ Tests pass a temporary home on the request state. They do not write `~/.favlo`.
30
+
31
+ A kept file expires through one integer in `~/.favlo/settings.json`. The sweep deletes a file whose age has reached that value and drops the matching job. The default for a new kind is one day when the pipeline note does not name another value.
32
+
33
+ ## Examples
34
+
35
+ Video: save `~/.favlo/videos/<id>.avi`, encode `<id>.mp4` from that file, then `resources/read` of `favlo://videos/{id}` reads the MP4 as `video/mp4`.
36
+
37
+ The same shape for a PNG or an audio clip: one directory per kind, one extension, one read of the saved file.
38
+
39
+ Wrong: keep the served bytes only on the request state and send those bytes.
40
+
41
+ Wrong: put `{"path": "/Users/example/clip.mp4"}` on the job.