Every provider in agent/models.yml is a LAN address, so a workstation that
leaves the house has no model at all. Add `openwebui (franksdank.cloud)`:
the already-public OpenWebUI vhost as an OpenAI-compatible provider that
proxies the same engines, with frank-dragoon and frank-zealot rows and the
WAN row as its own compaction target. LAN rows, modelRoles and the speech
runner stay untouched — the door is purely additive.
The key is command-backed (`apiKey: "!cat ~/.config/secrets/openwebui_api_key"`,
mode 600) instead of inline: a literal sk-... in a tracked file is a key in
every agent context on every box that pulls this repo, and the pre-commit
shape gate would block it anyway. Rotate = rewrite the file + restart omp,
because a `!cmd` value is cached for the process lifetime.
Compat blocks copy their LAN twins because the proxy was probed, not assumed
(2026-10-21): streaming SSE carries reasoning_content and tool_calls deltas
plus final usage, image_url content parts reach both vision towers, and
chat_template_kwargs is forwarded — proven on frank-zealot, where
enable_thinking false yields zero reasoning and true a real block.
frank-archon gets no WAN row: OpenWebUI answers 400 "Model not found"
because its picker never published it, so that path is a fleet change.
Verified end-to-end from a scratch HOME whose LAN baseUrls point at a dead
port, so any answer can only have come through the door (text and a real
tool round-trip); `omp models` still lists all four chat providers and the
tts runner, so the file validates. bats 137/137, kb-lint clean.
Docs: omp-docs/core/wan-model-access.md.
Two conflicts, both resolved to trunk, both proven content-free for the running
machine before the merge was committed:
- `agent/APPEND_SYSTEM.md` — the checkout's dirty copy and trunk differ in one line
only: #61's trim of the duplicated one-log reasoning, replaced by the owner pointer.
The doctrine text itself is byte-identical on both sides.
- `desk-1-home.kdl` — non-comment lines are byte-identical (`diff` on the stripped
file: no output), so the deployed modes are unchanged: `3440x1440@180.000` ×3 and
`1920x1080@60.001`. What changes is the comment: trunk's carries the measured mode
list (`3440x1440@239.998` exists), the reason 180 is deliberate, and the verbatim
mode-string law — the live copy still asserted "no 240 Hz mode exists", which the
panel contradicts. `niri validate` on the assembled config: valid.
Deployment state after this: the checkout is main, and `agent/memories/**` +
`agent/managed-skills/**` were committed by the heartbeat commit underneath. Refs #60#62
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and
`merge --ff-only` refuses while tracked paths are dirty. Discard is not available here
(workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed.
- `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already
byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new
prose — the commit exists so the trunk merge can proceed.
- `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat
owns (AGENTS.md § Live-sync tiers).
`ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the
only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the
inert all-zero AWS example id — and they appear inside the two skill pages that teach
that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged
gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal
dies with this landing. No `--no-verify` was used: the gate ran and its verdict is
recorded here.
Refs #61