@ruvector/ruvllm 3.0.0 → 4.0.1

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 (151) hide show
  1. package/GPU-LOOP.md +229 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +9 -0
  4. package/README.md +159 -360
  5. package/examples/gpu-loop.example.json +26 -0
  6. package/package.json +50 -121
  7. package/src/adapters-cli.mjs +23 -0
  8. package/src/adapters.mjs +91 -0
  9. package/src/cli.mjs +30 -0
  10. package/src/engine.mjs +238 -0
  11. package/src/fixture.mjs +38 -0
  12. package/src/gpu-host.mjs +47 -0
  13. package/src/gpu-loop-cli.mjs +67 -0
  14. package/src/gpu-loop.mjs +184 -0
  15. package/src/gpu-spool-adapter.mjs +80 -0
  16. package/src/vast-host-adapter.mjs +274 -0
  17. package/bin/cli.js +0 -1040
  18. package/dist/cjs/benchmarks/embedding-benchmark.d.ts +0 -102
  19. package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +0 -1
  20. package/dist/cjs/benchmarks/embedding-benchmark.js +0 -436
  21. package/dist/cjs/benchmarks/index.d.ts +0 -34
  22. package/dist/cjs/benchmarks/index.d.ts.map +0 -1
  23. package/dist/cjs/benchmarks/index.js +0 -132
  24. package/dist/cjs/benchmarks/model-comparison.d.ts +0 -71
  25. package/dist/cjs/benchmarks/model-comparison.d.ts.map +0 -1
  26. package/dist/cjs/benchmarks/model-comparison.js +0 -476
  27. package/dist/cjs/benchmarks/routing-benchmark.d.ts +0 -70
  28. package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +0 -1
  29. package/dist/cjs/benchmarks/routing-benchmark.js +0 -289
  30. package/dist/cjs/contrastive.d.ts +0 -229
  31. package/dist/cjs/contrastive.d.ts.map +0 -1
  32. package/dist/cjs/contrastive.js +0 -589
  33. package/dist/cjs/engine.d.ts +0 -160
  34. package/dist/cjs/engine.d.ts.map +0 -1
  35. package/dist/cjs/engine.js +0 -552
  36. package/dist/cjs/export.d.ts +0 -182
  37. package/dist/cjs/export.d.ts.map +0 -1
  38. package/dist/cjs/export.js +0 -422
  39. package/dist/cjs/federated.d.ts +0 -233
  40. package/dist/cjs/federated.d.ts.map +0 -1
  41. package/dist/cjs/federated.js +0 -525
  42. package/dist/cjs/index.d.ts +0 -68
  43. package/dist/cjs/index.d.ts.map +0 -1
  44. package/dist/cjs/index.js +0 -104
  45. package/dist/cjs/intelligence.d.ts +0 -136
  46. package/dist/cjs/intelligence.d.ts.map +0 -1
  47. package/dist/cjs/intelligence.js +0 -226
  48. package/dist/cjs/lora.d.ts +0 -251
  49. package/dist/cjs/lora.d.ts.map +0 -1
  50. package/dist/cjs/lora.js +0 -509
  51. package/dist/cjs/models.d.ts +0 -129
  52. package/dist/cjs/models.d.ts.map +0 -1
  53. package/dist/cjs/models.js +0 -323
  54. package/dist/cjs/native.d.ts +0 -140
  55. package/dist/cjs/native.d.ts.map +0 -1
  56. package/dist/cjs/native.js +0 -98
  57. package/dist/cjs/session.d.ts +0 -80
  58. package/dist/cjs/session.d.ts.map +0 -1
  59. package/dist/cjs/session.js +0 -203
  60. package/dist/cjs/simd.d.ts +0 -90
  61. package/dist/cjs/simd.d.ts.map +0 -1
  62. package/dist/cjs/simd.js +0 -209
  63. package/dist/cjs/sona.d.ts +0 -223
  64. package/dist/cjs/sona.d.ts.map +0 -1
  65. package/dist/cjs/sona.js +0 -562
  66. package/dist/cjs/streaming.d.ts +0 -55
  67. package/dist/cjs/streaming.d.ts.map +0 -1
  68. package/dist/cjs/streaming.js +0 -131
  69. package/dist/cjs/training.d.ts +0 -312
  70. package/dist/cjs/training.d.ts.map +0 -1
  71. package/dist/cjs/training.js +0 -610
  72. package/dist/cjs/types.d.ts +0 -696
  73. package/dist/cjs/types.d.ts.map +0 -1
  74. package/dist/cjs/types.js +0 -6
  75. package/dist/esm/benchmarks/embedding-benchmark.d.ts +0 -102
  76. package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +0 -1
  77. package/dist/esm/benchmarks/embedding-benchmark.js +0 -427
  78. package/dist/esm/benchmarks/index.d.ts +0 -34
  79. package/dist/esm/benchmarks/index.d.ts.map +0 -1
  80. package/dist/esm/benchmarks/index.js +0 -110
  81. package/dist/esm/benchmarks/model-comparison.d.ts +0 -71
  82. package/dist/esm/benchmarks/model-comparison.d.ts.map +0 -1
  83. package/dist/esm/benchmarks/model-comparison.js +0 -434
  84. package/dist/esm/benchmarks/routing-benchmark.d.ts +0 -70
  85. package/dist/esm/benchmarks/routing-benchmark.d.ts.map +0 -1
  86. package/dist/esm/benchmarks/routing-benchmark.js +0 -283
  87. package/dist/esm/contrastive.d.ts +0 -229
  88. package/dist/esm/contrastive.d.ts.map +0 -1
  89. package/dist/esm/contrastive.js +0 -578
  90. package/dist/esm/engine.d.ts +0 -160
  91. package/dist/esm/engine.d.ts.map +0 -1
  92. package/dist/esm/engine.js +0 -548
  93. package/dist/esm/export.d.ts +0 -182
  94. package/dist/esm/export.d.ts.map +0 -1
  95. package/dist/esm/export.js +0 -414
  96. package/dist/esm/federated.d.ts +0 -233
  97. package/dist/esm/federated.d.ts.map +0 -1
  98. package/dist/esm/federated.js +0 -520
  99. package/dist/esm/index.d.ts +0 -68
  100. package/dist/esm/index.d.ts.map +0 -1
  101. package/dist/esm/index.js +0 -84
  102. package/dist/esm/intelligence.d.ts +0 -136
  103. package/dist/esm/intelligence.d.ts.map +0 -1
  104. package/dist/esm/intelligence.js +0 -188
  105. package/dist/esm/lora.d.ts +0 -251
  106. package/dist/esm/lora.d.ts.map +0 -1
  107. package/dist/esm/lora.js +0 -504
  108. package/dist/esm/models.d.ts +0 -129
  109. package/dist/esm/models.d.ts.map +0 -1
  110. package/dist/esm/models.js +0 -282
  111. package/dist/esm/native.d.ts +0 -140
  112. package/dist/esm/native.d.ts.map +0 -1
  113. package/dist/esm/native.js +0 -93
  114. package/dist/esm/session.d.ts +0 -80
  115. package/dist/esm/session.d.ts.map +0 -1
  116. package/dist/esm/session.js +0 -199
  117. package/dist/esm/simd.d.ts +0 -90
  118. package/dist/esm/simd.d.ts.map +0 -1
  119. package/dist/esm/simd.js +0 -205
  120. package/dist/esm/sona.d.ts +0 -223
  121. package/dist/esm/sona.d.ts.map +0 -1
  122. package/dist/esm/sona.js +0 -556
  123. package/dist/esm/streaming.d.ts +0 -55
  124. package/dist/esm/streaming.d.ts.map +0 -1
  125. package/dist/esm/streaming.js +0 -126
  126. package/dist/esm/training.d.ts +0 -312
  127. package/dist/esm/training.d.ts.map +0 -1
  128. package/dist/esm/training.js +0 -603
  129. package/dist/esm/types.d.ts +0 -696
  130. package/dist/esm/types.d.ts.map +0 -1
  131. package/dist/esm/types.js +0 -5
  132. package/scripts/ensemble-model-compare.js +0 -287
  133. package/scripts/fix-esm-extensions.mjs +0 -181
  134. package/scripts/huggingface/README.md +0 -537
  135. package/scripts/huggingface/publish.sh +0 -112
  136. package/scripts/hybrid-model-compare.js +0 -373
  137. package/scripts/improved-model-compare.js +0 -288
  138. package/scripts/optimized-model-compare.js +0 -364
  139. package/scripts/real-model-compare.js +0 -280
  140. package/scripts/smoke-esm.mjs +0 -82
  141. package/scripts/training/agentic-flow-capabilities.json +0 -329
  142. package/scripts/training/claude-code-synth.js +0 -505
  143. package/scripts/training/claude-flow-capabilities.json +0 -1322
  144. package/scripts/training/claude-hard-negatives.js +0 -222
  145. package/scripts/training/contrastive-finetune.js +0 -517
  146. package/scripts/training/ecosystem-triplets.jsonl +0 -1467
  147. package/scripts/training/generate-ecosystem-triplets.js +0 -1324
  148. package/scripts/training/routing-dataset.js +0 -634
  149. package/scripts/training/ruvector-capabilities.json +0 -798
  150. package/scripts/training/validate-ecosystem.js +0 -381
  151. package/scripts/training/validation-results.json +0 -23
package/README.md CHANGED
@@ -1,388 +1,187 @@
1
- # @ruvector/ruvllm
1
+ # MetaHarness weight experiments
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@ruvector/ruvllm.svg)](https://www.npmjs.com/package/@ruvector/ruvllm)
4
- [![Downloads](https://img.shields.io/npm/dm/@ruvector/ruvllm)](https://www.npmjs.com/package/@ruvector/ruvllm)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
- [![GitHub Stars](https://img.shields.io/github/stars/ruvnet/ruvector?style=social)](https://github.com/ruvnet/ruvector)
3
+ <p align="center"><img src="https://raw.githubusercontent.com/ruvnet/ruvllm/ruvllm-npm-v4.0.1/docs/assets/gpu-job-loop.svg" alt="The GPU job loop checks a spending ceiling, rents the offer and arms a destroy timer, runs the pinned job, pulls raw outputs, checks them locally, then destroys the rental and confirms it is gone." width="100%"></p>
7
4
 
8
- **Self-learning LLM runtime for Node.js** — GGUF inference, TurboQuant KV-cache compression (6-8x memory savings), SONA adaptive learning, FlashAttention, speculative decoding, and SIMD-optimized kernels. Built in Rust, runs everywhere.
5
+ <p align="center"><img src="https://raw.githubusercontent.com/ruvnet/ruvllm/ruvllm-npm-v4.0.1/docs/assets/heldout-results.svg" alt="Held-out results on 256 untouched tasks: tool passes 149, 176 and 192 of 192 for base, coding-4b and coding-4b-r2; arithmetic 62, 64 and 46 of 64. coding-4b is kept; coding-4b-r2 is rejected." width="100%"></p>
9
6
 
10
- > Inference at **88-135 tok/s** on M4 Pro | **<1ms** SONA adaptation | **6-8x** KV-cache compression via TurboQuant
7
+ Published on npm as `@ruvector/ruvllm`. Version 4.0.0 replaces the 3.x
8
+ inference runtime from `ruvnet/ruvector` with this package, because ruvllm now
9
+ lives in `ruvnet/ruvllm`. The 3.x API and its CLI subcommands are not part of
10
+ 4.x; pin `@ruvector/ruvllm@3` to keep using them. The npm package ships the
11
+ JavaScript controller, GPU loop and Vast.ai host adapter. It does not ship the
12
+ native `weight_evolution` binary, model weights or adapters. Build the binary
13
+ from this repository and pass its path with `--binary`.
11
14
 
12
- ## Installation
13
-
14
- ```bash
15
+ ```sh
15
16
  npm install @ruvector/ruvllm
17
+ npx ruvllm --help # bounded weight-edit experiments
18
+ npx ruvllm-gpu-loop status --config /abs/private/gpu-loop.json
16
19
  ```
17
20
 
18
- ## Quick Start
19
-
20
- ```typescript
21
- import { RuvLLM, RuvLLMConfig } from '@ruvector/ruvllm';
22
-
23
- // Initialize with default configuration
24
- const llm = new RuvLLM();
25
-
26
- // Or with custom configuration
27
- const llm = new RuvLLM({ embeddingDim: 384, learningEnabled: true });
28
-
29
- // Routing, memory and embeddings (no model needed)
30
- const decision = llm.route('Explain quantum computing');
31
- llm.addMemory('RuvLLM routes queries with FastGRNN', { source: 'docs' });
32
- const hits = llm.searchMemory('how are queries routed?', 3);
33
- const vec = llm.embed('Explain quantum computing');
34
- ```
35
-
36
- ## Text Generation (GGUF)
37
-
38
- Text comes only from a model you load. `loadModel()` runs a local GGUF file
39
- on the native candle backend (CPU; Metal on macOS builds with the `metal`
40
- feature):
41
-
42
- ```typescript
43
- const llm = new RuvLLM();
44
- llm.loadModel('./qwen2.5-0.5b-instruct-q4_k_m.gguf', { maxContext: 4096 });
45
-
46
- const out = llm.chat([{ role: 'user', content: 'What is the capital of France?' }], {
47
- maxTokens: 64,
48
- temperature: 0,
49
- });
50
- // { text: 'The capital of France is Paris.', promptTokens: 15,
51
- // completionTokens: 8, finishReason: 'stop' }
52
- ```
53
-
54
- - **Architectures**: GGUF `llama`, `mistral`, `qwen2` (Qwen2.5) and `qwen3`.
55
- Any other architecture (phi, gemma, qwen3.5, ...) fails to load with an error
56
- naming it.
57
- - **Tokenizer**: a `tokenizer.json` next to the GGUF, else the tokenizer
58
- embedded in the GGUF. The embedded one works for byte-level BPE (`gpt2`)
59
- vocabularies such as Qwen and Llama 3; GGUFs with a SentencePiece vocabulary
60
- (Llama 2, Mistral, TinyLlama) need the `tokenizer.json`, otherwise loading
61
- fails with `RUVLLM_TOKENIZER_MISSING`.
62
- - **`chat()`** applies the model's chat template, read from the GGUF's
63
- embedded `tokenizer.chat_template` (ChatML for Qwen). A `qwen2`/`qwen3` GGUF
64
- whose template is not ChatML (e.g. DeepSeek-R1-Distill-Qwen) fails to load
65
- with `RUVLLM_MODEL_LOAD_FAILED` rather than run under the wrong format.
66
- - **`generate()`** continues the prompt verbatim; **`query()`** routes, then
67
- answers as a single chat message.
68
- - **Usage**: `promptTokens`/`completionTokens` are counted with the model's
69
- tokenizer; `finishReason` is `stop` (end-of-sequence token or a stop
70
- sequence) or `length` (`maxTokens` reached or the context is full).
71
- - **Blocking**: loading and generation are synchronous and block the event
72
- loop; run them in a worker thread if that matters.
73
-
74
- Without a loaded model, `generate()`, `query()`, `chat()` and
75
- `generateDetailed()` throw `RUVLLM_NO_LANGUAGE_MODEL`; they never return text
76
- that is not model output. For demos and tests, `new RuvLLM({ allowPlaceholder:
77
- true })` (or `RUVLLM_ALLOW_MOCK=1`) makes `generate()`/`query()` return the
78
- labelled `PLACEHOLDER_TEXT` instead, with a one-time warning.
79
-
80
- ### Native binary requirements
81
-
82
- Model loading needs a native binary built with the `candle` feature;
83
- `supportsModelLoading()` reports whether the installed one was.
84
-
85
- | Native binary | `loadModel()` |
86
- |---------------|---------------|
87
- | Built from this source (`npm run build:native`) | Works |
88
- | `@ruvector/ruvllm-<platform>` 3.x (built by the release workflow with `candle`) | Works |
89
- | `@ruvector/ruvllm-<platform>` 2.0.x | Throws `RUVLLM_NATIVE_TOO_OLD`: they predate model loading |
90
- | Built with `--features napi` only (no `candle`) | Throws `RUVLLM_NO_INFERENCE_BACKEND` |
91
- | None for your platform | Throws `RUVLLM_NATIVE_UNAVAILABLE` |
92
-
93
- To use a binary you built, point `RUVLLM_NATIVE_PATH` at it (it takes
94
- precedence over the installed platform package):
95
-
96
- ```bash
97
- npm run build:native # writes ruvllm.<platform>.node (needs a Rust toolchain)
98
- RUVLLM_NATIVE_PATH=$PWD/ruvllm.linux-x64-gnu.node node app.js
99
- ```
100
-
101
- Until the 3.x platform packages are on npm, build the binary from source as
102
- above, or use the ruvllm CLI (`ruvllm serve <model>`, an OpenAI-compatible
103
- server that exits if the model fails to load).
104
-
105
- | Error code | Meaning |
106
- |------------|---------|
107
- | `RUVLLM_NO_LANGUAGE_MODEL` | Generation was requested with no model loaded |
108
- | `RUVLLM_NATIVE_UNAVAILABLE` | No native binary could be loaded |
109
- | `RUVLLM_NATIVE_TOO_OLD` | The native binary predates model loading (2.0.x platform packages) |
110
- | `RUVLLM_NO_INFERENCE_BACKEND` | The native binary was built without the `candle` backend |
111
- | `RUVLLM_MODEL_NOT_FOUND` | The model path does not exist |
112
- | `RUVLLM_MODEL_LOAD_FAILED` | The file could not be loaded (unsupported architecture, not GGUF, ...) |
113
- | `RUVLLM_TOKENIZER_MISSING` | Weights loaded but no usable tokenizer was found |
114
-
115
- ## What's New in v2.5
116
-
117
- | Feature | Description |
118
- |---------|-------------|
119
- | **TurboQuant KV-Cache** | 2-4 bit asymmetric quantization with per-channel scale/zero-point — 6-8x memory reduction, <0.5% perplexity loss |
120
- | **TurboQuant Embedding Store** | Quantized vector storage with compressed search — 10-30x memory savings |
121
- | **H2O / PyramidKV Eviction** | Intelligent cache eviction policies for long-context inference |
122
- | **Optimized Inner Product** | Asymmetric distance on quantized data — skip decompression for 2-4x faster search |
123
- | **RuvLTRA Models** | Purpose-built 0.5B & 3B models for Claude Flow |
124
- | **Task-Specific LoRA** | 5 pre-trained adapters (coder, researcher, security, architect, reviewer) |
125
- | **HuggingFace Hub** | Download/upload models directly |
126
- | **Adapter Merging** | TIES, DARE, SLERP strategies |
127
- | **HNSW Routing** | 150x faster semantic matching |
128
- | **Evaluation Harness** | SWE-Bench testing with 5 ablation modes |
129
- | **mistral-rs Backend** | Production serving with PagedAttention, X-LoRA, ISQ |
130
-
131
- ## TurboQuant — KV-Cache Compression
132
-
133
- Reduce inference memory by 6-8x with <0.5% quality loss:
134
-
135
- ```typescript
136
- import { simd } from '@ruvector/ruvllm/simd';
137
-
138
- // TurboQuant compresses KV-cache entries at 2-4 bit precision
139
- // with per-channel asymmetric quantization (scale + zero-point).
140
- // Eviction policies (H2O, Sliding Window, PyramidKV) keep the
141
- // most important tokens in cache during long-context generation.
142
-
143
- // Supported bit widths: 2-bit (32x), 3-bit (10.7x), 4-bit (8x), 8-bit (4x)
144
- ```
145
-
146
- | Bits | Compression | Perplexity Loss | Use Case |
147
- |------|-------------|-----------------|----------|
148
- | 2-bit | 32x | ~2% | Maximum compression, edge devices |
149
- | 3-bit | 10.7x | <1% | Balanced — recommended for most uses |
150
- | 4-bit | 8x | <0.5% | High quality, long-context inference |
151
- | 8-bit | 4x | ~0% | Baseline quantization |
152
-
153
- ## CLI Usage
154
-
155
- ```bash
156
- # Query a model (this package's `ruvllm` bin; needs --model, see above)
157
- ruvllm query "What is machine learning?" --model ./qwen2.5-0.5b-instruct-q4_k_m.gguf
158
-
159
- # The commands below are the Rust ruvllm CLI (crate ruvllm-cli)
160
- # Stream output
161
- ruvllm query --stream "Write a poem"
162
-
163
- # Download a model
164
- ruvllm download ruvector/ruvltra-small-q4km
165
-
166
- # Benchmark
167
- ruvllm bench ./models/model.gguf
168
-
169
- # Run evaluation (SWE-Bench)
170
- ruvllm eval --model ./models/model.gguf --subset lite --max-tasks 50
171
- ```
172
-
173
- ## API Reference
174
-
175
- ### RuvLLM Class
176
-
177
- ```typescript
178
- class RuvLLM {
179
- constructor(config?: RuvLLMConfig);
180
-
181
- // Language model (see "Text Generation" above)
182
- loadModel(path: string, options?: LoadModelOptions): LoadedModelInfo;
183
- unloadModel(): void;
184
- isModelLoaded(): boolean;
185
- modelInfo(): LoadedModelInfo | null;
186
- supportsModelLoading(): boolean; // native binary can load models
187
-
188
- // Generation; all throw RUVLLM_NO_LANGUAGE_MODEL without a loaded model
189
- chat(messages: ChatMessage[], config?: GenerationConfig): GenerationResult;
190
- generateDetailed(prompt: string, config?: GenerationConfig): GenerationResult;
191
- generate(prompt: string, config?: GenerationConfig): string;
192
- query(text: string, config?: GenerationConfig): QueryResponse; // routed, + token usage
193
-
194
- // Routing, memory and embeddings
195
- route(text: string): RoutingDecision;
196
- addMemory(content: string, metadata?: Record<string, unknown>): MemoryId;
197
- searchMemory(text: string, k?: number): MemoryResult[];
198
- embed(text: string): Embedding;
199
-
200
- // Not in this package: token streaming (StreamingGenerator chunks a
201
- // finished generate() result), mistral-rs backends.
202
-
203
- // Get SONA learning stats
204
- sonaStats(): SonaStats | null;
205
-
206
- // Adapt on feedback
207
- adapt(input: Float32Array, quality: number): void;
208
- }
21
+ Run multiple bounded RuVLLM edits against one unchanged checkpoint, validate
22
+ supplied evaluations, package RVF evidence, restore every patched checkpoint,
23
+ and rank research-qualified candidates through MetaHarness. This controller
24
+ uses the actual Flywheel, Darwin and Weight-EFT packages pinned in
25
+ [package-lock.json](package-lock.json).
26
+
27
+ The runner does not perform inference, discover an effective weight edit, train
28
+ an adapter or activate a model. CPU fixtures exercise real file editing and
29
+ restoration with explicitly synthetic evaluation receipts. External evaluation
30
+ files remain caller-supplied evidence; hashes do not authenticate their origin.
31
+
32
+ ## Install and run the CPU fixture
33
+
34
+ Requirements: Linux or macOS, Node 22+, Python 3.12+, a C linker, and Rust 1.97.1
35
+ as pinned by `native/rust-toolchain.toml`. Activate any locally installed Rust
36
+ toolchain before using Cargo. From the repository root:
37
+
38
+ ```sh
39
+ (cd integrations/metaharness && npm ci --ignore-scripts)
40
+ (cd native && cargo build --locked --release --bin weight_evolution)
41
+ python3 native/verify_source.py
42
+ node integrations/metaharness/src/cli.mjs fixture \
43
+ --dir "$PWD/runtime/metaharness-fixture" \
44
+ --binary "$PWD/native/target/release/weight_evolution"
209
45
  ```
210
46
 
211
- ### Configuration
212
-
213
- ```typescript
214
- interface RuvLLMConfig {
215
- modelPath?: string; // GGUF to load in the constructor (throws if it cannot be loaded)
216
- modelOptions?: LoadModelOptions; // { maxContext?: number } for modelPath
217
- allowPlaceholder?: boolean; // generate()/query() return PLACEHOLDER_TEXT instead of
218
- // throwing when no model is loaded (default: false)
219
- strict?: boolean; // Throw instead of warning for unsupported options (`backend`)
220
- // ...plus routing/memory options (embeddingDim, hnswM, ...), see types.ts
221
- }
47
+ Create the fixture's parent directory first (`mkdir -p runtime`). Its own directory
48
+ must not exist: exclusive creation prevents accidental replacement. For another
49
+ fixture use a new directory. The report should select `fixture-improvement`, leave
50
+ `unevaluated-control` unqualified, verify RVF and exact rollback for both, and
51
+ report `inferencePerformed: false`, `independentConfirmation: false` and
52
+ `productionActivation: false`. A selected synthetic candidate says nothing about
53
+ actual model accuracy.
54
+
55
+ ## Configure real experiment inputs
56
+
57
+ Prepare reviewed source checkpoint, patch, policy and optional evaluation JSON
58
+ under explicit input roots. Native request/data contracts are described in the
59
+ [native guide](../../native/README.md). Patch generation remains model specific;
60
+ the controller does not guess useful tensor edits.
61
+
62
+ Run the project-local installer with paths you control:
63
+
64
+ ```sh
65
+ bash scripts/install-metaharness.sh \
66
+ --config-dir /absolute/private/operator-profile \
67
+ --read-root /absolute/checkpoints \
68
+ --read-root /absolute/experiment-inputs \
69
+ --policy /absolute/experiment-inputs/policy.json \
70
+ --output-root /absolute/private/experiment-outputs
222
71
  ```
223
72
 
224
- ### Generation Config and Result
225
-
226
- ```typescript
227
- interface GenerationConfig {
228
- maxTokens?: number; // default 256
229
- temperature?: number; // default 0.7; 0 = greedy
230
- topP?: number; // default 0.9, in (0, 1]
231
- topK?: number; // default 50; 0 disables
232
- repetitionPenalty?: number; // default 1.1
233
- stopSequences?: string[]; // stop text is not included in the output
234
- seed?: number; // reproducible sampling at temperature > 0
235
- }
236
-
237
- interface GenerationResult {
238
- text: string;
239
- promptTokens: number; // after the chat template, for chat()
240
- completionTokens: number; // includes an end-of-sequence token that ended generation
241
- finishReason: 'stop' | 'length' | 'cancelled';
73
+ It installs frozen npm dependencies without lifecycle scripts, builds the native
74
+ binary, verifies native provenance and runs its smoke fixture. It creates a
75
+ private runtime profile and Claude launcher without changing global settings.
76
+ Repeat `--read-root`/`--policy` for additional approved inputs. Existing profile
77
+ files are never replaced; use another directory for a new profile. Existing config
78
+ and output directories must be owner-only. `--configure-only` skips installation
79
+ and building but still checks native readiness.
80
+
81
+ Example plan inside an approved read root:
82
+
83
+ ```json
84
+ {
85
+ "schema": "ruvllm-experiment-plan/v1",
86
+ "evidenceMode": "external",
87
+ "source": "/absolute/checkpoints/source.safetensors",
88
+ "policy": "/absolute/experiment-inputs/policy.json",
89
+ "candidates": [
90
+ {
91
+ "id": "candidate-01",
92
+ "patch": "/absolute/experiment-inputs/patch.json",
93
+ "evaluation": "/absolute/experiment-inputs/evaluation.json"
94
+ }
95
+ ]
242
96
  }
243
97
  ```
244
98
 
245
- ## SIMD Module
246
-
247
- For direct access to optimized SIMD kernels:
248
-
249
- ```typescript
250
- import { simd } from '@ruvector/ruvllm/simd';
251
-
252
- // Dot product
253
- const result = simd.dotProduct(vecA, vecB);
254
-
255
- // Matrix multiplication
256
- const output = simd.matmul(matrix, vector);
257
-
258
- // Flash Attention
259
- const attended = simd.flashAttention(query, key, value, scale);
260
-
261
- // RMS Normalization
262
- simd.rmsNorm(hidden, weights, epsilon);
99
+ ```sh
100
+ node integrations/metaharness/src/cli.mjs run \
101
+ --config /absolute/private/operator-profile/runtime.json \
102
+ --plan /absolute/experiment-inputs/plan.json
263
103
  ```
264
104
 
265
- ## Performance (M4 Pro)
266
-
267
- | Operation | Performance |
268
- |-----------|-------------|
269
- | Inference | 88-135 tok/s |
270
- | Flash Attention | 320µs (seq=2048) |
271
- | HNSW Search | 17-62µs |
272
- | SONA Adapt | <1ms |
273
- | Evaluation | 5 ablation modes |
105
+ Omit `evaluation` to run mechanical checks without qualification. After an external
106
+ inference runner has evaluated a candidate, submit its hash-bound evaluation in a
107
+ new plan/run. Candidate checkpoint hashes are deterministic for the same patch;
108
+ new artifact paths do not relax identity checks. Paired baseline, protocol, suite,
109
+ runtime, precision and output-budget consistency remain the evaluator's responsibility.
274
110
 
275
- ## Evaluation Harness
111
+ Runs use new private `run-*` directories and preserve rejected candidates. Reports
112
+ bind config/plan/source/policy/binary/gate/patch/evaluation identities and record
113
+ rollback and RVF verification. Native rejection records a reason. Structural or
114
+ restoration failures abort; interrupted runs can leave artifacts. Reconcile those
115
+ directories before retrying; never erase failed evidence to manufacture success.
276
116
 
277
- > **Not in this npm package**: `EvaluationHarness` and `AblationMode` are
278
- > not exported by `@ruvector/ruvllm`. The sketch below shows the intended API.
117
+ ## Claude Code and Ruflo
279
118
 
280
- Run model evaluations with SWE-Bench integration:
119
+ Load [ruflo-metaharness](../../plugins/ruflo-metaharness/README.md) using the
120
+ generated `launch-claude.sh`, or set `RUVLLM_EXPERIMENT_CONFIG` and use Claude's
121
+ `--plugin-dir`. The `/ruflo-metaharness:weight-experiment` command and reviewer
122
+ agent guide the bounded workflow. Its single MCP tool accepts a plan path; the
123
+ model cannot override the operator configuration. The same stdio server can be
124
+ registered in a Ruflo project's MCP configuration. Portable wire tests exercise
125
+ the real engine; installed Claude/Ruflo client acceptance is separate.
281
126
 
282
- ```typescript
283
- import { RuvLLM, EvaluationHarness, AblationMode } from '@ruvector/ruvllm';
127
+ ## Scheduled GPU work
284
128
 
285
- const harness = new EvaluationHarness({
286
- modelPath: './models/model.gguf',
287
- enableHnsw: true,
288
- enableSona: true,
289
- });
129
+ For scheduled GPU work, use the [durable GPU loop](GPU-LOOP.md). It supports
130
+ host-owned ruOS secret references, Vast job descriptors, persisted reservations,
131
+ deadline-aware polling and confirmed cleanup. Local contract tests require no
132
+ live provider. The bundled file handoff keeps requests pending for a trusted host.
290
133
 
291
- // Run single evaluation
292
- const result = await harness.evaluate(
293
- 'Fix the null pointer exception',
294
- 'def process(data): return data.split()',
295
- AblationMode.Full
296
- );
134
+ ## Weight-EFT data and plans
297
135
 
298
- console.log(`Success: ${result.success}, Quality: ${result.qualityScore}`);
136
+ The data-only adapter CLI reads JSON stdin, with a 16 MiB bound:
299
137
 
300
- // Run ablation study (Baseline, RetrievalOnly, AdaptersOnly, R+A, Full)
301
- const report = await harness.runAblationStudy(tasks);
302
- for (const [mode, metrics] of Object.entries(report.modeMetrics)) {
303
- console.log(`${mode}: ${metrics.successRate * 100}% success`);
304
- }
138
+ ```sh
139
+ node integrations/metaharness/src/adapters-cli.mjs export < reviewed-archive-input.json > export.json
140
+ node integrations/metaharness/src/adapters-cli.mjs training-plan < training-input.json > plan.json
141
+ node integrations/metaharness/src/adapters-cli.mjs select < measured-candidates.json > selection.json
305
142
  ```
306
143
 
307
- ## mistral-rs Backend (Production Serving)
308
-
309
- For production deployments with 10-100+ concurrent users, use the mistral-rs backend:
310
-
311
- ```typescript
312
- import { RuvLLM, MistralBackend, PagedAttentionConfig } from '@ruvector/ruvllm';
313
-
314
- // Configure for production serving
315
- const backend = new MistralBackend({
316
- // PagedAttention: 5-10x more concurrent users
317
- pagedAttention: {
318
- blockSize: 16,
319
- maxBlocks: 4096,
320
- gpuMemoryFraction: 0.9,
321
- prefixCaching: true,
322
- },
323
- // X-LoRA: Per-token adapter routing
324
- xlora: {
325
- adapters: ['./adapters/coder', './adapters/researcher'],
326
- topK: 2,
327
- },
328
- // ISQ: Runtime quantization
329
- isq: {
330
- bits: 4,
331
- method: 'awq',
332
- },
333
- });
334
-
335
- const llm = new RuvLLM({ backend });
336
- await llm.loadModel('mistralai/Mistral-7B-Instruct-v0.2');
337
-
338
- // Serve multiple concurrent requests
339
- const response = await llm.query('Write production code');
144
+ `export` takes `{archive, evalHoldout, maxTokens?}`. Archive entries follow the
145
+ pinned Weight-EFT `DarwinTrajectory` contract (`instance_id`, `model`, `tier`,
146
+ boolean `resolved`, `messages`, `model_patch`). All actual evaluation instance IDs
147
+ must be in `evalHoldout`. Output contains standard `sft`/`dpo` arrays, drop reports
148
+ and input hashes. Reward-hacking filtering stays enabled, overlength traces are
149
+ dropped, and tool calls are preserved. These filters cannot authenticate outcomes
150
+ or detect all semantic contamination.
151
+
152
+ `training-plan` takes `{base:{id,paramsB},sftPath,dpoPath,adapterPrefix}`. It emits
153
+ upstream plans plus `executionStatus: not_executed` and
154
+ `runnerCompatibility: adapter-required`. This repository has no upstream
155
+ `ruvllm microlora` executable. Its existing fixed CUDA/PEFT experiment runner is
156
+ not a configurable SFT/DPO trainer. No GPU, model download or paid job is started.
157
+
158
+ `select` takes `{baseline,candidates,envelope}` with entries
159
+ `{id,score,evidenceSha256}`. It replays finite, supplied scores through Darwin's
160
+ contrastive engine. It is development ranking with an immutable envelope and no
161
+ independent confirmation; it cannot authenticate caller-supplied evidence. The
162
+ native runner applies its stricter qualification first.
163
+
164
+ ## Tests and benchmark
165
+
166
+ ```sh
167
+ (cd integrations/metaharness && npm test)
168
+ node --test plugins/ruflo-metaharness/test/*.test.mjs
169
+ node integrations/metaharness/bench/run.mjs --iterations 7 --warmup 2 --candidates 2
340
170
  ```
341
171
 
342
- > **Not in this npm package**: `MistralBackend` is not exported, the
343
- > `backend` option is ignored (with a `RUVLLM_UNSUPPORTED_OPTION` warning), and
344
- > `loadModel()` takes a local GGUF path, not a Hub id. mistral-rs serving is a
345
- > feature of the Rust crate (`mistral-rs` feature).
346
-
347
- ## Supported Models
348
-
349
- GGUF files loadable with `loadModel()` (architectures llama, mistral, qwen2, qwen3):
350
-
351
- - **RuvLTRA-Small** (494M) - Q4K, Q5K, Q8
352
- - **RuvLTRA-Medium** (3B) - Q4K, Q5K, Q8
353
- - **Qwen 2.5 / Qwen 3** (0.5B-72B)
354
- - **Llama 3.x** (8B-70B)
355
- - **Mistral** (7B-22B)
356
-
357
- Phi-3, Gemma-2 and Qwen3.5 GGUFs are not supported: loading fails with an
358
- error naming the architecture.
359
-
360
- ## Platform Support
361
-
362
- The table covers routing, memory and embeddings. Model loading additionally
363
- needs a native binary built with the `candle` feature (see "Native binary
364
- requirements").
365
-
366
- | Platform | Architecture | Status |
367
- |----------|--------------|--------|
368
- | macOS | arm64 (M1-M4) | ✅ Full support |
369
- | macOS | x64 | ✅ Supported |
370
- | Linux | x64 | ✅ Supported |
371
- | Linux | arm64 | ✅ Supported |
372
- | Windows | x64 | ✅ Supported |
373
-
374
- ## Related Packages
375
-
376
- - [@ruvector/core](https://www.npmjs.com/package/@ruvector/core) - Vector operations
377
- - [@ruvector/sona](https://www.npmjs.com/package/@ruvector/sona) - SONA learning engine
378
- - [@ruvector/ruvector](https://www.npmjs.com/package/@ruvector/ruvector) - Full Ruvector SDK
379
-
380
- ## Links
381
-
382
- - [GitHub Repository](https://github.com/ruvnet/ruvector)
383
- - [API Documentation](https://docs.rs/ruvllm)
384
- - [Crate (Rust)](https://crates.io/crates/ruvllm)
385
-
386
- ## License
387
-
388
- MIT OR Apache-2.0
172
+ Tests require the built native binary. In restricted agent environments the Node
173
+ test runner, native child processes and package fetching may require the host's
174
+ supported execution permission. Verify actual subtest counts; a file-only runner
175
+ summary is insufficient evidence. Do not disable TLS/checksums or native checks.
176
+
177
+ The benchmark compares fresh versus reused Node processes on identical CPU
178
+ fixtures, retaining raw latency samples and implementation/binary/lock hashes.
179
+ The reused process matches the MCP server architecture. All native hashing,
180
+ patch validation and byte restoration remain enabled. See the
181
+ [benchmark report](../../docs/benchmarks/metaharness-cpu.md) for measured scope
182
+ and limits; no model-performance claim follows from orchestration speed.
183
+
184
+ Architecture and threat boundaries are recorded in
185
+ [ADR 012](../../docs/adr/ADR-012-metaharness-bounded-experiment-runner.md),
186
+ [ADR 013](../../docs/adr/ADR-013-training-and-development-selection.md) and
187
+ [ADR 014](../../docs/adr/ADR-014-claude-ruflo-integration.md).
@@ -0,0 +1,26 @@
1
+ {
2
+ "schema": "ruvllm-gpu-loop/v1",
3
+ "stateRoot": "/absolute/private/gpu-loop-state",
4
+ "intervalSeconds": 60,
5
+ "maxAttempts": 2,
6
+ "budgetUsd": 0,
7
+ "jobs": [
8
+ {
9
+ "id": "qwen35-4b-paired-evaluation",
10
+ "provider": "vast.ai",
11
+ "model": {
12
+ "repo": "Qwen/Qwen3.5-4B",
13
+ "revision": "851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a"
14
+ },
15
+ "task": "evaluate",
16
+ "secretRef": "ruos.vast.primary",
17
+ "resource": { "instanceId": "REPLACE_WITH_EXISTING_INSTANCE_ID" },
18
+ "maxCostUsd": 1,
19
+ "timeoutSeconds": 1800,
20
+ "experiment": {
21
+ "configPath": "/absolute/private/operator-profile/runtime.json",
22
+ "planPath": "/absolute/experiment-inputs/plan.json"
23
+ }
24
+ }
25
+ ]
26
+ }