Fix #282: lenient type coercion for workflow StructuredOutput#315
Open
ericleepi314 wants to merge 1 commit into
Open
Fix #282: lenient type coercion for workflow StructuredOutput#315ericleepi314 wants to merge 1 commit into
ericleepi314 wants to merge 1 commit into
Conversation
Weak models (glm) emit JSON types as strings ("42", "true", arrays as
JSON-encoded strings) and burned every schema-repair retry on trivially
coercible mismatches, making structured workflow stages effectively
Anthropic/OpenAI-only.
coerce_to_schema runs before strict validation in the collector: keyed
strictly on what the schema expects (never guessing from the value),
recursive through properties/items, never raises, and anything
uncoercible passes through so strict validation reports the real error.
ajv coerceTypes parity choices: "3.0" -> 3 for integer schemas; a
string satisfying a union with "string" is never rewritten; NaN /
Infinity strings are rejected (not valid JSON numbers); bools never
become ints. The tool records the coerced value everywhere so all
consumers see one schema-conformant shape.
Closes #282
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4 tasks
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.
Closes #282
Summary
Weak models (glm) return JSON types as strings —
"42","true", arrays as JSON-encoded strings — and the workflow engine's strictStructuredOutputvalidation burned all schema-repair retries on trivially coercible mismatches (PR #266's known follow-up).coerce_to_schema(obj, schema)— a lenient, never-raising pre-pass run before strict validation inStructuredOutputCollector.offer:"42"→42forinteger,"3.14"→3.14fornumber,"true"/"false"→bool forboolean, JSON-encoded strings→json.loadsforarray/object(type-checked, then recursively coerced), integral floats→int forinteger.properties/items;typemay be a string or list;anyOf/oneOfdeliberately untouched (documented).coerceTypesparity (from critic review against the reference semantics):"3.0"→3for integer-only schemas; a string already satisfying a union with"string"is never rewritten;"NaN"/"Infinity"strings are rejected (parse as floats but aren't valid JSON numbers — the critic caught that they'd silently enter the output contract); bools never become ints.The injected tool now records
collector.value(the coerced shape) in the outbox and tool result, so every consumer sees the same schema-conformant object.Test plan
"3.0"/"3.5"integer-only behavior, string-union no-rewrite, bool-never-int, uncoercible pass-through, genuinely-wrong-output still errors/exhausts🤖 Generated with Claude Code