diff --git a/agent/models.yml b/agent/models.yml index 81dc64d..86273d0 100644 --- a/agent/models.yml +++ b/agent/models.yml @@ -16,7 +16,7 @@ providers: auth: none models: - id: frank-archon - # Model id renamed from frank-archon on 2026-10-08 (official + # Model id renamed from frank-medium on 2026-10-08 (official # unit-name scheme; the systemd service, scripts and runbooks keep # the frank-archon name — service names are unchanged). # Server-side compaction routes to compaction.remoteEndpoint in @@ -82,9 +82,11 @@ providers: auth: none models: - id: frank-dragoon - # Model id renamed from frank-dragoon on 2026-10-08 (official + # Model id renamed from frank-large on 2026-10-08 (official # unit-name scheme; the service/unit/scripts keep the frank-dragoon - # name — service names are unchanged). + # name — service names are unchanged). The pre-rename id is + # `frank-large`, recorded here because the callsign rename overwrote + # its own explanation and left "renamed from frank-dragoon". name: "frank-dragoon (dankclaw-gpu)" # Server-side compaction runs on the compaction.remoteEndpoint in # config.yml (192.168.0.143:7771 — frank-zealot's 3090); this steers the @@ -111,31 +113,80 @@ providers: maxTokens: 45056 reasoning: true # VISION ON as of 2026-10-06: the v2 vision tower loads beside the - # checkpoint (HALOGEN_VISION_TOWER; red-PNG probe verified on the - # card). image_url content parts only — the legacy top-level - # images field is the frank-zealot trap, do not repeat it here. + # checkpoint (HALOGEN_VISION_TOWER; priced at 0.8 GiB in the boot + # ledger, and re-probed 2026-10-21 — a 512 px solid-red PNG comes back + # "Red" at 282 prompt tokens). image_url content parts only — the + # legacy top-level images field is the frank-zealot trap, do not + # repeat it here. input: [text, image] compat: # flash-server emits thinking as `reasoning_content` — same # field as every engine this endpoint has run, no harness # change needed. reasoningContentField: "reasoning_content" - # Same Qwen3.8 template family (it ships inside the tokenizer - # bundle): any reasoning_effort outside {xhigh, medium, low} is - # rejected, not clamped — the fold stays mandatory. + # flash-server validates reasoning_effort against its own list and + # 400s anything else, naming it: "reasoning_effort 'maximum' + # unsupported; use minimal|low|medium|high|xhigh|max|none" (measured + # 2026-10-21). Every omp level is already spelled by the engine, so + # the map is identity — it exists to record that, not to fold. An + # earlier version rewrote high->xhigh and minimal->low to stop + # rejections that do not exist, and the rewrite asked the engine for + # a different thinking budget than the caller named. Levels really do + # differ here: thinking length on one prompt at max_tokens 2048 + # measured low 766 tokens, xhigh 614, max 1049 with the block closed + # at 1024 (reasoning_closed_at). The harness passes an unmapped level + # through verbatim (`compat.reasoningEffortMap?.[effort] ?? effort`), + # so removing an entry is a pass-through, never a 400. + # + # `max` still does not reach the engine, and the map is not why: the + # harness clamps the requested effort to the model's own effort ladder + # before the map applies, and its ladder for this model tops out at + # xhigh — captured on the wire 2026-10-21, `:max` left as + # `reasoning_effort: "xhigh"` with this identity map in place. The + # `max` row below is the engine-side half of the contract; it takes + # effect the moment the harness ladder gains `max`, and nothing here + # can force it sooner. + # + # Thinking OFF needs an explicit mode. The default disable mode sends + # the LOWEST effort rather than a switch — `:off` left the wire as + # `reasoning_effort: "minimal"` (captured), and minimal still thinks: + # a canned 26-token block on every "off" request. `none-effort` makes + # the harness send `reasoning_effort: "none"`, which this engine + # honours as a real switch: `reasoning_tokens: 0`, answer only, no + # thinking block in the rendered output (both verified 2026-10-21). + # + # Re-measure before changing any of it. The allow-list, in the + # engine's own words: + # curl -s :7770/v1/chat/completions -H 'content-type: application/json' \ + # -d '{"model":"frank-dragoon","messages":[{"role":"user","content":"x"}], + # "reasoning_effort":"maximum"}' + # -> 400 "reasoning_effort 'maximum' unsupported; use + # minimal|low|medium|high|xhigh|max|none" + # and read usage.completion_tokens_details.reasoning_tokens at + # max_tokens 2048 to see the levels separate. The wire itself is + # settled by pointing a scratch HOME at a logging proxy on :7799 that + # forwards to :7770 and running `omp --model …:off` — config claims + # are worth exactly what their last capture says. + reasoningDisableMode: none-effort reasoningEffortMap: - minimal: low + minimal: minimal low: low medium: medium - high: xhigh - max: xhigh - # The card's thinking recipe, on the wire. The flash-server - # engine HAS a server-side sampler (HALOGEN_TEMPERATURE/TOP_P/ - # TOP_K = 1.0 / 0.95 / 20 in frank-dragoon.env) — these match it, - # so per-request values are consistent, not load-bearing. + high: high + xhigh: xhigh + max: max + # The card's thinking recipe, on the wire. The flash-server engine + # HAS a server-side sampler (HALOGEN_TEMPERATURE/TOP_P/TOP_K = + # 1.0 / 0.95 / 20 in frank-dragoon.env), but an omitted parameter is + # the engine's choice, not a pinned one: top_k is sent explicitly so + # the recipe survives someone editing HALOGEN_TOP_K. The engine + # accepts top_k, min_p, presence_penalty and repetition_penalty + # (measured 2026-10-21, all 200) — only the values this endpoint is + # meant to run are pinned here. extraBody: temperature: 1.0 top_p: 0.95 + top_k: 20 "llamacpp (dankclaw-3090)": baseUrl: http://192.168.0.143:7771/v1 @@ -143,7 +194,7 @@ providers: auth: none models: - id: frank-zealot - # Model id renamed from frank-zealot on 2026-10-08 (official + # Model id renamed from frank-small on 2026-10-08 (official # unit-name scheme; the service/unit/scripts keep the # frank-zealot name — service names are unchanged). name: "frank-zealot (dankclaw-3090)" diff --git a/omp-docs/log.md b/omp-docs/log.md index 5f9f27d..96817a0 100644 --- a/omp-docs/log.md +++ b/omp-docs/log.md @@ -20,6 +20,21 @@ This page is the bundle's **only** work log: one file, at the root. Never start second one in a subdirectory or under another name — `scripts/kb-lint.sh` reports any `log.md` that is not this one. +## 2026-10-21 — an effort map folding against rejections that never existed + +`agent/models.yml` rewrote `minimal→low`, `high→xhigh` and `max→xhigh` for +frank-dragoon to dodge 400s the engine does not send: flash-server's own error names +its allow-list (`minimal|low|medium|high|xhigh|max|none`) and the harness passes an +unmapped level through verbatim, so the fold only asked for a different thinking +budget than the caller named. The map is identity now, and +`reasoningDisableMode: none-effort` was added because the default disable mode does +not disable — `:off` left as `reasoning_effort: "minimal"` and paid for a canned +thinking block, where `none` returns `reasoning_tokens: 0`. Both settled by capturing +the wire through a logging proxy rather than reading the config: a claim about what +the harness sends is worth exactly its last capture. The same pass restored the three +pre-callsign model ids (`frank-medium` / `frank-large` / `frank-small`) that the +2026-10-08 rename had overwritten inside its own explanatory comments. Refs #62 + ## 2026-10-21 — a documented mode the panel never had The home ultrawide had been running at 60 Hz for weeks while `desk-1-home.kdl`