@ruvector/ruvllm 3.0.0 → 4.0.0

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 +157 -362
  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,183 @@
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
+ Published on npm as `@ruvector/ruvllm`. Version 4.0.0 replaces the 3.x
4
+ inference runtime from `ruvnet/ruvector` with this package, because ruvllm now
5
+ lives in `ruvnet/ruvllm`. The 3.x API and its CLI subcommands are not part of
6
+ 4.x; pin `@ruvector/ruvllm@3` to keep using them. The npm package ships the
7
+ JavaScript controller, GPU loop and Vast.ai host adapter. It does not ship the
8
+ native `weight_evolution` binary, model weights or adapters. Build the binary
9
+ from this repository and pass its path with `--binary`.
7
10
 
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.
9
-
10
- > Inference at **88-135 tok/s** on M4 Pro | **<1ms** SONA adaptation | **6-8x** KV-cache compression via TurboQuant
11
-
12
- ## Installation
13
-
14
- ```bash
11
+ ```sh
15
12
  npm install @ruvector/ruvllm
13
+ npx ruvllm --help # bounded weight-edit experiments
14
+ npx ruvllm-gpu-loop status --config /abs/private/gpu-loop.json
16
15
  ```
17
16
 
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
- }
17
+ Run multiple bounded RuVLLM edits against one unchanged checkpoint, validate
18
+ supplied evaluations, package RVF evidence, restore every patched checkpoint,
19
+ and rank research-qualified candidates through MetaHarness. This controller
20
+ uses the actual Flywheel, Darwin and Weight-EFT packages pinned in
21
+ [package-lock.json](package-lock.json).
22
+
23
+ The runner does not perform inference, discover an effective weight edit, train
24
+ an adapter or activate a model. CPU fixtures exercise real file editing and
25
+ restoration with explicitly synthetic evaluation receipts. External evaluation
26
+ files remain caller-supplied evidence; hashes do not authenticate their origin.
27
+
28
+ ## Install and run the CPU fixture
29
+
30
+ Requirements: Linux or macOS, Node 22+, Python 3.12+, a C linker, and Rust 1.97.1
31
+ as pinned by `native/rust-toolchain.toml`. Activate any locally installed Rust
32
+ toolchain before using Cargo. From the repository root:
33
+
34
+ ```sh
35
+ (cd integrations/metaharness && npm ci --ignore-scripts)
36
+ (cd native && cargo build --locked --release --bin weight_evolution)
37
+ python3 native/verify_source.py
38
+ node integrations/metaharness/src/cli.mjs fixture \
39
+ --dir "$PWD/runtime/metaharness-fixture" \
40
+ --binary "$PWD/native/target/release/weight_evolution"
209
41
  ```
210
42
 
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
- }
43
+ Create the fixture's parent directory first (`mkdir -p runtime`). Its own directory
44
+ must not exist: exclusive creation prevents accidental replacement. For another
45
+ fixture use a new directory. The report should select `fixture-improvement`, leave
46
+ `unevaluated-control` unqualified, verify RVF and exact rollback for both, and
47
+ report `inferencePerformed: false`, `independentConfirmation: false` and
48
+ `productionActivation: false`. A selected synthetic candidate says nothing about
49
+ actual model accuracy.
50
+
51
+ ## Configure real experiment inputs
52
+
53
+ Prepare reviewed source checkpoint, patch, policy and optional evaluation JSON
54
+ under explicit input roots. Native request/data contracts are described in the
55
+ [native guide](../../native/README.md). Patch generation remains model specific;
56
+ the controller does not guess useful tensor edits.
57
+
58
+ Run the project-local installer with paths you control:
59
+
60
+ ```sh
61
+ bash scripts/install-metaharness.sh \
62
+ --config-dir /absolute/private/operator-profile \
63
+ --read-root /absolute/checkpoints \
64
+ --read-root /absolute/experiment-inputs \
65
+ --policy /absolute/experiment-inputs/policy.json \
66
+ --output-root /absolute/private/experiment-outputs
222
67
  ```
223
68
 
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';
69
+ It installs frozen npm dependencies without lifecycle scripts, builds the native
70
+ binary, verifies native provenance and runs its smoke fixture. It creates a
71
+ private runtime profile and Claude launcher without changing global settings.
72
+ Repeat `--read-root`/`--policy` for additional approved inputs. Existing profile
73
+ files are never replaced; use another directory for a new profile. Existing config
74
+ and output directories must be owner-only. `--configure-only` skips installation
75
+ and building but still checks native readiness.
76
+
77
+ Example plan inside an approved read root:
78
+
79
+ ```json
80
+ {
81
+ "schema": "ruvllm-experiment-plan/v1",
82
+ "evidenceMode": "external",
83
+ "source": "/absolute/checkpoints/source.safetensors",
84
+ "policy": "/absolute/experiment-inputs/policy.json",
85
+ "candidates": [
86
+ {
87
+ "id": "candidate-01",
88
+ "patch": "/absolute/experiment-inputs/patch.json",
89
+ "evaluation": "/absolute/experiment-inputs/evaluation.json"
90
+ }
91
+ ]
242
92
  }
243
93
  ```
244
94
 
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);
95
+ ```sh
96
+ node integrations/metaharness/src/cli.mjs run \
97
+ --config /absolute/private/operator-profile/runtime.json \
98
+ --plan /absolute/experiment-inputs/plan.json
263
99
  ```
264
100
 
265
- ## Performance (M4 Pro)
101
+ Omit `evaluation` to run mechanical checks without qualification. After an external
102
+ inference runner has evaluated a candidate, submit its hash-bound evaluation in a
103
+ new plan/run. Candidate checkpoint hashes are deterministic for the same patch;
104
+ new artifact paths do not relax identity checks. Paired baseline, protocol, suite,
105
+ runtime, precision and output-budget consistency remain the evaluator's responsibility.
266
106
 
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 |
107
+ Runs use new private `run-*` directories and preserve rejected candidates. Reports
108
+ bind config/plan/source/policy/binary/gate/patch/evaluation identities and record
109
+ rollback and RVF verification. Native rejection records a reason. Structural or
110
+ restoration failures abort; interrupted runs can leave artifacts. Reconcile those
111
+ directories before retrying; never erase failed evidence to manufacture success.
274
112
 
275
- ## Evaluation Harness
113
+ ## Claude Code and Ruflo
276
114
 
277
- > **Not in this npm package**: `EvaluationHarness` and `AblationMode` are
278
- > not exported by `@ruvector/ruvllm`. The sketch below shows the intended API.
115
+ Load [ruflo-metaharness](../../plugins/ruflo-metaharness/README.md) using the
116
+ generated `launch-claude.sh`, or set `RUVLLM_EXPERIMENT_CONFIG` and use Claude's
117
+ `--plugin-dir`. The `/ruflo-metaharness:weight-experiment` command and reviewer
118
+ agent guide the bounded workflow. Its single MCP tool accepts a plan path; the
119
+ model cannot override the operator configuration. The same stdio server can be
120
+ registered in a Ruflo project's MCP configuration. Portable wire tests exercise
121
+ the real engine; installed Claude/Ruflo client acceptance is separate.
279
122
 
280
- Run model evaluations with SWE-Bench integration:
123
+ ## Scheduled GPU work
281
124
 
282
- ```typescript
283
- import { RuvLLM, EvaluationHarness, AblationMode } from '@ruvector/ruvllm';
125
+ For scheduled GPU work, use the [durable GPU loop](GPU-LOOP.md). It supports
126
+ host-owned ruOS secret references, Vast job descriptors, persisted reservations,
127
+ deadline-aware polling and confirmed cleanup. Local contract tests require no
128
+ live provider. The bundled file handoff keeps requests pending for a trusted host.
284
129
 
285
- const harness = new EvaluationHarness({
286
- modelPath: './models/model.gguf',
287
- enableHnsw: true,
288
- enableSona: true,
289
- });
130
+ ## Weight-EFT data and plans
290
131
 
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
- );
132
+ The data-only adapter CLI reads JSON stdin, with a 16 MiB bound:
297
133
 
298
- console.log(`Success: ${result.success}, Quality: ${result.qualityScore}`);
299
-
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
- }
134
+ ```sh
135
+ node integrations/metaharness/src/adapters-cli.mjs export < reviewed-archive-input.json > export.json
136
+ node integrations/metaharness/src/adapters-cli.mjs training-plan < training-input.json > plan.json
137
+ node integrations/metaharness/src/adapters-cli.mjs select < measured-candidates.json > selection.json
305
138
  ```
306
139
 
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');
140
+ `export` takes `{archive, evalHoldout, maxTokens?}`. Archive entries follow the
141
+ pinned Weight-EFT `DarwinTrajectory` contract (`instance_id`, `model`, `tier`,
142
+ boolean `resolved`, `messages`, `model_patch`). All actual evaluation instance IDs
143
+ must be in `evalHoldout`. Output contains standard `sft`/`dpo` arrays, drop reports
144
+ and input hashes. Reward-hacking filtering stays enabled, overlength traces are
145
+ dropped, and tool calls are preserved. These filters cannot authenticate outcomes
146
+ or detect all semantic contamination.
147
+
148
+ `training-plan` takes `{base:{id,paramsB},sftPath,dpoPath,adapterPrefix}`. It emits
149
+ upstream plans plus `executionStatus: not_executed` and
150
+ `runnerCompatibility: adapter-required`. This repository has no upstream
151
+ `ruvllm microlora` executable. Its existing fixed CUDA/PEFT experiment runner is
152
+ not a configurable SFT/DPO trainer. No GPU, model download or paid job is started.
153
+
154
+ `select` takes `{baseline,candidates,envelope}` with entries
155
+ `{id,score,evidenceSha256}`. It replays finite, supplied scores through Darwin's
156
+ contrastive engine. It is development ranking with an immutable envelope and no
157
+ independent confirmation; it cannot authenticate caller-supplied evidence. The
158
+ native runner applies its stricter qualification first.
159
+
160
+ ## Tests and benchmark
161
+
162
+ ```sh
163
+ (cd integrations/metaharness && npm test)
164
+ node --test plugins/ruflo-metaharness/test/*.test.mjs
165
+ node integrations/metaharness/bench/run.mjs --iterations 7 --warmup 2 --candidates 2
340
166
  ```
341
167
 
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
168
+ Tests require the built native binary. In restricted agent environments the Node
169
+ test runner, native child processes and package fetching may require the host's
170
+ supported execution permission. Verify actual subtest counts; a file-only runner
171
+ summary is insufficient evidence. Do not disable TLS/checksums or native checks.
172
+
173
+ The benchmark compares fresh versus reused Node processes on identical CPU
174
+ fixtures, retaining raw latency samples and implementation/binary/lock hashes.
175
+ The reused process matches the MCP server architecture. All native hashing,
176
+ patch validation and byte restoration remain enabled. See the
177
+ [benchmark report](../../docs/benchmarks/metaharness-cpu.md) for measured scope
178
+ and limits; no model-performance claim follows from orchestration speed.
179
+
180
+ Architecture and threat boundaries are recorded in
181
+ [ADR 012](../../docs/adr/ADR-012-metaharness-bounded-experiment-runner.md),
182
+ [ADR 013](../../docs/adr/ADR-013-training-and-development-selection.md) and
183
+ [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
+ }