sheet_without_consent
A Pool's sheet names the job's parties to the members who read it, and the client hasn't consented before the first Task posts.
| Fix | Fails in | Suggests | Exit |
|---|---|---|---|
| Add a consent ask to the client ahead of the first role step: { ask: 'client', to: 'consent' }. | services/translation.ts:12 · deliver | deliver.consent: { ask: 'client', to: 'consent', expires: '7d' } | 1 |
Owned by Buyer, client, party: the page that explains what this gate holds.
✗ A Pool's sheet names the job's parties to the members who read it, and the client hasn't consented before the first Task posts. Add a consent ask to the client ahead of the first role step: { ask: 'client', to: 'consent' }. The translators Pool's sheet names the parties to the member who reads it, and translation posts its first Task with no consent from the client before it.
at services/translation.ts:12 · deliver
✗ 1 to fiximport { Service } from 'services.dev'
import { translators } from '../pools/translators.ts'
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: { pool: translators } },
deliver: {
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
sign: { by: 'translator', stamp: true },
},
price: 89,
})diff --git a/services/translation.ts b/services/translation.ts
index a72a731..5b336a0 100644
--- a/services/translation.ts
+++ b/services/translation.ts
@@ -10,6 +10,7 @@ export default Service({
rules,
roles: { translator: { pool: translators } },
deliver: {
+ consent: { ask: 'client', to: 'consent' },
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'] },
sign: { by: 'translator', stamp: true },✓ ready to sell · 1 Service · it keeps at least 80% of every jobimport { Pool } from 'services.dev'
export const translators = Pool({
name: 'translators',
roles: { translator: { credential: 'sworn translator' } },
join: { name: 'text', languages: 'language[]' },
verify: 'https://verify.example.test/translators',
sees: { teaser: ['act', 'fee_usd'], sheet: ['parties'] },
clear: { attest: ['I checked conflicts'], check: ['client'] },
fill: ['raise 10% 2h', 'widen 4h'],
})How the legal example passes this gate, in lines read from its files.
sees: { teaser: ['act', 'region', 'fee_usd', 'signals'], sheet: ['parties', 'kind', 'amount'] },
clear: { attest: ['I checked conflicts across my full book, including my firm'], check: ['client', 'applicant', 'recipient'] },deliver: {
consent: { ask: 'client', to: 'consent', expires: '7d' },Read them in context: The attorneys' Pool, Contract review.
{
"code": "sheet_without_consent",
"reason": "A Pool's sheet names the job's parties to the members who read it, and the client hasn't consented before the first Task posts.",
"next": "Add a consent ask to the client ahead of the first role step: { ask: 'client', to: 'consent' }. The translators Pool's sheet names the parties to the member who reads it, and translation posts its first Task with no consent from the client before it.",
"doc_url": "https://services.dev/docs/reference/check/sheet_without_consent",
"file": "services/translation.ts",
"line": 12,
"path": "deliver",
"suggest": {
"path": "deliver.consent",
"value": "{ ask: 'client', to: 'consent', expires: '7d' }"
}
}The whole document check --json prints
{
"ai": {
"cents_per_call": 42,
"simulated": true
},
"mcp": {
"tools": 13,
"tokens": 4529,
"sandbox": 9,
"budget": 8000
},
"files": [
{
"path": "rules.ts",
"lines": 6,
"kind": "rules",
"says": "rules 2026-10 · 1 Service · 1 row"
},
{
"path": "pools/translators.ts",