Correcting a command before allowing it
An approval card was Allow, Always, or Don't. A model proposing the right command with one flag wrong therefore cost a whole round trip to explain in prose. There is an Edit button on it now. Where the edit lands is the whole of the feature, and it is one line. `arguments` is the list `_run_calls` hands to `run_tool` as `parsed=`, and `run_tool` never re-parses -- so writing into it inside `_authorise` is the only mutation the runner can see. Editing the Item would do nothing: it is frozen and display-only. Two things had to move with it. The raw `call["arguments"]` string is rewritten beside the parsed dict, and the assistant turn is now built *after* `_authorise` rather than before it -- the old order told the model it ran what it proposed while something else ran, and every later round would have reasoned from a transcript that was quietly false. And `_remember_always` reads the edit, or "always allow this" would store a standing permission for a command nobody approved; it still derives the pattern itself through `policy.subject`, which yields nothing for a composed command line. Nothing is re-checked against the mode or the lists, and that is not a shortcut. The deny list resolves to ASK rather than to a refusal -- it means "always ask about this" -- so a person who has typed the command and pressed Allow is exactly the asking it was demanding, and re-asking would put the same card up with no way past it. It is the line the terminal panel already draws. The box is only offered where the detail *is* an argument and can be put back: a tool with no entry in `tool_labels.DETAIL_KEYS` gets a `k=repr(v)` summary, and a box there would silently change nothing. Both halves are always in the DOM with one hidden, rather than the field being created on click -- a field that does not exist until a handler runs is a field that submits nothing if the handler fails, and this one decides what runs on somebody's machine. The transcript says "edited by you". Attributing somebody's own typing to a model is the same misattribution as the other way round. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,7 +68,7 @@
|
||||
|
||||
{% else %}
|
||||
{% for item in ask.items %}
|
||||
<div class="interaction__question">
|
||||
<div class="interaction__question" x-data="{ editing: false }">
|
||||
<p class="interaction__title">{{ item.title }}</p>
|
||||
{% if item.purpose %}
|
||||
{# The model's own account of what this is for, above the thing itself.
|
||||
@@ -78,7 +78,44 @@
|
||||
<p class="interaction__purpose">It says: {{ item.purpose }}</p>
|
||||
{% endif %}
|
||||
{% if item.detail %}
|
||||
<pre class="interaction__detail">{{ item.detail }}</pre>
|
||||
{% if item.editable %}
|
||||
{#
|
||||
The command, correctable before it runs. A model proposing the right
|
||||
thing with one flag wrong is the common case, and Allow-or-Don't
|
||||
makes that a round trip to explain in prose.
|
||||
|
||||
Both halves are always in the DOM and one is hidden, rather than the
|
||||
box being created when Edit is pressed: a field that does not exist
|
||||
until a click is a field that submits nothing if the click handler
|
||||
ever fails, and this one decides what runs on somebody's machine.
|
||||
The textarea is disabled while hidden so an untouched card cannot
|
||||
post a `text.` field at all — that field means "this was edited",
|
||||
and an empty one arriving would be indistinguishable from a command
|
||||
somebody cleared.
|
||||
#}
|
||||
<div x-show="!editing">
|
||||
<pre class="interaction__detail">{{ item.detail }}</pre>
|
||||
<button class="btn btn--sm" type="button"
|
||||
@click="editing = true; $nextTick(() => $refs.edit{{ item.key }}.focus())">
|
||||
{{ icon("pencil", "icon--sm") }} Edit
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="editing" x-cloak>
|
||||
<label class="visually-hidden" for="edit-{{ item.key }}">
|
||||
Change this before it runs
|
||||
</label>
|
||||
<textarea class="textarea interaction__edit" id="edit-{{ item.key }}"
|
||||
name="text.{{ item.key }}" rows="3" spellcheck="false"
|
||||
x-ref="edit{{ item.key }}"
|
||||
:disabled="!editing">{{ item.detail }}</textarea>
|
||||
<p class="interaction__reason">
|
||||
Allow runs what is in the box. It is not checked against this
|
||||
chat's rules again — you typed it.
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<pre class="interaction__detail">{{ item.detail }}</pre>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if item.reason %}
|
||||
<p class="interaction__reason">{{ item.reason }}</p>
|
||||
|
||||
Reference in New Issue
Block a user