Conversation
`ask` checked that the questions hash was non-empty and sent whatever was
in it. `questions: { "q" => "is this urgent?" }` was serialized, posted,
billed as input tokens, and came back as MissingAnswers -- a report that
the answer was missing for a question that was never a question. An
unknown type behaved the same way, and a choice question with no criteria
earned a 422.
Two ids that stringify to the same thing were worse than a wasted
request. Answers come back keyed by the stringified id, so `:a` and `"a"`
in one map are two questions, one answer, and a MissingAnswers naming
whichever one lost.
Validate the map before building the body: each value a Hash, a type from
the three the API defines, instructions present, and the criteria that
type requires (1..255 options for choice, 2..10 levels for score, the
same bounds the builders enforce). Blank and colliding ids are refused.
RequestError names the id.
Hand-rolled question hashes are now held to the same rules as built ones,
which is the point: the builders were the only validation, and nothing
made you use them. Questions.validate! is public so a caller assembling
questions elsewhere can run the same check.
nil instructions are allowed through: EntryType in the official SDKs
covers null for state, instructions, and criteria alike.
Co-Authored-By: Claude Opus 5 (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.
askchecked that the questions hash was non-empty and sent whatever was in it.That request was serialized, posted, and billed as input tokens, and came back as a report that the answer was missing for something that was never a question. An unknown type behaved the same way; a choice question with no criteria earned a 422.
Two ids that stringify to the same thing were worse than a wasted request. Answers come back keyed by the stringified id, so
:aand"a"in one map are two questions, one answer, and aMissingAnswersnaming whichever one lost.The fix
Validate the map before building the body: each value a Hash, a type from the three the API defines, instructions present, and the criteria that type requires (1..255 options for choice, 2..10 levels for score — the same bounds the builders enforce, which do match the docs). Blank and colliding ids are refused.
RequestErrornames the id and nothing goes out.Hand-rolled question hashes are now held to the same rules as built ones, which is the point: the builders were the only validation and nothing made you use them.
Questions.validate!(question, id:)is public for callers assembling questions elsewhere.nilinstructions are allowed through —EntryTypein the official SDKs coversnullfor state, instructions and criteria alike.Tests
test/question_validation_test.rb, 18 cases, each asserting the transport was never called. One existing test that asserted the send-then-fail behaviour for an unknown type now asserts it's refused first.Draft: part of a security and API-coverage audit, opened for reference rather than as a request for immediate review. Independent of the other branches, each off
main. Suite green on Ruby 3.2.11, 3.3.8 and 3.4.8.🤖 Generated with Claude Code