client_decision_gated

The running jobjob_7Hq2 · delivered · document.fr-CA.pdf · $49.00 charged

A rules row reserves a decision to the client, and the step isn't an ask to the client, or a guard ahead of it refuses what the client would decide.

FixFails inSuggestsExit
Make the step an ask to the client party, and turn the guard into a signal: the client sees every offer.services/translation.ts:12 · deliver.choosedeliver.choose: { ask: 'client', to: 'decide', choices: [...] }1

Owned by Two sovereigns: the page that explains what this gate holds.

npx services.dev check
  ✗ A rules row reserves a decision to the client, and the step isn't an ask to the client, or a guard ahead of it refuses what the client would decide. Make the step an ask to the client party, and turn the guard into a signal: the client sees every offer. choose is the client's decision alone under rules 2026-10, and choose is done by ai: make it an ask to client.
    at services/translation.ts:12 · deliver.choose
✗ 1 to fix
services/translation.ts
import { Service } from 'services.dev'
import rules from '../rules.ts'

export default Service({
  name: 'Translation',
  description: 'A document, translated and signed.',
  input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA', client: 'party' },
  output: { document: 'file' },
  rules,
  roles: { translator: { credential: 'sworn translator' } },
  deliver: {
    choose: 'ai',
    translate: 'ai',
    harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
    sign: { by: 'translator', stamp: true },
  },
  price: 89,
})
git add -A && git diff --staged
diff --git a/services/translation.ts b/services/translation.ts
index f1b7df0..8bf1bf0 100644
--- a/services/translation.ts
+++ b/services/translation.ts
@@ -9,7 +9,7 @@ export default Service({
   rules,
   roles: { translator: { credential: 'sworn translator' } },
   deliver: {
-    choose: 'ai',
+    choose: { ask: 'client', to: 'decide', choices: ['formal', 'plain'] },
     translate: 'ai',
     harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
     sign: { by: 'translator', stamp: true },
npx services.dev check
✓ ready to sell · 1 Service · it keeps at least 80% of every job
rules.ts
import { Rules } from 'services.dev'

export default Rules({
  version: '2026-10',
  services: {
    translation: {
      sign: { reserved: 'sworn translator', where: '*', position: 'A sworn translator signs a translation filed with a registry.' },
      choose: { client: true, position: 'Which register a translation takes is the client\'s decision.' },
    },
  },
})

How the legal example passes this gate, in lines read from its files.

examples/legal/rules.ts
'demand-letter': {
// …
  settle: { client: true, position: 'Whether to settle, and for how much, is the client\'s decision alone.' },
examples/legal/services/demand-letter.ts
deliver: {
// …
  settle: { ask: 'client', to: 'decide', choices: ['accept', 'counter', 'close the file'], when: job => job.output.settlement !== undefined },

Read them in context: The rules table, Demand letter.

npx services.dev check --json · the client_decision_gated failure
{
  "code": "client_decision_gated",
  "reason": "A rules row reserves a decision to the client, and the step isn't an ask to the client, or a guard ahead of it refuses what the client would decide.",
  "next": "Make the step an ask to the client party, and turn the guard into a signal: the client sees every offer. choose is the client's decision alone under rules 2026-10, and choose is done by ai: make it an ask to client.",
  "doc_url": "https://services.dev/docs/reference/check/client_decision_gated",
  "file": "services/translation.ts",
  "line": 12,
  "path": "deliver.choose",
  "suggest": {
    "path": "deliver.choose",
    "value": "{ ask: 'client', to: 'decide', choices: [...] }"
  }
}
The whole document check --json prints
npx services.dev check --json
{
  "ai": {
    "cents_per_call": 42,
    "simulated": true
  },
  "mcp": {
    "tools": 13,
    "tokens": 4529,
    "sandbox": 9,
    "budget": 8000
  },
  "files": [
    {
      "path": "rules.ts",
      "lines": 7,
      "kind": "rules",
      "says": "rules 2026-10 · 1 Service · 2 rows"
    }
  ],
  "services": [