Detect streamed tool-call anomalies without quantization claims #102

Open
nsaspy wants to merge 12 commits from feat/58-tool-call-anomaly into fix/61-alert-policy
Owner

Tracks the first bounded detector family from #58, stacked on the verified #61 transport/policy stack.

What changed

  • reconstruct non-streaming and SSE-streamed tool calls by stable tool-call index before validation, including interleaved calls and fragmented function names/arguments;
  • normalize providers that resend cumulative or repeated full function names so wea + weather + weather reconstructs as weather, not duplicated text;
  • emit deterministic tool_arguments_invalid_json model-behavior evidence for complete reconstructed arguments that fail JSON decoding;
  • emit a separate tool_name_not_requested detector when the reconstructed function name is absent from the request's declared tool/function set;
  • valid split/interleaved tool calls emit no anomaly;
  • persist append-only anomalies.jsonl through a dedicated AnomalyActor;
  • run live anomaly analysis only after transport classification accepts a clean completed response, so malformed partial tool args from a truncated/error stream remain transport evidence only;
  • keep detector persistence best-effort so anomaly analysis cannot block forwarding, immutable capture, transport evidence, recovery, or expert projection;
  • exclude prompt text and raw tool arguments from anomaly projections; evidence contains bounded structural metadata only;
  • default quantization to unknown; an explicitly grounded quantization value may annotate the observation but does not change detector ID or score;
  • record verified boundaries in Org-roam and the project Prolog KB.

RED evidence

Initial test-only head d9660780546156ad14391815192f5713d1318f7f: 134 tests ran; exactly six new tool-call contracts errored because llm_log.tool_call_anomaly did not exist. Every inherited transport/routing/alert contract stayed green.

Hardening test head ef16bf098f35c8e0f437aba2f1ac5804bb5cf0d5: 136 tests ran; exactly two failures exposed real missing behavior:

  • cumulative streamed function names reconstructed as weaweatherweather instead of weather;
  • live clean malformed tool calls did not produce anomalies.jsonl.
    Everything else remained green.

GREEN evidence

  • Initial implementation head 528c6e5cc4494ffccbc55260f7b3819f3bc51725: Analytics and Quota exact-head workflows both passed, including delivered package build.
  • Hardening/live implementation head a9ce4d44f9c0d234d8eafc110cc6984a419009de: Analytics run 84 and Quota run 89 passed, including full Python regression, adversarial analytics, delivered package build, cumulative-name normalization, live anomaly persistence, and the cross-domain regression proving transport-truncated malformed tool calls emit only stream_protocol_error and zero model anomalies.
  • Final exact head 0b910c52121b0a37c6395961d0994013da8a5b99: Analytics run 89 and Quota run 94 both passed after Org-roam/Prolog knowledge promotion; Quota again built the delivered Python package.

Boundary

This slice is observe-only model-behavior evidence. An anomaly is not automatically task failure, is not a transport error, and is not a bit-width detector. JSON Schema argument conformance, structured response-format violations, repetition/loop detection, output-length baselines, encoding corruption, self-correction signals, canary drift and any external anomaly notification transport remain separate #58 slices.

No merge is performed here.

Tracks the first bounded detector family from #58, stacked on the verified #61 transport/policy stack. ## What changed - reconstruct non-streaming and SSE-streamed tool calls by stable tool-call index before validation, including interleaved calls and fragmented function names/arguments; - normalize providers that resend cumulative or repeated full function names so `wea` + `weather` + `weather` reconstructs as `weather`, not duplicated text; - emit deterministic `tool_arguments_invalid_json` model-behavior evidence for complete reconstructed arguments that fail JSON decoding; - emit a separate `tool_name_not_requested` detector when the reconstructed function name is absent from the request's declared tool/function set; - valid split/interleaved tool calls emit no anomaly; - persist append-only `anomalies.jsonl` through a dedicated `AnomalyActor`; - run live anomaly analysis only after transport classification accepts a clean completed response, so malformed partial tool args from a truncated/error stream remain transport evidence only; - keep detector persistence best-effort so anomaly analysis cannot block forwarding, immutable capture, transport evidence, recovery, or expert projection; - exclude prompt text and raw tool arguments from anomaly projections; evidence contains bounded structural metadata only; - default quantization to `unknown`; an explicitly grounded quantization value may annotate the observation but does not change detector ID or score; - record verified boundaries in Org-roam and the project Prolog KB. ## RED evidence Initial test-only head `d9660780546156ad14391815192f5713d1318f7f`: 134 tests ran; exactly six new tool-call contracts errored because `llm_log.tool_call_anomaly` did not exist. Every inherited transport/routing/alert contract stayed green. Hardening test head `ef16bf098f35c8e0f437aba2f1ac5804bb5cf0d5`: 136 tests ran; exactly two failures exposed real missing behavior: - cumulative streamed function names reconstructed as `weaweatherweather` instead of `weather`; - live clean malformed tool calls did not produce `anomalies.jsonl`. Everything else remained green. ## GREEN evidence - Initial implementation head `528c6e5cc4494ffccbc55260f7b3819f3bc51725`: Analytics and Quota exact-head workflows both passed, including delivered package build. - Hardening/live implementation head `a9ce4d44f9c0d234d8eafc110cc6984a419009de`: Analytics run 84 and Quota run 89 passed, including full Python regression, adversarial analytics, delivered package build, cumulative-name normalization, live anomaly persistence, and the cross-domain regression proving transport-truncated malformed tool calls emit only `stream_protocol_error` and zero model anomalies. - Final exact head `0b910c52121b0a37c6395961d0994013da8a5b99`: Analytics run 89 and Quota run 94 both passed after Org-roam/Prolog knowledge promotion; Quota again built the delivered Python package. ## Boundary This slice is observe-only model-behavior evidence. An anomaly is not automatically task failure, is not a transport error, and is not a bit-width detector. JSON Schema argument conformance, structured response-format violations, repetition/loop detection, output-length baselines, encoding corruption, self-correction signals, canary drift and any external anomaly notification transport remain separate #58 slices. No merge is performed here.
Some checks failed
Analytics API / test (pull_request) Failing after 4s
Quota telemetry exact-head contract / quota-contracts (pull_request) Failing after 3s
Analytics API / package (pull_request) Has been skipped
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/58-tool-call-anomaly:feat/58-tool-call-anomaly
git switch feat/58-tool-call-anomaly

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch fix/61-alert-policy
git merge --no-ff feat/58-tool-call-anomaly
git switch feat/58-tool-call-anomaly
git rebase fix/61-alert-policy
git switch fix/61-alert-policy
git merge --ff-only feat/58-tool-call-anomaly
git switch feat/58-tool-call-anomaly
git rebase fix/61-alert-policy
git switch fix/61-alert-policy
git merge --no-ff feat/58-tool-call-anomaly
git switch fix/61-alert-policy
git merge --squash feat/58-tool-call-anomaly
git switch fix/61-alert-policy
git merge --ff-only feat/58-tool-call-anomaly
git switch fix/61-alert-policy
git merge feat/58-tool-call-anomaly
git push origin fix/61-alert-policy
Sign in to join this conversation.
No description provided.