@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/docs/CLI.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # CLI reference
2
2
 
3
- The `freellama` command exposes local diagnostics, deterministic model routing, managed task
4
- execution, benchmarking, and the Ollama-compatible proxy. The front page covers the shortest path;
5
- this page is the complete command map.
3
+ The `freellama` command starts and inspects the local management layer that agents use to offload
4
+ work. It exposes diagnostics, model routing, managed execution, resource controls, benchmarking,
5
+ and Ollama-compatible passthrough. Use the [README CLI section](https://github.com/bgauryy/FreeLlama/blob/main/README.md#or-use-the-cli) for first
6
+ use and this reference to look up commands and controls.
6
7
 
7
8
  ## Choose a command
8
9
 
@@ -11,34 +12,34 @@ flowchart TD
11
12
  Q{"What do you need?"}
12
13
  Q -->|"Prepare first use"| I["init"]
13
14
  Q -->|"Inspect this machine"| D["doctor or machine"]
14
- Q -->|"Inspect or choose a model"| M["models, route, or recommend"]
15
- Q -->|"Execute a managed request"| T["session, natural-route, or task"]
15
+ Q -->|"Inspect or choose a model"| M["models or route"]
16
+ Q -->|"Execute a managed request"| T["session or task"]
16
17
  Q -->|"Run the control plane"| S["serve"]
17
18
  Q -->|"Preserve only Ollama APIs"| P["proxy"]
18
- Q -->|"Measure or compare"| B["bench-all, run, or eval"]
19
- Q -->|"Create a routing policy"| E["policy-from-eval"]
20
- Q -->|"Compare CLI and MCP"| L["tools"]
19
+ Q -->|"Measure models"| B["bench-all"]
20
+ Q -->|"Write a routing policy"| PE["policy from-eval"]
21
21
  ```
22
22
 
23
23
  | Command | Purpose | Needs `freellama serve` |
24
24
  |---|---|---|
25
- | `init` | Inspect prerequisites and print a side-effect-free first-run plan | No |
25
+ | `init` | Inspect prerequisites and print a side-effect-free first-run plan with readiness flags | No |
26
26
  | `serve` | Run the control plane and Ollama-compatible proxy | Starts it |
27
27
  | `auth-token` | Create a new mode-0600 bearer-token file without printing the secret | No |
28
28
  | `models` | List installed models, capabilities, residency, and evidence | Yes |
29
29
  | `machine` | Print portable host RAM, CPU, OS, architecture, disk, and the local Ollama endpoint | Yes |
30
- | `session` | Create an affinity scope for related tasks | Yes |
30
+ | `status` | Live queues (also as a page at `http://127.0.0.1:11435/_freellama/ui`), current and adaptive limits, circuit breakers, loaded models, host memory, Ollama's effective settings, today's usage | Yes |
31
+ | `usage` | Task and token totals per day and per model (`--days`, default 7) | Yes |
32
+ | `config` | Effective runtime settings and the source of each; `--reload` re-reads the runtime file | Yes |
33
+ | `session` | Create model affinity for related tasks | Yes |
34
+ | `scope` | Create, inspect, fork, or delete bounded message history | Yes |
35
+ | `warm` | Warm an installed model through managed admission | Yes |
31
36
  | `route` | Choose a model and request profile without executing it | Yes |
32
- | `recommend` | Return an installed route or a reviewed installation plan | Yes |
33
- | `natural-route` | Convert natural language to a route intent locally, then route it | Yes |
34
37
  | `task` | Route and execute one nonstreaming task | Yes |
38
+ | `jobs` | List, inspect, cancel, or remove deferred tasks and warming operations | Yes |
35
39
  | `proxy` | Run only the Ollama-compatible retry and telemetry sidecar | No |
36
40
  | `bench-all` | Measure installed models by capability group | No |
37
- | `policy-from-eval` | Generate policy from quality-evaluation pass rates | No |
38
- | `tools` | Print MCP tools and their CLI equivalents | No |
41
+ | `policy from-eval` | Write a task policy (`platform.toml`) from a quality-evaluation aggregate and the installed tags | No |
39
42
  | `doctor` | Inspect Ollama, hardware, versions, and effective settings | No |
40
- | `run` | Run a frozen suite against one Ollama build | No |
41
- | `eval` | Compare the same frozen suite against stock and candidate builds | No |
42
43
 
43
44
  Run `npx @octocodeai/freellama <command> --help` for every accepted flag and enum value. The executable's help
44
45
  is authoritative; this page explains how the commands fit together.
@@ -46,13 +47,16 @@ is authoritative; this page explains how the commands fit together.
46
47
  ## Start the control plane
47
48
 
48
49
  ```bash
49
- npx @octocodeai/freellama serve --recommendation-catalog recommendations.example.toml
50
+ npx @octocodeai/freellama serve
50
51
  ```
51
52
 
52
53
  The default listener is `http://127.0.0.1:11435`, and the default Ollama upstream is
53
54
  `http://127.0.0.1:11434`. Use `--listen` and `--upstream` to change them. Nonloopback listeners
54
55
  require `--allow-remote` and a token from `--auth-token-file` or
55
- `FREELLAMA_AUTH_TOKEN_FILE`. Authentication applies to managed and passthrough routes.
56
+ `FREELLAMA_AUTH_TOKEN_FILE`. Authentication applies to managed and passthrough routes. The token
57
+ file must be a regular file, not a symlink, and hold one token of at least 32 bytes; surrounding
58
+ whitespace is trimmed. On Unix it must also be owner-only (mode 0600). Windows file permissions
59
+ (ACLs) are not checked, so protect the file with your user profile's permissions there.
56
60
 
57
61
  `serve` persists bounded adaptive feedback under the platform data directory by default. Override
58
62
  the path with `--feedback-file`; use `--ephemeral-feedback` only for disposable runs. See the
@@ -91,20 +95,80 @@ placement.
91
95
 
92
96
  ### Bound admission
93
97
 
94
- `--max-concurrent-tasks` is the primary/GPU cost budget, not a request count; it defaults to 2.
95
- `--cpu-max-concurrent-tasks` controls the independent CPU pool and defaults to 1. Embedding costs 1,
96
- chat costs 2, and vision costs 4 (capped to the selected backend's pool). A saturated GPU pool does
98
+ `--max-concurrent-tasks` is the primary/GPU cost budget, not a request count. Without a flag or
99
+ runtime-file value it defaults to 2 units per `OLLAMA_NUM_PARALLEL` slot of
100
+ the Ollama server (read from its process environment where visible; Ollama's own default is 1, so 2).
101
+ `freellama config` shows the effective value and where it came from.
102
+ `--cpu-max-concurrent-tasks` controls the independent CPU pool and defaults to 1. Default base costs
103
+ are embedding 1, chat 2, and vision 4. Embeddings multiply their base by `ceil(input_items/4)`;
104
+ the acquired charge is capped to the selected backend's pool. Configure overrides in `[task_costs]`;
105
+ see [monitoring controls](MONITORING.md#adaptive-concurrency). A saturated GPU pool does
97
106
  not consume CPU permits. `--max-queue-wait-seconds` defaults to 120; when no permit becomes
98
- available, FreeLlama refuses the task with HTTP 503 instead of waiting forever.
107
+ available, FreeLlama refuses the task with HTTP 503 (`admission_timeout`) instead of waiting forever.
108
+ A task can ask for a shorter wait with `max_wait_seconds` (`maxWaitSeconds` in MCP); it can never
109
+ exceed the configured one. Omit it to use the server's waiting budget.
110
+ That deadline covers weighted admission, host-resource waiting, and model-transition locking together.
111
+ `--max-queued-tasks` (default 16) and `--cpu-max-queued-tasks` (default 8) also bound how many
112
+ parsed requests can be retained per backend; a full queue receives 429 (`admission_queue_full`)
113
+ immediately, and cancelled clients release their waiter. Every capacity refusal carries a
114
+ `Retry-After` header and `retry_after_seconds`, estimated from queue depth and the backend's recent
115
+ task duration, so clients back off instead of retrying hot. Health exposes the queue depth, oldest wait, in-flight work, and
116
+ refusal/timeout/cancellation counters.
99
117
 
100
118
  These are conservative workload-unit defaults, not detected core or RAM counts. Tune them from
101
119
  queue-wait receipts and resident-memory observations on the target host. Ollama still controls
102
120
  decoding concurrency with `OLLAMA_NUM_PARALLEL`. It also owns a separate internal queue through
103
121
  `OLLAMA_MAX_QUEUE`: managed tasks enter that queue only after FreeLlama admission, while raw proxy
104
122
  traffic enters it directly. Start an unmeasured deployment with one loaded model and one parallel
105
- stream per Ollama process.
106
-
107
- `route`, `recommend`, and `task` accept
123
+ stream per Ollama process. In `serve`, raw passthrough defaults to one full-lifetime streaming
124
+ request; override with `--raw-proxy-max-concurrent-requests` only after measurement. A raw request
125
+ over the cap waits up to `--raw-queue-wait-seconds` (default 10) and is then refused with 429 and
126
+ `Retry-After`; `0` restores immediate refusal.
127
+
128
+ All of these, plus pinned models, idle eviction, adaptive concurrency, the circuit breaker, and
129
+ context sizing, can also live in a runtime file (`--runtime-config`) that `serve` re-reads when it
130
+ changes. See [Monitoring and live tuning](MONITORING.md). The standalone
131
+ `proxy` command keeps its cap opt-in for compatibility.
132
+
133
+ The local host-pressure gate reports low available RAM below 15% and clears it above 20% after two
134
+ healthy samples; minimum reserves are 1 GiB and 2 GiB, respectively. Tune the percentages with
135
+ `--resource-hold-available-percent` and `--resource-resume-available-percent`; the hold value must be
136
+ lower than the resume value, and neither can exceed 100. Health reports the policy, sampled signals,
137
+ unknown measurements, and reserved memory. These flags do not change Ollama or OS settings.
138
+
139
+ On macOS, low available RAM is advisory and never refuses a task. Effective available RAM is free
140
+ memory plus a bounded reclaimable estimate, so it can be far lower than what the OS can actually
141
+ reclaim. When it does not cover already-reserved bytes, the task's estimated bytes, and the reserve,
142
+ FreeLlama first unloads idle unpinned runners, then dispatches anyway: the receipt reports
143
+ `status: "admitted_low_memory_estimate"` and `assessment.memory_advisory: "below_reserve"` with
144
+ `required_with_reserve_bytes` and `effective_available_bytes`. Ollama and the OS decide whether the
145
+ load fits. On Linux, Windows, and other platforms, where available RAM already counts reclaimable
146
+ cache (and is the hard cap in a container), the same shortfall unloads idle runners and then holds the
147
+ new load with `held_insufficient_capacity` until capacity returns, refusing with 503 at its deadline.
148
+ OS memory pressure holds work on every platform. Active swapping and low RAM hold new loads only:
149
+ an already-resident runner adds no memory and stays admitted. CPU-load (one-minute load at or above
150
+ 1.5 per logical CPU) and thermal-throttling holds apply to CPU-assigned work and to cold loads, which
151
+ decode weights on the host cores and add a new heat source; a bounded request on a runner already
152
+ resident on the GPU neither waits for the cores nor cools the package by waiting, so it proceeds. The receipt's `resource_admission.assessment.held_by`
153
+ lists the holds that applied to the request.
154
+ Both `serve` and `proxy` accept `--resource-telemetry-policy`:
155
+
156
+ - `require-memory` (default): wait or refuse local inference when available RAM is unknown, including
157
+ raw requests with zero forecast bytes. Missing thermal data alone does not block this policy.
158
+ - `require-all`: require all signals applicable to the collector. The built-in Linux collector does
159
+ not provide OS pressure or thermal signals and marks those as unsupported; custom collectors must
160
+ provide them. Unsupported signals are not evidence of healthy hardware.
161
+ - `best-effort`: explicitly permit unknown telemetry unless an observed pressure hold is active.
162
+
163
+ Remote upstreams bypass local host policy. Raw metadata and empty unload requests remain available
164
+ during a hold. Route receipts separate `queue_readiness` from `resource_readiness`, and include
165
+ `resource_assessment` without acquiring a permit. Resource refusals return a human-readable `error`,
166
+ a stable `code`, and an object-valued `resource_admission`; timeout during metadata inspection reports
167
+ its phase and omits estimates that were not obtained.
168
+
169
+ See [resource admission](ARCHITECTURE.md#managed-task-execution) for scope and limitations.
170
+
171
+ `route` and `task` accept
108
172
  `--execution-preference auto|prefer-cpu|prefer-gpu`. This is a fallback-capable hint over models
109
173
  already assigned by the operator; it never rewrites raw passthrough and never makes an ineligible
110
174
  model eligible. Preview the route and inspect the `execution` receipt to confirm whether the hint
@@ -115,6 +179,10 @@ placement; the default `configured` accepts the operator assignment and observes
115
179
 
116
180
  Start with the read-only guided receipt, then inspect available models. `init` never pulls a model;
117
181
  it stops at exact-tag approval and prints the next prerequisite, serve, managed-task, and MCP steps.
182
+ Its `status` is `blocked` when Ollama is unavailable, `setup_required` when the managed service or
183
+ installed models are missing, and `ready` when all three are present. Separate `readiness` flags
184
+ identify the missing part. Readiness does not qualify a model for a particular task; use a route
185
+ preview to inspect eligibility and rejection reasons.
118
186
 
119
187
  ```bash
120
188
  npx @octocodeai/freellama init
@@ -135,14 +203,10 @@ npx @octocodeai/freellama route \
135
203
 
136
204
  Task kinds are `completion`, `coding`, `code-repair`, `tools`, `browser`, `vision`, `embedding`, and
137
205
  `long-context`. Objectives are `fastest`, `balanced`, and `quality`. `fastest` can use capability
138
- and local benchmark evidence alone; `balanced` and `quality` require a policy for that task.
139
-
140
- `recommend` is side-effect-free. If no installed model qualifies, it can return an installation
141
- plan from the reviewed recommendation catalog, but it never pulls a model.
142
-
143
- `natural-route` asks the configured local intent model to produce structured intent, validates that
144
- intent, and then invokes the same deterministic router as `route`. It does not let the intent model
145
- choose the final model directly.
206
+ and local benchmark evidence alone. Default `balanced` prefers eligible task-policy candidates;
207
+ without them it falls back to capability/context-compatible models and reports low confidence
208
+ and missing quality evidence. `quality` requires a policy unless you supply an explicit model.
209
+ An explicit minimum-confidence gate still refuses insufficient evidence in every objective.
146
210
 
147
211
  ## Execute tasks
148
212
 
@@ -157,19 +221,43 @@ Useful task options include:
157
221
 
158
222
  - `--model` for an exact installed model.
159
223
  - `--session` for affinity across related requests.
160
- - `--context-tokens` for a minimum context requirement.
224
+ - `--scope-id` and `--scope-revision` together for bounded message history.
225
+ - `--keep-alive` for an explicit residency duration.
226
+ - `--context-tokens` for the complete input and output context window (`num_ctx`).
161
227
  - repeatable `--required-capability` constraints.
162
228
  - repeatable `--image` paths for vision tasks.
163
229
  - `--input-file` for batched embedding input, one item per line.
164
230
  - `--min-confidence low|medium` to refuse insufficiently evidenced routes before generation.
231
+ - `--priority interactive|normal|background` for fair admission scheduling.
232
+ - `--max-wait-seconds` for a shorter admission/resource wait budget.
233
+ - `--timeout-seconds` for a total deadline including discovery, waiting, loading, and inference.
234
+ - `--stop-on-repetition` to stream the task and stop once the output repeats itself, keeping all
235
+ generated text.
236
+ - `--defer` to return a job ID immediately.
237
+
238
+ Inspect deferred work with `jobs`, retrieve a result with `jobs --id <uuid>`, and cancel one task
239
+ with `jobs --id <uuid> --cancel`. Remove one task with `jobs --id <uuid> --remove`: active work is
240
+ cancelled first, then its retained record and result are deleted. Use the exact ID returned at
241
+ submission; `--cancel` and `--remove` are mutually exclusive. The same operations are available
242
+ through MCP `task_jobs`.
243
+ Cancellation and removal wait for local execution permits to be released; they do not unload a shared model
244
+ or confirm that the physical runner has stopped.
245
+
246
+ Jobs stay in server memory: at most 64 receipts, 1 MiB per input, and 2 MiB per retained result or
247
+ error. Finished receipts expire after 10 minutes and can be evicted earlier to make room for new
248
+ work. A restart discards all jobs. Admission queue limits still apply, and deferred work can fail
249
+ after acceptance. See [monitoring](MONITORING.md) for states and waiting reasons.
165
250
 
166
251
  Create a session with `session`, then pass its identifier to related `route` or `task` calls. A
167
252
  route preview honors an existing affinity but does not create or change one. Only a successfully
168
253
  admitted task execution binds the session to its selected model. Reuse never bypasses capability,
169
254
  policy, or memory checks.
170
255
 
171
- The CLI has no keep-alive flag. MCP `run_task` accepts `keepAlive`: `"0"` unloads after the request,
172
- `"-1"` pins the runner, and omission leaves Ollama's default in place.
256
+ `task --keep-alive` and MCP `run_task.keepAlive` control residency: `"0"` requests immediate
257
+ unload, `"-1"` requests indefinite retention, and omission selects finite adaptive retention.
258
+ `session` retains affinity only; use `scope` for revision-protected message history and `warm`
259
+ for an admitted runner load. See [Scope history and model warming](SCOPES_AND_WARMING.md) for
260
+ input shapes, limits, and CLI examples.
173
261
 
174
262
  ## Earn medium routing confidence
175
263
 
@@ -178,7 +266,7 @@ benchmark record for the selected model.
178
266
 
179
267
  ```mermaid
180
268
  flowchart LR
181
- Q["Quality evaluation aggregate"] --> P["policy-from-eval"]
269
+ Q["Quality evaluation aggregate"] --> P["freellama policy from-eval"]
182
270
  P --> PF["platform.toml"]
183
271
  T["Local throughput benchmark"] --> BR["benchmark-report.json"]
184
272
  PF --> S["freellama serve"]
@@ -186,34 +274,64 @@ flowchart LR
186
274
  S --> C["Medium confidence for configured, measured routes"]
187
275
  ```
188
276
 
189
- Generate the policy from correctness data and the benchmark report from local runtime data:
277
+ Generate the policy from correctness data with `policy from-eval` and the benchmark report from
278
+ local runtime data:
190
279
 
191
280
  ```bash
192
- npx @octocodeai/freellama policy-from-eval \
193
- --aggregate benchmark/local/results/<model>/aggregate.json \
281
+ npx @octocodeai/freellama policy from-eval \
282
+ --aggregate aggregate.json \
194
283
  --task coding \
195
284
  --min-pass 0.8 \
196
285
  --out platform.toml
197
286
 
198
287
  npx @octocodeai/freellama bench-all --output benchmark-report.json
199
- npx @octocodeai/freellama serve --recommendation-catalog recommendations.example.toml
288
+ npx @octocodeai/freellama serve
200
289
  ```
201
290
 
202
- `serve` discovers `platform.toml` and `benchmark-report.json` in its working directory. Explicit
203
- `--policy-file` and `--benchmark-report` values take precedence.
291
+ `serve` resolves each file in this order: the explicit flag, its environment variable, the working
292
+ directory, then the per-user config directory (`$XDG_CONFIG_HOME/freellama/` or
293
+ `~/.config/freellama/`; `%APPDATA%\FreeLlama\` on Windows).
204
294
 
205
- `policy-from-eval` reads `pass_at_1`, not the throughput produced by `bench-all`. It refuses expired
206
- aggregates and fewer than three trials unless `--allow-smoke` is explicit, and it skips models that
207
- are not installed. This prevents speed data from being mislabeled as quality evidence.
295
+ | File | Flag | Environment variable | Discovered name |
296
+ |---|---|---|---|
297
+ | Task policy | `--policy-file` | `FREELLAMA_POLICY_FILE` | `platform.toml` |
298
+ | Benchmark report | `--benchmark-report` | `FREELLAMA_BENCHMARK_REPORT` | `benchmark-report.json` |
208
299
 
209
- ## Compare the CLI and MCP surfaces
300
+ A task policy file has this shape:
210
301
 
211
- ```bash
212
- npx @octocodeai/freellama tools
302
+ ```toml
303
+ schema_version = 1
304
+
305
+ [policies.code_repair]
306
+ qualified_models = ["qwen3.8:27b-mlx"] # best first; quality-qualified only
307
+
308
+ # Optional request defaults for one exact tag on this task: think and num_predict (>= 1).
309
+ [policies.code_repair.model_options."qwen3.8:27b-mlx"]
310
+ think = false
311
+ num_predict = 512
213
312
  ```
214
313
 
215
- The command prints the maintained parity map. MCP-only operations are `delegate_research` and the
216
- online `models { view: "library" }` view. CLI-only operations include `serve`, `proxy`, `session`,
217
- `recommend`, `natural-route`, `bench-all`, `policy-from-eval`, `run`, and `eval`.
314
+ `serve` rejects unknown fields, including `num_ctx`: context size is routing-owned, so set
315
+ `context_tokens` per request instead. Caller request options win over `model_options`, and
316
+ `think = true` applies only to models with the thinking capability. See the annotated
317
+ [platform.example.toml](https://github.com/bgauryy/FreeLlama/blob/main/platform.example.toml).
318
+
319
+ The MCP server autostarts `serve` with its own environment and an arbitrary working directory, so
320
+ put a machine-wide policy in the config directory or set the variables in the MCP client's `env`.
321
+ `serve` prints each file it picked up.
322
+
323
+ Replace `MODEL` with the directory containing your completed quality-evaluation aggregate.
324
+
325
+ `policy from-eval` reads `pass_at_1`, not the throughput produced by `bench-all`. It refuses
326
+ expired aggregates and fewer than three trials unless `--allow-smoke` is explicit, and it skips
327
+ models that are not installed on `--ollama-endpoint` (default `FREELLAMA_OLLAMA_ENDPOINT`, then
328
+ `http://127.0.0.1:11434`). This prevents speed data from being mislabeled as quality evidence.
329
+ It accepts the task kinds `route` accepts, with `-` or `_` (`code-repair` or `code_repair`), writes
330
+ to stdout unless `--out` is given, and reports a refusal as one `error: ...` line with exit status 1.
331
+
332
+ ## Compare the CLI and MCP surfaces
333
+
334
+ MCP-only operations are `delegate_research` and the online `models { view: "library" }` view.
335
+ CLI-only operations include `serve`, `proxy`, `bench-all`, `policy from-eval`, and `auth-token`.
218
336
 
219
- For the six MCP tool contracts, read the [MCP package reference](../packages/mcp/README.md).
337
+ For the MCP tool contracts, read the [MCP package reference](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/README.md).
@@ -1,10 +1,15 @@
1
1
  # Run models on CPU and GPU
2
2
 
3
- Use two Ollama processes when a large model should remain on the GPU while smaller helper models run
4
- on the CPU. FreeLlama assigns exact model tags to the secondary process, pins those managed requests
5
- with `num_gpu: 0`, and reports the selected backend in catalog and task responses.
3
+ To separate GPU work from CPU helpers, configure two Ollama processes and assign exact helper-model
4
+ tags to the secondary process. FreeLlama routes managed tasks within those assignments, applies
5
+ `num_gpu: 0` to CPU requests, and reports both the selected backend and observed processor placement.
6
6
 
7
- This configuration is useful for embeddings, intent interpretation, and other small helper models.
7
+ The calling agent submits tasks and placement preferences. FreeLlama coordinates admission,
8
+ memory checks, and model transitions for each backend; the operator configures the processes and
9
+ eligible tags. A configured CPU backend is intent: inspect the placement observation before
10
+ treating it as proof of CPU execution.
11
+
12
+ This configuration is useful for embeddings, short classification, and other small helper models.
8
13
  Benchmark large CPU workloads before adopting them. Apple silicon shares memory bandwidth; systems
9
14
  with discrete GPUs have different contention and transfer costs, so neither result transfers
10
15
  without measurement.
@@ -23,7 +28,9 @@ machine-specific:
23
28
 
24
29
  `doctor` reports `machine.memory_bytes` on macOS, Linux, and Windows. It reports
25
30
  `machine.unified_memory_bytes` only when unified memory is known; that compatibility field is not a
26
- VRAM estimate on discrete-GPU hosts. Model-library fit is therefore a host-memory preflight, and
31
+ VRAM estimate on discrete-GPU hosts. `machine.gpu` names the accelerator when the OS reports it
32
+ (Apple model and core count, or NVIDIA name and memory on Linux), and `performance_cpus` /
33
+ `efficiency_cpus` split hybrid CPUs on macOS. These are identity facts, not placement proof. Model-library fit is therefore a host-memory preflight, and
27
34
  actual accelerator placement must come from Ollama's resident-runner report.
28
35
 
29
36
  An agent can choose `auto`, `prefer_cpu`, or `prefer_gpu`, but it cannot invent topology. The
@@ -110,7 +117,10 @@ unsafe or ambiguous configurations:
110
117
  - A CPU model assignment without `--cpu-upstream`
111
118
  - Empty model names
112
119
  - The same socket expressed through aliases such as `localhost:11434` and `127.0.0.1:11434`
113
- - A non-loopback listener or upstream
120
+ - A nonloopback upstream
121
+
122
+ A nonloopback FreeLlama listener requires `--allow-remote` and bearer-token authentication.
123
+ See the [production runbook](PRODUCTION.md) for remote ingress requirements.
114
124
 
115
125
  Set independent admission budgets when the defaults do not fit the workload:
116
126
 
@@ -120,13 +130,18 @@ Set independent admission budgets when the defaults do not fit the workload:
120
130
  --cpu-upstream http://127.0.0.1:11436 \
121
131
  --cpu-model nomic-embed-text:latest \
122
132
  --max-concurrent-tasks 2 \
123
- --cpu-max-concurrent-tasks 1
133
+ --cpu-max-concurrent-tasks 1 \
134
+ --max-queued-tasks 16 \
135
+ --cpu-max-queued-tasks 8
124
136
  ```
125
137
 
126
138
  The defaults above admit one ordinary primary-backend chat (cost 2) and one CPU embedding (cost 1)
127
139
  at the same time. They are conservative workload units for the common `OLLAMA_NUM_PARALLEL=1`
128
140
  layout, not a profile of the development Mac. Increase them only after measuring queue wait,
129
141
  resident memory, and Ollama's own parallel setting on the target host.
142
+ Queue cardinality and wait time are separate bounds: excess waiters are refused immediately, while
143
+ an admitted waiter may remain until `--max-queue-wait-seconds`. Automatic backend selection checks
144
+ that the actual task cost fits the current slot snapshot before following historical speed.
130
145
 
131
146
  ## Let an agent express placement intent
132
147
 
@@ -194,12 +209,14 @@ The `execution` object separates the configured `backend`, requested compatibili
194
209
  post-run `observation`. The source is Ollama `/api/ps`; direct inspection remains useful:
195
210
 
196
211
  ```bash
197
- curl --silent http://127.0.0.1:11434/api/ps | jq '.models[] | {name, size_vram}'
198
- curl --silent http://127.0.0.1:11436/api/ps | jq '.models[] | {name, size_vram}'
212
+ curl --silent http://127.0.0.1:11434/api/ps | jq '.models[] | {name, size, size_vram}'
213
+ curl --silent http://127.0.0.1:11436/api/ps | jq '.models[] | {name, size, size_vram}'
199
214
  ```
200
215
 
201
- A fully CPU-loaded model reports `size_vram:0`; a fully GPU-loaded model reports positive resident
202
- VRAM. `observation.status` is `verified`, `mismatch`, or unavailable. Unknown, mixed, and mismatched
216
+ A fully CPU-loaded model reports `size_vram:0`; a fully GPU-loaded model reports positive VRAM
217
+ covering its resident `size`. Compare both values from the same `/api/ps` entry. Installed `/api/tags`
218
+ file bytes can differ from resident memory and cannot prove a mixed placement. Positive VRAM without
219
+ total resident size stays unknown. `observation.status` is `verified`, `mismatch`, or unavailable. Unknown, mixed, and mismatched
203
220
  samples are reported but excluded from adaptive feedback.
204
221
 
205
222
  ## Understand concurrency
@@ -208,10 +225,16 @@ Each backend has its own weighted admission pool and its own resident/shared and
208
225
  transition/exclusive lock. CPU and GPU model transitions therefore do not block each other, and a
209
226
  GPU burst cannot spend the CPU helper's permit:
210
227
 
228
+ Both pools also share local host-pressure sampling and forecast-memory reservations. Independent
229
+ queues do not imply independent RAM on a unified-memory machine. A request can wait for available
230
+ headroom even when its backend has a free weighted permit. Inspect `admission.resources` in health
231
+ and `execution.resource_admission` in task receipts. Unknown thermal or GPU measurements are not
232
+ reported as healthy readings. See [the execution architecture](ARCHITECTURE.md) for the complete gate.
233
+
211
234
  ```mermaid
212
235
  flowchart TD
213
236
  T["Managed task"] --> B{"Selected backend"}
214
- B -->|"GPU"| GA["GPU admission pool<br/>default 2 units"]
237
+ B -->|"GPU"| GA["GPU admission pool<br/>default 2 units per Ollama slot"]
215
238
  B -->|"CPU"| CA["CPU admission pool<br/>default 1 unit"]
216
239
  GA --> GL{"Resident?"}
217
240
  CA --> CL{"Resident?"}
@@ -229,16 +252,28 @@ FreeLlama can overlap requests across the two servers even when each Ollama proc
229
252
  `OLLAMA_NUM_PARALLEL=1`. Raising `OLLAMA_NUM_PARALLEL` affects parallel requests within one server
230
253
  and multiplies K/V-cache memory; it is a separate tuning decision. `OLLAMA_MAX_QUEUE` likewise
231
254
  bounds each Ollama process after FreeLlama admission. It does not replace either backend's weighted
232
- FreeLlama budget or queue-wait deadline.
255
+ FreeLlama budget, bounded waiter count, or queue-wait deadline. Raw passthrough uses a separate
256
+ one-stream default cap in `serve`; its permit is held until the streamed response ends or is dropped.
257
+
258
+ The runtime file's `[task_costs]` table can tune individual task-kind weights without increasing
259
+ the entire pool's ceiling. Default vision weight four can serialize two vision requests under a
260
+ four-unit budget even when Ollama has two slots. A lower weight requires a qualified workload;
261
+ it does not add engine slots or relax memory checks. See
262
+ [monitoring controls](MONITORING.md#adaptive-concurrency).
263
+ Mutating raw requests also require exclusive access to the primary backend's managed transition
264
+ lock and receive 503 while it is busy. Metadata GET/HEAD calls remain available. This prevents raw
265
+ inference or model lifecycle calls from overlapping a managed generation on that backend.
233
266
 
234
267
  ## Understand automatic feedback
235
268
 
236
269
  With `executionPreference: "auto"`, unpinned `fastest` and `balanced` work can select a backend from
237
- observed warm task duration. The loop is deliberately bounded:
270
+ comparable observed warm task duration. Learned hints require two eligible backends, explicit
271
+ context, and a known execution payload-control projection. A decision-only preview cannot supply
272
+ that payload projection and uses capacity and policy signals. The loop is bounded:
238
273
 
239
274
  ```mermaid
240
275
  flowchart LR
241
- X["Successful resident task"] --> O["Record duration by<br/>task + backend"]
276
+ X["Comparable warm serial task"] --> O["Record duration by<br/>task + backend + profile"]
242
277
  O --> N{"At least 3 samples<br/>on both backends?"}
243
278
  N -->|"No"| D["Keep deterministic default"]
244
279
  N -->|"Yes"| C{"More than 10% faster<br/>per work unit?"}
@@ -248,13 +283,25 @@ flowchart LR
248
283
  ```
249
284
 
250
285
  Generation compares decode nanoseconds per output token; embeddings compare total nanoseconds per
251
- input token. Buckets are model-specific and reset when the selected model changes. Only physically
252
- verified placement contributes; cold transitions and assignment mismatches do not. A difference
286
+ input token. Each task/backend has one current profile window, reset when identity changes.
287
+ Identity includes installed/resident digest, rate metric kind, explicit observed context, effective controls,
288
+ endpoint-attributed process settings, and serial admission class. Unknown or changed evidence,
289
+ cold transitions, and overlapping managed work supply no speed sample. A difference
253
290
  of 10% or less is treated as noise. Feedback never overrides an explicit model, session affinity,
254
291
  capability or policy guards, or the `quality` objective. The CLI persists the bounded, versioned,
255
- prompt-free aggregate snapshot atomically by default; `--ephemeral-feedback` opts into reset-on-
256
- restart behavior. `GET /_freellama/v1/health` exposes persistence status, sample counts, readiness,
257
- and per-backend admission capacity so an agent can inspect the loop instead of guessing.
292
+ prompt-free snapshot atomically by default; `--ephemeral-feedback` opts into reset-on-restart
293
+ behavior. Legacy aggregate fields survive loading but do not qualify learned hints. Health's
294
+ `decision_ready` describes the stored profile window; the current request must independently
295
+ match it before routing can use its speed. `GET /_freellama/v1/health` exposes profile identity,
296
+ profile sample counts, persistence status, and per-backend admission capacity. Physically verified
297
+ warm completions still contribute legacy duration diagnostics even when their interval cannot
298
+ qualify a speed-learning sample.
299
+
300
+ Configured processor intent, verified placement, and speed-learning eligibility remain separate
301
+ receipt fields. Missing endpoint-attributed process inspection disables learned hints and recovery,
302
+ including remote backends; ordinary routing, admission, and pressure/error safeguards still work.
303
+ Fresh process probes run for candidate serial learning or an eligible learned-route lookup, not
304
+ for pinned, quality-only, preview-only, or single-backend route selection.
258
305
 
259
306
  ## Interpret the measured Mac result
260
307
 
@@ -307,7 +354,6 @@ and `execution.lifecycle`; a failed unload is reported without discarding the co
307
354
  Prefer the following assignments:
308
355
 
309
356
  - Small embedding models
310
- - Lightweight intent models
311
357
  - Short extraction or classification helpers with measured CPU behavior
312
358
 
313
359
  Benchmark these assignments before adopting them:
@@ -318,7 +364,7 @@ Benchmark these assignments before adopting them:
318
364
 
319
365
  The local measurement receipt is written to
320
366
  `.octocode/evals/cpu-gpu-concurrency-benchmark.md`. Git intentionally ignores that path, so the
321
- trial table in "Interpret the measured result" carries the durable result while the local artifact
367
+ trial table in ["Interpret the measured Mac result"](#interpret-the-measured-mac-result) carries the durable result while the local artifact
322
368
  retains the full run detail.
323
369
 
324
370
  ## Troubleshoot the secondary backend
@@ -337,7 +383,7 @@ can also be unavailable until the secondary server returns. Raw passthrough to t
337
383
  continues to work because it does not depend on catalog discovery.
338
384
 
339
385
  For the surrounding runtime settings, see
340
- [Ollama and FreeLlama optimization](OLLAMA_SYSTEM_OPTIMIZATION.md). For all `serve` flags, see the
386
+ [Ollama and FreeLlama optimization](dev/OLLAMA_SYSTEM_OPTIMIZATION.md). For all `serve` flags, see the
341
387
  [CLI reference](CLI.md).
342
388
 
343
389
  ## Upstream sources