From f025c811c02662311ace686fd9e2470a335bb1d5 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Fri, 25 Sep 2026 17:44:36 -0700 Subject: [PATCH] decisions: open, a reason in invalid-arguments refusals (M5b) Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/decisions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/decisions.md b/docs/decisions.md index 525bf3a..257232c 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -64,6 +64,7 @@ Newest first. A decision that changes `docs/design.md` lands in the same commit | Thinking cap size. It starts at 4,096 tokens so that the right size can be found from data. From M2b every completion logs its reasoning-token count and whether the cap fired. Revisit once 200 completions are logged, or sooner if the owner sees answers cut short: raise the cap if more than 5% of completions hit it. Each hit also costs a re-read of that turn. | after M2b has run for a while | | Whether `proto`'s structs should refuse the JSON array form. serde's derived `Deserialize` accepts `[…]` in field order, so `"body":[]` decodes as `Empty`; true of every `proto` struct since M1. Not an authority problem (the values are validated the same way); closing it needs hand-written `Deserialize` for every struct. Found by the M3a plan checks. | before M7 | | Repository licence. Crates are `publish = false` until it is chosen. | before publishing | +| A reason in an invalid-arguments refusal. `loopd` answers every `invalid_arguments` denial with one fixed sentence, because `proto::DenyReason` carries no detail; on the device (2026-09-25) the model needed two extra calls to find that `note` takes no `file`. Giving the reason means a detail in `ToolResponse::Denied`: a wire change (fixtures, `loopd`, the audit log), and a choice about echoing model-written text. | M5b | | Audit integrity beyond a self-contained hash chain (for example anchoring the chain head outside `brokerd`). Deferred by the owner on 2026-09-17 to a later revision. | after v0 | | How an approval whose arguments do not fit one Mattermost post is shown. Settled on 2026-09-18: what is being approved is never truncated, in any channel, because the unseen tail is where injected text would put its payload; `bxctl` prints arguments in full. Leading option for Mattermost: a thread of numbered chunks split on character boundaries of the escaped text, where only a reply or reaction on the last post counts and that post repeats the id, the chunk count and the hash of the whole; above some number of chunks, the post points to `bxctl approvals` and approval is local only. The post size limit and rate limits must be checked against the Mattermost API reference first. | M4 | | Secret store: settled 2026-09-23 (systemd credentials, environment, owner-only file; P15 proposed). Where `brokerd` reads tool secrets from, and whether `SecretStore` moves out of `gatewayd` into a shared place, is decided when a tool first needs a secret. | when a tool needs a secret |