diff --git a/.corviduo-canonicals.toml b/.corviduo-canonicals.toml index 06ab4d6..7de677e 100644 --- a/.corviduo-canonicals.toml +++ b/.corviduo-canonicals.toml @@ -120,8 +120,8 @@ id = "worldtree-conversation-api-spec-v1" canonical_source = "Worldtree" canonical_path = "docs/conversation-api-spec.md" consumer_path = "docs/conversation-api-spec.md" -pinned_sha256_16 = "2d73d50b8680b893" -pinned_at = "2026-07-13T07:54:05+00:00" +pinned_sha256_16 = "70aabcb30af6c615" +pinned_at = "2026-07-18T18:51:00+00:00" tolerate_drift = true # prose reference; OpenAPI+SSE are the gates # Worldtree persona render canons (d2) — the deterministic affect->NL the agent is @@ -155,8 +155,8 @@ id = "worldtree-affect-egress-consumer-reference-v1" canonical_source = "Worldtree" canonical_path = "docs/affect-egress-consumer-reference.md" consumer_path = "docs/vendor/worldtree-persona-canon/affect-egress-consumer-reference.md" -pinned_sha256_16 = "b2406e237df00dcb" -pinned_at = "2026-07-13T07:54:05+00:00" +pinned_sha256_16 = "35eb71ba9090ad63" +pinned_at = "2026-07-18T18:51:00+00:00" tolerate_drift = true # prose reference; the d2 render-canon JSONs are the gates # --------------------------------------------------------------------------- diff --git a/docs/conversation-api-spec.md b/docs/conversation-api-spec.md index 2084d98..f3467a5 100644 --- a/docs/conversation-api-spec.md +++ b/docs/conversation-api-spec.md @@ -1,8 +1,8 @@ # Worldtree Conversation API — Client Interface Specification -**Version:** 1.0 -**Date:** 2026-04-15 -**Status:** Stable (pre-auth) +**Version:** 1.1 +**Date:** 2026-07-18 +**Status:** Stable **Contract:** `docs/contracts/conversation_api.contract.md` This document specifies the external interface for clients integrating with the Worldtree Conversation API. It is the reference for building web apps, TUI clients, bridges, or any system that needs to converse with Worldtree agents. @@ -1533,7 +1533,7 @@ for (const tc of items) { ## Ephemeral Templates (issue #161) -Ephemeral templates are a second tier of agent, distinct from foundational persistent agents (Mimir, Soong, etc.). They have no persona, no memory, no tools, and no motivational context. The consumer supplies the system prompt and (optionally) the model at session-create time; that config is frozen for the session's lifetime. +Ephemeral templates are a second tier of agent, distinct from foundational persistent agents (Mimir, Lofn, etc.). They have no persona, no memory, no tools, and no motivational context. The consumer supplies the system prompt and (optionally) a **role** — a purpose-named model role per ADR-0012, not a raw model id — at session-create time; that config is frozen for the session's lifetime. (The raw `model` selector was retired at the model-role cutover, 2026-06-09.) **Echo** is the first ephemeral template — a blank-slate per-session host that becomes whatever the consumer's system prompt instills. @@ -1548,8 +1548,8 @@ Authorization: Bearer { "ephemeral_templates": { "echo": { - "allowed_models": ["glm5-turbo", "glm4.7", "glm4.5-air", "granite-structured", "qwen3.6-35-a3b"], - "default_model": "glm5-turbo", + "allowed_roles": ["echo"], + "default_role": "echo", "system_prompt_max_bytes": 32768 } } @@ -1566,7 +1566,7 @@ POST /sessions "agent_id": "echo", "config": { "system_prompt": "You are a careful, skeptical frame-clarifier...", - "model": "glm5-turbo" + "role": "echo" } } ``` @@ -1580,9 +1580,10 @@ POST /sessions | `system_prompt_required` | `config.system_prompt` missing or null | | `system_prompt_empty` | `config.system_prompt` is whitespace-only | | `system_prompt_too_large` | `config.system_prompt` > 32768 bytes UTF-8 | -| `model_not_allowed` | `config.model` present but not in `echo_allowed_models` | +| `model_not_allowed` | `config.model` present and non-empty — the raw-model selector is retired; select via `config.role` | +| `role_required` | `config.role` present but empty or not a string | -**`config.model` resolution:** When `config.model` is omitted (or `null`), the server resolves it to `echo.default_model` from `config/defaults.yaml`. The resolved value is always populated in the session snapshot; `model` is never left absent or null in the stored config. +**`config.role` resolution:** When `config.role` is omitted (or `null`), the server resolves it to `default_role` (`"echo"`). The resolved value is always populated in the session snapshot; `role` is never left absent or null in the stored config. Role→model mapping happens server-side at turn time per ADR-0012 (`config/model_roles.yaml`); create-time validation does not enumerate models. **Response:** Same 201 shape as foundational sessions, with two new fields: @@ -1593,7 +1594,7 @@ POST /sessions "kind": "ephemeral", "config": { "system_prompt": "You are a careful, skeptical frame-clarifier...", - "model": "glm5-turbo" + "role": "echo" }, "message_count": 0, "created_at": "...", @@ -1612,7 +1613,7 @@ POST /sessions/{id}/messages SSE, cancel, `persist_partial`, rate limits, and error shapes are bit-identical to foundational sessions. The only differences are pre-turn: - **System prompt:** `session.config.system_prompt` verbatim — not extended with registry text, persona, or motivational context. -- **Provider:** resolved by `session.config.model`. +- **Provider:** resolved from `session.config.role` (role→model per ADR-0012). - **Tools:** empty `[]` — no tools loaded, no tool schemas declared. ### Scope diff --git a/docs/vendor/worldtree-persona-canon/affect-egress-consumer-reference.md b/docs/vendor/worldtree-persona-canon/affect-egress-consumer-reference.md index c2bc61d..1d7625f 100644 --- a/docs/vendor/worldtree-persona-canon/affect-egress-consumer-reference.md +++ b/docs/vendor/worldtree-persona-canon/affect-egress-consumer-reference.md @@ -7,8 +7,8 @@ available to consumers) versus what stays **hidden** (the rendered natural- language strings injected into the agent's system prompt, never emitted). **Source of truth:** the render code (`core/persona/renderer.py`, `core/persona/stance_render.py`) and the two vendored canon files -(`core/persona/canon/d2-mood-render-canon-v1.json` = mood/PAD; -`d2-render-canon-v1.json` = relationship). Owner of the canon strings: +(`core/persona/canon/d2-mood-render-canon-v2.json` = mood/PAD — the renderer +loads v2; `d2-render-canon-v1.json` = relationship). Owner of the canon strings: `brokkr-smithy-dev` (R22/R24 relational + mood render). ---