@octocodeai/freellama-mcp-server 0.1.0 → 0.6.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.
- package/CONFIGURATION.md +108 -0
- package/DEVELOPING.md +109 -0
- package/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +18 -0
- package/README.md +261 -243
- package/assets/logo.jpg +0 -0
- package/dist/index.js +2305 -1332
- package/dist/research/bash-agent.js +2435 -0
- package/dist/research/octocode-agent.js +1639 -0
- package/docs/ARCHITECTURE.md +294 -87
- package/docs/CLI.md +171 -53
- package/docs/CPU_GPU_ROUTING.md +69 -23
- package/docs/MODEL_SELECTION.md +126 -3
- package/docs/MONITORING.md +293 -0
- package/docs/PRODUCTION.md +53 -25
- package/docs/README.md +36 -0
- package/docs/SCOPES_AND_WARMING.md +225 -0
- package/docs/TESTING.md +113 -8
- package/native/index.d.ts +186 -150
- package/native/index.js +3 -3
- package/package.json +15 -11
- package/adapters/agent_context.py +0 -663
- package/adapters/agent_transport.py +0 -84
- package/adapters/bash_agent.py +0 -370
- package/adapters/octocode_agent.py +0 -394
- package/docs/ADR_RESOURCE_AWARE_BACKEND_ROUTING.md +0 -55
- package/docs/ECONOMICS.md +0 -105
- package/docs/INDEX.md +0 -15
- package/docs/OLLAMA_SIDECAR.md +0 -76
- package/docs/OLLAMA_SYSTEM_OPTIMIZATION.md +0 -254
- package/docs/PRODUCT_POSITIONING.md +0 -291
package/docs/MODEL_SELECTION.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# Choose local models
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
To offload a task, select an installed model with the required capabilities and measured quality,
|
|
4
|
+
then check its memory fit under the intended concurrency. FreeLlama applies model eligibility
|
|
5
|
+
and admission; the calling agent still verifies the output.
|
|
6
|
+
|
|
7
|
+
The measurements in this guide come from one Apple M4 Pro machine with 48 GB unified memory and
|
|
8
|
+
are not compiled into routing. Re-run
|
|
5
9
|
`npx @octocodeai/freellama doctor`, `models`, `bench-all`, and your quality suite on the target hardware.
|
|
6
10
|
`doctor.machine.memory_bytes` is host RAM; a discrete GPU's usable VRAM must be observed separately.
|
|
7
11
|
|
|
12
|
+
For supported features and sourced publisher use-case guidance, inspect
|
|
13
|
+
`models {view:"installed", includeLibrary:true}` through MCP. [Model metadata](#model-metadata) explains digest matching, variant capabilities,
|
|
14
|
+
custom-model fallbacks, and how to read family claims without treating them as quality measurements.
|
|
15
|
+
|
|
8
16
|
```mermaid
|
|
9
17
|
flowchart TD
|
|
10
18
|
T{"What must the task do?"}
|
|
@@ -24,6 +32,15 @@ flowchart TD
|
|
|
24
32
|
grounded research, image description, OCR, and summarization. Using one large multimodal model also
|
|
25
33
|
avoided contention between separate heavy text and vision runners.
|
|
26
34
|
|
|
35
|
+
Read the [retained model profile](https://github.com/bgauryy/FreeLlama/blob/main/skills/freellama/references/model-profile-qwen3.8-27b-mlx.md)
|
|
36
|
+
and [delegation measurements](https://github.com/bgauryy/FreeLlama/blob/main/skills/freellama/references/task-delegation.md) for scope and limits.
|
|
37
|
+
These examples do not establish that a tag is installed or suitable on your host.
|
|
38
|
+
|
|
39
|
+
Dedicated OCR models answer best to the prompts their model card documents; send them with base64
|
|
40
|
+
`images` in `run_task`. A model that repeats its answer until the output cap can run with
|
|
41
|
+
`stopOnRepetition:true`. See [Route images](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/README.md#route-images)
|
|
42
|
+
for the early stop and the `output_check` receipt.
|
|
43
|
+
|
|
27
44
|
`muse-glimmer:30b-mlx` was a credible alternative and answered 29 of 30 questions correctly
|
|
28
45
|
(96.7%) with the Bash adapter, but it was slower and did not add a required capability in this
|
|
29
46
|
workload.
|
|
@@ -48,7 +65,7 @@ keywords, repository search was both faster and more accurate in the measured sa
|
|
|
48
65
|
|
|
49
66
|
## Place helper models on CPU when useful
|
|
50
67
|
|
|
51
|
-
A small embedding or
|
|
68
|
+
A small embedding or helper model can be assigned to a second CPU Ollama process while a large
|
|
52
69
|
generation model remains resident on the primary GPU-capable process. This can overlap independent
|
|
53
70
|
work, but it does not make CPU inference fast. Apple silicon shares memory bandwidth; discrete-GPU
|
|
54
71
|
systems have different transfer and contention costs and need their own benchmark.
|
|
@@ -63,3 +80,109 @@ this machine and workload, not a universal model-placement rule. Follow
|
|
|
63
80
|
`bench-all` measures local performance. A quality benchmark measures correctness. FreeLlama needs
|
|
64
81
|
both the generated task policy and local benchmark data before grading a route medium confidence.
|
|
65
82
|
See the [CLI reference](CLI.md#earn-medium-routing-confidence) for the commands.
|
|
83
|
+
|
|
84
|
+
## Model metadata
|
|
85
|
+
|
|
86
|
+
The MCP `models` tool reads your Ollama instance and can enrich results with Ollama's public model
|
|
87
|
+
library. Supported features and advertised use cases are metadata: they do not change routing
|
|
88
|
+
confidence, and exact-model benchmarks and policy remain the quality evidence. The CLI's `models`
|
|
89
|
+
command reports the core catalog and does not expose these enrichment flags.
|
|
90
|
+
|
|
91
|
+
| Request | Result | External access |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `models {view:"installed"}` | Managed inventory with a `knowledge` object for each model | Local backend data only |
|
|
94
|
+
| `models {view:"installed", includeLibrary:true}` | Inventory enriched with public guidance for verified local tags | Fetches model family and tag pages from ollama.com |
|
|
95
|
+
| `models {view:"detail", model:"gemma3:1b"}` | Ollama details, maximum context, and supported-use explanations | Selected Ollama endpoint only |
|
|
96
|
+
| `models {view:"detail", model:"gemma3:1b", includeLibrary:true}` | Details plus public guidance after a tag and digest check | Selected Ollama endpoint and ollama.com |
|
|
97
|
+
| `models {view:"library", query:"coding"}` | Public family search with descriptions and advertised feature chips | ollama.com and optional local inventory/profile reads |
|
|
98
|
+
| `models {view:"library", model:"gemma3"}` | All public tags with size, digest prefix, context, modalities, and cloud status | ollama.com and optional local inventory/profile reads |
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
| Option | Valid views | Default | Meaning |
|
|
102
|
+
|---|---|---|---|
|
|
103
|
+
| `includeLibrary` | `installed`, `detail` | `false` | Requests public metadata; the default makes no website calls |
|
|
104
|
+
| `includeReadme` | Library step 2, or `detail` with `includeLibrary:true` | `false` | Returns README text, capped at 65,536 characters, with its format and truncation flag |
|
|
105
|
+
| `includeVerbose` | `detail` | `false` | Returns Ollama's license and Modelfile fields independently of README enrichment |
|
|
106
|
+
| `limit`, `cursor` | `raw`, library tag listings; `limit` also applies to library search | Tag/raw page size 20; search limit 10 | Pages large lists; the tag cursor rejects a changed tag list |
|
|
107
|
+
| `ollamaEndpoint` | Direct Ollama views and library inventory reads | Configured Ollama endpoint | Chooses the Ollama instance; enriched managed inventory uses each model's assigned backend |
|
|
108
|
+
|
|
109
|
+
An incompatible option returns an error before any lookup. Installed enrichment omits full READMEs;
|
|
110
|
+
request one model's detail to read its README.
|
|
111
|
+
|
|
112
|
+
### Supported features
|
|
113
|
+
|
|
114
|
+
`knowledge.supportedFeatures` preserves the feature strings from the selected source
|
|
115
|
+
(`supportedFeaturesSource`: `ollama_api` or `freellama_catalog`). Unknown future strings stay visible
|
|
116
|
+
but do not create routing requirements. `knowledge.supportedUseCases` explains each recognized
|
|
117
|
+
feature with `capability`, `use`, `reason`, and `basis:"supported_feature"`;
|
|
118
|
+
`knowledge.quality` stays `"metadata_only"`.
|
|
119
|
+
|
|
120
|
+
| Feature | Supported workflow | What to evaluate separately |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| `completion` | Text generation | Coding, summarization, reasoning, and instruction-following accuracy |
|
|
123
|
+
| `tools` | Tool calls | Argument correctness, tool selection, and agent-loop reliability |
|
|
124
|
+
| `vision` | Image input | OCR and visual understanding accuracy |
|
|
125
|
+
| `audio` | Audio workflows advertised by the model | Supported audio task and accuracy |
|
|
126
|
+
| `embedding` | Retrieval and similarity vectors | Retrieval quality on your documents |
|
|
127
|
+
| `thinking` | A thinking mode | Reasoning accuracy, latency, and token cost |
|
|
128
|
+
| `insert` | Suffix-based text insertion | Completion accuracy in the target code or text |
|
|
129
|
+
| `image` | Image generation | Output quality and supported controls |
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
### Public guidance and provenance
|
|
133
|
+
|
|
134
|
+
For a verified installed model, `knowledge.library` contains the source page, tag-page URL,
|
|
135
|
+
`fetchedAt`, `expiresAt`, `cached`, exact public tag metadata, and:
|
|
136
|
+
|
|
137
|
+
| Field | Meaning |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `description` | The public family description |
|
|
140
|
+
| `advertisedFamilyCapabilities` | Family feature chips; these do not extend the local tag's capabilities |
|
|
141
|
+
| `advertisedUseCases` | Recognized coding, tool-calling, image-understanding/OCR, reasoning, embedding, summarization, question-answering, translation, and long-context claims |
|
|
142
|
+
| `advertisedUseCases[].evidence` | A bounded source excerpt, source URL, and fetch timestamp |
|
|
143
|
+
| `usageNotes` | Bounded excerpts about requirements, restrictions, context, memory, languages, or query prefixes |
|
|
144
|
+
| `readmeAvailable` | Whether a README was extracted |
|
|
145
|
+
| `readme` | Requested text with `format` (`markdown` or `text`) and `truncated` |
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
Advertised uses have `basis:"advertised"`, `scope:"family"`, and `quality:"unmeasured"`. Extraction
|
|
149
|
+
skips fenced code and negative statements; an omitted use means no recognized claim, not absence.
|
|
150
|
+
These labels are not the `run_task` task enum. Local capabilities filter advertised uses: a family
|
|
151
|
+
vision chip cannot make `gemma3:1b` a vision candidate.
|
|
152
|
+
|
|
153
|
+
Installed enrichment requires the exact public tag and a digest-prefix match of at least 12 hex
|
|
154
|
+
characters. Custom names are never mapped by architecture or guessed base model; without a verified
|
|
155
|
+
match, public guidance is withheld. Library step 2 describes public models before installation, so
|
|
156
|
+
its guidance stays family-scoped; each `tags[]` entry carries its own modalities, context, digest
|
|
157
|
+
prefix, and `cloud` flag. Search's `cloudAvailable` badge does not prove local downloads are absent.
|
|
158
|
+
|
|
159
|
+
### Lookup states
|
|
160
|
+
|
|
161
|
+
| `library.status` | Meaning | Next action |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| `not_requested` | Website enrichment was not requested | Set `includeLibrary:true` if external lookup is useful |
|
|
164
|
+
| `matched` | Installed tag and public digest prefix match | Read the sourced guidance, then evaluate the exact tag |
|
|
165
|
+
| `available` | Public family and tag pages were parsed in library step 2 | Inspect the exact tag before recommending a download |
|
|
166
|
+
| `unverified` | Digest or current backend inventory could not be verified | Recheck local inventory; retain local feature information |
|
|
167
|
+
| `digest_mismatch` | The public tag differs from the installed digest | Treat public guidance as unavailable for this installed model |
|
|
168
|
+
| `tag_not_found` | The parsed public tag list has no exact matching tag | Check the source and custom-model provenance |
|
|
169
|
+
| `unmatched` | The name cannot resolve to an exact public Ollama name | Keep use-case suitability unknown until provenance is verified |
|
|
170
|
+
| `not_found` | A requested public page returned HTTP 404 | Check the source URL or custom name |
|
|
171
|
+
| `unavailable` | Transport, timeout, HTTP refusal, or page-size limit prevented lookup | Retry later; local results remain available |
|
|
172
|
+
| `parse_error` | HTML content or tag rows were not recognized | Inspect the source; do not conclude the model is absent |
|
|
173
|
+
| `remote_model`, `remote_tag` | Remote Ollama fields or a hosted tag identify cloud execution | Select a local download tag for local execution |
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
`localModel:false` flags detected remote entries; cloud tags never become local trial
|
|
177
|
+
recommendations. This metadata is not processor-placement evidence.
|
|
178
|
+
|
|
179
|
+
### Cache and request bounds
|
|
180
|
+
|
|
181
|
+
Each MCP process caches at most 128 families: successes for one hour, failures for one minute;
|
|
182
|
+
concurrent requests share one lookup and a restart clears the cache. Installed enrichment runs at
|
|
183
|
+
most four family lookups concurrently. Requests use GET, refuse redirects, cap each page at 2 MiB,
|
|
184
|
+
and time out after the smaller of 10 seconds and `FREELLAMA_MCP_FETCH_TIMEOUT_SECONDS`. They disclose
|
|
185
|
+
the requested public family name to ollama.com. Download size does not establish runtime memory
|
|
186
|
+
fit, placement, or quality, and model discovery never authorizes a pull. Sources:
|
|
187
|
+
[model details API](https://docs.ollama.com/api-reference/show-model-details),
|
|
188
|
+
[model-list API](https://docs.ollama.com/api/tags).
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Runtime status and live tuning
|
|
2
|
+
|
|
3
|
+
Use runtime status to inspect how FreeLlama manages delegated work: per-backend queues and
|
|
4
|
+
admission, memory pressure, resident models, execution usage, and resource holds. The operator can
|
|
5
|
+
reload supported limits without a restart; the calling agent can use these observations to decide
|
|
6
|
+
whether to wait, narrow a task, or handle it itself.
|
|
7
|
+
|
|
8
|
+
The API endpoints in this reference are served under `/_freellama/v1/` and use the same bearer
|
|
9
|
+
token as the rest of the control API when authentication is enabled.
|
|
10
|
+
|
|
11
|
+
Open **`http://127.0.0.1:11435/_freellama/ui`** (the address `serve` prints at startup) for a live
|
|
12
|
+
page of the same data, refreshed every two seconds: backends and queues, raw traffic, host RAM and
|
|
13
|
+
VRAM, Ollama's settings, loaded models with their current tasks and load times, and the last
|
|
14
|
+
eviction. The page itself is static and needs no token; when auth is on it asks for the bearer
|
|
15
|
+
token and keeps it only for the browser tab.
|
|
16
|
+
|
|
17
|
+
| Endpoint | CLI | MCP | What it returns |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| `GET /status` | `freellama status` | `doctor {view:"status"}` | Live view of every backend, the raw proxy, loaded models, host, Ollama settings, and today's usage |
|
|
20
|
+
| `GET /usage?days=N` | `freellama usage --days N` | `doctor {view:"usage", days:N}` | Totals per day and per model (default 7 days) |
|
|
21
|
+
| `GET /metrics` | | | Prometheus text exposition |
|
|
22
|
+
| `GET /config` | `freellama config` | | Effective runtime settings and the source of each |
|
|
23
|
+
| `POST /config/reload` | `freellama config --reload` | | Re-read the runtime file now; `422` keeps the last good values |
|
|
24
|
+
| `GET /jobs` | `freellama jobs` | `task_jobs {action:"list"}` | Deferred job metadata without prompts or retained results |
|
|
25
|
+
| `GET /jobs/:id` | `freellama jobs --id <uuid>` | `task_jobs {action:"get", jobId}` | One job receipt and its retained result or error |
|
|
26
|
+
| `POST /jobs/:id/cancel` | `freellama jobs --id <uuid> --cancel` | `task_jobs {action:"cancel", jobId}` | Cancellation receipt after local permits are released |
|
|
27
|
+
| `DELETE /jobs/:id` | `freellama jobs --id <uuid> --remove` | `task_jobs {action:"remove", jobId}` | Stops active work, releases local permits, and removes the retained record |
|
|
28
|
+
|
|
29
|
+
## Read the live status
|
|
30
|
+
|
|
31
|
+
`status` answers "why is my task waiting?" in one call:
|
|
32
|
+
|
|
33
|
+
- **`backends.gpu` / `backends.cpu`**: admission (units in use, current limit, ceiling, queue depth,
|
|
34
|
+
oldest wait, refusal and timeout counters), the adaptive limiter state, and the circuit breaker
|
|
35
|
+
(`closed`, `open` with seconds remaining, or `half_open`).
|
|
36
|
+
- **`raw_proxy`**: active and waiting raw streams against their cap and wait budget.
|
|
37
|
+
- **`loaded_models`**: Ollama's `/api/ps` with total and VRAM bytes, context length, expiry, and
|
|
38
|
+
whether the model is pinned.
|
|
39
|
+
- **`host`**: available and reserved RAM, whether the pressure gate is holding, and discrete-GPU
|
|
40
|
+
total and free memory (`nvidia-smi` or amdgpu sysfs) when available. Optional `gpu_activity`
|
|
41
|
+
reports driver counters separately from resident memory. On macOS, `thermal_pressure` is the
|
|
42
|
+
system thermal pressure level (`nominal`, `moderate`, `heavy`, `trapping`, `sleeping`); `heavy`
|
|
43
|
+
or worse holds CPU-assigned work and cold loads. Other platforms report `null`.
|
|
44
|
+
- **`ollama`**: the Ollama server's effective `OLLAMA_*` settings with a source for each — the
|
|
45
|
+
running process's environment (Linux `/proc/<pid>/environ`, macOS `ps eww` for a same-user
|
|
46
|
+
process), `launchctl getenv` for the macOS app, FreeLlama's own environment, or Ollama's default.
|
|
47
|
+
A remote endpoint is never probed and is reported as unknown.
|
|
48
|
+
- **`usage_today`**: tasks, errors, tokens, and busy time since midnight UTC.
|
|
49
|
+
- **`task_jobs`**: deferred task IDs, selected models, configured backends, priorities, total
|
|
50
|
+
deadlines, states, and waiting reasons. States cover discovery, admission, resources, runner
|
|
51
|
+
transitions, loading, execution, and completion. Metadata excludes the original payload.
|
|
52
|
+
|
|
53
|
+
Use `run_task {defer:true}` in MCP or `task --defer` in the CLI to get a job handle. A list or
|
|
54
|
+
status request omits results; fetching one ID returns its retained result or structured failure.
|
|
55
|
+
Terminal states are `completed`, `failed`, `cancelled`, and `expired`. Cancellation is per task,
|
|
56
|
+
waits for local permits to be released, and does not unload a shared runner. Process-local job
|
|
57
|
+
retention limits are documented in [CLI controls](CLI.md#execute-tasks).
|
|
58
|
+
|
|
59
|
+
Removal uses the same exact job ID. It cancels active work before discarding the record, returns
|
|
60
|
+
`{id, removed:true, status, scope:"process_memory"}`, and omits the saved result. The ID then returns
|
|
61
|
+
`404` on lookup or another removal. Other jobs and installed models are unaffected. Local
|
|
62
|
+
cancellation closes the upstream request; physical computation may continue on a shared runner.
|
|
63
|
+
|
|
64
|
+
`ollama.config` describes the primary process; `ollama.cpu_config` describes the CPU process when
|
|
65
|
+
configured. Process attribution matches `OLLAMA_HOST` to the selected endpoint, so separate
|
|
66
|
+
parallelism and KV cache settings size each backend independently. Fallback sources remain visible
|
|
67
|
+
when process settings cannot be observed.
|
|
68
|
+
|
|
69
|
+
Process settings are cached for five seconds and refreshed on discovery or monitoring requests,
|
|
70
|
+
including after an Ollama restart. Each config receipt includes `observed_at` and
|
|
71
|
+
`observation_scope: "process_snapshot"`. Refresh also updates backend memory estimates and
|
|
72
|
+
invalidates the use of measurements taken under different parallelism or KV cache settings.
|
|
73
|
+
FreeLlama admission limits remain governed by its runtime configuration.
|
|
74
|
+
|
|
75
|
+
`host.gpu_activity` is nullable. When available, it identifies its `source`,
|
|
76
|
+
`scope: "observed_devices_all_processes"`, `window: "driver_defined"`, and individual `devices`.
|
|
77
|
+
Each device has an identity, nullable `busy_percent`, and nullable `memory_busy_percent`. Apple
|
|
78
|
+
devices may add `allocated_memory_bytes`, the driver's allocated memory across all processes.
|
|
79
|
+
An observed zero means the driver reported zero; a missing or malformed counter remains unknown.
|
|
80
|
+
Use `host.sample_age_ms` to check freshness.
|
|
81
|
+
|
|
82
|
+
NVIDIA activity comes from the same bounded `nvidia-smi` query as memory. Apple Silicon activity
|
|
83
|
+
comes from the accelerator's `PerformanceStatistics` in a bounded IORegistry read. Those Apple
|
|
84
|
+
properties are driver-specific and may disappear or change; the read can cover only the devices
|
|
85
|
+
within its retained output. AMD, Windows, unsupported drivers, and unavailable reads report unknown activity. The counters include other processes, use a driver-defined observation
|
|
86
|
+
window, and do not attribute activity to a FreeLlama task or establish bandwidth or energy
|
|
87
|
+
efficiency. They are diagnostics and do not alter admission or pressure decisions.
|
|
88
|
+
|
|
89
|
+
Each backend's admission `queue_depth` includes both `slot_waiters` and `resource_waiters`.
|
|
90
|
+
A resource waiter returns its execution slot after two seconds but remains in the bounded queue
|
|
91
|
+
until capacity recovers, its deadline expires, or it is cancelled.
|
|
92
|
+
|
|
93
|
+
## Record usage
|
|
94
|
+
|
|
95
|
+
Every managed task updates in-memory usage totals and offers one record to a bounded writer queue.
|
|
96
|
+
The record contains time, model, backend, task kind, priority, outcome, HTTP status, prompt and
|
|
97
|
+
output tokens, duration, queue wait, load time, and output tokens per second. It contains no prompt
|
|
98
|
+
or response text. One worker writes records in order; task completion does not wait for disk.
|
|
99
|
+
|
|
100
|
+
The writer queue defaults to 128 records. Configure its positive startup-only capacity through
|
|
101
|
+
`usage_queue_capacity` or `FREELLAMA_USAGE_QUEUE_CAPACITY`; runtime reload does not resize the worker.
|
|
102
|
+
A full queue or unavailable worker drops the record; a disk
|
|
103
|
+
failure records a failed write. Inspect `usage_ledger` in `status`, or `ledger` in `usage`, for
|
|
104
|
+
`pending`, `failed`, `dropped`, `records`, `capacity`, and `last_error`. The durability contract is
|
|
105
|
+
`asynchronous_best_effort`: pending records can be lost on a crash, and in-memory totals can exceed
|
|
106
|
+
persisted totals. Error evidence remains visible after later successful writes.
|
|
107
|
+
|
|
108
|
+
`serve` replays a bounded regular-file ledger at startup and rotates it to `usage.jsonl.1` at
|
|
109
|
+
16 MiB. Successful writes contribute to restart totals; completion is not a zero-loss persistence
|
|
110
|
+
promise. Embedded callers can use the bounded `flush_ledger` barrier for orderly teardown; it
|
|
111
|
+
confirms attempted writes, not recovery of dropped/failed records or a filesystem sync.
|
|
112
|
+
|
|
113
|
+
The ledger lives next to the feedback file in the platform data directory. Choose another path with
|
|
114
|
+
`--usage-file` (or `FREELLAMA_USAGE_FILE`), or keep totals in memory only with `--ephemeral-usage`.
|
|
115
|
+
|
|
116
|
+
## Scrape metrics
|
|
117
|
+
|
|
118
|
+
`/metrics` exposes counters (`freellama_tasks_total`, `freellama_prompt_tokens_total`,
|
|
119
|
+
`freellama_output_tokens_total`, `freellama_task_seconds_total`, `freellama_queue_wait_seconds_total`,
|
|
120
|
+
`freellama_load_seconds_total`, `freellama_raw_requests_total`, `freellama_evictions_total`,
|
|
121
|
+
`freellama_circuit_open_total`, `freellama_concurrency_limit_changes_total`) labelled by model,
|
|
122
|
+
backend, task, and outcome, plus gauges for admission, queues, the raw proxy, host and GPU memory,
|
|
123
|
+
loaded models, and `freellama_ollama_num_parallel`. Point Prometheus, Grafana Agent, or any
|
|
124
|
+
OpenMetrics-compatible scraper at it.
|
|
125
|
+
|
|
126
|
+
## Back-pressure
|
|
127
|
+
|
|
128
|
+
FreeLlama waits for safe capacity within a deadline and bounds the retained backlog:
|
|
129
|
+
|
|
130
|
+
| Situation | Status | `code` |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| Managed queue full | `429` | `admission_queue_full` |
|
|
133
|
+
| Raw proxy over its cap after `raw_queue_wait_seconds` | `429` | |
|
|
134
|
+
| Managed wait exceeded `max_queue_wait_seconds` (or the task's `max_wait_seconds`) | `503` | `admission_timeout` |
|
|
135
|
+
| OS pressure, swapping, CPU, thermal, or required telemetry still holds when the waiting budget expires (low available RAM alone only warns; low RAM and swapping never hold an already-resident runner) | `503` | `resource_admission_unavailable` |
|
|
136
|
+
| Backend circuit open | `503` | `upstream_circuit_open` |
|
|
137
|
+
|
|
138
|
+
These capacity refusals carry a `Retry-After` header and `retry_after_seconds` in the body. For a queue it
|
|
139
|
+
is estimated from the queue depth, the lanes that can run at once (current limit divided by the
|
|
140
|
+
task's cost), and the backend's recent average service time, which excludes queue wait (1 to 120
|
|
141
|
+
seconds). A task can ask for a shorter wait with `max_wait_seconds` (`maxWaitSeconds`
|
|
142
|
+
in MCP); the server caps it at the configured maximum.
|
|
143
|
+
|
|
144
|
+
## Circuit breaker
|
|
145
|
+
|
|
146
|
+
After `breaker_failures` consecutive upstream failures on a backend (connection errors, `500`,
|
|
147
|
+
`502`, or `504`), its circuit opens for `breaker_cooldown_seconds`; tasks routed there fail fast
|
|
148
|
+
with `503` rather than queueing behind a broken Ollama. When the cooldown ends, one probe request is
|
|
149
|
+
let through: success closes the circuit, failure reopens it. `4xx` responses such as an unknown
|
|
150
|
+
model do not count. Set `breaker_failures = 0` to disable it.
|
|
151
|
+
|
|
152
|
+
## Adaptive concurrency
|
|
153
|
+
|
|
154
|
+
Managed task costs are configurable through the runtime file's `[task_costs]` table. Valid keys
|
|
155
|
+
are `completion`, `coding`, `code_repair`, `tools`, `browser`, `vision`, `embedding`, and
|
|
156
|
+
`long_context`. Each value is a positive integer through 4294967295. Omitted kinds retain their
|
|
157
|
+
defaults: vision four, embeddings one, and other tasks two. Embeddings multiply their base by
|
|
158
|
+
`ceil(input_items/4)`; the acquired charge cannot exceed the pool's current limit.
|
|
159
|
+
|
|
160
|
+
For a qualified light OCR workload, `[task_costs]` with `vision = 2` permits two vision requests
|
|
161
|
+
under a four-unit budget while leaving other task costs unchanged. This is an operator setting,
|
|
162
|
+
not automatic quality or fit qualification. The memory governor and Ollama's final admission
|
|
163
|
+
still apply.
|
|
164
|
+
|
|
165
|
+
A task captures its cost when execution starts. Reload affects tasks that start afterward;
|
|
166
|
+
already queued or active tasks keep their captured cost. `config` reports effective values and
|
|
167
|
+
the runtime-file source; invalid keys, zero,
|
|
168
|
+
or overflow reject the reload and retain the last good configuration. Preview advice, health
|
|
169
|
+
costs, and execution receipts use the resolved policy. Health retains its summary aliases and
|
|
170
|
+
exposes the complete task-kind map under `admission.costs.base_by_task`. Task kinds remain
|
|
171
|
+
caller-declared; these weights are cooperative scheduling policy, not workload classification.
|
|
172
|
+
See the
|
|
173
|
+
[runtime example](https://github.com/bgauryy/FreeLlama/blob/main/freellama.runtime.example.toml) for the table syntax.
|
|
174
|
+
|
|
175
|
+
With `adaptive_concurrency = "cpu"` (the default) or `"all"`, each pool's limit moves between 1 and
|
|
176
|
+
its configured ceiling:
|
|
177
|
+
|
|
178
|
+
- **Down (halve)** on an upstream error, host memory pressure (PSI or the pressure gate), or output
|
|
179
|
+
throughput below 70% of the matching execution profile's baseline. Decreases are at least
|
|
180
|
+
10 seconds apart.
|
|
181
|
+
- **Up (+1 unit)** after five consecutive comparable healthy rate observations. Generation uses
|
|
182
|
+
output tokens per decode second; embeddings use input tokens per model-reported total second.
|
|
183
|
+
The profile records the metric kind, and unlike kinds cannot train or recover together.
|
|
184
|
+
|
|
185
|
+
Only completed warm executions with verified placement and a comparable observed profile train
|
|
186
|
+
speed baselines or healthy recovery. Identity includes model digest, explicit observed context,
|
|
187
|
+
backend/process settings, effective controls, and admission class. Fresh endpoint-attributed
|
|
188
|
+
process observations bracket candidate serial samples. Unknown identity, changed controls,
|
|
189
|
+
parallel intervals, invalid rate observations, and incomplete or canceled execution break the
|
|
190
|
+
recovery streak. Failures and observed memory pressure retain their safety decreases.
|
|
191
|
+
|
|
192
|
+
Serial samples require one managed task throughout the interval: unchanged admitted/released
|
|
193
|
+
counters, active charge, capacity, and policy epoch reject transient overlap or capacity changes.
|
|
194
|
+
This avoids comparing serial request speed with legitimate parallel decoding. It does not prove
|
|
195
|
+
that no external Ollama client ran concurrently. A successful parallel execution can therefore
|
|
196
|
+
report verified placement and `feedback.accepted:true` while
|
|
197
|
+
`execution.throughput_learning.eligible:false`; it contributes no comparable speed sample.
|
|
198
|
+
|
|
199
|
+
Each backend retains at most one adaptive profile window per task kind. Status exposes
|
|
200
|
+
`adaptive.profile_windows` keyed by task; `baseline_output_tokens_per_second` is a compatibility
|
|
201
|
+
output-only summary by model and can omit additional task windows for the same model. Embedding
|
|
202
|
+
windows report their explicit input-rate kind separately. Use the task windows for learning
|
|
203
|
+
evidence. See [automatic feedback](CPU_GPU_ROUTING.md#understand-automatic-feedback) for
|
|
204
|
+
persisted routing windows.
|
|
205
|
+
|
|
206
|
+
The CPU backend is adaptive by default because oversubscribing it shows up as a throughput collapse
|
|
207
|
+
rather than an error. Every change is counted in metrics and shown in `status`.
|
|
208
|
+
|
|
209
|
+
## Model residency and eviction
|
|
210
|
+
|
|
211
|
+
Omitted managed `keep_alive` values use finite retention informed by measured reuse and loading.
|
|
212
|
+
Explicit values take precedence. For governed prewarming, profile compatibility, and retention
|
|
213
|
+
settings, see [Scope history and model warming](SCOPES_AND_WARMING.md).
|
|
214
|
+
|
|
215
|
+
When a model about to load needs room, FreeLlama unloads idle runners itself (`keep_alive: 0`)
|
|
216
|
+
instead of letting the load wait, fail, or spill to CPU. It does this in three cases: host RAM
|
|
217
|
+
can fall below the reserve, the host is already holding for low memory, or (discrete GPU) the
|
|
218
|
+
model does not fit in free VRAM, where Ollama otherwise chooses its own victim.
|
|
219
|
+
|
|
220
|
+
Which runners go is a small optimisation, in the spirit of llama-swap's `evict_costs` and LocalAI's
|
|
221
|
+
busy-aware LRU:
|
|
222
|
+
|
|
223
|
+
- **Never unloaded:** the model being loaded, `pinned_models`, `keep_alive: -1` runners, runners
|
|
224
|
+
Ollama is still loading, and any model with a FreeLlama task queued or running (unloading it forces an immediate reload). Busy status is checked again right before each unload.
|
|
225
|
+
- **Not for a model bigger than the GPU:** it spills to the CPU whatever is unloaded, so VRAM is
|
|
226
|
+
left alone.
|
|
227
|
+
- **Cost of unloading a runner** = its reload time (Ollama's measured `load_duration` from earlier
|
|
228
|
+
loads, or size ÷ 1.5 GB/s before the first one) × (1 + recent uses, decaying with a 30-minute
|
|
229
|
+
half-life; only tasks served count) × its `eviction_costs` weight (default 1).
|
|
230
|
+
- **Choice:** the set of runners with the lowest total cost that frees enough memory; ties go to
|
|
231
|
+
fewer runners, then less memory freed beyond what is needed. Only the memory that matters is
|
|
232
|
+
counted: VRAM for a GPU fit, the host-RAM part for a spill, the whole runner on CPU or unified
|
|
233
|
+
memory.
|
|
234
|
+
|
|
235
|
+
Every managed receipt that caused an eviction carries the plan under
|
|
236
|
+
`memory_reservation.eviction`: what was unloaded, its cost and reload estimate, and what was kept
|
|
237
|
+
and why. `status` and the page show the latest one that unloaded something. Eviction runs once per
|
|
238
|
+
task, after admission and before the memory wait, and is never cancelled halfway by a deadline.
|
|
239
|
+
Set `evict_idle_models = false` to leave residency entirely to Ollama.
|
|
240
|
+
|
|
241
|
+
## Who decides what: FreeLlama and Ollama
|
|
242
|
+
|
|
243
|
+
Two schedulers that both guess at memory can disagree. The split is:
|
|
244
|
+
|
|
245
|
+
| Decision | Owner | How |
|
|
246
|
+
|---|---|---|
|
|
247
|
+
| Exact memory of a loaded runner | Ollama | Measured; FreeLlama reads it from `/api/ps` |
|
|
248
|
+
| Whether a new load fits | Both, Ollama final | FreeLlama estimates from Ollama's past measurements, then Ollama loads or refuses |
|
|
249
|
+
| Decoding slots per model | Ollama | `OLLAMA_NUM_PARALLEL`; FreeLlama's primary budget defaults to two weighted units per slot |
|
|
250
|
+
| Admission, priority, queue limits, back-pressure | FreeLlama | Weighted pools, 429/503 with `Retry-After` |
|
|
251
|
+
| Which idle runner to unload, and when | FreeLlama | The cost planner above, before Ollama has to choose |
|
|
252
|
+
| Context size | Ollama by default | `num_ctx` is left to Ollama when its default covers the request |
|
|
253
|
+
|
|
254
|
+
To keep the estimates honest, FreeLlama learns from every runner Ollama reports as resident,
|
|
255
|
+
including ones loaded by raw clients, and saves those measurements to `footprints.json` next to the
|
|
256
|
+
usage ledger. After a restart a model it has seen before is sized from Ollama's measurement, not a
|
|
257
|
+
formula. Each measurement records the `OLLAMA_NUM_PARALLEL` and KV-cache type it was taken under and
|
|
258
|
+
is used only while those match, so changing either setting falls back to the formula until Ollama
|
|
259
|
+
measures again. A larger context than any measured one is sized as the measurement plus exactly the extra
|
|
260
|
+
KV cache, when the model's KV shape is known.
|
|
261
|
+
|
|
262
|
+
## Context sizing and Ollama's defaults
|
|
263
|
+
|
|
264
|
+
Sending `num_ctx` on a request pins the runner to that size: a later request for the same model
|
|
265
|
+
with a different or missing `num_ctx` forces Ollama to reload it, and Ollama's automatic
|
|
266
|
+
out-of-memory shrink-and-retry only applies when the context was not requested explicitly.
|
|
267
|
+
|
|
268
|
+
With `context_mode = "ollama_default"` (the default), FreeLlama sizes the context as before but
|
|
269
|
+
omits `num_ctx` when Ollama's own default for the model is known, covers the request, and is at most
|
|
270
|
+
`auto_context_max` (32768). The default is resolved in Ollama's order: the Modelfile's `num_ctx`,
|
|
271
|
+
then `OLLAMA_CONTEXT_LENGTH`, then (discrete GPU only) Ollama's VRAM tier — 4096 below 24 GiB, 32768
|
|
272
|
+
below 48 GiB, 262144 above. Receipts show `context_sizing.num_ctx_sent` and the default used.
|
|
273
|
+
Memory estimates always use the context Ollama can allocate. Use `"explicit"` to always
|
|
274
|
+
send `num_ctx`.
|
|
275
|
+
|
|
276
|
+
## Change settings without a restart
|
|
277
|
+
|
|
278
|
+
Put any of the settings above in a TOML file and start `serve --runtime-config <file>` (or set
|
|
279
|
+
`FREELLAMA_RUNTIME_CONFIG`). Start from
|
|
280
|
+
[`freellama.runtime.example.toml`](https://github.com/bgauryy/FreeLlama/blob/main/freellama.runtime.example.toml). `serve` checks the file every
|
|
281
|
+
two seconds and applies changes to live admission pools; a waiting task sees the new limit at once.
|
|
282
|
+
|
|
283
|
+
Precedence for every setting, strongest first: CLI flag, environment variable (where one exists),
|
|
284
|
+
the runtime file, the built-in default. Only these settings have an environment variable:
|
|
285
|
+
`FREELLAMA_MAX_QUEUE_WAIT_SECONDS`, `FREELLAMA_EVICT_IDLE_MODELS`, `FREELLAMA_USAGE_QUEUE_CAPACITY`,
|
|
286
|
+
and the individual `FREELLAMA_SCOPE_*` and `FREELLAMA_KEEP_ALIVE_*` limits. Set every other key in
|
|
287
|
+
the runtime file or with its CLI flag. A flag or variable pins a value, so editing the file cannot
|
|
288
|
+
override it; `freellama config` shows which source won: `cli`, `env`, `file`, a default source
|
|
289
|
+
such as `default` or `ollama_num_parallel`, or `env_invalid` when a set variable failed validation.
|
|
290
|
+
A malformed file or an unknown key is rejected at reload and the previous values stay in force.
|
|
291
|
+
|
|
292
|
+
The default GPU budget follows the Ollama server: 2 units per `OLLAMA_NUM_PARALLEL` slot (one chat
|
|
293
|
+
per decoding slot), read from the running Ollama process where visible.
|
package/docs/PRODUCTION.md
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
# Prepare FreeLlama for production
|
|
2
2
|
|
|
3
|
-
This runbook prepares
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
This runbook prepares the FreeLlama management layer for agents using local models in a
|
|
4
|
+
single-operator or trusted-team deployment. Configure the Ollama backends, model evidence,
|
|
5
|
+
authentication, and resource limits before agents submit work.
|
|
6
|
+
|
|
7
|
+
FreeLlama supports authenticated nonloopback listeners. Put TLS and tenant-specific rate limits
|
|
8
|
+
at an external ingress when traffic crosses a machine boundary; FreeLlama's bearer token does
|
|
9
|
+
not provide tenant isolation or billing.
|
|
7
10
|
|
|
8
11
|
## Meet the prerequisites
|
|
9
12
|
|
|
10
13
|
- Install one Ollama CLI and server version. Run `freellama doctor` and resolve any mismatch.
|
|
11
14
|
- Install Node.js 20 or later for MCP and npm distribution use.
|
|
12
|
-
- Use the release artifacts for your operating system, or build with Rust 1.
|
|
15
|
+
- Use the release artifacts for your operating system, or build with Rust 1.88 or later.
|
|
13
16
|
- Preinstall and benchmark exact model tags. Discovery never authorizes a pull.
|
|
14
17
|
- Keep the primary and optional CPU Ollama processes on distinct loopback sockets.
|
|
18
|
+
- In a slim or distroless container, install the CA bundle (`ca-certificates`) or set
|
|
19
|
+
`SSL_CERT_FILE` if any upstream uses `https://`. Without one, FreeLlama starts with an empty trust
|
|
20
|
+
store and warns: plain-HTTP upstreams work, HTTPS upstreams fail their certificate check.
|
|
15
21
|
|
|
16
22
|
After a tag has been published, install that exact checksummed release on macOS or Linux:
|
|
17
23
|
|
|
@@ -28,9 +34,14 @@ published tag:
|
|
|
28
34
|
powershell -ExecutionPolicy Bypass -File .\scripts\install.ps1 -Version VERSION
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
The repository has no CI or release workflows; they were removed (see git history). Build, verify,
|
|
38
|
+
and publish artifacts with the [release procedure](../RELEASE.md). The publish verifier checks that
|
|
39
|
+
a version tag matches the workspace version.
|
|
40
|
+
Live E2E and hardware qualification remain separate operator checks; verify those receipts before tagging.
|
|
41
|
+
|
|
42
|
+
For manual assembly, build and test every claimed target in a clean
|
|
32
43
|
environment, place each executable and matching addon under `release-artifacts/<target>/`, run
|
|
33
|
-
`
|
|
44
|
+
`node scripts/assemble-release.mjs release-artifacts release` and `yarn release:verify:publish`, then attach
|
|
34
45
|
`release/SHA256SUMS` and binaries to the release. Publish the eight `@octocodeai/freellama-native-*` packages
|
|
35
46
|
first, followed by the exact-version `@octocodeai/freellama` and `@octocodeai/freellama-mcp-server` packages. Configure
|
|
36
47
|
registry credentials in the release environment; never store them in the repository.
|
|
@@ -52,9 +63,13 @@ swap, eviction churn, or unacceptable queueing.
|
|
|
52
63
|
| `OLLAMA_MAX_QUEUE` | Workload-specific, bounded value | Limits Ollama's internal queue independently of FreeLlama admission |
|
|
53
64
|
|
|
54
65
|
Do not set a global `OLLAMA_CONTEXT_LENGTH` merely to maximize the advertised window. Managed
|
|
55
|
-
FreeLlama tasks
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
FreeLlama text tasks estimate a sufficient context and can omit `num_ctx` when Ollama's known default
|
|
67
|
+
covers the request within the configured automatic bound. Explicit context requests send `num_ctx`.
|
|
68
|
+
A larger context and a larger `OLLAMA_NUM_PARALLEL` multiply K/V-cache memory. See
|
|
69
|
+
[context sizing](MONITORING.md#context-sizing-and-ollamas-defaults) for defaults and receipts.
|
|
70
|
+
Direct Ollama clients still follow the
|
|
71
|
+
server's context configuration. Current context documentation describes VRAM-tiered 4k/32k/256k
|
|
72
|
+
defaults while the FAQ still says 4096, so treat `/api/ps` `context_length` after load as authority.
|
|
58
73
|
|
|
59
74
|
`freellama doctor` returns `local_conservative_config_posture` as a **non-mutating** portable
|
|
60
75
|
starting profile. It names the source of each value (`observed_process` or `configuration_hint`),
|
|
@@ -63,11 +78,13 @@ parallel stream, and a finite internal queue before benchmarking. It also report
|
|
|
63
78
|
`host_runtime_signals` with source and permission scope. Treat unavailable GPU-memory, thermal, or
|
|
64
79
|
power signals as unavailable; do not substitute host RAM or a guessed value.
|
|
65
80
|
|
|
66
|
-
FreeLlama and Ollama have separate queues. FreeLlama
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
FreeLlama and Ollama have separate queues. FreeLlama caps retained managed waiters per backend with
|
|
82
|
+
`--max-queued-tasks`/`--cpu-max-queued-tasks`, then waits for at most
|
|
83
|
+
`--max-queue-wait-seconds`. An admitted request can then enter Ollama's internal queue,
|
|
84
|
+
which is bounded by `OLLAMA_MAX_QUEUE`. Raw compatibility traffic bypasses weighted managed
|
|
85
|
+
admission and enters the primary Ollama queue through a separate one-stream default cap in `serve`.
|
|
86
|
+
Set all limits from observed latency and overload behavior; changing one does not configure the
|
|
87
|
+
others.
|
|
71
88
|
|
|
72
89
|
The following flow shows where each production setting applies:
|
|
73
90
|
|
|
@@ -76,20 +93,22 @@ flowchart LR
|
|
|
76
93
|
C["Client"] --> FQ["FreeLlama admission<br/>weighted budget + wait deadline"]
|
|
77
94
|
FQ -->|"refused"| E503["503 server busy"]
|
|
78
95
|
FQ -->|"admitted"| OQ["Ollama queue<br/>OLLAMA_MAX_QUEUE"]
|
|
79
|
-
RAW["Raw /api/* or /v1/*"] -->
|
|
96
|
+
RAW["Raw /api/* or /v1/*"] --> RC["Raw stream cap<br/>default 1 in serve"]
|
|
97
|
+
RC -->|"refused"| E503
|
|
98
|
+
RC -->|"admitted until EOF/drop"| OQ
|
|
80
99
|
OQ --> S["Ollama scheduler<br/>loaded models + parallel streams"]
|
|
81
100
|
S --> M["Runner memory<br/>num_ctx x K/V cache"]
|
|
82
101
|
```
|
|
83
102
|
|
|
84
103
|
These values are conservative starting points, not universal constants. NVIDIA, AMD, Apple, and
|
|
85
104
|
CPU-only hosts must pass hardware validation before promotion. See
|
|
86
|
-
[Ollama and FreeLlama optimization](OLLAMA_SYSTEM_OPTIMIZATION.md) for the ownership boundary and
|
|
105
|
+
[Ollama and FreeLlama optimization](dev/OLLAMA_SYSTEM_OPTIMIZATION.md) for the ownership boundary and
|
|
87
106
|
[Run models on CPU and GPU](CPU_GPU_ROUTING.md) for device-specific controls.
|
|
88
107
|
|
|
89
108
|
Put the values in the service manager that owns each Ollama process: launchd on macOS, systemd or
|
|
90
109
|
the container definition on Linux, and the Windows service wrapper. Shell exports and
|
|
91
110
|
`launchctl setenv` are useful diagnostics but are login-session state, not a reboot-persistent
|
|
92
|
-
production configuration. After a real service restart, rerun `doctor` and `scripts/check.sh` and
|
|
111
|
+
production configuration. After a real service restart, rerun `doctor` and `skills/freellama/scripts/check.sh` and
|
|
93
112
|
require the same visible values before admitting work.
|
|
94
113
|
|
|
95
114
|
## Create the security and state files
|
|
@@ -122,6 +141,18 @@ Only physically verified warm samples are saved. A corrupt or unsupported snapsh
|
|
|
122
141
|
fail instead of silently discarding routing evidence. Use `--ephemeral-feedback` only for
|
|
123
142
|
disposable tests.
|
|
124
143
|
|
|
144
|
+
## Bound conversation history and residency
|
|
145
|
+
|
|
146
|
+
Scope histories and deferred jobs are process-local and are discarded on restart. Configure
|
|
147
|
+
`[scopes]` and `[warming]` limits in the runtime file from measured workload needs; finite history
|
|
148
|
+
bounds and automatic retention remain separate from host-memory reserves. Warm loads use the same
|
|
149
|
+
admission and placement checks as tasks. See [Scope history and model warming](SCOPES_AND_WARMING.md)
|
|
150
|
+
for expected revisions, forks, explicit history reads, and residency precedence.
|
|
151
|
+
|
|
152
|
+
Usage persistence is asynchronous best effort. Inspect pending, dropped, failed, and error evidence
|
|
153
|
+
in `status.usage_ledger`; task success does not prove its usage record reached disk. See
|
|
154
|
+
[Usage recording](MONITORING.md#record-usage) for replay, rotation, and shutdown boundaries.
|
|
155
|
+
|
|
125
156
|
## Configure MCP
|
|
126
157
|
|
|
127
158
|
Set these values in the MCP host environment:
|
|
@@ -143,7 +174,7 @@ direct Ollama requests, and managed FreeLlama tasks send their own `num_ctx`.
|
|
|
143
174
|
|
|
144
175
|
## Verify lifecycle and placement
|
|
145
176
|
|
|
146
|
-
`keep_alive:0`
|
|
177
|
+
`keep_alive:0` preserves placement evidence. FreeLlama temporarily holds the runner,
|
|
147
178
|
observes `/api/ps`, records eligible feedback, explicitly unloads it, and verifies that it is no
|
|
148
179
|
longer resident before returning. Inspect both `execution.observation` and
|
|
149
180
|
`execution.lifecycle.status`.
|
|
@@ -166,12 +197,9 @@ the Ollama process does not expose to FreeLlama.
|
|
|
166
197
|
Run compile and deterministic test checks from clean checkouts on Windows, Linux, and macOS. Live
|
|
167
198
|
accelerator acceptance is separate because build machines do not necessarily represent production
|
|
168
199
|
GPU drivers or memory topology. Prepare Apple Metal, NVIDIA Linux, AMD Linux, and NVIDIA Windows
|
|
169
|
-
hosts, then run
|
|
200
|
+
hosts, then run a hardware acceptance check directly on each host.
|
|
170
201
|
|
|
171
|
-
|
|
172
|
-
portable runner in `benchmark/hardware/run_validation.py` executes GPU coding and CPU embedding
|
|
173
|
-
concurrently, verifies physical processor receipts, checks admission receipts, and writes a JSON
|
|
174
|
-
artifact. Add `--vision-model` and `--vision-image` for that host's OCR/vision gate.
|
|
202
|
+
The portable hardware runners were removed from the repository; they remain in git history.
|
|
175
203
|
|
|
176
204
|
Do not mark a hardware row validated until its archived receipt says `verdict: accept`. Missing
|
|
177
205
|
hardware is an explicit release gap, not a result that documentation can waive.
|
|
@@ -188,7 +216,7 @@ Promote a release only when all conditions pass:
|
|
|
188
216
|
6. Restart testing proves feedback reloads and a corrupt snapshot fails startup.
|
|
189
217
|
7. Immediate unload reports verified pre-unload placement and verified post-unload absence.
|
|
190
218
|
8. Every claimed hardware row has a real archived acceptance receipt.
|
|
191
|
-
9. The MCP
|
|
219
|
+
9. The MCP schemas match the published tool surface and pass its context-budget contract.
|
|
192
220
|
|
|
193
221
|
Rollback by returning the listener to loopback, stopping the new service, and starting the prior
|
|
194
222
|
checksummed binary with the same policy and feedback snapshot. Never downgrade across an unsupported
|