585 Commits
Author SHA1 Message Date
Benson WongandGitHub 6c7f9587dd docker/unified: add cuda13 with multi-platform support for arm64 (#1093)
Key changes: 

- add cuda13 container for Ampere to Blackwell GPUs
- support DGX Spark (GB10) with arm64 cuda 13 manifests
- enable ik_llama on vulkan container 
- map `LLAMA_SWAP_*` env vars to llama-server CLI flags with backwards support
- refactor GHA/docker build to accept variants

closes: #905, #1066
supercedes: PR #841, PR #1084
v254
2026-09-05 09:22:52 -07:00
jlacour-gitandGitHub 82ccfbf27f filters: set-if-undefined params via "?" key suffix (#1075)
A `setParams` / `setParamsByID` key ending in `?` is set-if-undefined:
the value is applied only when the request doesn't already carry that
parameter. Plain keys keep forcing their values, and a config that
doesn't use the suffix behaves exactly as before.

Fixes: #1052
2026-09-05 00:29:28 -07:00
Benson WongandGitHub 41f143110d ui/tailcat: mask connection token, add shareable peer config (#1091)
Hide tailnet server token in the UI and add an easy to copy/paste
Peer config that is easy to send to connect to the server. 

- Add missing configuration overview documentation 
- Fix out of date docs
- Fix minor bug for listing tailcat server models

Fixes #1092
2026-09-05 00:13:31 -07:00
Benson WongandGitHub 8365956000 ui/help: raise Docs Agent max_tokens from 4096 to 65536 (#1089) 2026-09-04 07:58:04 -07:00
Benson WongandGitHub afba24b4e3 ui/help: refine Help agent topics and controls (#1088)
Linux CI / run-tests (push) Failing after 3m59s
UI Tests / run-tests (push) Failing after 5m32s
Windows CI / run-tests (push) Canceled after 0s
Refresh documentation suggestions and streamline the Help experience.

- align sidebar footer links and add topic refresh action
- remove the speculative-decoding article and stale search hint
- increase agent loop limit while hiding iteration display
v253
2026-09-03 23:32:30 -07:00
Benson WongandGitHub a77f107d77 Replace config path argument with jq query support (#1087)
The Docs Agent's get_config tool would fail on very large
configs with lots of models. Replace it with a jq expression 
so the agent can request very specific parts of the configuration
without adding too many extra tokens to the context.

- add jq expression support to Doc Agent's Tools
- move Help out of the Playground into the main sidebar 
- add more tips to the Help front page

Updates #1085
2026-09-03 23:02:52 -07:00
Benson WongandGitHub 8a06d56b54 tailcat: add private server and peer connectivity (#1074)
Validate JSON Schema / validate-schema (push) Failing after 35s
UI Tests / run-tests (push) Successful in 58s
Linux CI / run-tests (push) Failing after 4m19s
Windows CI / run-tests (push) Canceled after 0s
Expose llama-swap through Tailcat virtual TCP listeners and route peer
requests through Tailcat transports.

- validate server identities, caller allowlists, and published model IDs
- restrict the default remote HTTP surface and retain Tailcat request sources
- add UI status, activity attribution, configuration docs, and schema support
- make Tailcat transport diagnostics opt-in with server.tailcat.debug

fixes: #1073
2026-09-03 14:19:29 -07:00
DamirandGitHub 7a14664d98 docker/unified: make CUDA version and architectures configurable (#1072)
- Add option to specify CUDA version and architectures during image
building. If not provided, it should behave just like now.
- Include Stable Diffusion UI in SD binaries. 
- Fix ik_llama.cpp build for arm64 architecture:
https://github.com/ikawrakow/ik_llama.cpp/issues/1684.
2026-08-31 16:09:17 -07:00
Benson WongandGitHub e31a1adee4 Split Docker build into per-project stages for CI (#1071)
Big refactor to split the build stages for the unified container to be built in parallel. 

- parallel building of binaries to speed up full container build (~6+hr to 1.5hr) 
- split cuda and vulkan pipelines to be independent (vulkan is much faster)
- establish pattern for building building binaries for final image (easier to add new resources)
- use llama-swap-build for build containers to avoid untagged clean up script

Fixes: #1069
v252
2026-08-30 11:57:20 -07:00
Benson WongandGitHub e2d6f930f9 ui: improve Help page (#1070)
UI Tests / run-tests (push) Successful in 53s
Linux CI / run-tests (push) Failing after 2m30s
Windows CI / run-tests (push) Canceled after 0s
- tighten up the UI with a Work block that includes reasoning and tool
calls
- remove values matching defaults when listing the configuration
2026-08-30 09:21:27 -07:00
Benson WongandGitHub 6ffd67fdf2 internal/reference: add indexed docs and /api/tools endpoints (#1054)
Validate JSON Schema / validate-schema (push) Successful in 37s
Build Containers / build-and-push (cpu) (push) Failing after 39s
Build Containers / build-and-push (cuda) (push) Failing after 30s
Build Containers / build-and-push (cuda13) (push) Failing after 29s
Build Containers / build-and-push (intel) (push) Failing after 30s
Build Containers / build-and-push (musa) (push) Failing after 29s
Build Containers / build-and-push (rocm) (push) Failing after 40s
Build Containers / build-and-push (vulkan) (push) Failing after 32s
Build Containers / delete-untagged-containers (push) Skipped
Linux CI / run-tests (push) Failing after 2m33s
UI Tests / run-tests (push) Successful in 43s
Windows CI / run-tests (push) Canceled after 0s
Add an Docs agent to the playground that can help the user with more
advanced configuration.

- add mcp 2026-07-28 (stateless mcp) framework 
- add MCP tools for doc search and config search
- add initial set of guides for key topics
- add Docs to the Playground
- removed out of data documentation and plans
2026-08-29 23:43:09 -07:00
32c3d66cd3 config,server: add startup profile hook (#1053)
Validate JSON Schema / validate-schema (push) Successful in 45s
Linux CI / run-tests (push) Failing after 2m34s
Windows CI / run-tests (push) Canceled after 0s
An optional `hooks.on_startup.profile` setting for activating a profile
on startup and after a configuration reload:

```yaml
profiles:
  coding:
    pins:
      llm-code: "gpt-oss-120b"

hooks:
  on_startup:
    profile: "coding"
```

Another attempt to close #992 after unsuccessful #993 ;)

Co-authored-by: David Soušek <david.sousek@intelogy.co.uk>
2026-08-29 11:26:54 -07:00
1fc0490592 expose context_window on models endpoint (#1063)
Linux CI / run-tests (push) Failing after 2m13s
Windows CI / run-tests (push) Canceled after 0s
Some OpenAI-compatible gateways read the context size from a
**context_window** field on the models endpoint (e.g. Bifrost, following
GROQ's convention) instead of **context_length**.

llama-swap only exposed the latter, so such gateways silently dropped
the context size configured in model capabilities.

Add context_window to the /v1/models and /models responses, mirroring
the capabilities-based context_length value, so both field names carry
the same number. The field is renderer-owned like context_length: a
context_window key in a model's metadata block is dropped when
capabilities are rendered, matching the existing behavior.

Tests assert the mirrored value alongside context_length, including the
metadata precedence and passthrough cases.

---
Replaces #1062 (closed when the head repository was reworked).

Co-authored-by: Chris <chrispaulm@users.noreply.github.com>
2026-08-28 09:58:54 -07:00
cphlipotandGitHub 51d1969c19 cmd/wol-proxy: add -api-key option for use in health checks (#1055)
add a -api-key option that the user can optionally provide to give
wol-proxy a private api key it will use for authenticating its
health checks against the llama-swap server.

This is api key is not used as part of any client request, and
clients connecting to the wol-proxy will still need to provide their
own api keys matching one of the ones in the destination llama-swap's
config.yaml

Fixes: #1051
2026-08-27 21:55:20 -07:00
cphlipotandGitHub a6f5ae3d0d cmd/wol-proxy: add liveness check (#1057)
If a server suspends without hanging up the connection, the wol-proxy
may be left with an open, but unresponsive connection.

this PR adds a simple check to ensure connection remains responsive
if not, we assume system suspended and attempt to re-send the wol
packet. While this is assumption, it is relatively safe since sending
extra unneeded wol packets would have little negative impact if that
happened.

fixes #1056
2026-08-27 21:54:38 -07:00
HugoandGitHub 8a32e055f5 Typo (#1049)
Linux CI / run-tests (push) Failing after 2m12s
Windows CI / run-tests (push) Canceled after 0s
2026-08-24 08:26:25 -07:00
Bernardo Gallegos-VallejoandGitHub 4cd0247afa config: accept video as an input and output modality (#1048)
Validate JSON Schema / validate-schema (push) Successful in 39s
Linux CI / run-tests (push) Failing after 2m20s
Windows CI / run-tests (push) Canceled after 0s
capabilities.in and capabilities.out accepted text, audio and image but not video, so a multimodal model that takes video input could not declare it and /v1/models reported it as image-only.

video is added to the shared validModalities set, which makes it valid on both in and out; tests assert both sides explicitly so that stays a decision rather than a side effect of the two lists sharing one map.

Updated together so no layer disagrees: the validModalities map, both validation error messages, both config-schema.json enums, and the valid-values comments in config.example.yaml.

Fixes: #1014
2026-08-23 17:35:20 -07:00
Bernardo Gallegos-VallejoandGitHub bfbb99c654 cli: add -validate flag to check config and exit (#1046)
UI Tests / run-tests (push) Successful in 38s
Linux CI / run-tests (push) Successful in 1m49s
Windows CI / run-tests (push) Canceled after 0s
Adds a -validate boolean flag that loads the config via the existing
config.LoadConfigSources and exits without starting the server,
detecting hardware, or binding a listener. Exits 0 when the config loads
cleanly and 1 when it does not, printing a one-line result either way.

The logic lives in runValidate(configPath, configDir string, out
io.Writer) int rather than inline in main() so it can be tested
directly.

Fixes: #1034
2026-08-23 12:56:02 -07:00
Shinko SaijoandGitHub 9b4b3a08e7 ui: ignore IME composition Enter in keydown handlers (#1045)
Improve text entry so input Enter is IME aware and does not submit prompts unintentionally. 

Fixes #1044
2026-08-23 07:33:33 -07:00
Benson WongandGitHub 4ec317589b internal: record client disconnects as 499, not 200 or 502 (#1040)
Linux CI / run-tests (push) Failing after 3m15s
Windows CI / run-tests (push) Canceled after 0s
A client that hangs up before a response is written was logged and
recorded as a successful 200 with a 0-byte body: the cancellation
branches return without touching the ResponseWriter, so the access log's
seeded 200 was what got reported, and the metrics path filed it through
the "empty body, recording minimal metrics" success arm. Aborted
requests were invisible to status-code monitoring. Once the model was
loaded, the same hangup surfaced as a 502, blaming a healthy upstream.

Add swaputil.StatusClientClosedRequest (nginx's non-standard 499) as the
sentinel. It is recorded only, never written to the connection: the
client is already gone, and on a streamed response a late WriteHeader
would just log "superfluous response.WriteHeader".

- add StatusMarker/MarkClientClosed to swaputil; the response recorders
  implement it and forward outward so log and metrics agree
- derive the sentinel in the access-log and metrics middleware, which
  covers every cancellation branch instead of each one separately
- classify cancellation in the model and peer proxy ErrorHandlers so a
  client hangup no longer reports 502
- record cancelled requests with a client-disconnected ErrorMsg at debug
  level and without a capture, since an impatient caller is normal
  traffic rather than a server fault
- tag health check polls so a booting upstream is not logged as a proxy
  error once per second

A response that already started keeps the status the client actually
received.

fix: #1029
v251
2026-08-22 23:58:47 -07:00
Benson WongandGitHub 23432e65f0 internal/server: rate limit sendBuffer full warnings (#1043) 2026-08-22 22:58:01 -07:00
Benson WongandGitHub 0bdb372019 internal/server: parse vLLM speculative decoding metrics (#1039)
vLLM started with --per-request-spec-decode-metrics reports draft token
counts in the response's metrics.speculative_decoding object. Map those
onto the existing draft token fields so the activity table's drafted
acceptance rate works for vLLM the same way it already does for
llama-server's timings.

- read num_draft_tokens/num_accepted_draft_tokens from
  metrics.speculative_decoding
- require both counters so the rate is never derived from a partial
  object
- cover non-streaming, streaming and partial-object responses in tests

fix: #1032
2026-08-22 09:29:57 -07:00
cb536168c4 internal/swaputil: OpenAI-compatible error bodies (#1038)
Error responses used a string-valued "error" field, so OpenAI clients
that read body["error"]["message"] hit a string where they expected an
object. Home Assistant's OpenAI-style conversation integration turns
that into an opaque 500 instead of a retryable "server busy" signal
when concurrencyLimit sheds a request.

Every JSON error body now uses the OpenAI envelope, with error.type and
error.code derived from the HTTP status:

  {"src":"llama-swap",
   "error":{"message":"Too many requests","type":"rate_limit_error",
            "param":null,"code":"concurrency_limit"}}

- add ErrorEnvelope/ErrorDetail and NewErrorEnvelope() in swaputil
- render SendResponse's JSON branch and ConcurrencyLimitError.Body()
  through the envelope, keeping status codes and Retry-After unchanged
- route the two remaining http.Error() call sites (process not ready,
  peer proxy failure) through SendResponse so they use the envelope too
- keep the top-level "src" marker and the text/plain and text/html
  response formats as they were

fix: #1037

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-22 08:04:51 -07:00
Benson WongandGitHub 23c28febf1 docker/unified: build audio.cpp as a deployment build (#1023) 2026-08-18 20:12:17 -07:00
Ignacio HuertaandGitHub b40d20e916 ui: render ANSI colors in logs (#1019)
UI Tests / run-tests (push) Successful in 35s
fixes: #838
2026-08-18 08:35:29 -07:00
Benson WongandGitHub 08f1076cb7 ui-svelte: Add markdown activity export (#1020)
Linux CI / run-tests (push) Failing after 2m57s
UI Tests / run-tests (push) Successful in 44s
Windows CI / run-tests (push) Canceled after 0s
- Add export of logs to activity table 
- Fix drag / drop of columns 
- Fix broken copy and paste in UI
- Rename ui-svelte to ui

Fix #1016
2026-08-16 20:08:00 -07:00
Benson WongandGitHub 60226b6377 docker/unified: add llama-bench, vllm-wrapper, audio.cpp (#1011)
New binaries included in the unified container: 

- add llama-bench
- add vllm-wrapper
- add audio.cpp

fixes: #714, #985, #998,
v250
2026-08-14 08:45:40 -07:00
Benson WongandGitHub 44a17d70df README.md: reorder list of features
Linux CI / run-tests (push) Failing after 13s
UI Tests / run-tests (push) Successful in 1m50s
Windows CI / run-tests (push) Canceled after 0s
- add section for audio.cpp 
- make /comfyui/ endpoint more clear
- small tweaks
2026-08-13 22:58:10 -07:00
Spitsyn Andrey AleksandrovichandGitHub 3bccbefe4d Support argv-based vLLM startup in vllm-wrapper (#979)
Improve vllm-wrapper support for native vLLM installations and systemd-managed vLLM processes.

It introduces three related features:

    Passing the vLLM startup command as separate arguments after --.
    Forwarding logs from a systemd user unit through the wrapper with --journal-unit.
    Terminating the active proxy after a successful sleep request with --stop-pid.
2026-08-13 22:44:22 -07:00
GeorgeandGitHub be683dc0ba ui-svelte,internal/server: show capability tags on Models page (#1007)
Add an opt-in setting to surface capability badges next to each model on the Models list. 
All capability tags from the Details tab are shown in canonical order,
each with a distinct muted pastel color; the context window badge sits
last (rightmost). Disabled by default to keep the list dense; toggle in Settings.

LLM Disclosure: Yes, GLM-5.2 helped along

Fixes #1006
2026-08-13 22:40:52 -07:00
Chaser HuangandGitHub 2edfa739c1 api: support /v1/task/run for audio.cpp (#982)
This PR enables llama-swap to route the [generic task
API](https://github.com/0xShug0/audio.cpp/blob/main/app/server/README.md#post-v1tasksrun)
from [audio.cpp](https://github.com/0xShug0/audio.cpp)

audio.cpp provides OpenAI-compatible transcriptions and speech API, thus
already supported by current main branch llama-swap. This further PR
enables audio-related tasks like VAD or audio-gen to be routed to an
audio.cpp backend.
2026-08-13 22:38:17 -07:00
Benson WongandGitHub be50598239 AGENTS.md: tweak rules around pull requests 2026-08-11 20:27:58 -07:00
Benson WongandGitHub 3e583ade9b CONTRIBUTING.md: update rules
Recently issues and pull requests are coming in at the same time. Updating the rules to clarify what is acceptable.
2026-08-11 20:24:51 -07:00
cphlipotandGitHub 038ae45942 expose meta.n_ctx on models endpoint (#984)
Linux CI / run-tests (push) Failing after 2m30s
Windows CI / run-tests (push) Canceled after 0s
Some tools are trying to auto-detect max context size for models
using llama.cpp's /models endpoint instead of /props since it is
exposed in both places.

Add the meta.n_ctx to the /models response to improve compatibility
with other tools.

updates: #999
2026-08-11 12:25:03 -07:00
cphlipotandGitHub 6333ee355d router: add /models endpoint (#983)
Updates #999
2026-08-11 12:24:14 -07:00
Benson WongandGitHub f94c94ac61 various: improvements to code layout and naming (#1003)
Validate JSON Schema / validate-schema (push) Successful in 46s
UI Tests / run-tests (push) Successful in 52s
Linux CI / run-tests (push) Successful in 4m11s
Windows CI / run-tests (push) Canceled after 0s
- rename model.workarounds to model.compat
- rename internal/shared to internal/swaputil, a better package name
v249
2026-08-09 23:21:10 -07:00
Benson WongandGitHub 249797faad internal/server: add ComfyUI compatibility endpoint (#1002)
Add a dedicated /comfyui/ passthrough backed by the reserved
comfyui_auto local model.

- preserve escaped upstream paths such as encoded workflow separators
- allow only the root path to start an unloaded ComfyUI model
- enforce a minimum concurrency limit of 50 for the reserved model
- add example upstream.ignorePaths to prevent unintentional swaps by
ComfyUI
- add model.workarounds.ignoreWebsockets so ComfyUI does not block
swapping

fixes: #1001
fixes: #1000
2026-08-09 22:01:42 -07:00
Benson WongandGitHub 00515cdf37 internal/server,shared: preserve percent encoded in upstream (#988)
Linux CI / run-tests (push) Failing after 3m7s
Windows CI / run-tests (push) Canceled after 0s
fixes: #986
closes: #987
updates: #1000
v248
2026-08-08 10:26:02 -07:00
Benson Wong 40027d62fd ui-svelte: security update
Linux CI / run-tests (push) Successful in 3m42s
UI Tests / run-tests (push) Successful in 1m4s
Windows CI / run-tests (push) Canceled after 0s
v247
2026-08-04 05:35:06 +00:00
Benson WongandGitHub 298848de59 internal/hw: detect inference host hardware (#978)
Detect the hardware available to the inference host and expose it
through the API and UI.

- Detect operating system, CPU, memory, and accelerator details
- Provide a hardware snapshot endpoint with platform-specific collectors
- Show an overview and copyable text summary in the UI

update: #977
2026-08-03 22:34:07 -07:00
Benson WongandGitHub 22df230ba7 ui-svelte: show configured selectors and strategies on Models page (#975)
UI Tests / run-tests (push) Successful in 1m6s
Linux CI / run-tests (push) Failing after 2m50s
Windows CI / run-tests (push) Canceled after 0s
Surface selector strategy and targets via the existing /v1/models
listing (meta.llamaswap) and render them in a Selectors card under the
Profiles card.

- add strategy, targets, and spillover to selector records in /v1/models
- map selector metadata onto Model in the playground models loader
- render Selectors card: id - name, description, linked targets
- move the unlisted-models toggle into the Local models header
- rename "Profile models" section to "Profiles"

fix: #974
v246
2026-08-02 19:52:39 -07:00
Michel MartiandGitHub 8d61908b13 internal/perf: fix rocm-smi GPU memory utilization (#973)
Linux CI / run-tests (push) Failing after 2m39s
Windows CI / run-tests (push) Canceled after 0s
2026-08-02 08:18:38 -07:00
Michel MartiandGitHub 1f3c68edb6 docker: install rocm-smi for vulkan backend (#968)
Add the rocm-smi package to the vulkan container image so performance
monitoring for AMD GPUs is available out of the box.
2026-08-01 06:09:16 -07:00
Benson WongandGitHub 30470a4d72 ui-svelte: show profiles on model page (#966)
UI Tests / run-tests (push) Successful in 59s
Show active profile mappings separately from configured local and peer
models.

- display profile pin targets and disabled mappings
- group local and peer models into dedicated sections
- identify the selected profile with an active status badge

fix: #961
v245
2026-07-30 21:53:36 -07:00
Benson WongandGitHub 27782ab563 AGENTS.md,CONTRIBUTING.md: update contribution guidelines (#964)
Build Containers / build-and-push (cpu) (push) Failing after 52s
Build Containers / build-and-push (cuda) (push) Failing after 51s
Build Containers / build-and-push (cuda13) (push) Failing after 53s
Build Containers / build-and-push (intel) (push) Failing after 51s
Build Containers / build-and-push (rocm) (push) Failing after 58s
Build Containers / build-and-push (musa) (push) Failing after 1m0s
Build Containers / build-and-push (vulkan) (push) Failing after 47s
Build Containers / delete-untagged-containers (push) Skipped
- add CONTRIBUTING.md
- update AGENTS.md to be clearer and more concise

Fixes: #956
Closes: #821
2026-07-30 00:02:02 -07:00
Benson WongandGitHub b9c3738d81 docker: add -watch-config (#963)
automatically reload the configuration when it changes

updates: #905
2026-07-29 22:49:10 -07:00
Benson WongandGitHub 0c4233363e internal/matrix: solve matrix expressions symbolically (#960)
Linux CI / run-tests (push) Failing after 14m55s
Windows CI / run-tests (push) Has been cancelled
Compile matrix DSL expressions into an immutable AST/DAG and evaluate
only the requested and running models when choosing evictions. This
removes eager Cartesian expansion and the maxDSLExpansions limit.

- move DSL parsing and symbolic evaluation into internal/matrix
- resolve aliases and link named references during compilation
- project each runtime query onto target and running-model bitsets
- memoize AST nodes and prune duplicate or dominated mask states
- preserve ordered tie-breaking and reconstruct full witness sets
- use symbolic containment for spillover selector validation
- compile programmatic matrix configurations on router creation
- document the design, complexity, and concurrency guarantees
- test one million theoretical combinations and over 64 models
- benchmark 100, 1K, 10K, and 100K theoretical combinations

Benchmarks ran on QEMU Virtual CPU 2.5+ with three 500 ms samples.

At 10K theoretical combinations:

- validation: 9.71 ms, 6.53 MB, and 81,401 allocs before; 12.38 us, 14.3
KB, and 122 allocs after
- solver setup: 1.31 ms and 1.37 MB before; 22.4 ns and 16 B after
- eviction solve: 809 us and 16 B before; 9.04 us and 7.97 KB after

At 100K theoretical combinations with the symbolic implementation:

- validation: 15.10 us, 16.1 KB, and 149 allocs
- solver setup: 23.6 ns, 16 B, and one allocation
- eviction solve: 16.17 us, 13.7 KB, and 193 allocs

At 100 combinations, solve time increases from 3.07 us to 4.72 us, and
allocation rises from 16 B to 3.82 KB. At 1K combinations, solve time
drops from 50.8 us to 7.23 us.

Written to GPT 5.6-Sol (high). Verified and reviewed with Opus 5 and
Kimi K3.
I don't understand what's going because these models know more than me
on writing a DSL compiler.

fixes #951
v244
2026-07-27 22:49:23 -07:00
Benson WongandGitHub 4c50064e3d internal/config: relax matrix model reference constraints (#957)
Linux CI / run-tests (push) Failing after 2m42s
Validate JSON Schema / validate-schema (push) Failing after 14m55s
Windows CI / run-tests (push) Has been cancelled
- increase matrix.var id size to 32 characters and allow - and .
- model IDs can be used in matrix sets and evict_costs

fixes: #699
closes: #715
v243
2026-07-25 21:52:35 -07:00
Ilya KislenkoandGitHub 4bffcfa539 cmd/vllm-wrapper: add helper for sleep/wake (#941)
add a standalone cmd/vllm-wrapper that can be used in cmd and 
cmdStop configurations for signaling vLLM to sleep or wake a model
2026-07-25 21:49:29 -07:00
Benson WongandGitHub fa607fe04e internal/config: refactor macro expansion (#955)
Resolve configuration macros against an untyped YAML representation
before decoding the typed Config. This materializes YAML anchors and
preserves scalar types without maintaining field-specific replacement
paths.

- apply environment, global, and model macros in their defined scopes
- centralize MODEL_ID, PORT, PID, key, and unknown-macro handling
- remove the capability-specific raw decoder and replacement loops
- document macro ordering, scope, and runtime behavior
- add coverage for anchors, scope isolation, validation, and runtime
macros

fixes #919
2026-07-25 21:46:29 -07:00