@octocodeai/freellama-mcp-server 0.10.0 → 0.12.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 (54) hide show
  1. package/CONFIGURATION.md +82 -3
  2. package/DEVELOPING.md +40 -9
  3. package/README.md +316 -213
  4. package/dist/agent-cli.js +16963 -0
  5. package/dist/index.js +4896 -4036
  6. package/dist/research/bash-agent.js +287 -108
  7. package/dist/research/coder-agent.js +455 -127
  8. package/dist/research/github-agent.js +276 -94
  9. package/dist/research/octocode-agent.js +276 -94
  10. package/docs/AGENT_CLI.md +234 -0
  11. package/docs/API.md +160 -0
  12. package/docs/ARCHITECTURE.md +158 -50
  13. package/docs/ASSESSMENT.md +131 -0
  14. package/docs/BENCHMARK.md +381 -0
  15. package/docs/BUILD_AND_NOTES.md +12 -3
  16. package/docs/CLI.md +62 -17
  17. package/docs/CPU_GPU_ROUTING.md +22 -9
  18. package/docs/DEFERRED_JOBS.md +17 -4
  19. package/docs/FEATURES.md +97 -43
  20. package/docs/LLAMACPP.md +133 -0
  21. package/docs/LOCAL_MODELS.md +26 -20
  22. package/docs/MODEL_FORMS_AND_RESULTS.md +14 -6
  23. package/docs/MODEL_INTROSPECTION.md +9 -2
  24. package/docs/MODEL_SELECTION.md +38 -9
  25. package/docs/MONITORING.md +110 -12
  26. package/docs/OLLAMA_REVIEW.md +226 -0
  27. package/docs/PRODUCTION.md +68 -25
  28. package/docs/PROMPTS.md +119 -0
  29. package/docs/README.md +22 -6
  30. package/docs/RELIABILITY.md +207 -0
  31. package/docs/RUST_RESOURCE_AUDIT.md +65 -0
  32. package/docs/SCOPES_AND_WARMING.md +12 -5
  33. package/docs/TESTING.md +112 -6
  34. package/docs/TUNING.md +12 -8
  35. package/docs/assets/benchmark-results-2026-11-14.html +4 -0
  36. package/docs/assets/tool-calling-2026-11-14-bonsai-9b/TABLE.md +14 -0
  37. package/docs/assets/tool-calling-2026-11-14-lfm3-vl/TABLE.md +14 -0
  38. package/docs/assets/tool-calling-table.md +14 -0
  39. package/docs/cookbooks/README.md +9 -2
  40. package/docs/cookbooks/batch-text.md +4 -2
  41. package/docs/cookbooks/classify.md +19 -3
  42. package/docs/cookbooks/coding.md +13 -4
  43. package/docs/cookbooks/find-code.md +8 -3
  44. package/docs/cookbooks/jobs.md +8 -8
  45. package/docs/cookbooks/memory-and-caching.md +2 -2
  46. package/docs/cookbooks/ocr.md +3 -3
  47. package/docs/cookbooks/research-agent.md +32 -2
  48. package/docs/cookbooks/speech-to-text.md +1 -1
  49. package/docs/cookbooks/sweep.md +4 -1
  50. package/docs/octocode/GITHUB.md +4 -4
  51. package/docs/octocode/LOCAL.md +5 -4
  52. package/native/index.d.ts +1 -1
  53. package/package.json +6 -6
  54. package/docs/COMPARISON.md +0 -40
@@ -0,0 +1,207 @@
1
+ # Result checks and local tool-calling evidence
2
+
3
+ `check:` lines are review hints. A clean result does not establish factual correctness, a safe
4
+ edit, an appropriate tool choice, or authority to execute a call. This page keeps two separate
5
+ measurements: deterministic accuracy of those hints and observed tool-calling behavior of exact
6
+ installed local models. [Machine-local model calibration](MODEL_SELECTION.md#turn-measurements-into-routing-evidence)
7
+ measures another concern: which eligible model has local performance and policy evidence. Neither substitutes for the calling agent's verification.
8
+
9
+ ## Accuracy of result checks
10
+
11
+ The versioned [30-case labeled corpus](../scripts/reliability/check-fixtures.mjs) tests human-labeled
12
+ review risks against the actual exported check functions. Every input, label, emitted check and
13
+ outcome from the original checker is in [the baseline report](assets/result-check-accuracy.json);
14
+ the repaired checker has a separate [numeric-tokens-v2 report](assets/result-check-accuracy-v2.json). These synthetic
15
+ regression cases include deliberate blind spots; their proportions do not estimate production
16
+ accuracy. The labels and detector thresholds were visible during implementation.
17
+
18
+ A positive means a specific warning about a review-worthy risk, rather than any nonempty `check:`
19
+ line. Generic spot-check reminders and structural success messages are not positive detections.
20
+ Unsupported tool-schema keywords produce an explicit unchecked warning and count as a review risk.
21
+
22
+ The original checker baseline:
23
+
24
+ | Review-risk family | Cases | True positives | False positives | True negatives | False negatives | Precision | Recall |
25
+ |---|---:|---:|---:|---:|---:|---:|---:|
26
+ | Source factual risk | 12 | 2 | 2 | 2 | 6 | 50% | 25% |
27
+ | Instructions in input data | 4 | 1 | 1 | 1 | 1 | 50% | 50% |
28
+ | Dropped extraction values | 4 | 1 | 0 | 1 | 2 | 100% | 33.3% |
29
+ | Tool structural risk | 10 | 8 | 0 | 2 | 0 | 100% | 100% |
30
+
31
+ Precision is `TP / (TP + FP)`; recall is `TP / (TP + FN)`. Empty denominators are unknown. Do not
32
+ combine the families into one reliability score: they ask different questions.
33
+
34
+ The 2026-11-15 numeric-token repair fixes two existing labeled cases: `8080` no longer matches a
35
+ source token `18080`, and comma grouping is normalized in both directions. Human risk labels and
36
+ the original report are unchanged. On the same 12 source-risk cases, the repaired checker has
37
+ TP 3, FP 1, TN 3, FN 5: precision 75%, recall 37.5%. Other family counts are unchanged. These cases are
38
+ now regression evidence after fixes, not held-out confirmation or production accuracy. The
39
+ remaining genuine misses stay visible in both reports. Exact token matching can also warn about
40
+ valid derived counts such as `×2` and `×1`; the checker does not verify arithmetic or counting.
41
+
42
+ The source check looks for short backtick spans and numeric tokens somewhere in the supplied
43
+ files. Reversed relationships, incorrect negation, unquoted invented names,
44
+ and quotes longer than 60 characters can escape it. Correct derived totals and other formatting changes can still trigger warnings. The extraction check recognizes certain identifiers left null, but does
45
+ not compare a wrong non-null value. The injection check catches selected instruction patterns;
46
+ benign quotations can trigger it and paraphrases can evade it. A warning is a reason to inspect
47
+ the answer, not proof of hallucination or a successful attack.
48
+
49
+ Tool checks reject malformed native `response.message.tool_calls` containers and nonstring
50
+ function names, and flag duplicate provided names as ambiguous. They validate known names, JSON-object arguments, nested properties, required fields,
51
+ additional properties, array items, JSON types, enums, constants, numeric bounds and string/array
52
+ length bounds. Objects allow additional properties unless their schema forbids them. Unsupported
53
+ keywords, including `$ref`, `pattern`, `format`, `oneOf` and `anyOf`, are explicitly unchecked.
54
+ Malformed values for supported validation keywords also produce unchecked warnings.
55
+ This is a bounded structural checker, not a complete JSON Schema implementation or a tool policy.
56
+ A structurally valid call can still name the wrong city or perform an unauthorized action.
57
+
58
+ Reproduce the report with no Ollama, downloads or inference:
59
+
60
+ ```sh
61
+ node scripts/reliability/result-check-accuracy.mjs --out /tmp/result-check-accuracy.json
62
+ node --test scripts/reliability/*.test.mjs
63
+ ```
64
+
65
+ The output file must not already exist. The offline test compares the generated report to the
66
+ versioned current artifact and checks that the baseline human labels remain unchanged and keeps known false positives and false negatives visible. After changing
67
+ a detector, review changed labels and outcomes, regenerate into a new file, then replace the
68
+ artifact deliberately. Other unit tests cover confidence bands, nearest-match reminders,
69
+ SEARCH/REPLACE matches, padding, fallback receipts and vision heuristics; these are contracts,
70
+ not measured factual accuracy of those families.
71
+
72
+ ## Public tool-calling smoke suite
73
+
74
+ The [runner](../scripts/reliability/tool-calling.mjs) calls Ollama directly with the frozen
75
+ [tool schemas, prompts and deterministic grader](../scripts/reliability/tool-cases.mjs). It tests:
76
+
77
+ - Choosing a weather tool among alternatives and returning the tool result.
78
+ - Integer arguments and a second assistant turn after arithmetic output.
79
+ - Nested object and array arguments under closed schemas.
80
+ - Avoiding tools for a plain response and asking for a missing city.
81
+ - Declining an unavailable action without inventing a tool.
82
+ - Treating an instruction inside a simulated tool result as untrusted data.
83
+
84
+ No real tool action is performed. A simulated result is supplied only after the expected tool
85
+ and exact argument values match. The grader requires the requested final text, so inspect the raw
86
+ transcript when a semantically similar answer fails. Passing the seven public cases once is a
87
+ smoke result, not a population reliability estimate, a safety guarantee, or a model ranking.
88
+ The runner does not measure FreeLlama admission, routing, MCP transport, or physical CPU/GPU
89
+ placement. Tool choice and argument columns are first-turn outcomes on expected-call cases;
90
+ follow-up is conditional on an accepted first call. Complete-case success includes both turns.
91
+
92
+ [Ollama's tool-calling contract](https://docs.ollama.com/capabilities/tool-calling) leaves execution
93
+ to the caller: preserve the assistant message, append each `{role:"tool", tool_name, content}`
94
+ result, and send the updated conversation with the tools. It also documents parallel calls,
95
+ agent loops and streamed accumulation. The present suite measures only single-call first turns
96
+ and one follow-up; it has no live evidence for parallel calls, longer dependent loops, streamed
97
+ tool calls or real tool side effects. [The chat API](https://docs.ollama.com/api/chat) defines the
98
+ native `message`, `done` and tool fields used by the grader.
99
+
100
+ Each run records exact installed tags, manifest digests, sizes, capabilities, Ollama and Node
101
+ versions, harness/case SHA-256 hashes, Git commit and dirty files, host memory/load before and
102
+ after, residency, all request/response bodies, errors and every planned denominator. An Ollama
103
+ manifest digest identifies the tag manifest; it is not a GGUF file hash. No retry is hidden.
104
+ New runs also record an acquisition UUID and strict grader version. The `tool-strict-v2` grader
105
+ rejects malformed call containers and requires a question or request for the missing city rather
106
+ than accepting any city mention. It is still a bounded oracle, not full semantic verification.
107
+ Legacy reports replay their original v1 grader so historical scores are not silently rewritten.
108
+ Infrastructure errors and timeouts remain non-passes in complete-case denominators; cases not
109
+ attempted after a stop remain visible. HTTP abort does not prove inference has stopped.
110
+
111
+ The runner requires an exact installed tag that reports `tools` capability. It never pulls,
112
+ unloads, deletes, or starts a service. Requests are sequential with context 4096, temperature 0,
113
+ seed 42, `think:false`, at most 256 generated tokens and a 45-second request timeout by default.
114
+ `keep_alive:"60s"` lets Ollama expire the warmed model naturally. Response bodies are capped at
115
+ 2 MiB. Inspect current available memory, residency and other workloads before starting; disk
116
+ size does not establish runtime fit. Check final residency before a subsequent run, especially
117
+ after a timeout.
118
+
119
+ ```sh
120
+ # Read-only inventory; every model remains unmeasured.
121
+ node scripts/reliability/tool-calling.mjs --inventory --out /tmp/tool-inventory
122
+ # Explicit bounded inference on one exact installed tag; output directory must be new.
123
+ node scripts/reliability/tool-calling.mjs --model 'EXACT_INSTALLED_TAG' --out /tmp/tool-run
124
+ # A declared repeat count runs every case that many times without automatic retries.
125
+ node scripts/reliability/tool-calling.mjs --model 'EXACT_INSTALLED_TAG' --repeats 3 --out /tmp/tool-repeat
126
+ ```
127
+
128
+ `--endpoint`, `--timeout-ms` and `--max-tokens` override the defaults and are preserved in the
129
+ manifest. Changing them changes the evaluation conditions. Keep all audit files when sharing a
130
+ result: `manifest.json`, `trials.jsonl`, `summary.json`, `TABLE.md`, and `final-state.json`; failed
131
+ preflight runs retain `fatal.json`. The offline runner tests use fake HTTP responses and prove
132
+ harness contracts only.
133
+
134
+ ## Measured on 2026-11-14
135
+
136
+ Ollama 0.40.15 on macOS arm64, Node v26.4.0, 32 GiB RAM and 12 logical CPUs. Each selected model
137
+ ran the same seven public cases once, with identical harness/case hashes and the default request
138
+ settings above. Both started with no resident Ollama models. Estimated available memory was
139
+ 11.9 GB before LFM3-VL and 6.7 GB before Bonsai; macOS pressure level was 1. Other development
140
+ work ran on the host and swap was already in use, so these runs support no latency or resource
141
+ comparison. Models expired naturally; no pull, explicit unload or deletion was issued.
142
+
143
+ | Exact installed tag | Complete strict cases | Tool choice | Exact arguments | Follow-up | Evidence |
144
+ |---|---:|---:|---:|---:|---|
145
+ | `lfm3-vl:2b-q4_K_M` | 5/7 | 4/4 | 4/4 | 3/4 | [Raw run](assets/tool-calling-2026-11-14-lfm3-vl/trials.jsonl), [manifest](assets/tool-calling-2026-11-14-lfm3-vl/manifest.json) |
146
+ | `bonsai-2:9b` | 6/7 | 4/4 | 4/4 | 3/4 | [Raw run](assets/tool-calling-2026-11-14-bonsai-9b/trials.jsonl), [manifest](assets/tool-calling-2026-11-14-bonsai-9b/manifest.json) |
147
+ | `bonsai-2:27b` | — | — | — | — | Unmeasured |
148
+ | `nimble-v3:9b-q4_K_M` | — | — | — | — | Unmeasured |
149
+ | `lfm3-omni:2b-q4_K_M` | — | — | — | — | Unmeasured |
150
+ | `hf.co/openbmb/MiniCPM-OCR-1.0-gguf:Q4_K_M` | — | — | — | — | Unmeasured |
151
+ | `hf.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-4GB:Q4_K_M` | — | — | — | — | Unmeasured |
152
+ | `embeddinggemma-2:740m-q8_0` | — | — | — | — | Unmeasured |
153
+ | `lfm3-audio:2b-q4_K_M` | — | — | — | — | Unmeasured |
154
+ | `phonon:en` | — | — | — | — | Unmeasured |
155
+ | `strands-decider:2b-nvfp4` | — | — | — | — | Unmeasured |
156
+ | `nomic-embed-text:v1.5` | — | — | — | — | Unmeasured |
157
+
158
+ The [generated full table](assets/tool-calling-table.md) includes every installed tag and its
159
+ manifest digest. A dash means no trial was run; installed status and advertised tools support
160
+ are not reliability evidence. Non-tool models remain unmeasured rather than receiving a score
161
+ for a task they do not advertise.
162
+
163
+ All four expected first tool calls and arguments were correct for both measured models. Both
164
+ also avoided unnecessary calls in all three non-call cases. Strict weather continuation failed
165
+ because LFM3-VL returned `WEATHER:18` and Bonsai returned `WEATHER:18°C`, while the prompt requested
166
+ exactly `WEATHER:18C`. LFM3-VL's other failure was an appropriate prose refusal to delete a file
167
+ instead of the requested exact `UNAVAILABLE`. These are format failures, not observed dangerous
168
+ tool execution or wrong weather values. The prompt-in-tool-result case passed once per model;
169
+ that does not establish general injection resistance. The small exposed suite cannot rank the
170
+ models or justify broad reliability percentages.
171
+
172
+ Regrade the raw responses and regenerate the combined table without inference:
173
+
174
+ ```sh
175
+ node scripts/reliability/tool-report.mjs \
176
+ --run docs/assets/tool-calling-2026-11-14-lfm3-vl \
177
+ --run docs/assets/tool-calling-2026-11-14-bonsai-9b \
178
+ --out /tmp/tool-calling-table.md
179
+ ```
180
+
181
+ The reporter checks recorded initial prompts, tool schemas, model tags and options against the
182
+ frozen case definition and manifest, and verifies every assistant/tool-result continuation. A
183
+ manifest-recorded `--max-tokens` override is allowed; an unexplained changed request is rejected.
184
+ It replays the recorded strict grader, verifies summaries and rejects pooling incompatible
185
+ harness/case hashes, runtime versions, request limits or strict grader versions. Copied directory
186
+ paths cannot multiply evidence: duplicate acquisitions are rejected by recorded run identity.
187
+ These checks validate retained transcripts; hashes and captured requests do not independently
188
+ attest physical model execution, unchanged weights, host identity or an untampered acquisition.
189
+ Ordinary offline tests reproduce the checked-in table from the raw artifacts.
190
+
191
+ ## Post-hoc interpretation of strict failures
192
+
193
+ The separate [`tool-format-adjudication-v1` report](assets/tool-outcomes-v1.json) applies narrow
194
+ deterministic rules to the same 14 retained responses. It preserves all 11 historical strict
195
+ passes and identifies the three failures described above as format-only: the reference Celsius
196
+ temperature with an omitted/degree suffix, or a whole-response explicit inability to delete files
197
+ without a tool call. Wrong temperatures, different units, extra calls, contrary claims or text
198
+ outside those rules remain unresolved. The rules were written after reading these failures;
199
+ this is explanatory regression evidence, not a new inference, an independent semantic quality
200
+ study, a replacement score or a finding that every strict pass is factually correct.
201
+
202
+ ```sh
203
+ node scripts/reliability/tool-outcomes.mjs \
204
+ --run docs/assets/tool-calling-2026-11-14-lfm3-vl \
205
+ --run docs/assets/tool-calling-2026-11-14-bonsai-9b \
206
+ --out /tmp/tool-outcomes-v1.json
207
+ ```
@@ -0,0 +1,65 @@
1
+ # Rust resource and panic audit
2
+
3
+ The resource boundary now measures Windows physical-memory headroom and requires that observation
4
+ by default. It also propagates telemetry reader-thread creation failures after killing and reaping
5
+ the child process. Test assertions using `unwrap()` were retained.
6
+
7
+ ## Scope and findings
8
+
9
+ The initial production-library scan used `cargo clippy -p freellama-core --lib -- -W clippy::unwrap_used
10
+ -W clippy::expect_used -W clippy::await_holding_lock`. It found no production `unwrap()` or
11
+ `await_holding_lock` diagnostics and 30 explicit `expect()` sites at that audit stage. This is a lint census, not proof
12
+ that every panic or deadlock is impossible. Deep review covered resource sampling, reservation
13
+ accounting, and the holder cache; additional lock spot checks covered raw admission, scope history,
14
+ telemetry, and the SQLite store.
15
+
16
+ | Boundary | Finding and disposition |
17
+ |---|---|
18
+ | [Resource governor](../packages/rust-core/src/platform/resources/governor.rs) | Its three `expect()` calls state private invariants: the constant default policy validates, a sampling handle is installed before it is awaited, and a sample is saved before the cache is read. The Tokio state mutex serializes these transitions. Keep the explicit invariants. |
19
+ | Governor synchronous accounting mutex | All lock acquisitions recover poisoned guards. They protect generation/reservation updates and do not span an await. A fault-injection test poisons the lock and verifies both permit release and conservative reservation decisions. |
20
+ | Governor sampling await | The Tokio mutex intentionally spans the shared sampling handle await so cancellation leaves one reusable in-flight sample. Existing cancellation and concurrent-reservation tests cover the affected behavior. A panicking sampler becomes `sampler_failed` with unknown memory and refused admission. |
21
+ | [Bounded subprocess](../packages/rust-core/src/platform/resources/sampling.rs) | Reader creation previously used `thread::spawn`, which can panic after a child was started. It now uses fallible `Builder::spawn`; failure kills/reaps the child and returns the I/O error. Reader-buffer locks recover poison and guard only bounded buffer updates. Existing deadline, output-cap, and inherited-pipe tests pass. OS thread-exhaustion injection was not run. |
22
+ | [Memory holders](../packages/rust-core/src/platform/resources/holders.rs) | The diagnostic cache recovers poisoned locks and releases its mutex before OS commands and `spawn_blocking` awaits. Holder output does not authorize admission. |
23
+ | Store, telemetry, scope and raw-admission spot checks | Their synchronous mutex helpers recover poisoned guards. Inspected async paths release these guards before awaits. This does not establish every application-level lock ordering or runtime contention property. |
24
+
25
+ ## Windows memory contract
26
+
27
+ [The Windows collector](../packages/rust-core/src/platform/resources/windows.rs) runs one
28
+ unprivileged, noninteractive PowerShell CIM query with a 1.5-second command deadline and the shared
29
+ 64-KiB output cap. It accepts only successful command output containing one JSON object.
30
+ [Microsoft defines](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-operatingsystem)
31
+ `TotalVisibleMemorySize` and `FreePhysicalMemory` in KiB. Conversion uses checked multiplication;
32
+ the total must be positive and available memory must not exceed it. Missing, malformed, negative,
33
+ fractional, overflowing, or inconsistent readings cannot authorize a load under `require-memory`.
34
+ Observed zero remains zero.
35
+
36
+ The collector does not invent CPU-load, OS-pressure, thermal, swap, or GPU observations. These stay
37
+ unknown, so `require-all` holds work on Windows. Operators can explicitly select `best-effort` for
38
+ unknown-memory admission. See [monitoring](MONITORING.md) for the receipt fields and policy.
39
+
40
+ ## Verification and limits
41
+
42
+ `cargo test -p freellama-core --lib platform::resources` passed 59 tests with one live-host test
43
+ ignored on the macOS development host. The new fixtures exercise valid Windows conversion,
44
+ unknown metrics, bad/missing/overflowing input, zero headroom, policy defaults, poisoned accounting,
45
+ and sampler panic. Those tests are grouped in
46
+ [`resources/tests/windows.rs`](../packages/rust-core/src/platform/resources/tests/windows.rs) and
47
+ [`resources/governor/audit_tests.rs`](../packages/rust-core/src/platform/resources/governor/audit_tests.rs);
48
+ the existing resource contracts remain enabled in `resources/tests.rs`. The strict production-library check
49
+ `cargo clippy -p freellama-core --lib -- -D clippy::unwrap_used -D clippy::await_holding_lock`
50
+ passed. A subsequent local workspace check with
51
+ `cargo clippy --workspace --all-targets --all-features -- -D warnings` also passed after engine work
52
+ settled; that gate does not enable `expect_used` or prove every `expect()` safe.
53
+ The explicit read-only live-host smoke also passed on macOS in 60 ms after the subprocess change.
54
+
55
+ The [CI workflow](../.github/workflows/ci.yml) configures the actual PowerShell/CIM smoke on
56
+ Windows, in addition to cross-platform parser fixtures. No completed hosted Windows result is
57
+ recorded by this local audit. Actual Windows startup, CIM permissions, command timing, and hardware
58
+ behavior need that run. Reproduce the read-only host smoke there with:
59
+
60
+ ```sh
61
+ cargo test -p freellama-core --lib live_host_resource_observation -- --ignored --nocapture
62
+ ```
63
+
64
+ No model was loaded, downloaded, or executed for these checks. The audit does not claim complete
65
+ panic freedom, measured contention, or live Windows GPU qualification.
@@ -5,6 +5,11 @@ model needs preparation before related work. FreeLlama manages these controls th
5
5
  admission and memory checks as task execution. The calling agent owns conversation instructions,
6
6
  task dependencies, and verification.
7
7
 
8
+ Scope history is a core facility; the selected engine still validates every retained message.
9
+ The [llama.cpp adapter](LLAMACPP.md) accepts only text messages and its fixed context contract.
10
+ The warming, eviction, preload and adaptive keep-alive behavior in this guide applies to Ollama;
11
+ external-engine warm and unload requests are refused.
12
+
8
13
  ## Ownership
9
14
 
10
15
  | State | Owner | Lifetime and meaning |
@@ -85,8 +90,9 @@ not append history.
85
90
 
86
91
  Limits reject an oversized transcript instead of silently deleting earlier instructions. If a task
87
92
  cannot fit, narrow its input, create a compact replacement scope, or fork a suitable snapshot. The
88
- caller owns any semantic summary and its verification. Stored history also contributes to managed
89
- context sizing; the selected model's context boundary still applies. Scoped image or audio input
93
+ caller owns any semantic summary and its verification. Stored history also contributes to Ollama-managed
94
+ context sizing; the selected model's context boundary still applies. llama.cpp uses its configured
95
+ fixed window and does not verify exact input-token fit. Scoped image or audio input
90
96
  requires explicit `context_tokens` (`contextTokens` through MCP). Its context receipt estimates
91
97
  text and reports total multimodal token cost as unknown. Encoded media is retained in history,
92
98
  but its bytes are not counted as text tokens. Text plus the finite output reserve must fit the
@@ -226,8 +232,9 @@ The runtime file's `[preload]` table loads models without a caller asking:
226
232
  say which devices that Ollama process may allocate on, and nothing in FreeLlama verifies it
227
233
  (`gpu_capacity_scope` stays `host_aggregate_not_verified_for_backend`), so a speculative load
228
234
  could displace work on a pool it cannot see. The skip reason is `GPU device eligibility for this
229
- Ollama backend is unverified` (`opportunistic_warm_skipped`). Unified-memory hosts and the CPU
230
- backend, where host memory is the budget, still predict. Explicit warms, startup preloads and
235
+ Ollama backend is unverified` (`opportunistic_warm_skipped`). A local primary backend on a
236
+ unified-memory or CPU-only host can still predict using host memory as its budget. A dedicated
237
+ secondary CPU backend does not predict. Explicit warms, startup preloads and
231
238
  managed tasks on a discrete GPU run through ordinary admission.
232
239
 
233
240
  Each preload is a background warm under the usual admission, memory and pressure rules, and the
@@ -244,7 +251,7 @@ npx @octocodeai/freellama warm --model MODEL_TAG \
244
251
 
245
252
  ## Adaptive keep-alive
246
253
 
247
- When a managed request omits `keep_alive`, FreeLlama selects a finite duration from measured reuse
254
+ When an Ollama-managed request omits `keep_alive`, FreeLlama selects a finite duration from measured reuse
248
255
  and load cost, within the runtime `[warming]` bounds. Explicit per-call values take precedence,
249
256
  including immediate unload (`"0"`) and indefinite residency (`"-1"`). Use
250
257
  `--keep-alive=-1` in the CLI so the negative value remains attached to its flag. The configured eviction policy and available
package/docs/TESTING.md CHANGED
@@ -25,7 +25,7 @@ yarn build
25
25
  ```
26
26
 
27
27
  The root build compiles the host Rust release binary, NAPI addon, and MCP JavaScript bundles
28
- (server and research adapters). The native `.node` addon remains external to the JavaScript bundle because it is selected
28
+ (server, the agent CLI behind `freellama run`, `chat`, `gateway`…, and research adapters). The native `.node` addon remains external to the JavaScript bundle because it is selected
29
29
  by platform triple at runtime. Published packages resolve it from an OS/CPU/libc-specific optional
30
30
  dependency rather than compiling Rust during installation.
31
31
 
@@ -61,6 +61,64 @@ lifecycle test is disabled unless the operator explicitly sets `FREELLAMA_TEST_P
61
61
  `qwen2.5:0.5b` and `FREELLAMA_TEST_PULL_SIZE_BYTES` to the exact reported download size. The test
62
62
  rechecks that size and reads every installed-model page before allowing the round trip.
63
63
 
64
+ ## Continuous integration
65
+
66
+ [`.github/workflows/ci.yml`](../.github/workflows/ci.yml) configures the deterministic tiers on every push,
67
+ every pull request and on demand (`gh workflow run CI`), on Ubuntu, macOS and Windows:
68
+ `yarn install --immutable`, `yarn lint:rust` (Ubuntu), `yarn build`, `yarn typecheck`,
69
+ and `yarn test:rust`. Ubuntu and macOS run the full `yarn test:js` and `yarn test:release`; the latter's fake
70
+ executable fixtures require a POSIX shell. The native build must reproduce the committed TypeScript
71
+ declarations. Windows additionally runs the read-only live host-resource observation to exercise
72
+ PowerShell/CIM, beyond parser fixtures.
73
+
74
+ Windows runs the workflow's explicit JavaScript allowlist: launcher and PowerShell installer,
75
+ agent CLI, gateway/auth/TLS/response limits, job calibration/selection, and result/tool-call checker
76
+ contracts. Their execution uses Node, local HTTP/TLS or PowerShell fixtures, not Unix shell tools.
77
+ This is a portable-contract lane, not the full JavaScript suite: it excludes the POSIX research and
78
+ coder execution/path suites, the shell installer, and the benchmark/reliability script suites.
79
+ In particular, coder execution names `/bin/sh`; restricted research shell discovery and workspace
80
+ path semantics remain POSIX-oriented. Git Bash being installed is not a native Windows adapter
81
+ port. Schema/checker coverage does not qualify those adapters on Windows. Linux/macOS retain the
82
+ complete suites; native Windows adapter support needs its own implementation and validation.
83
+ The workflow selects Node 22 and the stable Rust channel; local development uses the compiler
84
+ in `rust-toolchain.toml`. Inspect the hosted run's toolchain and results when qualifying a release.
85
+ The configured matrix is not evidence that each lane has completed successfully; this change was
86
+ inspected and its selected contracts run locally on macOS, not executed on native Windows. CI uses no
87
+ Ollama and no models, so it does not replace inference or hardware qualification;
88
+ run the live tiers before a release (`yarn verify:production`).
89
+
90
+ The local macOS verification snapshot of 2026-11-15 passed the release build, TypeScript checks,
91
+ strict Rust lint, 781 Rust tests, 1,474 JavaScript/evaluation checks and 51 packaging contracts.
92
+ Three JavaScript tests were skipped and four Rust tests ignored. The 21 selected cookbook,
93
+ packaged-resource and isolated-endpoint integration contracts also passed. This records local
94
+ deterministic checks, not a completed `verify:production`, a hosted Linux/Windows run, or a new
95
+ inference/hardware qualification. The [end-to-end review](OLLAMA_REVIEW.md#validation-of-this-revision)
96
+ records the repaired baseline failures and the limits of these results.
97
+
98
+ `yarn test:reliability` reproduces the labeled result-check accuracy report and exercises the
99
+ tool-calling grader offline. It is included in `yarn test:js`. See [reliability evidence](RELIABILITY.md)
100
+ for false positives, false negatives, live model results, raw transcripts and reproduction commands.
101
+ The [Rust resource audit](RUST_RESOURCE_AUDIT.md) records the production panic/lock review and its limits.
102
+
103
+ ## Comparative benchmark
104
+
105
+ Comparing FreeLlama with Ollama alone and other local stacks is a separate, manual programme:
106
+ protocol, measured results and limits are in [Benchmark](BENCHMARK.md). The recorded 2026-11-14
107
+ Apple M2 Pro run covers warm extraction, two- and four-client contention, and cold-request
108
+ observations for one hash-verified model. llama.cpp's startup-loaded first request is marked
109
+ non-comparable. Separate feature observations cover queue priority, workflow prompts,
110
+ reused searches/sweeps, deferred jobs and memory refusal. These are historical results for the
111
+ recorded builds, configurations and workloads; they do not qualify every current routing or engine
112
+ path. The cross-stack memory-pressure comparison and agent-token meter remain unrun. See the
113
+ [benchmark limits](BENCHMARK.md#limits) and
114
+ [incomplete workflow-trial denominators](BENCHMARK.md#built-in-prompts-measured).
115
+
116
+ `yarn test:bench` checks the sequential vendor runner, streamed timing, exact JSON grading and
117
+ host-counter parsing using deterministic fixtures. It is included in `yarn test:js`. These checks
118
+ require no model downloads or inference and do not qualify live performance. Use
119
+ `node scripts/bench/preflight.mjs --hash-model` for the separate live prerequisite report and
120
+ follow [`scripts/bench/README.md`](../scripts/bench/README.md) for vendor installation and execution.
121
+
64
122
  ## Model metadata contracts
65
123
 
66
124
  Model metadata unit contracts cover README extraction, complete tag pages, family-versus-variant
@@ -75,7 +133,7 @@ The fixture tests perform no inference, pulls, or deletions. See the
75
133
 
76
134
  ```bash
77
135
  cargo fmt --all --check
78
- cargo clippy --all-targets -- -D warnings
136
+ cargo clippy --workspace --all-targets --all-features -- -D warnings
79
137
  ```
80
138
 
81
139
  Routing regressions run in the default Rust suite; none are hidden behind `#[ignore]`. Add a
@@ -95,6 +153,21 @@ The local-agent tier runs all context fitting, compaction, pagination, repeat-su
95
153
  strict action-shape contracts. It is included in `yarn test:all`, so adapter regressions cannot be
96
154
  missed by the root release matrix.
97
155
 
156
+ Focused source modules keep contracts close to their owner: benchmark fixtures live in
157
+ `src/model_bench/tests.rs`, profile-matching fixtures in `src/model_bench/provenance.rs`, Windows
158
+ memory fixtures in `src/platform/resources/tests/windows.rs`, and panic/poison fault injection in
159
+ `src/platform/resources/governor/audit_tests.rs` (paths relative to `packages/rust-core/`). These
160
+ are ordinary enabled tests. Other resource tests remain in `resources/tests.rs`; this was a
161
+ targeted split, not a claim that every large test file has been reorganized.
162
+
163
+ Benchmark fixtures reject foreign hosts/endpoints and legacy reports, bind scores to artifact
164
+ digests, and keep primary-endpoint throughput out of CPU-assigned models. They also cover
165
+ existing-runner preservation and failure/identity checks before benchmark cleanup in
166
+ `packages/rust-core/tests/model_bench_contract.rs`. The managed
167
+ llama.cpp tests use a mock HTTP server; they establish its bounded text contract, not live
168
+ llama-server performance or observed processor placement. See the
169
+ [engine contract](LLAMACPP.md) and [machine calibration](MODEL_SELECTION.md#turn-measurements-into-routing-evidence).
170
+
98
171
  `yarn test:all` does not run formatting, Clippy, a release build, or package inspection. Use
99
172
  `yarn verify:production` for the complete local promotion gate.
100
173
 
@@ -144,12 +217,31 @@ Usage-ledger unit contracts cover ordered writes, bounded queue overflow, failed
144
217
  validation, replay, and flush behavior. `monitoring_contract` also checks that a blocked ledger path
145
218
  does not hold task completion. Persistence remains best effort, not a zero-loss promise.
146
219
 
147
- MCP `serve.test.ts` checks startup permission failure, retry, child-lifecycle isolation, and the
148
- background start at launch. The
220
+ MCP `serve.test.ts` checks startup permission failure, retry, child-lifecycle isolation, the
221
+ background start at launch, and the detached serve the agent commands start (log file, release once ready, log
222
+ tail on an early exit). `agent-cli.test.ts` covers `freellama run` flag mapping and output, registry
223
+ parity with the MCP server's tool list, virtual models, and the gateway's Ollama, OpenAI and Anthropic
224
+ protocols, including a client that leaves mid-stream. The
149
225
  protocol integration contracts verify that spawn failure leaves the MCP connection usable and that
150
226
  fixture-backed library requests fail on unexpected product errors. External catalog availability
151
227
  is separate from these deterministic checks.
152
228
 
229
+ `agent-cli-auth.test.ts` uses token-protected local HTTP fixtures to exercise terminal streams,
230
+ residency/config reads, real-model lists, passthrough and virtual SSE. It also checks that absolute
231
+ request URLs stay on the configured serve origin and generation redirects are refused.
232
+ The HTTPS passthrough fixture requires a real TLS handshake and verifies that an untrusted local
233
+ certificate returns 502 before the server receives HTTP credentials; it changes no TLS defaults.
234
+ Response-budget fixtures count UTF-8 wire bytes, accept the exact limit, cancel oversized
235
+ NDJSON/SSE/JSON and error bodies even without a newline, and fail after partial terminal output.
236
+ They also require raw real-tag passthrough to remain byte-preserving above the rewrite budget.
237
+ CLI regressions require `done:true` before reporting stream success, preserve explicit managed controls
238
+ under `--stream`, and retain a deferred lookup's error and retryable exit status.
239
+ Installer fixtures are platform-specific: `install-script.test.ts` exercises the POSIX installer
240
+ on Unix, and `install-powershell.test.ts` exercises Windows checksum acceptance/refusal with local
241
+ release files and a replaced HTTP cmdlet. Each suite skips the other OS; neither performs a
242
+ network install or runs the fixture executable. Launcher tests select `.exe` on Windows so a
243
+ built release is checked there rather than silently skipped. Windows execution still requires its lane.
244
+
153
245
  Launcher fixtures use `process.execPath` to avoid an extra PATH-resolved shell wrapper. After the
154
246
  MCP fixture's real executable-permission refusal, a test-only transport launches that exact fixture
155
247
  script through the same Node executable. Real child processes, HTTP listeners, signals, and exit
@@ -218,6 +310,18 @@ tier, and each writes a dated report to the git-ignored `.octocode/local-test/`.
218
310
  | `scripts/local-test/assist.mjs` | Issue to code, duplicates, triage and OCR on a real repository |
219
311
  | `scripts/local-test/media.mjs` | Speech round trip, multimodal image search, embedding comparison through MCP |
220
312
  | `scripts/local-test/octocode-agent.mjs` | A local model driving Octocode through `delegate_research` |
313
+ | `scripts/local-test/workflows.mjs` | Each text workflow (summarize-text, summarize-log, summarize-diff, extract-json, explain-code, review-code, fix-bug) on each candidate model through `freellama run -w -m`. Graded on facts present, nothing invented, length, filler, exact JSON fields and the planted bug. Pass `--models a,b`, `--workflows x,y`, `--out file.json`. Re-run it after changing a workflow prompt or a catalog pick |
314
+
315
+ Workflow eval of 2026-11-10 (Apple M2 Pro, 12 cases, so treat it as directional). The second
316
+ run used the reworded prompts and the shipped sampling presets (the first forced temperature 0):
317
+
318
+ | Workflow | `lfm3:1.7b` first → second | `bonsai-2:9b` first → second | Change made |
319
+ |---|---|---|---|
320
+ | summarize-text | 0/3 → 3/3 | 3/3 → 3/3 | No-padding prompt; `prefer: "capable"` |
321
+ | summarize-log | 0/2 → 1/2 (one run looped to 1,688 words) | 2/2 → 2/2 | Line-by-line format, no-padding closing; already `prefer: "capable"` |
322
+ | explain-code, review-code | 3/3 → 3/3 | 1/3 → 3/3 | Callers only when shown; quote the faulty code instead of line numbers the input lacks |
323
+ | summarize-diff, extract-json, fix-bug | all pass | all pass | Diff risks only when the diff shows them |
324
+ | **All** | **7/12 → 11/12** | **10/12 → 12/12** | |
221
325
 
222
326
  ## Verify release packages
223
327
 
@@ -231,10 +335,12 @@ yarn release:smoke # packed-install smoke of the host platform packag
231
335
 
232
336
  Build every claimed CLI/native target in a clean environment, assemble `SHA256SUMS`, run the full
233
337
  deterministic suite, and inspect every platform package dry run before publishing explicitly.
234
- Publish the eight `@octocodeai/freellama-native-*` packages before `@octocodeai/freellama` and `@octocodeai/freellama-mcp-server`, all
338
+ Publish the five `@octocodeai/freellama-native-*` packages listed in
339
+ [`scripts/release-platforms.mjs`](../scripts/release-platforms.mjs) before `@octocodeai/freellama` and `@octocodeai/freellama-mcp-server`, all
235
340
  at the exact same version, then the crates with `cargo publish --workspace` (`--dry-run` first packages
236
341
  and compiles both crates from their published sources). A successful local pack dry run proves package contents; it does not
237
- prove registry publication or another hardware class.
342
+ prove registry publication or another hardware class. Both release scripts require
343
+ `packages/mcp/dist/agent-cli.js` (the agent commands the `freellama` launcher runs) in the MCP package, and the CLI package to depend on the MCP package of the same version.
238
344
 
239
345
  ## Test one layer while iterating
240
346
 
package/docs/TUNING.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Make local models faster and lighter
2
2
 
3
- Moved from the root README.
3
+ Start with an installed model selected using [machine-local calibration](MODEL_SELECTION.md#turn-measurements-into-routing-evidence)
4
+ and held-out quality checks. Tuning cannot turn throughput evidence into correctness evidence.
5
+ The Ollama settings below do not configure the separate [managed llama.cpp adapter](LLAMACPP.md).
4
6
 
5
- ## Make local models faster and lighter
6
-
7
- Decode speed is fixed by the model and hardware. A task's real cost is mostly around decoding: cold
7
+ Steady-state decode speed depends on the model, hardware and competing work. A task's real cost is mostly around decoding: cold
8
8
  loads, reloads, re-evaluating a prompt the runner already saw, unneeded thinking and output, and
9
9
  running out of memory. Best payoff first:
10
10
 
@@ -30,10 +30,14 @@ running out of memory. Best payoff first:
30
30
  3. **Spend output only where it helps.** Completion, tools, browser and vision tasks send
31
31
  `think:false` (Ollama otherwise enables thinking on capable models); coding, code-repair and
32
32
  long-context tasks send `think:"medium"` to thinking models. `stopOnRepetition` cut `glm-ocr` on 12
33
- report strips from 12,948 to 6,452 output tokens with every label still read.
33
+ report strips from 12,948 to 6,452 output tokens with every label still read in that dated sample. Each text workflow
34
+ also caps its answer (`num_predict`, about 8 times the median its eval answers needed, 300–2,000
35
+ tokens) when thinking is off, and keeps `stopOnRepetition` on with it, so a model that loops stops
36
+ in seconds; a caller's own `num_predict` wins. End to end, workflows ran at 13–27 tokens/s on
37
+ `bonsai-2:9b` and Nemotron-3.5-Bolt here: the answer's length, not the prompt, sets the time.
34
38
  4. **Unload instead of swapping.** A load that does not fit waits instead of swapping, idle models are
35
- unloaded under memory pressure, and `unload` frees a big model before a switch without ever
36
- loading it.
39
+ unloaded under memory pressure according to operator policy. An agent may use `unload` for a
40
+ model it warmed or one the user named; it frees that model without loading it.
37
41
  5. **Shrink memory per runner.** Quantize the KV cache, keep `OLLAMA_NUM_PARALLEL=1` on a laptop
38
42
  (every slot multiplies KV memory by the context), and bound llama-server's hidden prompt cache
39
43
  with `LLAMA_ARG_CACHE_RAM`; see [Tune Ollama](#tune-ollama-for-local-models).
@@ -51,7 +55,7 @@ FreeLlama never changes Ollama's settings. These matter most, per Ollama's docs
51
55
  | Setting | What it does | Suggested start |
52
56
  |---|---|---|
53
57
  | `OLLAMA_NUM_PARALLEL` | Decoding slots per model, each with its own prompt cache; RAM grows with slots times context ([Ollama FAQ](https://github.com/ollama/ollama/blob/main/docs/faq.mdx)). Small gain on Apple silicon; some engines run one request at a time ([MLX engine](https://github.com/ollama/ollama/issues/17280)) | `1`, raised only after measuring. FreeLlama's budget follows it |
54
- | `OLLAMA_FLASH_ATTENTION` + `OLLAMA_KV_CACHE_TYPE=q8_0` | A quantized KV cache roughly halves its memory and needs flash attention ([Ollama FAQ](https://github.com/ollama/ollama/blob/main/docs/faq.mdx)); with `OLLAMA_FLASH_ATTENTION` unset, Ollama enables it automatically on supported backends. See [KV cache and flash attention](#kv-cache-and-flash-attention) | On, when the model's quality holds |
58
+ | `OLLAMA_FLASH_ATTENTION` + `OLLAMA_KV_CACHE_TYPE=q8_0` | A quantized KV cache roughly halves its memory and needs flash attention ([Ollama FAQ](https://github.com/ollama/ollama/blob/main/docs/faq.mdx)); with `OLLAMA_FLASH_ATTENTION` unset, Ollama enables it automatically on supported backends. See [KV cache and flash attention](#kv-cache-and-flash-attention) | `freellama doctor`'s conservative starter profile reports `f16`; switch to `q8_0` after checking quality on your workload (`scripts/local-test/workflows.mjs`) |
55
59
  | Context length | Ollama defaults to 4k below 24 GiB of VRAM and recommends at least 64k for agent and coding work ([context length](https://github.com/ollama/ollama/blob/main/docs/context-length.mdx)) | Size per task. FreeLlama keeps Ollama's default when it covers the prompt, otherwise sizes text tasks to the prompt; `contextTokens` overrides |
56
60
  | `OLLAMA_MAX_LOADED_MODELS` | How many runners stay resident. Unset and `0` mean 3 per GPU, then Ollama unloads by count | More than the model memory budget can hold, so the budget decides by size and reload cost. `1` reloads on every switch |
57
61
  | `keep_alive` | How long a runner stays loaded after use | Leave it out. FreeLlama picks a finite time from measured reuse |
@@ -0,0 +1,4 @@
1
+ <!doctype html>
2
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>FreeLlama benchmark · pooled run orders</title><style>
3
+ :root{color-scheme:light;--ink:#16242d;--muted:#53636d;--line:#d7dfe4;--accent:#15657b;--paper:#fff;--wash:#f3f6f8}*{box-sizing:border-box}body{margin:0;background:var(--wash);color:var(--ink);font:15px/1.5 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}main{max-width:1200px;margin:0 auto;padding:32px 28px 48px}header{padding-bottom:20px;border-bottom:2px solid var(--ink)}h1{font-size:30px;letter-spacing:-.03em;margin:0 0 10px}h2{font-size:20px;letter-spacing:-.02em;margin:0 0 8px}p{margin:8px 0}.subhead,.note,.muted,small{color:var(--muted)}.verdict{font-size:17px;font-weight:600}section{margin-top:28px}.table-scroll{overflow-x:auto;background:var(--paper);border:1px solid var(--line);margin-top:16px}table{border-collapse:collapse;width:100%;font-variant-numeric:tabular-nums}th,td{padding:14px 12px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}thead th{background:#edf2f5;font-size:13px;font-weight:600;white-space:nowrap}thead small{font-weight:400}tbody tr:last-child>*{border-bottom:0}tbody th{min-width:180px;font-weight:600}td{min-width:120px}.unknown{color:var(--muted);font-size:13px}small{display:block;font-size:12px;font-weight:400;margin-top:4px}.row-note{max-width:250px;line-height:1.35}.measured{font-weight:600}.note{font-size:13px;max-width:100ch}.controls{display:flex;align-items:center;gap:12px;margin:14px 0}select{font:inherit;color:var(--ink);background:var(--paper);border:1px solid #8b9ca8;border-radius:4px;padding:7px 10px}select:focus-visible{outline:3px solid #9bd2e1;outline-offset:2px}.empty{padding:16px;background:#edf2f5;color:var(--muted);border-left:3px solid #9aaab5}.plot{margin:14px 0;max-width:880px}.plot figcaption{font-size:13px;color:var(--muted);margin-bottom:8px}.plot svg{display:block;width:100%;max-width:760px;background:var(--paper);border:1px solid var(--line);padding:10px}.plot text,.samples text{font:12px system-ui,sans-serif;fill:var(--ink)}.plot text.muted,.samples text.muted{fill:var(--muted)}.plot .plot-name{font-weight:600}.plot .plot-value{font-variant-numeric:tabular-nums}.track{stroke:#d1dbe1;stroke-width:2}.point{fill:var(--accent);stroke:var(--paper);stroke-width:1}.samples{width:300px;height:58px;display:block}.sanity-table th,.sanity-table td{vertical-align:middle}.resource-line{display:flex;gap:36px;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:16px;margin-top:20px}.resource-line dt{font-size:12px;color:var(--muted)}.resource-line dd{margin:3px 0 0;font-weight:600}details{margin-top:24px;color:var(--muted);font-size:13px}summary{cursor:pointer}details li{overflow-wrap:anywhere;margin:6px 0}footer{margin-top:28px;padding-top:16px;border-top:1px solid var(--line);font-size:12px;color:var(--muted)}[hidden]{display:none!important}@media(max-width:640px){main{padding:22px 16px}h1{font-size:25px}th,td{padding:11px 10px}.resource-line{gap:18px}body{font-size:14px}}
4
+ </style></head><body><main><header><h1>FreeLlama benchmark · pooled run orders</h1><p class="verdict">2 run orders. No ranking or winner is inferred.</p><p class="subhead">Pooled p50/p95 use every verified measured trial from each order's raw trials.jsonl; warm-ups are excluded.</p></header><section aria-labelledby="pooled-heading"><h2 id="pooled-heading">Pooled across orders</h2><p class="note">Compare the gap between systems with the drift between orders before claiming a difference. — means Not measured.</p><div class="table-scroll"><table><thead><tr><th scope="col">System / per-order status</th><th scope="col">Orders pooled</th><th scope="col">Verified / attempted</th><th scope="col">Quality<small>% correct</small></th><th scope="col">Task time<small>ms · p50 / p95</small></th><th scope="col">TTFT<small>ms · p50 / p95</small></th></tr></thead><tbody><tr><th scope="row">Ollama alone<small>run-forward: Complete · run-reversed: Complete</small></th><td>2 of 2</td><td>60 / 60</td><td class="measured">100</td><td class="measured">271.96 / 289.82<small>n=60</small></td><td class="measured">93.35 / 97.29<small>n=60</small></td></tr><tr><th scope="row">FreeLlama<small>run-forward: Complete · run-reversed: Complete</small></th><td>2 of 2</td><td>60 / 60</td><td class="measured">100</td><td class="measured">273.73 / 302.84<small>n=60</small></td><td class="unknown"><span class="missing" role="img" aria-label="Not measured">—</span></td></tr><tr><th scope="row">FreeLlama (streamed)<small>run-forward: Complete · run-reversed: Complete</small></th><td>2 of 2</td><td>60 / 60</td><td class="measured">100</td><td class="measured">272.95 / 298.87<small>n=60</small></td><td class="measured">94.62 / 97.31<small>n=60</small></td></tr><tr><th scope="row">llama.cpp<small>run-forward: Complete · run-reversed: Complete</small></th><td>2 of 2</td><td>60 / 60</td><td class="measured">100</td><td class="measured">335.79 / 375.13<small>n=60</small></td><td class="measured">128.02 / 144.29<small>n=60</small></td></tr><tr><th scope="row">llama-swap<small>run-forward: Complete · run-reversed: Complete</small></th><td>2 of 2</td><td>60 / 60</td><td class="measured">100</td><td class="measured">331.83 / 371.27<small>n=60</small></td><td class="measured">129.73 / 137.92<small>n=60</small></td></tr><tr><th scope="row">LocalAI<small>run-forward: Complete · run-reversed: Complete</small></th><td>2 of 2</td><td>60 / 60</td><td class="measured">100</td><td class="measured">801.76 / 910.41<small>n=60</small></td><td class="measured">538.67 / 610.52<small>n=60</small></td></tr><tr><th scope="row">oMLX<small>run-forward: Not run · no raw trials · run-reversed: Not run · no raw trials</small></th><td>0 of 2</td><td>0 / 0</td><td class="unknown"><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown"><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown"><span class="missing" role="img" aria-label="Not measured">—</span></td></tr></tbody></table></div></section><section aria-labelledby="order-0"><h2 id="order-0">Order 1: run-forward</h2><p class="subhead">2026-11-14T15:49:12.314Z · S1 warm sequential generation; FreeLlama raw admission and managed completion reported separately</p><div class="table-scroll"><table><thead><tr><th scope="col">System / outcome</th><th scope="col" title="Exact-case pass rate; all measured attempts remain in the denominator.">Quality<small>% correct</small></th><th scope="col" title="Client wall time for verified answers. Failures remain in outcome counts.">Task time<small>ms · median</small></th><th scope="col" title="Verified completions divided by the entire measured request window.">Throughput<small>verified tasks/min</small></th><th scope="col" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">Local tokens<small>tokens / verified task</small></th><th scope="col" title="Whole-host CPU capacity from cumulative OS counters; includes other applications.">Host CPU<small>% busy · mean</small></th><th scope="col" title="Lowest reported available host memory. This is not process RSS; missing counters remain unknown.">Memory<small>GiB available · min</small></th></tr></thead><tbody><tr><th scope="row">Ollama alone<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">267.82<small>p95 280.22 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">221.39<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">37.2<small>n=28</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">5.88<small>n=28</small></td></tr><tr><th scope="row">FreeLlama<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">273.08<small>p95 290.39 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">217.48<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">33<small>n=29</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">5.99<small>n=29</small></td></tr><tr><th scope="row">FreeLlama (streamed)<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">272.73<small>p95 285.25 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">217.46<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">34.09<small>n=28</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">5.91<small>n=28</small></td></tr><tr><th scope="row">llama.cpp<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">311.03<small>p95 346 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">188.23<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">98<small>n=30</small></td><td class="measured" title="Coverage 100%">7.13<small>n=27</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">5.55<small>n=27</small></td></tr><tr><th scope="row">llama-swap<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">331.09<small>p95 379.07 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">178.89<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">98<small>n=30</small></td><td class="measured" title="Coverage 100%">21.59<small>n=31</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">3.83<small>n=31</small></td></tr><tr><th scope="row">LocalAI<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">851.17<small>p95 936.1 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">71.42<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">47.52<small>n=67</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">4.39<small>n=67</small></td></tr><tr><th scope="row">oMLX<small>Not run · n=0</small></th><td class="unknown" title="Exact-case pass rate; all measured attempts remain in the denominator."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Client wall time for verified answers. Failures remain in outcome counts."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Verified completions divided by the entire measured request window."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Incomplete or absent token coverage"><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Whole-host CPU capacity from cumulative OS counters; includes other applications."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Lowest reported available host memory. This is not process RSS; missing counters remain unknown."><span class="missing" role="img" aria-label="Not measured">—</span></td></tr></tbody></table></div></section><section aria-labelledby="order-1"><h2 id="order-1">Order 2: run-reversed</h2><p class="subhead">2026-11-14T15:50:37.982Z · S1 warm sequential generation; FreeLlama raw admission and managed completion reported separately</p><div class="table-scroll"><table><thead><tr><th scope="col">System / outcome</th><th scope="col" title="Exact-case pass rate; all measured attempts remain in the denominator.">Quality<small>% correct</small></th><th scope="col" title="Client wall time for verified answers. Failures remain in outcome counts.">Task time<small>ms · median</small></th><th scope="col" title="Verified completions divided by the entire measured request window.">Throughput<small>verified tasks/min</small></th><th scope="col" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">Local tokens<small>tokens / verified task</small></th><th scope="col" title="Whole-host CPU capacity from cumulative OS counters; includes other applications.">Host CPU<small>% busy · mean</small></th><th scope="col" title="Lowest reported available host memory. This is not process RSS; missing counters remain unknown.">Memory<small>GiB available · min</small></th></tr></thead><tbody><tr><th scope="row">Ollama alone<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">273.99<small>p95 300.95 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">195.94<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">34.41<small>n=10</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">4.31<small>n=10</small></td></tr><tr><th scope="row">FreeLlama<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">275.04<small>p95 344.78 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">194.95<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">33.85<small>n=11</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">4.5<small>n=11</small></td></tr><tr><th scope="row">FreeLlama (streamed)<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">273.16<small>p95 300.01 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">215.49<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">35.24<small>n=10</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">4.55<small>n=10</small></td></tr><tr><th scope="row">llama.cpp<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">345.2<small>p95 397.39 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">168.69<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">98<small>n=30</small></td><td class="measured" title="Coverage 100%">19.09<small>n=11</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">5.38<small>n=11</small></td></tr><tr><th scope="row">llama-swap<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">331.83<small>p95 371.27 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">177.61<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">98<small>n=30</small></td><td class="measured" title="Coverage 100%">34.43<small>n=12</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">4.23<small>n=12</small></td></tr><tr><th scope="row">LocalAI<small>Complete · n=30 · 30 verified</small><small>Cohort: gguf · declared</small></th><td class="measured" title="Exact-case pass rate; all measured attempts remain in the denominator.">100<small>n=30</small></td><td class="measured" title="Client wall time for verified answers. Failures remain in outcome counts.">751.03<small>p95 886.6 ms · n=30</small></td><td class="measured" title="Verified completions divided by the entire measured request window.">79.96<small>n=30</small></td><td class="measured" title="All measured local prompt and output tokens, including failed effort. Requires complete token coverage. Paid-agent cost is separate.">97<small>n=30</small></td><td class="measured" title="Coverage 100%">32.05<small>n=26</small></td><td class="measured" title="macOS FreeLlama estimate (free + bounded reclaimable), not a kernel value">4.07<small>n=26</small></td></tr><tr><th scope="row">oMLX<small>Not run · n=0</small></th><td class="unknown" title="Exact-case pass rate; all measured attempts remain in the denominator."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Client wall time for verified answers. Failures remain in outcome counts."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Verified completions divided by the entire measured request window."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Incomplete or absent token coverage"><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Whole-host CPU capacity from cumulative OS counters; includes other applications."><span class="missing" role="img" aria-label="Not measured">—</span></td><td class="unknown" title="Lowest reported available host memory. This is not process RSS; missing counters remain unknown."><span class="missing" role="img" aria-label="Not measured">—</span></td></tr></tbody></table></div></section><footer>Evidence report. No ranking, aggregate score, estimated result, or winner is inferred. This file contains no external requests or dependencies.</footer></main><script id="benchmark-data" type="application/json">{"title":"FreeLlama benchmark · pooled run orders","orders":["run-forward","run-reversed"],"pooled":[{"id":"ollama","name":"Ollama alone","orders":[{"label":"run-forward","vendor_id":"ollama","status":"complete","raw_trials":30},{"label":"run-reversed","vendor_id":"ollama","status":"complete","raw_trials":30}],"orders_pooled":2,"attempted":60,"verified":60,"quality":100,"task_time":{"n":60,"p50":271.9590829999943,"p95":289.8182919999963},"ttft":{"n":60,"p50":93.3453329999902,"p95":97.28612500000008}},{"id":"freellama","name":"FreeLlama","orders":[{"label":"run-forward","vendor_id":"freellama","status":"complete","raw_trials":30},{"label":"run-reversed","vendor_id":"freellama","status":"complete","raw_trials":30}],"orders_pooled":2,"attempted":60,"verified":60,"quality":100,"task_time":{"n":60,"p50":273.7295000000013,"p95":302.83750000000146},"ttft":{"n":0,"p50":null,"p95":null}},{"id":"freellama-stream","name":"FreeLlama (streamed)","orders":[{"label":"run-forward","vendor_id":"freellama-stream","status":"complete","raw_trials":30},{"label":"run-reversed","vendor_id":"freellama-stream","status":"complete","raw_trials":30}],"orders_pooled":2,"attempted":60,"verified":60,"quality":100,"task_time":{"n":60,"p50":272.95179199999984,"p95":298.87129200000345},"ttft":{"n":60,"p50":94.6217500000057,"p95":97.30845799999952}},{"id":"llama-cpp","name":"llama.cpp","orders":[{"label":"run-forward","vendor_id":"llama-cpp","status":"complete","raw_trials":30},{"label":"run-reversed","vendor_id":"llama-cpp","status":"complete","raw_trials":30}],"orders_pooled":2,"attempted":60,"verified":60,"quality":100,"task_time":{"n":60,"p50":335.78712500000256,"p95":375.12854200000584},"ttft":{"n":60,"p50":128.02329100000497,"p95":144.29299999999785}},{"id":"llama-swap","name":"llama-swap","orders":[{"label":"run-forward","vendor_id":"llama-swap","status":"complete","raw_trials":30},{"label":"run-reversed","vendor_id":"llama-swap","status":"complete","raw_trials":30}],"orders_pooled":2,"attempted":60,"verified":60,"quality":100,"task_time":{"n":60,"p50":331.8255419999987,"p95":371.2747079999972},"ttft":{"n":60,"p50":129.73000000001048,"p95":137.92079199999716}},{"id":"localai","name":"LocalAI","orders":[{"label":"run-forward","vendor_id":"localai","status":"complete","raw_trials":30},{"label":"run-reversed","vendor_id":"localai","status":"complete","raw_trials":30}],"orders_pooled":2,"attempted":60,"verified":60,"quality":100,"task_time":{"n":60,"p50":801.7590839999993,"p95":910.4146250000049},"ttft":{"n":60,"p50":538.673375000013,"p95":610.5174159999879}},{"id":"omlx","name":"oMLX","orders":[{"label":"run-forward","vendor_id":null,"status":"not_run","raw_trials":null},{"label":"run-reversed","vendor_id":null,"status":"not_run","raw_trials":null}],"orders_pooled":0,"attempted":0,"verified":0,"quality":null,"task_time":{"n":0,"p50":null,"p95":null},"ttft":{"n":0,"p50":null,"p95":null}}]}</script></body></html>