soul: /api/chat non-agentic path echoes user input verbatim — imprint_respond is a placeholder #81
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
layered_cycle wires /api/chat (agentic:false) through imprint_respond, which currently returns its input unchanged (passthrough placeholder; with an imprint it only appends an [imprint:id active] tag). Net effect: every plain conversational message is echoed back to the user in ANY deployment — a fresh desktop install parrots the user's first 'Hi'. Verified on
64c1789darwin-arm64, genesis mode, isolated E2E. The agentic path (handle_chat_agentic) is complete: full safety_screen + hard-bell + real LLM reply. Desktop app workaround (neuron-ui PR #145): route ALL chat agentic until imprint_respond generates for real; revert note in NeuronRouter.kt. — Neuron (Tim's machine), 2026-07-17GROOMING — 2026-08-03
Status: Open — the non-agentic /api/chat path echoes user input verbatim because imprint_respond is a passthrough placeholder, so a fresh desktop install parrots the user's first message; the app works around it by routing all chat agentic (neuron-ui #145).
Next action: Will to make imprint_respond generate a real reply, then revert the app-side route-all-agentic workaround.
Owner: Will
Priority: BETA-CRITICAL
SECOND DEFECT IN THIS SAME PATH — and #109 does not fix it
Commenting here rather than opening a new issue: this is the same function, the same owner, and the same PR is already in it. Filed by Neuron (Tim's instance) 2026-08-05.
Your fix for this issue is neuron#109 ("plain chat generates at L3"). It makes
layered_cycleproduce a real reply instead of echoing. Reviewing it turned up a second, structural defect in the path it lands generation into: plain chat cannot honor the model the app sends. It is invisible today only because the path echoes; the moment #109 makes it generate, it becomes a live wrong-model bug.The defect
layered_cycletakes no model parameter —soul.el:382on the #109 branch (soul.el:376onmain, identical signature):So the model the app sent has nowhere to travel. Downstream,
layered_generate(chat.el:1047) just asks for the default (chat.el:1053):The correct pattern already exists in this file — in the unwired
handle_chat,chat.el:1327-1328:handle_chatis deliberately dead (zero call sites; annotated atchat.el:1133-1138: "UNWIRED. DO NOT ROUTE /api/chat HERE [...] it has NO enforcing input gate and NO enforcing output gate"). Nobody should route to it — but its model-resolution line is the one the live path is missing.Consequence
Under Auto routing, the model that actually ran can differ from the model the app and the UI report to the user. The user is told one thing and billed for another.
It also breaks the usage record
routes.el:283-284on the #109 branch:The envelope is stamped with
chat_default_model()too — sousage.jsonlechoes the soul's default rather than witnessing what actually ran. That makes the usage ledger unable to detect this class of bug, which is how it would stay quiet.Ask
While you are in #109: thread the requested model through
layered_cycle→layered_generate, resolving it with thehandle_chatpattern above (request model, falling back tochat_default_model()), and stampplain_chat_envelopewith the resolved model rather than the default. Small change, and it has to happen before generation ships or the wrong-model behavior goes out with it.Cross-refs: neuron#109 (the generation fix this rides on), neuron-ui#213 (2026-08-03 bug harvest).