Skip to content

[feature] Approvals: decline a tool call with an instruction #326

Description

@AetherAI3

Problem and result

Tool approval currently returns a boolean and a denied call receives a generic “not approved” result. When the user wants a smaller change or an offline test instead, the model must guess why it was refused or wait for another chat turn.

Add an optional bounded instruction when declining a specific tool call, for example “Use the offline unit suite.” Return it once as part of that call’s denial result so the current run can choose a better next step.

Acceptance checks

  • Introduce a typed verdict containing approval/denial and optional denial feedback. Bind feedback to the original call ID and return it exactly once through the normal tool-result path on supported local and cloud host loops.
  • Feedback cannot approve the call, trigger execution, dispatch a slash/shell command, reset the failure budget, or cause a denied operation to be retried automatically. Preserve argument and authority checks.
  • Use a separate short-lived input buffer and lease for feedback. Bound its length and allow skipping/cancelling it; preserve the main draft, cursor, reviewed shell attachments, streaming input, and pending queue.
  • Retain existing non-TTY decisions and automatic approval behavior. Do not invent feedback for --yes or intercept PTY/password ownership. A declined call without a note retains a clear generic denial.
  • Feedback is ephemeral turn data, not new prompt history, generic logs, or RC fields. Any explicit transcript/export behavior follows the existing sharing contract.
  • Fixtures cover deny-with-note, deny-without-note, cancellation, concurrent queued input, duplicate call IDs/delivery, and local/hosted tool-result parity. Verify the denied executor never runs.

Landing boundary

This improves the interactive tool approval path. It does not duplicate remote-control structured verdict work in #302 or add persistent approval policies. Reuse the composer’s pure editing helpers under a distinct lease; do not add history search inside approval prompts.

Evidence and planning

Package: Run control and context. Priority: P2. Rough engineering estimate: 1–2 days, including focused fixtures; this is a planning estimate, not a measured benchmark.

Reviewed against v4.20.0 at 4f1717bc120917e1b04d0baa939855417ef866a4: src/core/tool_approval.ts, src/commands/code.ts, src/commands/chat.ts, test/tool_approval.test.ts.

Comparator: Claude Code permission prompts support answering with a comment. Aether can make a refused tool result equally actionable without expanding its authority.

Created from the LOOP-19 review of the README, all 23 open issues, four open PRs, and recent shipped work on 2026-10-09. These are proposed changes; the acceptance checks below have not been executed.

Activity

  1. added
    featureNew product capability or integration work
    on Oct 9, 2026
  2. AetherAI3 commented on Oct 9, 2026

    @AetherAI3
    OwnerAuthor

    Landed in PR #334 (squash commit 50c3c06df57d6108f57f22cc7f82b7d83dc34469); this issue closed on merge.

    Evidence:

    • npm run build passed.
    • npm run docs:check passed; all 6 generated documentation outputs match.
    • 126 focused tests passed across approval feedback, local and hosted tool results, composer input ownership, queued drafts, skill host loop, and failure budgets.
    • Fixtures verify a denied executor never runs; the original call ID receives its bounded note once; duplicate call IDs are suppressed; cancellation releases the separate input lease; and the main draft and queue remain intact.

    GitHub Actions CI could not start any job. The run annotation says the account is locked due to a billing issue (run 37957960203); those jobs ran no steps, so they provide no code result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew product capability or integration work

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions