diff --git a/skills/lemonade-router-builder/SKILL.md b/skills/lemonade-router-builder/SKILL.md index c5f094a..cb32839 100644 --- a/skills/lemonade-router-builder/SKILL.md +++ b/skills/lemonade-router-builder/SKILL.md @@ -237,6 +237,13 @@ The `x-lemonade-route` response header carries the matched rule id (or `x_lemonade_route`: `{ route_to, matched_rule, default_used, outputs, trace[] }` - useful for verifying each rule fires as expected. +**Read `default_used`, not the rationale.** A fallback returns HTTP 200 with no +error, so the silent failure Step 4 warns about is invisible unless you check +the trace. `"default_used": true` with `"matched_rule": ""` is the signature. +In Mode A an empty `rationale` on its own is *not* a fallback signal - a +successful route to a non-first candidate commonly returns one. See +[reference.md](reference.md#reading-a-mode-a-trace). + ## Defaults summary | Field | Default when the user doesn't say | diff --git a/skills/lemonade-router-builder/examples.md b/skills/lemonade-router-builder/examples.md index 9bdc050..ceb2c21 100644 --- a/skills/lemonade-router-builder/examples.md +++ b/skills/lemonade-router-builder/examples.md @@ -7,6 +7,19 @@ should produce. Note what was defaulted: names, ids, thresholds, `on_error`, is derived from the default candidate rather than a fixed literal, so the examples below each get a distinct name. +**These are shape references, not runnable policies.** Each names models a +given host may not have. They all pass `scripts/validate.py`, which +deliberately cannot check model existence - that needs a live server. Register +one against a host missing a referenced model and the server rejects it: + +``` +400 Collection component not registered: ''. + Pull or register it before referencing it in a collection. +``` + +That is correct, documented behaviour. Substitute models the target host +actually has (`GET /api/v1/models`) before registering. + ## 1. Pure intent, no concrete signals → LLM-as-router diff --git a/skills/lemonade-router-builder/reference.md b/skills/lemonade-router-builder/reference.md index 6bf2ece..1a59aaa 100644 --- a/skills/lemonade-router-builder/reference.md +++ b/skills/lemonade-router-builder/reference.md @@ -190,6 +190,29 @@ for keyword/metadata conditions. Registration errors come back as descriptive parser messages (e.g. `routing.default_model 'X' must be listed in routing.candidates`); fix the field it names and re-POST. +### Reading a Mode A trace + +Mode A has no author-supplied rule ids, so `matched_rule` reports synthetic +ones - `__route_0`, `__route_1`, ... - one per entry in `routing.candidates`, +in declaration order. + +Two things about these traces are easy to misread. Observed at 11.5.2: + +- **An empty `rationale` is not a failure signal.** Routing to a candidate + other than the first commonly returns `"rationale": ""` and `"score": 0.0` + on a perfectly successful decision. +- **Fallback has one unambiguous signature** - all three together: + + ```json + { "default_used": true, "matched_rule": "", "rationale": "", "score": 0.0 } + ``` + + with `x-lemonade-route: default`. Check `default_used`, not the rationale. + +A fallback returns HTTP 200 with no error field, so a policy that falls back on +every single request is indistinguishable from a working one unless you ask for +the trace. + ## Desktop-editor compatibility Users may open the generated policy in the Lemonade desktop app's Hybrid