A question that offers real choices, and says how many you may take
Three things about `ask_user`, all of them about the card being answerable rather than about the tool being callable. Options are required now, and they are objects: a label, and a line of description where the label alone does not say what choosing it would mean. "Rewrite it" and "Patch it" are two words that do not tell you which one loses your uncommitted work. They stack one per line, because a row of chips has nowhere to put the second line and no room to read the first. The model says whether they are exclusive. Only it knows whether its options are alternatives or a set, and the card has to show which -- a radio group offered where checkboxes were meant loses every answer but one. Exclusive is the default, being the cheaper mistake. A `multiple` question posts the same field name once per ticked box, so the endpoint gathers choices into a list; the `setdefault` it did before kept the first and dropped the rest, which is an answer that says something the reader did not. And "Something else" is added here, on every question, with the box behind it revealed by `:has()` and no JavaScript at all. The model is told never to write an "other" option of its own, because its version would be a choice with no box behind it -- a word submitted that means nothing. It carries a sentinel rather than an answer, and the endpoint swaps in what was typed beside it, or drops it when the box was left empty rather than telling the model the answer is "__other__". Typing no longer beats picking. That rule belonged to a box that was always visible next to the options; this one only exists once its own option is chosen, so picking is the answer and the box is one of the things you can pick. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ffe4966aac
commit
c0b72df6af
@@ -54,6 +54,32 @@ MAX_OPTIONS = 6
|
||||
# what it learned.
|
||||
MAX_QUESTIONS = 8
|
||||
|
||||
# The value the "Something else" row submits. A sentinel rather than a real
|
||||
# option, because it is the one choice on the card the model did not write: it
|
||||
# is added by this code, always, to every question. That is the whole reason the
|
||||
# model is told never to offer an "Other" of its own -- two of them is one that
|
||||
# does nothing, and the model's version would have no box behind it.
|
||||
OTHER = "__other__"
|
||||
|
||||
# How many characters of an option's description are kept. It is a sentence
|
||||
# explaining a choice, not a paragraph, and it is model output landing in a
|
||||
# card somebody is meant to read at a glance.
|
||||
MAX_OPTION_CHARS = 240
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Option:
|
||||
"""One answer offered for a question.
|
||||
|
||||
A `label` alone reads as a button; the optional `description` is what makes
|
||||
a real choice possible -- "Rewrite it" and "Patch it" say nothing about
|
||||
which loses your uncommitted work. Both are model output and are escaped
|
||||
where they are shown.
|
||||
"""
|
||||
|
||||
label: str
|
||||
description: str = ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Item:
|
||||
@@ -83,7 +109,18 @@ class Item:
|
||||
# explanation somebody reads as the application's own would be a card
|
||||
# vouching for it.
|
||||
purpose: str = ""
|
||||
options: tuple[str, ...] = ()
|
||||
options: tuple[Option, ...] = ()
|
||||
# Whether more than one option may be chosen. The model says which, because
|
||||
# only the model knows whether its options are alternatives ("rewrite or
|
||||
# patch") or a set ("which of these to include"). Exclusive is the default:
|
||||
# a radio group offered where checkboxes were meant costs one clarifying
|
||||
# round, while checkboxes offered for alternatives invite an answer that
|
||||
# contradicts itself.
|
||||
multiple: bool = False
|
||||
# Whether "Something else" is offered, with the box behind it. True for a
|
||||
# question -- the options are the model's guess at the answers and it can be
|
||||
# wrong -- and false for an approval, where the choice is Allow or Don't and
|
||||
# a third way out would mean nothing.
|
||||
allow_free_text: bool = True
|
||||
# Whether `detail` can be corrected before this is allowed. Only where the
|
||||
# detail *is* one argument and can be put back where it came from -- a tool
|
||||
|
||||
Reference in New Issue
Block a user