feat(evals): multi-turn conversation category + Personal posture for eval container - #616
Merged
Conversation
…ntainer Adds a dedicated Multi-Turn Conversation category to the eval suite that exercises `chat -p --resume` across 2-5 turn scripted sessions and captures per-turn cache + timing metrics. Infrastructure: - eval_metrics gains a turn_number column (PK now includes it) - run_prompt_resume: new helper that invokes chat -p --resume against a named session and appends output to a shared per-case STDOUT_FILE so existing assertion helpers work against the full concatenated transcript - run_multi_turn_case: runs N scripted prompts through one session per run, captures per-turn metrics via the LAST_TURN_USAGE_LINE hand-off - print_metrics_summary: new "Multi-Turn Cache Evolution" section shows cached vs uncached tokens and prompt_ms trending per-turn so cache growth/decay is visible at a glance Cases: - multi_turn_text_recall: 3 turns, pure text recall across a distractor - multi_turn_text_growth: 5 short chit-chat turns (cache growth probe) - multi_turn_tool_carryover: 2 turns, tool result → text recall - multi_turn_tool_repeat: 3 turns, two distinct file reads + recall - multi_turn_python_app: 4 turns — write greet() function, add __main__ and run it, recall signature from memory, add style parameter and run twice. Exercises the full text↔tool alternation pipeline. Eval container now runs as Personal deployment posture. Previously the container inherited StrictDefaults=true → Public audience → shell_disabled, which silently degraded shell_execute tool calls to policy denials. Assertions that only checked for the [tool:call] marker never caught it. Setting DeploymentPosture=Personal + ShellExecutionMode=HostAllowed + StrictDefaults=false lets all tools execute for real. HeadlessChannel plain-text usage line fix: when the turn streamed text deltas (Console.Write without newline), force a newline before the [usage] line so downstream parsers can anchor on ^[usage].
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a dedicated Multi-Turn Conversation category to the eval suite that exercises
chat -p --resumeacross 2-5 turn scripted sessions and captures per-turn KV cache + timing metrics. Also fixes a latent eval container misconfiguration that was silently degrading shell-using cases to tool-call-marker-only checks.What's new
Multi-turn eval infrastructure
eval_metricstable gains aturn_numbercolumn (primary key now includes it)run_prompt_resume— new helper that invokeschat -p --resume <session>against a named session and appends output to a shared per-caseSTDOUT_FILEso existing assertion helpers still work against the full concatenated transcriptrun_multi_turn_case— runs N scripted prompts through one session per run, captures per-turn metrics via aLAST_TURN_USAGE_LINEhand-offprint_metrics_summary— new "Multi-Turn Cache Evolution" section showscachedvsuncachedtokens andprompt_mstrending per turn so cache growth/decay is visible at a glanceNew Category 8: Multi-Turn Conversation (5 cases)
multi_turn_text_recallmulti_turn_text_growthmulti_turn_tool_carryovermulti_turn_tool_repeatmulti_turn_python_appEval container posture fix (the latent bug)
Previously the eval container inherited strict defaults:
Existing cases like `complex_diagnose_self` and `tool_shell` were "passing" because their assertions only checked for the `[tool:call] shell_execute` marker in stdout — which fires whether execution succeeds or is denied. The model was requesting shell, getting policy-denied, and the assertion was happy.
Fix: eval container now runs as:
```
NETCLAW_Security__DeploymentPosture=Personal
NETCLAW_Security__ShellExecutionMode=HostAllowed
NETCLAW_Security__StrictDefaults=false
NETCLAW_Tools__ShellMode=HostAllowed
```
SignalR/headless sessions already resolve to `TrustAudience.Personal`, and the Personal profile's default `ApprovalPolicy=null` means all tools are Auto-approved. Now shell_execute runs for real.
HeadlessChannel plain-text usage line fix
When a turn streams text deltas (
Console.Writewithout newline), the subsequent[usage]line landed at the tail of the same line instead of on its own line, breaking^[usage]anchors. Now we emit a newline before the usage line when deltas happened during the turn.Verified results
1-iteration eval run on this branch (
c5ca08ff-...):Performance baseline observation (saved to memorizer)
The Cache Evolution table reveals that conversation history is NOT being cached across turns in the current testlab setup.
cached_tokensstays flat at ~4781 (system prompt only) whileuncachedgrows linearly with conversation length. This is because Caddy round-robins same-session requests between the two llama-server GPU processes, so follow-up turns hit a cold cache 50% of the time.Example from
multi_turn_python_app:This is exactly the baseline measurement needed to validate session-sticky routing once it lands. Stored in memorizer under Local LLM Strategy project.
Test plan
Out of scope (follow-ups)