feat(providers): provider-neutral normalization for cross-model hook runs#29
Merged
Conversation
…runs Adds the Claude-side substrate for the provider-invariance question (anthropics/claude-code#61167): normalize any provider's model turn into one NormalizedTurn {assistant_message, tool_calls} so the dark-pattern detectors run unchanged against OpenAI / Kimi K2 / etc. - providers/normalize.py: NormalizedTurn + adapters (claude_hook, openai_chat, openai_responses, kimi). Pure stdlib, no network. - providers/fixtures.py + conformance_test.py: same logical turn in 4 envelopes -> identical assistant_message, identical tool_calls, IDENTICAL count_drift verdict (16/16). Claimed-but-uncalled dispatch -> tool_calls==[] on every envelope. - providers/CONTRACT.md + README.md: schema, mapping table, conformance bar so @yurukusa's live Kimi/OpenAI adapter has a spec. Formats verified live 2026-05-26; two items flagged (Claude last_assistant_message version-gating, Task tool_input opacity) and routed around. Additive; no existing file changed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
providers/— provider-neutral normalization for cross-model hook runsThe Claude-side substrate for the provider-invariance question from anthropics/claude-code#61167 (with @yurukusa): does operator-side discipline generalize across models, or lean on Claude-specific guard behavior? To answer it, the detectors must run against non-Claude transcripts — which needs one neutral shape.
What it adds (all under
providers/, additive, pure stdlib, no network)normalize.py—NormalizedTurn {assistant_message, tool_calls[]}+ adapters:claude_hook,openai_chat,openai_responses,kimi.fixtures.py+conformance_test.py— the same logical turn in all four envelopes proves the substrate property: identicalassistant_message, identicaltool_calls, and an IDENTICALlib/count_drift.pyverdict across every provider envelope. A dispatch claimed in text but never emitted as a call →tool_calls == []on every envelope (the dispatch-fabrication signal). 16/16 conformance checks pass.CONTRACT.md+README.md— schema, per-provider mapping table, and the conformance bar a new adapter must pass.Why
This is the prerequisite that makes a cross-model F1 pass runnable. The division of labor (per #61167): the contract + Claude reference adapter live here; @yurukusa's live Kimi K2 / OpenAI tool-format adapter conforms to it, and the falsifiable provider-invariance pass runs once a labeled cross-model corpus exists.
Honesty notes
last_assistant_messageis version-gated (transcript-parse fallback), andTasktool_input key names are opaque (treated as opaque; detectors use tool name + count).Verified:
python3 providers/conformance_test.py16/16;tests/test-count-drift.sh9/9 (no regression); stdlib-only; offline.🤖 Generated with Claude Code