|
| 1 | +--- |
| 2 | +"@objectstack/spec": minor |
| 3 | +"@objectstack/platform-objects": patch |
| 4 | +--- |
| 5 | + |
| 6 | +feat(spec)!: remove `tool.requiresConfirmation` — a safety flag nothing enforced (#3715, ADR-0033 §2) |
| 7 | + |
| 8 | +`ToolSchema.requiresConfirmation` accepted `true` and no execution path ever read |
| 9 | +it. Not the LLM tool set (a tool reaches the model as name/description/parameters |
| 10 | +only), not `ToolRegistry.execute`, not `POST /ai/tools/:name/execute`, and not the |
| 11 | +MCP bridge — which derives `destructiveHint` from a hardcoded name list. Setting |
| 12 | +it on a destructive tool produced **no pause**. |
| 13 | + |
| 14 | +For an ordinary dead property that is untidy. For a **safety** property it is |
| 15 | +false compliance, which is the case ADR-0049 exists for: an author gates a |
| 16 | +destructive tool, sees the flag accepted, and ships believing a human is in the |
| 17 | +loop. It is made worse by the near-miss — `action.ai.requiresConfirmation` has |
| 18 | +the same name and **does** work, so the mistake reads as correct in review. |
| 19 | +ADR-0033 §2 already resolved to delete this one. |
| 20 | + |
| 21 | +## Migration |
| 22 | + |
| 23 | +- **FROM:** `requiresConfirmation: true` on a tool definition |
| 24 | +- **TO:** put the operation behind an action and set `ai.requiresConfirmation: |
| 25 | + true` there — that is the flag the HITL approval queue reads |
| 26 | + (`packages/runtime/src/action-execution.ts`) and the only path that actually |
| 27 | + stops execution. |
| 28 | +- For AI *metadata* mutations there is nothing to migrate: the ADR-0033 |
| 29 | + draft/publish workspace is the gate — nothing is live until a human publishes. |
| 30 | + |
| 31 | +**`ToolSchema` is now `.strict()`.** This is load-bearing, not tidying. Removing a |
| 32 | +key from a non-strict schema swaps one silent no-op for another: zod strips the |
| 33 | +key wordlessly, the author keeps writing it, and the safety flag goes on meaning |
| 34 | +nothing — the "silent strip" ADR-0032 / #1535 closed for objects. The retired key |
| 35 | +now **rejects**, and the error carries the FROM → TO above, because a parse error |
| 36 | +is the one channel every consumer bumping `@objectstack/spec` is guaranteed to |
| 37 | +hit. |
| 38 | + |
| 39 | +Strictness applies to *all* unknown keys on a tool definition, so a typo |
| 40 | +(`buildIn`, `catagory`) is now a located parse error instead of a silently |
| 41 | +dropped field. |
| 42 | + |
| 43 | +Also removed: the Studio form row, its four generated locale bundles (the |
| 44 | +`en`/`zh-CN`/`ja-JP`/`es-ES` strings still promised *"Ask user to approve before |
| 45 | +executing (for destructive actions)"* — a translated false promise), the |
| 46 | +liveness-ledger entry, and the generated reference-doc row. |
| 47 | + |
| 48 | +objectui's `ToolPreview.tsx` reads the field via `!!d.requiresConfirmation`, so it |
| 49 | +degrades to "not shown" with no error; removing that badge is a follow-up in that |
| 50 | +repo. |
0 commit comments