Agents now recommend a decision, and adoption measures whether you agreed
Release notes 2026-09-15 — vocion-core#321 (merged): an action proposal carries suggestedDecision (approve, reject, snooze); the review API filters on it; adoption pairs the human's decision with the agent's advice. A reject recommendation can hold a run back from auto-execute, never release one.

Shipped: vocion-core#321, merged to main on 2026-09-15. Part of the 2026-09-15 release notes.
The outcome
Earned autonomy needs evidence, and the evidence is agreement: how often the agent's judgement matched the person's. Until now an agent could say how confident it was but never what it thought should happen, so the adoption metric read every approval as agreement — including the cases where the agent would have said no.
What it is
An action proposal may now carry proposal.suggestedDecision — approve, reject or snooze — plus an optional suggestedSnoozeUntil. Because proposal is a jsonb column with a TypeScript type, this is a type widening, not a new column; the numbered migration 0089 is a COMMENT ON COLUMN, paired with a concurrent index on (org_id, proposal->>'suggestedDecision') for pending and failed rows.
- The API surfaces and filters on it. Every pending row carries the recommendation;
GET /api/v1/reviews?suggestedDecision=rejectreturns only the items the agent wanted turned down. - Adoption measures agreement. The human's decision is paired with the advice: same outcome is agreement, different is disagreement.
editedandrewrittencount as approvals, matching how the existing approval rate already treats them. - The review card badges the recommendation, and the
propose_actionagent tool asks for it.
The one rule worth knowing
Fail-safe only. A reject or snooze recommendation can hold a run back from auto-execute; it can never release one. Confidence still governs the trust ladder (trust.yaml, docs/entities/trust.md). Three docstrings in packages/core/src/services/ReviewService.ts say so explicitly, because this is the kind of rule that gets relaxed by accident.
The vocabulary is deliberately two-tensed: the stored decision is past tense (approved, rejected), the recommendation present tense (approve, reject). Advice and fact are different things.
Why it matters for autonomy
The Product Design Manifesto says automation is earned — Observe → Recommend → Assist → Execute with approval → Execute within bounds → Operate autonomously — and every step up needs demonstrated performance. Agreement rate per action kind is that demonstration. When an agent has recommended the same decision the person made for weeks, a workspace has grounds to move that action class one rung up the trust ladder.
Two small fixes rode along: a blank decision reason falls through to the note, in the stored record and in the API.
The screenshot shows a decision screen from the Needs-you inbox on a local workspace; the recommendation chip is the same idea, surfaced on an ask.
Where this lives in the repo
- Service and the fail-safe rule:
services/ReviewService.ts(parseSuggestedDecision, the auto-execute hold) - Migration and index:
packages/core/migrations/0089_action_run_suggested_decision.sqland itsconcurrent/companion - API filter:
app/api/v1/reviews/route.ts(?suggestedDecision=) - Adoption agreement:
services/adoption/AdoptionService.ts - The agent tool:
services/agents/tools/proposeAction.ts - PR: #321, closing #320