@volter/twin-cohere 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +224 -0
  2. package/defaults/handlers.json +26 -0
  3. package/dist/defaults/handlers.json +26 -0
  4. package/dist/src/cli.d.ts +2 -0
  5. package/dist/src/cli.js +31 -0
  6. package/dist/src/cohere-budget.d.ts +55 -0
  7. package/dist/src/cohere-budget.js +171 -0
  8. package/dist/src/cohere-capabilities.d.ts +14 -0
  9. package/dist/src/cohere-capabilities.js +1852 -0
  10. package/dist/src/cohere-conformance.d.ts +17 -0
  11. package/dist/src/cohere-conformance.js +464 -0
  12. package/dist/src/cohere-connector.d.ts +150 -0
  13. package/dist/src/cohere-connector.js +625 -0
  14. package/dist/src/cohere-models.d.ts +21 -0
  15. package/dist/src/cohere-models.js +73 -0
  16. package/dist/src/cohere-scenario.d.ts +57 -0
  17. package/dist/src/cohere-scenario.js +176 -0
  18. package/dist/src/cohere-server.d.ts +16 -0
  19. package/dist/src/cohere-server.js +184 -0
  20. package/dist/src/cohere-stub.d.ts +119 -0
  21. package/dist/src/cohere-stub.js +321 -0
  22. package/dist/src/cohere-twin.d.ts +82 -0
  23. package/dist/src/cohere-twin.js +1243 -0
  24. package/dist/src/cohere-types.d.ts +226 -0
  25. package/dist/src/cohere-types.js +40 -0
  26. package/dist/src/index.d.ts +15 -0
  27. package/dist/src/index.js +84 -0
  28. package/package.json +71 -0
  29. package/src/cli.ts +30 -0
  30. package/src/cohere-budget.ts +197 -0
  31. package/src/cohere-capabilities.ts +1855 -0
  32. package/src/cohere-conformance.ts +489 -0
  33. package/src/cohere-connector.ts +709 -0
  34. package/src/cohere-models.ts +79 -0
  35. package/src/cohere-scenario.ts +194 -0
  36. package/src/cohere-server.ts +195 -0
  37. package/src/cohere-stub.ts +337 -0
  38. package/src/cohere-twin.ts +1290 -0
  39. package/src/cohere-types.ts +231 -0
  40. package/src/index.ts +159 -0
@@ -0,0 +1,1852 @@
1
+ // Cohere capability manifest — the EXPECTED REAL-PRODUCT SURFACE (the target), authored TOP-DOWN
2
+ // from what the Cohere API actually does — NOT from what this twin has built. This is the honest
3
+ // denominator: most entries start as `todo` and coverage reads LOW until the twin truly reaches
4
+ // 100% of the API. `verify()` (required to count as done) is ground truth; `expected:'done'` only
5
+ // on capabilities we genuinely claim, so a broken one shows as a regression.
6
+ //
7
+ // ── HOW THE DENOMINATOR WAS ENUMERATED (so it is not a self-portrait) ───────────────────
8
+ // Every operation cohere-ai@8.1.0 can issue was extracted during this build, from the SDK's own
9
+ // `reference.md` operation index cross-checked against the `core.url.join(..., "<path>")` literal
10
+ // in each generated client. That is **45 SDK methods over 33 distinct HTTP endpoints**:
11
+ //
12
+ // root client (11) : chat, chatStream, generate, generateStream, embed, rerank, classify,
13
+ // summarize, tokenize, detokenize, checkApiKey
14
+ // v2 (5) : chat, chatStream, parse, embed, rerank
15
+ // batches (4) : list, create, retrieve, cancel
16
+ // connectors (6) : list, create, get, delete, update, oAuthAuthorize
17
+ // datasets (5) : list, create, getUsage, get, delete
18
+ // embedJobs (4) : list, create, get, cancel
19
+ // finetuning (7) : listFinetunedModels, createFinetunedModel, getFinetunedModel,
20
+ // deleteFinetunedModel, updateFinetunedModel, listEvents,
21
+ // listTrainingStepMetrics
22
+ // models (2) : get, list
23
+ // audio (1) : transcriptions.create
24
+ //
25
+ // The twin serves 27 of those 33 endpoints. The six it does NOT serve (`/v1/generate` ×2,
26
+ // `/v1/summarize`, `/v2/parse`, `/v2/audio/transcriptions`, and the seven finetuning paths, plus
27
+ // the four batches paths) are enumerated below as `todo` — they are REAL Cohere surface, and a
28
+ // denominator that omitted them would be a self-portrait. So are the deployment planes the SDK
29
+ // also ships clients for (`AwsClient` / `BedrockClient` / `SagemakerClient`), which are Cohere
30
+ // models served through AWS rather than through api.cohere.com.
31
+ //
32
+ // ── THERE ARE NO CARVE-OUTS ─────────────────────────────────────────────────────────────
33
+ // The twin returns DETERMINISTIC STUBS for model generation, pseudo-vectors for embeddings, a
34
+ // lexical-overlap score for rerank and a hash heuristic for classify — and those ARE the twin's
35
+ // answer, not a shortfall from a "real" one. The protocol envelope (shapes, streaming, tool calls,
36
+ // UPPER-CASE finish reasons, two-level usage) is faithful. Every entry here is done or todo.
37
+ //
38
+ // The tokenizer is a TODO: Cohere's tokenizers are published, downloadable, static JSON artifacts,
39
+ // and this pack already SERVES their URLs from the model catalog, so vendoring one is fully offline
40
+ // and fully deterministic (`cohere.tokenize.bpe_vocabulary`).
41
+ //
42
+ // (Cohere is an API-first vendor: its dashboard is incidental tooling for keys, billing and usage,
43
+ // not where the work happens — docs/contributing/architecture.md C1b — so this pack ships no mirror, and there are
44
+ // no UI capabilities to verify.)
45
+ import { mkdtempSync, rmSync } from 'node:fs';
46
+ import { tmpdir } from 'node:os';
47
+ import { join } from 'node:path';
48
+ import { projectResources } from '@volter/world-core';
49
+ import { checkCapabilities, verifyBoundary, isInfrastructureError, harnessError } from '@volter/world-tooling';
50
+ import { CohereBudget, CohereBudgetError, cohereCallWeight } from "./cohere-budget.js";
51
+ import { checkCohereConformance } from "./cohere-conformance.js";
52
+ import { cohereRequestForAction, fullSyncCohere, liveCohereExecute, mapConnector, mapDataset, mapEmbedJob, pollTimestamp, pushPendingCohereActions, syncCohereFromReal, unpushableReason, } from "./cohere-connector.js";
53
+ import { COHERE_ENDPOINTS } from "./cohere-models.js";
54
+ import { createCohereScenarioEngine } from "./cohere-scenario.js";
55
+ import { handleCohereTwinRequest } from "./cohere-twin.js";
56
+ /** A FIXED `occurredAt` keeps ids/timestamps deterministic across runs. */
57
+ const PINNED_AT = '2026-08-31T12:00:00.000Z';
58
+ /** Run a sequence of real Cohere requests against an ISOLATED root; return all responses. The
59
+ * root is threaded EVERYWHERE — an omitted root silently falls back to the operator's real
60
+ * `~/.volter` state dir, which is gitignored, so the verify would pass while poisoning later
61
+ * runs. */
62
+ async function withRoot(steps) {
63
+ const root = mkdtempSync(join(tmpdir(), 'cohere-cap-'));
64
+ const h = (s) => handleCohereTwinRequest({
65
+ method: s.m, path: s.p, root, occurredAt: PINNED_AT,
66
+ ...(s.b === undefined ? {} : { body: JSON.stringify(s.b) }),
67
+ ...(s.h ? { headers: s.h } : {}),
68
+ ...(s.ro ? { readOnly: true } : {}),
69
+ });
70
+ try {
71
+ return await verifyBoundary('cohere.withRoot', () => steps(h));
72
+ }
73
+ finally {
74
+ rmSync(root, { recursive: true, force: true });
75
+ }
76
+ }
77
+ /** Collect the streaming events for a request against an isolated root. */
78
+ function withStream(path, body, fn) {
79
+ return new Promise((resolve, reject) => {
80
+ const root = mkdtempSync(join(tmpdir(), 'cohere-cap-'));
81
+ const events = [];
82
+ handleCohereTwinRequest({ method: 'POST', path, body: JSON.stringify(body), root, occurredAt: PINNED_AT, sseSink: (e) => events.push(e) })
83
+ .then((final) => resolve(fn(events, final)))
84
+ .catch((err) => { if (isInfrastructureError(err))
85
+ reject(harnessError('cohere.withStream', err));
86
+ else
87
+ resolve(false); })
88
+ .finally(() => rmSync(root, { recursive: true, force: true }));
89
+ });
90
+ }
91
+ /** A connector verify against a recording fake executor + an isolated root. */
92
+ async function withConnector(fn, reply) {
93
+ const root = mkdtempSync(join(tmpdir(), 'cohere-conn-'));
94
+ const calls = [];
95
+ const execute = async (method, path, body) => {
96
+ calls.push({ method, path, ...(body ? { body } : {}) });
97
+ return reply ? reply(method, path) : defaultVendorReply(method, path);
98
+ };
99
+ try {
100
+ return await verifyBoundary('cohere.withConnector', () => fn(execute, calls, root));
101
+ }
102
+ finally {
103
+ rmSync(root, { recursive: true, force: true });
104
+ }
105
+ }
106
+ // REAL-SHAPED vendor rows. A connector verify green over an input the vendor could not emit has
107
+ // proven fidelity against a client that does not exist, so these carry the FULL field set each
108
+ // mapper reads — every key the vendor's own schema declares required, not the subset a lax `?? null`
109
+ // default would paper over.
110
+ const REAL_DATASET = { id: 'ds-real-1', name: 'real-dataset', created_at: '2026-08-01T00:00:00Z', updated_at: '2026-08-02T00:00:00Z', dataset_type: 'embed-input', validation_status: 'validated', validation_error: null, validation_warnings: [], required_fields: ['text'], preserve_fields: [], dataset_parts: [], schema: null };
111
+ const REAL_CONNECTOR = { id: 'conn-real-1', organization_id: 'org-real', name: 'real-connector', description: 'the real one', url: 'https://real.test/search', created_at: '2026-08-01T00:00:00Z', updated_at: '2026-08-03T00:00:00Z', excludes: ['secret'], auth_type: 'oauth', oauth: { client_id: 'cid', authorize_url: 'https://a.test', token_url: 'https://t.test', scope: null }, auth_status: 'valid', active: true, continue_on_failure: false };
112
+ const REAL_EMBED_JOB = { job_id: 'job-real-1', name: 'real-job', status: 'processing', created_at: '2026-08-04T00:00:00Z', input_dataset_id: 'ds-real-1', output_dataset_id: null, model: 'embed-english-v3.0', truncate: 'END', meta: null };
113
+ /**
114
+ * The fake vendor's reply, keyed on METHOD **and** path.
115
+ *
116
+ * The method half is load-bearing: a path-only fake would answer `POST /v1/connectors` with the
117
+ * LIST envelope, so `pushCohereAction`'s id extraction would never once be exercised against a
118
+ * realistic create response and would silently fall back to the local subject id on every run —
119
+ * which is precisely the bug the duplicate-on-pull finding turns on. A LIST answers the collection;
120
+ * a CREATE answers the vendor's own (per-type, NON-uniform) create envelope.
121
+ */
122
+ function defaultVendorReply(method, path) {
123
+ const bare = path.split('?')[0];
124
+ if (method === 'GET') {
125
+ if (bare === '/v1/datasets')
126
+ return { datasets: [REAL_DATASET] };
127
+ if (bare === '/v1/connectors')
128
+ return { connectors: [REAL_CONNECTOR], total_count: 1 };
129
+ if (bare === '/v1/embed-jobs')
130
+ return { embed_jobs: [REAL_EMBED_JOB] };
131
+ return {};
132
+ }
133
+ if (method === 'POST') {
134
+ // Three DIFFERENT create envelopes, exactly as the vendor's schemas declare them.
135
+ if (bare === '/v1/connectors')
136
+ return { connector: { ...REAL_CONNECTOR, id: 'conn-vendor-minted' } };
137
+ if (bare === '/v1/embed-jobs')
138
+ return { job_id: 'job-vendor-minted', meta: null };
139
+ if (bare === '/v1/datasets')
140
+ return { id: 'ds-vendor-minted' };
141
+ if (bare.endsWith('/cancel'))
142
+ return {};
143
+ return {};
144
+ }
145
+ if (method === 'PATCH')
146
+ return { connector: { ...REAL_CONNECTOR, name: 'patched' } };
147
+ if (method === 'DELETE')
148
+ return {};
149
+ return {};
150
+ }
151
+ const ok = (r) => r.status >= 200 && r.status < 300;
152
+ const field = (r, k) => r.body?.[k];
153
+ const message = (r) => String(r.body?.message ?? '');
154
+ /** Cohere's error envelope has EXACTLY one key. Asserting the count is what catches a drift toward
155
+ * the OpenAI `{error:{...}}` shape, which no positive assertion on `message` would notice. */
156
+ const bareError = (r, status) => r.status === status && !!r.body && typeof r.body === 'object' && Object.keys(r.body).join(',') === 'message';
157
+ // ── shorthands (mirror the anthropic/mistral manifests) ──
158
+ const done = (id, area, title, dimension, tier, verify) => ({ id, area, title, dimension, tier, expected: 'done', verify });
159
+ const todo = (id, area, title, dimension, tier) => ({ id, area, title, dimension, tier, expected: 'todo' });
160
+ /** The multipart `data` part every dataset create must carry — `datasets.create` in cohere-ai
161
+ * unconditionally appends it, so the vendor never sees a fileless create (§9 round 1, finding 6). */
162
+ const DATA_FILE = { content: '{"text":"a"}' };
163
+ const CHAT = (extra = {}) => ({ model: 'command-a-03-2025', messages: [{ role: 'user', content: 'hello twin' }], ...extra });
164
+ const TOOL = { type: 'function', function: { name: 'get_weather', description: 'w', parameters: { type: 'object', properties: { city: { type: 'string' }, days: { type: 'integer' } } } } };
165
+ /**
166
+ * THE AREAS CENSUS (TWIN-87). Enumerated TOP-DOWN from cohere-ai@8.1.0's own client surface — the
167
+ * root client's method groups plus every sub-client directory under `api/resources/`
168
+ * (v2, batches, connectors, datasets, embedJobs, finetuning, models, audio) and the three
169
+ * deployment clients the package also ships (`AwsClient`, `BedrockClient`, `SagemakerClient`) —
170
+ * NOT from this manifest's own `area` values, which would make the bijection a tautology.
171
+ *
172
+ * `connectors` is Cohere's PRODUCT (its RAG connector registry); `connector` is this twin's
173
+ * pull/push plane. Two different things that unfortunately share a word; both are real areas.
174
+ */
175
+ export const COHERE_AREAS = [
176
+ 'audio',
177
+ 'auth',
178
+ 'batches',
179
+ 'chat',
180
+ 'chat_v1',
181
+ 'classify',
182
+ 'conformance',
183
+ 'connector',
184
+ 'connectors',
185
+ 'datasets',
186
+ 'deployments',
187
+ 'determinism',
188
+ 'embed',
189
+ 'embed_jobs',
190
+ 'errors',
191
+ 'finetuning',
192
+ 'generate',
193
+ 'models',
194
+ 'parse',
195
+ 'rerank',
196
+ 'summarize',
197
+ 'tokenize',
198
+ ];
199
+ export const COHERE_CAPABILITIES = [
200
+ // ══ THE HONEST CARVE-OUTS ═════════════════════════════════════════════════════════════
201
+ todo('cohere.tokenize.bpe_vocabulary', 'tokenize', "Tokenize with Cohere's REAL published BPE vocabulary (vendored tokenizer JSON), not a learned word-segment map", 'api', 'common'),
202
+ todo('cohere.deployments.aws_planes', 'deployments', 'Serve the Bedrock and SageMaker planes the cohere-ai SDK also targets (BedrockClient/SagemakerClient/AwsClient, SigV4-signed against AWS hosts), so a regionally-deployed client reaches the twin instead of failing closed', 'api', 'niche'),
203
+ // ══ CHAT v2 — the protocol envelope, faithful ═════════════════════════════════════════
204
+ done('cohere.chat.create', 'chat', 'v2 chat: the faithful envelope (id/finish_reason/message/usage, and NO `choices`)', 'api', 'core', () => withRoot(async (h) => {
205
+ const r = await h({ m: 'POST', p: '/v2/chat', b: CHAT() });
206
+ if (!ok(r))
207
+ return false;
208
+ const b = r.body;
209
+ // The three keys an OpenAI-shaped copy would add, asserted ABSENT. A positive assertion on
210
+ // `message` alone would not notice a `choices` array riding alongside it.
211
+ if (b.choices !== undefined || b.object !== undefined || b.created !== undefined)
212
+ return false;
213
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(String(b.id)))
214
+ return false;
215
+ if (b.finish_reason !== 'COMPLETE' || b.message?.role !== 'assistant')
216
+ return false;
217
+ if (b.message?.content?.[0]?.type !== 'text')
218
+ return false;
219
+ return typeof b.message.content[0].text === 'string' && b.message.content[0].text.includes('hello twin');
220
+ })),
221
+ done('cohere.chat.stub_labeled', 'chat', 'v2 chat: the stub is clearly labeled as a twin stub (not real output)', 'api', 'core', () => withRoot(async (h) => {
222
+ const r = await h({ m: 'POST', p: '/v2/chat', b: CHAT() });
223
+ const text = r.body.message?.content?.[0]?.text;
224
+ return ok(r) && text.includes('[twin-stub:command-a-03-2025]') && text.includes('no model weights are run');
225
+ })),
226
+ done('cohere.chat.usage_two_levels', 'chat', 'v2 chat: usage carries BOTH `billed_units` and `tokens` sub-objects', 'api', 'core', () => withRoot(async (h) => {
227
+ const short = await h({ m: 'POST', p: '/v2/chat', b: CHAT() });
228
+ const long = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ messages: [{ role: 'user', content: 'x'.repeat(400) }] }) });
229
+ const a = short.body.usage;
230
+ const c = long.body.usage;
231
+ // @ai-sdk/cohere's `cohereUsageSchema` marks `billed_units` nullish but `tokens` REQUIRED,
232
+ // and `convertCohereUsage` reads `usage.tokens.*` — a flat OpenAI-shaped usage dies there.
233
+ if (typeof a?.billed_units?.input_tokens !== 'number' || typeof a?.tokens?.input_tokens !== 'number')
234
+ return false;
235
+ if (typeof a?.billed_units?.output_tokens !== 'number' || typeof a?.tokens?.output_tokens !== 'number')
236
+ return false;
237
+ // The count MOVES with the input — a hardcoded constant would satisfy the shape checks above.
238
+ return c.tokens.input_tokens > a.tokens.input_tokens * 5;
239
+ })),
240
+ done('cohere.chat.tool_calls', 'chat', 'v2 chat: tools → `tool_calls` + `tool_plan` + finish_reason TOOL_CALL', 'api', 'core', () => withRoot(async (h) => {
241
+ const r = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ tools: [TOOL] }) });
242
+ if (!ok(r))
243
+ return false;
244
+ const b = r.body;
245
+ if (b.finish_reason !== 'TOOL_CALL')
246
+ return false;
247
+ if (typeof b.message?.tool_plan !== 'string' || !b.message.tool_plan.includes('get_weather'))
248
+ return false;
249
+ const call = b.message?.tool_calls?.[0];
250
+ if (call?.type !== 'function' || call?.function?.name !== 'get_weather')
251
+ return false;
252
+ // `arguments` is a STRING on the wire, and it parses to the tool's declared schema shape.
253
+ const args = JSON.parse(call.function.arguments);
254
+ if (args.city !== '' || args.days !== 0)
255
+ return false;
256
+ // A tool turn carries NO `content` — Cohere omits the empty half rather than sending null.
257
+ return b.message.content === undefined;
258
+ })),
259
+ done('cohere.chat.tool_choice_none', 'chat', 'v2 chat: `tool_choice: NONE` forbids a tool call even with tools declared', 'api', 'common', () => withRoot(async (h) => {
260
+ const forced = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ tools: [TOOL] }) });
261
+ const none = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ tools: [TOOL], tool_choice: 'NONE' }) });
262
+ // Both halves: the tool DOES fire without the flag, and does NOT with it. Asserting only the
263
+ // second would pass on a twin that never made tool calls at all.
264
+ return forced.body.finish_reason === 'TOOL_CALL'
265
+ && none.body.finish_reason === 'COMPLETE'
266
+ && none.body.message?.tool_calls === undefined
267
+ && typeof none.body.message?.content?.[0]?.text === 'string';
268
+ })),
269
+ done('cohere.chat.thinking', 'chat', 'v2 chat: `thinking: {type:enabled}` prepends a `thinking` content item', 'api', 'common', () => withRoot(async (h) => {
270
+ const off = await h({ m: 'POST', p: '/v2/chat', b: CHAT() });
271
+ const on = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ thinking: { type: 'enabled' } }) });
272
+ const offTypes = (off.body.message?.content ?? []).map((c) => c.type);
273
+ const onTypes = (on.body.message?.content ?? []).map((c) => c.type);
274
+ return JSON.stringify(offTypes) === '["text"]' && JSON.stringify(onTypes) === '["thinking","text"]';
275
+ })),
276
+ done('cohere.chat.stream_events', 'chat', 'v2 chat streaming: the vendor event sequence, terminated by [DONE]', 'api', 'core', () => withStream('/v2/chat', CHAT({ stream: true }), (events, final) => {
277
+ const types = events.filter((e) => !e.done).map((e) => String(e.data.type));
278
+ if (types[0] !== 'message-start')
279
+ return false;
280
+ if (!types.includes('content-start') || !types.includes('content-delta') || !types.includes('content-end'))
281
+ return false;
282
+ if (types[types.length - 1] !== 'message-end')
283
+ return false;
284
+ // The `[DONE]` terminator cohere-ai's `core.Stream` is constructed to look for.
285
+ if (events[events.length - 1]?.done !== true)
286
+ return false;
287
+ // `content-start` carries a full content BLOCK; `content-delta` carries just `{text}`. The
288
+ // two shapes DIFFER, and @ai-sdk/cohere's discriminated union rejects a mix-up.
289
+ const start = events.find((e) => e.data?.type === 'content-start').data;
290
+ if (start.delta?.message?.content?.type !== 'text' || start.delta.message.content.text !== '')
291
+ return false;
292
+ const delta = events.find((e) => e.data?.type === 'content-delta').data;
293
+ if (delta.delta?.message?.content?.type !== undefined)
294
+ return false;
295
+ // The reassembled deltas equal the unary answer — the chunking is a SPLIT, not a second
296
+ // generation, which is the property a streaming caller actually relies on.
297
+ const joined = events.filter((e) => e.data?.type === 'content-delta').map((e) => e.data.delta.message.content.text).join('');
298
+ return joined === final.body.message.content[0].text;
299
+ })),
300
+ done('cohere.chat.stream_message_end', 'chat', 'v2 chat streaming: `message-end` carries finish_reason + the full usage', 'api', 'core', () => withStream('/v2/chat', CHAT({ stream: true }), (events, final) => {
301
+ const end = events.find((e) => e.data?.type === 'message-end')?.data;
302
+ if (!end)
303
+ return false;
304
+ return end.delta?.finish_reason === 'COMPLETE'
305
+ && end.delta?.usage?.tokens?.output_tokens === final.body.usage.tokens.output_tokens
306
+ && end.id === final.body.id;
307
+ })),
308
+ done('cohere.chat.stream_tool_calls', 'chat', 'v2 chat streaming: tool-plan/tool-call event triple reassembles the call', 'api', 'common', () => withStream('/v2/chat', CHAT({ stream: true, tools: [TOOL] }), (events, final) => {
309
+ const types = events.filter((e) => !e.done).map((e) => String(e.data.type));
310
+ if (!types.includes('tool-plan-delta') || !types.includes('tool-call-start') || !types.includes('tool-call-delta') || !types.includes('tool-call-end'))
311
+ return false;
312
+ const start = events.find((e) => e.data?.type === 'tool-call-start').data;
313
+ // The START frame carries the id and name with EMPTY arguments; the deltas carry the
314
+ // argument string in pieces, which the caller accumulates.
315
+ if (start.delta?.message?.tool_calls?.function?.name !== 'get_weather')
316
+ return false;
317
+ if (start.delta.message.tool_calls.function.arguments !== '')
318
+ return false;
319
+ const args = events.filter((e) => e.data?.type === 'tool-call-delta')
320
+ .map((e) => e.data.delta.message.tool_calls.function.arguments).join('');
321
+ if (args !== final.body.message.tool_calls[0].function.arguments)
322
+ return false;
323
+ const end = events.find((e) => e.data?.type === 'message-end').data;
324
+ return end.delta.finish_reason === 'TOOL_CALL';
325
+ })),
326
+ done('cohere.chat.stream_needs_transport', 'chat', 'v2 chat: `stream:true` with no streaming transport is refused, not silently unary', 'api', 'niche', () => withRoot(async (h) => {
327
+ const r = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ stream: true }) });
328
+ return bareError(r, 400) && message(r).includes('streaming transport');
329
+ })),
330
+ done('cohere.chat.validation_model', 'chat', 'v2 chat: missing model → the bare `{message}` 400', 'api', 'core', () => withRoot(async (h) => {
331
+ const r = await h({ m: 'POST', p: '/v2/chat', b: { messages: [{ role: 'user', content: 'x' }] } });
332
+ return bareError(r, 400) && message(r) === 'invalid request: model is required';
333
+ })),
334
+ done('cohere.chat.validation_messages', 'chat', 'v2 chat: missing / empty / bad-role messages each 400 with their own message', 'api', 'core', () => withRoot(async (h) => {
335
+ const missing = await h({ m: 'POST', p: '/v2/chat', b: { model: 'command-a-03-2025' } });
336
+ const empty = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ messages: [] }) });
337
+ const badRole = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ messages: [{ role: 'developer', content: 'x' }] }) });
338
+ return bareError(missing, 400) && message(missing) === 'invalid request: messages is required'
339
+ && bareError(empty, 400) && message(empty) === 'invalid request: messages must not be empty'
340
+ && bareError(badRole, 400) && message(badRole).includes('messages[0].role must be one of');
341
+ })),
342
+ done('cohere.chat.model_not_found', 'chat', 'v2 chat: unknown model AND wrong-endpoint model both 404 like the vendor', 'api', 'core', () => withRoot(async (h) => {
343
+ const unknown = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ model: 'gpt-4o' }) });
344
+ // The sharper case: a REAL Cohere model that serves a different endpoint. An OpenAI-shaped
345
+ // twin would happily generate from it.
346
+ const wrongEndpoint = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ model: 'embed-v4.0' }) });
347
+ return bareError(unknown, 404) && message(unknown) === "model 'gpt-4o' not found, make sure the correct model ID was used and that you have access to the model."
348
+ && bareError(wrongEndpoint, 404) && message(wrongEndpoint).includes("model 'embed-v4.0' not found");
349
+ })),
350
+ done('cohere.chat.closed_enums', 'chat', 'v2 chat: `tool_choice` and `safety_mode` are the vendor\'s CLOSED UPPER-CASE sets', 'api', 'common', () => withRoot(async (h) => {
351
+ // The documented sets are literals here, never imported from the handler — an imported
352
+ // constant could not catch the set drifting.
353
+ for (const v of ['REQUIRED', 'NONE']) {
354
+ if (!ok(await h({ m: 'POST', p: '/v2/chat', b: CHAT({ tools: [TOOL], tool_choice: v }) })))
355
+ return false;
356
+ }
357
+ for (const v of ['CONTEXTUAL', 'STRICT', 'OFF']) {
358
+ if (!ok(await h({ m: 'POST', p: '/v2/chat', b: CHAT({ safety_mode: v }) })))
359
+ return false;
360
+ }
361
+ // …and a value OUTSIDE each set is refused. Cohere's enums are UPPER-CASE, so the
362
+ // lower-case spelling most vendors use is exactly the wrong-looking-plausible input.
363
+ const lowerChoice = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ tools: [TOOL], tool_choice: 'none' }) });
364
+ const badMode = await h({ m: 'POST', p: '/v2/chat', b: CHAT({ safety_mode: 'contextual' }) });
365
+ return bareError(lowerChoice, 400) && bareError(badMode, 400);
366
+ })),
367
+ todo('cohere.chat.citations', 'chat', 'v2 chat: `documents` + citation_options → grounded citations on the response', 'api', 'core'),
368
+ todo('cohere.chat.response_format_json', 'chat', 'v2 chat: `response_format` json_object / json_schema constrained output', 'api', 'core'),
369
+ todo('cohere.chat.logprobs', 'chat', 'v2 chat: `logprobs: true` → the LogprobItem array on the response', 'api', 'niche'),
370
+ todo('cohere.chat.strict_tools', 'chat', 'v2 chat: `strict_tools` schema-constrained tool arguments', 'api', 'niche'),
371
+ todo('cohere.chat.stop_sequences', 'chat', 'v2 chat: `stop_sequences` → finish_reason STOP_SEQUENCE', 'api', 'core'),
372
+ todo('cohere.chat.max_tokens_truncation', 'chat', 'v2 chat: `max_tokens` truncation → finish_reason MAX_TOKENS', 'api', 'core'),
373
+ todo('cohere.chat.image_content', 'chat', 'v2 chat: image content parts for the vision models (command-a-vision)', 'api', 'common'),
374
+ todo('cohere.chat.priority', 'chat', 'v2 chat: the `priority` request parameter', 'api', 'niche'),
375
+ // ══ CHAT v1 — a DIFFERENT protocol, not a versioned alias ═════════════════════════════
376
+ done('cohere.chat_v1.create', 'chat_v1', 'v1 chat: flat `text` + chat_history + meta (NOT the v2 envelope)', 'api', 'core', () => withRoot(async (h) => {
377
+ const r = await h({ m: 'POST', p: '/v1/chat', b: { message: 'v1 hello', model: 'command-r-08-2024' } });
378
+ if (!ok(r))
379
+ return false;
380
+ const b = r.body;
381
+ // v1 has NO `message` object and NO `usage`; it has `text` and `meta`. A twin that served
382
+ // one envelope for both versions would fail exactly here.
383
+ if (b.message !== undefined || b.usage !== undefined)
384
+ return false;
385
+ if (typeof b.text !== 'string' || !b.text.includes('[twin-stub:command-r-08-2024]') || !b.text.includes('v1 hello'))
386
+ return false;
387
+ if (b.finish_reason !== 'COMPLETE')
388
+ return false;
389
+ return b.meta?.api_version?.version === '1' && b.meta?.billed_units?.input_tokens > 0;
390
+ })),
391
+ done('cohere.chat_v1.chat_history', 'chat_v1', 'v1 chat: the reply appends USER + CHATBOT turns onto the supplied history', 'api', 'common', () => withRoot(async (h) => {
392
+ const r = await h({ m: 'POST', p: '/v1/chat', b: { message: 'second', chat_history: [{ role: 'USER', message: 'first' }, { role: 'CHATBOT', message: 'reply' }] } });
393
+ const hist = r.body.chat_history;
394
+ return ok(r) && hist.length === 4
395
+ && hist[0].message === 'first' && hist[1].message === 'reply'
396
+ && hist[2].role === 'USER' && hist[2].message === 'second'
397
+ && hist[3].role === 'CHATBOT' && String(hist[3].message).includes('[twin-stub:');
398
+ })),
399
+ done('cohere.chat_v1.validation_message', 'chat_v1', "v1 chat: a v2-shaped `messages` array is refused — v1 requires `message`", 'api', 'core', () => withRoot(async (h) => {
400
+ const v2shaped = await h({ m: 'POST', p: '/v1/chat', b: { messages: [{ role: 'user', content: 'x' }], model: 'command-r-08-2024' } });
401
+ const empty = await h({ m: 'POST', p: '/v1/chat', b: { message: '' } });
402
+ return bareError(v2shaped, 400) && message(v2shaped) === 'invalid request: message is required'
403
+ && bareError(empty, 400);
404
+ })),
405
+ done('cohere.chat_v1.stream_ndjson', 'chat_v1', 'v1 chat streaming: NDJSON `event_type` frames, a DIFFERENT wire from v2 SSE', 'api', 'common', () => withStream('/v1/chat', { message: 'stream v1', stream: true }, (events, final) => {
406
+ const kinds = events.filter((e) => !e.done).map((e) => String(e.data.event_type));
407
+ if (kinds[0] !== 'stream-start' || kinds[kinds.length - 1] !== 'stream-end')
408
+ return false;
409
+ if (!kinds.includes('text-generation'))
410
+ return false;
411
+ // v1's frames are tagged `event_type`, NOT v2's `type` — the discriminator differs.
412
+ if (events.some((e) => !e.done && e.data.type !== undefined))
413
+ return false;
414
+ const first = events[0].data;
415
+ if (first.is_finished !== false)
416
+ return false;
417
+ const end = events[events.length - 1].data;
418
+ if (end.is_finished !== true || end.finish_reason !== 'COMPLETE')
419
+ return false;
420
+ const joined = events.filter((e) => e.data?.event_type === 'text-generation').map((e) => e.data.text).join('');
421
+ return joined === final.body.text && end.response.text === final.body.text;
422
+ })),
423
+ todo('cohere.chat_v1.connectors', 'chat_v1', 'v1 chat: `connectors` RAG retrieval → search_queries / search_results / documents', 'api', 'common'),
424
+ todo('cohere.chat_v1.tool_results', 'chat_v1', 'v1 chat: `tools` + `tool_results` multi-step tool loop', 'api', 'common'),
425
+ todo('cohere.chat_v1.citations', 'chat_v1', 'v1 chat: `documents` + citation_quality → the ChatCitation array', 'api', 'common'),
426
+ todo('cohere.chat_v1.prompt_truncation', 'chat_v1', 'v1 chat: `prompt_truncation` AUTO/OFF over an oversized history', 'api', 'niche'),
427
+ todo('cohere.chat_v1.conversation_id', 'chat_v1', 'v1 chat: server-side `conversation_id` history persistence', 'api', 'niche'),
428
+ // ══ EMBED ═════════════════════════════════════════════════════════════════════════════
429
+ done('cohere.embed.v2_by_type', 'embed', 'v2 embed: vectors keyed BY TYPE, every requested type present and agreeing', 'api', 'core', () => withRoot(async (h) => {
430
+ const r = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query', texts: ['alpha', 'beta'], embedding_types: ['float', 'int8', 'uint8', 'binary', 'ubinary', 'base64'], output_dimension: 256 } });
431
+ if (!ok(r))
432
+ return false;
433
+ const b = r.body;
434
+ if (b.response_type !== 'embeddings_by_type')
435
+ return false;
436
+ const e = b.embeddings;
437
+ if (e.float?.length !== 2 || e.float[0].length !== 256)
438
+ return false;
439
+ if (e.int8?.[0]?.length !== 256 || e.uint8?.[0]?.length !== 256)
440
+ return false;
441
+ // binary packs ONE BIT per dimension, 8 to a byte — so its array is dim/8 long, not dim.
442
+ if (e.binary?.[0]?.length !== 32 || e.ubinary?.[0]?.length !== 32)
443
+ return false;
444
+ if (typeof e.base64?.[0] !== 'string')
445
+ return false;
446
+ // binary vs ubinary is a SIGNEDNESS difference over the same packed bytes, and it is the only
447
+ // property separating them. Without this the signing branch could be deleted and every verify
448
+ // would stay green (§9 round two, MINOR 8).
449
+ const bin = e.binary[0];
450
+ const ubin = e.ubinary[0];
451
+ for (let i = 0; i < bin.length; i++) {
452
+ if (((bin[i] + 256) % 256) !== ubin[i])
453
+ return false; // same bits
454
+ if (ubin[i] < 0 || ubin[i] > 255)
455
+ return false; // unsigned range
456
+ if (bin[i] < -128 || bin[i] > 127)
457
+ return false; // signed range
458
+ }
459
+ // …and the two really do DIFFER somewhere, or "signed" would be vacuous over this input.
460
+ if (!bin.some((v, i) => v !== ubin[i]))
461
+ return false;
462
+ // Every type is a view of the SAME vector, not an independently generated one.
463
+ if (e.int8[0][0] !== Math.max(-128, Math.min(127, Math.round(e.float[0][0] * 127))))
464
+ return false;
465
+ if (e.uint8[0][0] !== Math.max(0, Math.min(255, Math.round((e.float[0][0] + 1) * 127.5))))
466
+ return false;
467
+ // Distinct inputs give distinct vectors — otherwise "deterministic per input" is vacuous.
468
+ return JSON.stringify(e.float[0]) !== JSON.stringify(e.float[1]) && JSON.stringify(b.texts) === '["alpha","beta"]';
469
+ })),
470
+ done('cohere.embed.v1_floats_default', 'embed', 'v1 embed: the DEFAULT answer is the FLAT float shape, not the by-type one', 'api', 'core', () => withRoot(async (h) => {
471
+ const flat = await h({ m: 'POST', p: '/v1/embed', b: { model: 'embed-english-v3.0', input_type: 'search_query', texts: ['gamma'] } });
472
+ const byType = await h({ m: 'POST', p: '/v1/embed', b: { model: 'embed-english-v3.0', input_type: 'search_query', texts: ['gamma'], embedding_types: ['float'] } });
473
+ const fb = flat.body;
474
+ const tb = byType.body;
475
+ // cohere-ai models `EmbedResponse` as a union discriminated on `response_type`; always
476
+ // answering by-type would land every default v1 caller in the wrong union arm.
477
+ if (fb.response_type !== 'embeddings_floats' || !Array.isArray(fb.embeddings) || !Array.isArray(fb.embeddings[0]))
478
+ return false;
479
+ if (fb.embeddings[0].length !== 1024)
480
+ return false;
481
+ if (tb.response_type !== 'embeddings_by_type' || !Array.isArray(tb.embeddings?.float))
482
+ return false;
483
+ // The two shapes carry the SAME vector — asking for a type changes the packaging only.
484
+ return JSON.stringify(tb.embeddings.float[0]) === JSON.stringify(fb.embeddings[0]);
485
+ })),
486
+ done('cohere.embed.v2_requires_input_type', 'embed', 'v2 embed REQUIRES `input_type`; v1 does not — the sharpest version difference', 'api', 'core', () => withRoot(async (h) => {
487
+ const v2Missing = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', texts: ['x'] } });
488
+ const v2Present = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query', texts: ['x'] } });
489
+ // v1 with a LEGACY-shaped call still needs one for a v3 model — that refusal lives in the
490
+ // handler, not the schema, which is why both halves are asserted here.
491
+ const v1MissingV3 = await h({ m: 'POST', p: '/v1/embed', b: { model: 'embed-english-v3.0', texts: ['x'] } });
492
+ return bareError(v2Missing, 400) && message(v2Missing) === 'invalid request: input_type is required'
493
+ && ok(v2Present)
494
+ && bareError(v1MissingV3, 400) && message(v1MissingV3).includes("input_type is required for model 'embed-english-v3.0'");
495
+ })),
496
+ done('cohere.embed.closed_enums', 'embed', 'embed: embedding_types / input_type / truncate / output_dimension are closed sets', 'api', 'common', () => withRoot(async (h) => {
497
+ const base = { model: 'embed-v4.0', input_type: 'search_query', texts: ['x'] };
498
+ // The documented sets, as LITERALS. Each accepted value is exercised, and one value outside
499
+ // each set is refused — a bijection with the vendor's documented set, not a spot check.
500
+ for (const t of ['float', 'int8', 'uint8', 'binary', 'ubinary', 'base64']) {
501
+ if (!ok(await h({ m: 'POST', p: '/v2/embed', b: { ...base, embedding_types: [t] } })))
502
+ return false;
503
+ }
504
+ for (const it of ['search_document', 'search_query', 'classification', 'clustering', 'image']) {
505
+ if (!ok(await h({ m: 'POST', p: '/v2/embed', b: { ...base, input_type: it } })))
506
+ return false;
507
+ }
508
+ for (const tr of ['NONE', 'START', 'END']) {
509
+ if (!ok(await h({ m: 'POST', p: '/v2/embed', b: { ...base, truncate: tr } })))
510
+ return false;
511
+ }
512
+ for (const d of [256, 512, 1024, 1536]) {
513
+ if (!ok(await h({ m: 'POST', p: '/v2/embed', b: { ...base, output_dimension: d } })))
514
+ return false;
515
+ }
516
+ const badType = await h({ m: 'POST', p: '/v2/embed', b: { ...base, embedding_types: ['float16'] } });
517
+ const badInput = await h({ m: 'POST', p: '/v2/embed', b: { ...base, input_type: 'search' } });
518
+ const badTrunc = await h({ m: 'POST', p: '/v2/embed', b: { ...base, truncate: 'end' } });
519
+ const badDim = await h({ m: 'POST', p: '/v2/embed', b: { ...base, output_dimension: 999 } });
520
+ return bareError(badType, 400) && bareError(badInput, 400) && bareError(badTrunc, 400) && bareError(badDim, 400)
521
+ && message(badDim) === 'invalid request: output_dimension must be one of 256, 512, 1024, 1536';
522
+ })),
523
+ done('cohere.embed.dimensions_by_model', 'embed', 'embed: each model produces its own documented dimensionality', 'api', 'common', () => withRoot(async (h) => {
524
+ const dim = async (model) => {
525
+ const r = await h({ m: 'POST', p: '/v1/embed', b: { model, input_type: 'search_query', texts: ['x'] } });
526
+ return ok(r) ? r.body.embeddings[0].length : -1;
527
+ };
528
+ // The `light` models are 384-dimensional, the full v3 models 1024, embed-v4.0 1536.
529
+ return await dim('embed-english-v3.0') === 1024
530
+ && await dim('embed-english-light-v3.0') === 384
531
+ && await dim('embed-multilingual-light-v3.0') === 384
532
+ && await dim('embed-v4.0') === 1536;
533
+ })),
534
+ done('cohere.embed.normalized', 'embed', 'embed: the pseudo-vectors are L2-normalized, like real embeddings', 'api', 'niche', () => withRoot(async (h) => {
535
+ const r = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query', texts: ['norm me'] } });
536
+ const v = r.body.embeddings.float[0];
537
+ const norm = Math.sqrt(v.reduce((a, x) => a + x * x, 0));
538
+ return ok(r) && Math.abs(norm - 1) < 1e-9;
539
+ })),
540
+ done('cohere.embed.validation_inputs', 'embed', 'embed: no texts/images/inputs → 400; wrong-endpoint model → 404', 'api', 'common', () => withRoot(async (h) => {
541
+ const none = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query' } });
542
+ const chatModel = await h({ m: 'POST', p: '/v2/embed', b: { model: 'command-a-03-2025', input_type: 'search_query', texts: ['x'] } });
543
+ return bareError(none, 400) && message(none).includes('one of texts, images or inputs')
544
+ && bareError(chatModel, 404);
545
+ })),
546
+ done('cohere.embed.v2_inputs_form', 'embed', 'v2 embed: the structured `inputs` form (content parts), not just `texts`', 'api', 'niche', () => withRoot(async (h) => {
547
+ const viaInputs = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query', inputs: [{ content: [{ type: 'text', text: 'structured' }] }] } });
548
+ const viaTexts = await h({ m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query', texts: ['structured'] } });
549
+ // The two spellings of the same input produce the SAME vector — proof `inputs` is really
550
+ // flattened rather than hashed as a JSON blob.
551
+ return ok(viaInputs)
552
+ && JSON.stringify(viaInputs.body.embeddings.float[0]) === JSON.stringify(viaTexts.body.embeddings.float[0]);
553
+ })),
554
+ todo('cohere.embed.images', 'embed', 'embed: real image inputs (base64 data URIs) with image_tokens billing', 'api', 'common'),
555
+ todo('cohere.embed.max_tokens', 'embed', 'v2 embed: the `max_tokens` per-input cap and its truncation semantics', 'api', 'niche'),
556
+ todo('cohere.embed.token_limit_refusal', 'embed', 'embed: refuse an input past the model context length when truncate=NONE', 'api', 'core'),
557
+ // ══ RERANK ════════════════════════════════════════════════════════════════════════════
558
+ done('cohere.rerank.v2_order', 'rerank', 'v2 rerank: results ordered by descending relevance, scores in [0,1]', 'api', 'core', () => withRoot(async (h) => {
559
+ const r = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', query: 'apple pie recipe', documents: ['how to service a car engine', 'a recipe for apple pie', 'apple orchard tours'] } });
560
+ if (!ok(r))
561
+ return false;
562
+ const results = r.body.results;
563
+ if (results.length !== 3)
564
+ return false;
565
+ // The lexically-closest document wins, and the order is strictly descending.
566
+ if (results[0].index !== 1)
567
+ return false;
568
+ for (let i = 1; i < results.length; i++)
569
+ if (results[i].relevance_score > results[i - 1].relevance_score)
570
+ return false;
571
+ if (results.some((x) => x.relevance_score < 0 || x.relevance_score > 1))
572
+ return false;
573
+ // Rerank is billed in SEARCH UNITS, not tokens.
574
+ return r.body.meta?.billed_units?.search_units === 1 && r.body.meta?.billed_units?.input_tokens === undefined;
575
+ })),
576
+ done('cohere.rerank.v2_strings_only', 'rerank', 'v2 rerank: `documents` must be STRINGS (v1 accepts objects)', 'api', 'core', () => withRoot(async (h) => {
577
+ const objV2 = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', query: 'q', documents: [{ text: 'y' }] } });
578
+ const objV1 = await h({ m: 'POST', p: '/v1/rerank', b: { query: 'q', documents: [{ text: 'y' }] } });
579
+ // Both halves: v2 REFUSES the object form and v1 ACCEPTS it. Asserting only the refusal
580
+ // would pass on a twin that refused object documents everywhere.
581
+ return bareError(objV2, 400) && message(objV2) === 'invalid request: documents[0] must be a string'
582
+ && ok(objV1);
583
+ })),
584
+ done('cohere.rerank.top_n', 'rerank', 'rerank: `top_n` truncates to the N best, keeping original indices', 'api', 'common', () => withRoot(async (h) => {
585
+ const r = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', query: 'apple pie', documents: ['engine oil', 'apple pie recipe', 'orchard', 'pie crust'], top_n: 2 } });
586
+ const results = r.body.results;
587
+ // The indices are positions in the ORIGINAL document list, not in the truncated result.
588
+ return ok(r) && results.length === 2 && results[0].index === 1 && results.every((x) => x.index >= 0 && x.index < 4);
589
+ })),
590
+ done('cohere.rerank.v1_return_documents', 'rerank', 'v1 rerank: `return_documents` rides the text back; v2 has no such option', 'api', 'common', () => withRoot(async (h) => {
591
+ const withDocs = await h({ m: 'POST', p: '/v1/rerank', b: { query: 'apple', documents: ['apple pie', 'engine'], return_documents: true } });
592
+ const without = await h({ m: 'POST', p: '/v1/rerank', b: { query: 'apple', documents: ['apple pie', 'engine'] } });
593
+ const v2 = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', query: 'apple', documents: ['apple pie', 'engine'], return_documents: true } });
594
+ return withDocs.body.results[0].document?.text === 'apple pie'
595
+ && without.body.results[0].document === undefined
596
+ // v2 IGNORES the option rather than honouring an option its schema does not declare.
597
+ && v2.body.results[0].document === undefined;
598
+ })),
599
+ done('cohere.rerank.v1_rank_fields', 'rerank', 'v1 rerank: `rank_fields` selects which object fields are scored', 'api', 'niche', () => withRoot(async (h) => {
600
+ const docs = [{ title: 'engine oil', body: 'apple pie recipe' }, { title: 'apple pie recipe', body: 'engine oil' }];
601
+ const onTitle = await h({ m: 'POST', p: '/v1/rerank', b: { query: 'apple pie', documents: docs, rank_fields: ['title'] } });
602
+ const onBody = await h({ m: 'POST', p: '/v1/rerank', b: { query: 'apple pie', documents: docs, rank_fields: ['body'] } });
603
+ // Scoring different fields of the SAME documents must produce different winners, or
604
+ // `rank_fields` is not actually being honoured.
605
+ return onTitle.body.results[0].index === 1 && onBody.body.results[0].index === 0;
606
+ })),
607
+ done('cohere.rerank.validation', 'rerank', 'rerank: missing query / empty documents / wrong-endpoint model each refused', 'api', 'common', () => withRoot(async (h) => {
608
+ const noQuery = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', documents: ['x'] } });
609
+ const noDocs = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', query: 'q', documents: [] } });
610
+ const wrongModel = await h({ m: 'POST', p: '/v2/rerank', b: { model: 'command-a-03-2025', query: 'q', documents: ['x'] } });
611
+ return bareError(noQuery, 400) && bareError(noDocs, 400) && bareError(wrongModel, 404);
612
+ })),
613
+ todo('cohere.rerank.max_tokens_per_doc', 'rerank', 'v2 rerank: `max_tokens_per_doc` chunking of long documents', 'api', 'niche'),
614
+ todo('cohere.rerank.max_chunks_per_doc', 'rerank', 'v1 rerank: `max_chunks_per_doc` and its billing effect', 'api', 'niche'),
615
+ // ══ CLASSIFY ══════════════════════════════════════════════════════════════════════════
616
+ done('cohere.classify.create', 'classify', 'classify: the full classification shape, confidences summing to 1', 'api', 'core', () => withRoot(async (h) => {
617
+ const r = await h({ m: 'POST', p: '/v1/classify', b: { inputs: ['a great day', 'a terrible day'], examples: [{ text: 'good', label: 'positive' }, { text: 'bad', label: 'negative' }] } });
618
+ if (!ok(r))
619
+ return false;
620
+ const cs = r.body.classifications;
621
+ if (cs.length !== 2 || cs[0].input !== 'a great day')
622
+ return false;
623
+ if (!['positive', 'negative'].includes(cs[0].prediction))
624
+ return false;
625
+ if (cs[0].classification_type !== 'single-label')
626
+ return false;
627
+ // `labels` is a MAP from label to `{confidence}`, and every declared label appears.
628
+ if (Object.keys(cs[0].labels).sort().join(',') !== 'negative,positive')
629
+ return false;
630
+ const sum = Object.values(cs[0].labels).reduce((a, l) => a + l.confidence, 0);
631
+ if (Math.abs(sum - 1) > 1e-3)
632
+ return false;
633
+ // The prediction really is the argmax of the label map, not an unrelated pick.
634
+ const best = Object.entries(cs[0].labels).sort((a, b) => b[1].confidence - a[1].confidence)[0][0];
635
+ if (best !== cs[0].prediction)
636
+ return false;
637
+ return r.body.meta?.billed_units?.classifications === 2;
638
+ })),
639
+ done('cohere.classify.validation', 'classify', 'classify: no inputs / no examples-or-preset / one label each refused', 'api', 'common', () => withRoot(async (h) => {
640
+ const noInputs = await h({ m: 'POST', p: '/v1/classify', b: { examples: [{ text: 'a', label: 'x' }, { text: 'b', label: 'y' }] } });
641
+ const noLabelSpace = await h({ m: 'POST', p: '/v1/classify', b: { inputs: ['x'] } });
642
+ const oneLabel = await h({ m: 'POST', p: '/v1/classify', b: { inputs: ['x'], examples: [{ text: 'a', label: 'only' }, { text: 'b', label: 'only' }] } });
643
+ const noLabel = await h({ m: 'POST', p: '/v1/classify', b: { inputs: ['x'], examples: [{ text: 'a' }] } });
644
+ return bareError(noInputs, 400) && bareError(noLabelSpace, 400) && message(noLabelSpace).includes('examples or preset')
645
+ && bareError(oneLabel, 400) && message(oneLabel).includes('at least 2 unique labels')
646
+ && bareError(noLabel, 400);
647
+ })),
648
+ done('cohere.classify.preset_is_not_fabricated', 'classify', 'classify: an unmodeled `preset` fails like the vendor — it never invents a label space', 'api', 'core', () => withRoot(async (h) => {
649
+ // §9 round two, m-R2.5. An earlier version accepted ANY preset string and invented
650
+ // ['positive','negative'], returning confident-looking classifications against labels the
651
+ // caller never named — a fake success on a path filed as `cohere.classify.preset`, and the
652
+ // same class the detokenize path treats as a hard rule.
653
+ const r = await h({ m: 'POST', p: '/v1/classify', b: { inputs: ['x'], preset: 'my-saved-preset' } });
654
+ if (!bareError(r, 404) || !message(r).includes("preset 'my-saved-preset' not found"))
655
+ return false;
656
+ // …and the EXAMPLES path still works, so this is a refusal of the unmodeled option rather
657
+ // than of classification itself.
658
+ const withExamples = await h({ m: 'POST', p: '/v1/classify', b: { inputs: ['x'], examples: [{ text: 'a', label: 'p' }, { text: 'b', label: 'n' }] } });
659
+ return ok(withExamples) && withExamples.body.classifications.length === 1;
660
+ })),
661
+ todo('cohere.classify.preset', 'classify', 'classify: a saved `preset` as the label space instead of inline examples', 'api', 'niche'),
662
+ todo('cohere.classify.multi_label', 'classify', 'classify: multi-label classification against a finetuned model', 'api', 'niche'),
663
+ todo('cohere.classify.truncate', 'classify', 'classify: the `truncate` parameter over oversized inputs', 'api', 'niche'),
664
+ // ══ TOKENIZE / DETOKENIZE ═════════════════════════════════════════════════════════════
665
+ done('cohere.tokenize.round_trip', 'tokenize', 'tokenize → detokenize round-trips the exact input, whitespace included', 'api', 'core', () => withRoot(async (h) => {
666
+ const text = 'hello brave\nnew world ';
667
+ const tok = await h({ m: 'POST', p: '/v1/tokenize', b: { text, model: 'command-a-03-2025' } });
668
+ if (!ok(tok))
669
+ return false;
670
+ const tb = tok.body;
671
+ if (tb.tokens.length !== tb.token_strings.length || tb.tokens.length === 0)
672
+ return false;
673
+ if (tb.token_strings.join('') !== text)
674
+ return false;
675
+ const back = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: tb.tokens, model: 'command-a-03-2025' } });
676
+ return ok(back) && back.body.text === text;
677
+ })),
678
+ done('cohere.tokenize.vocabulary_is_learned', 'tokenize', 'detokenize refuses an id the twin never issued (never fabricates text)', 'api', 'core', () => withRoot(async (h) => {
679
+ // A FRESH root has an empty vocabulary, so ANY id is unknown — the honest answer is a 400,
680
+ // never a placeholder string that the caller would read as real detokenized text.
681
+ const cold = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: [12345], model: 'command-a-03-2025' } });
682
+ if (!bareError(cold, 400) || !message(cold).includes('unknown token id 12345'))
683
+ return false;
684
+ await h({ m: 'POST', p: '/v1/tokenize', b: { text: 'known words', model: 'command-a-03-2025' } });
685
+ // …and after a tokenize, an id INSIDE the learned vocabulary works while one outside still
686
+ // does not. Both halves, so "it always 400s" cannot pass.
687
+ const warm = await h({ m: 'POST', p: '/v1/tokenize', b: { text: 'known words', model: 'command-a-03-2025' } });
688
+ const good = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: warm.body.tokens, model: 'command-a-03-2025' } });
689
+ const stillBad = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: [warm.body.tokens[0], 999_999], model: 'command-a-03-2025' } });
690
+ return ok(good) && good.body.text === 'known words' && bareError(stillBad, 400);
691
+ })),
692
+ done('cohere.tokenize.dirty_state_vocabulary', 'tokenize', 'DIRTY STATE: a later tokenize never breaks an earlier call\'s detokenize', 'api', 'core', () => withRoot(async (h) => {
693
+ // A fresh-root verify structurally CANNOT catch this class. The vocabulary is built up over
694
+ // MANY calls, and the hazard is a later segment claiming an id an earlier segment already
695
+ // holds — after which the earlier caller's detokenize silently returns the WRONG text.
696
+ const first = await h({ m: 'POST', p: '/v1/tokenize', b: { text: 'alpha beta gamma', model: 'command-a-03-2025' } });
697
+ const firstTokens = first.body.tokens;
698
+ // Twenty more tokenizes, growing the vocabulary well past the first call's segments.
699
+ for (let i = 0; i < 20; i++) {
700
+ await h({ m: 'POST', p: '/v1/tokenize', b: { text: `filler${i} words ${i} more`, model: 'command-a-03-2025' } });
701
+ }
702
+ const back = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: firstTokens, model: 'command-a-03-2025' } });
703
+ if (!ok(back) || back.body.text !== 'alpha beta gamma')
704
+ return false;
705
+ // …and the ids are STABLE: re-tokenizing the original text yields the same ids, so a client
706
+ // that cached them is not silently invalidated by other traffic.
707
+ const again = await h({ m: 'POST', p: '/v1/tokenize', b: { text: 'alpha beta gamma', model: 'command-a-03-2025' } });
708
+ return JSON.stringify(again.body.tokens) === JSON.stringify(firstTokens);
709
+ })),
710
+ done('cohere.tokenize.collision_probe', 'tokenize', 'two segments preferring the same id get DISTINCT ids (no silent overwrite)', 'api', 'common', () => withRoot(async (h) => {
711
+ // Build the collision deliberately rather than hoping for one: every segment's preferred id
712
+ // is a pure hash, so a large vocabulary makes a collision near-certain, and the invariant
713
+ // under test is that EVERY distinct segment maps to its OWN id and back.
714
+ const words = [];
715
+ for (let i = 0; i < 400; i++)
716
+ words.push(`w${i}`);
717
+ const text = words.join(' ');
718
+ const tok = await h({ m: 'POST', p: '/v1/tokenize', b: { text, model: 'command-a-03-2025' } });
719
+ if (!ok(tok))
720
+ return false;
721
+ const ids = tok.body.tokens;
722
+ const strings = tok.body.token_strings;
723
+ // Distinct segments must have distinct ids — a silent overwrite shows up as a duplicate id
724
+ // for two different strings.
725
+ const pairs = new Map();
726
+ for (let i = 0; i < ids.length; i++) {
727
+ const prev = pairs.get(ids[i]);
728
+ if (prev !== undefined && prev !== strings[i])
729
+ return false;
730
+ pairs.set(ids[i], strings[i]);
731
+ }
732
+ const back = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: ids, model: 'command-a-03-2025' } });
733
+ return ok(back) && back.body.text === text;
734
+ })),
735
+ done('cohere.tokenize.validation', 'tokenize', 'tokenize/detokenize: `model` is REQUIRED on both (unlike v1 embed/rerank)', 'api', 'common', () => withRoot(async (h) => {
736
+ const noModel = await h({ m: 'POST', p: '/v1/tokenize', b: { text: 'x' } });
737
+ const noText = await h({ m: 'POST', p: '/v1/tokenize', b: { model: 'command-a-03-2025' } });
738
+ const badModel = await h({ m: 'POST', p: '/v1/tokenize', b: { text: 'x', model: 'nope' } });
739
+ const detNoModel = await h({ m: 'POST', p: '/v1/detokenize', b: { tokens: [1] } });
740
+ const detNoTokens = await h({ m: 'POST', p: '/v1/detokenize', b: { model: 'command-a-03-2025' } });
741
+ return bareError(noModel, 400) && message(noModel) === 'invalid request: model is required'
742
+ && bareError(noText, 400) && bareError(badModel, 404)
743
+ && bareError(detNoModel, 400) && bareError(detNoTokens, 400);
744
+ })),
745
+ // ══ MODELS ════════════════════════════════════════════════════════════════════════════
746
+ done('cohere.models.list', 'models', 'GET /v1/models: the real catalog with `next_page_token`', 'api', 'core', () => withRoot(async (h) => {
747
+ const r = await h({ m: 'GET', p: '/v1/models' });
748
+ if (!ok(r))
749
+ return false;
750
+ const b = r.body;
751
+ if (!Array.isArray(b.models) || b.next_page_token !== null)
752
+ return false;
753
+ // Real, checkable catalog facts — not just "an array came back".
754
+ const chat = b.models.find((m) => m.name === 'command-a-03-2025');
755
+ const embed = b.models.find((m) => m.name === 'embed-v4.0');
756
+ return chat?.context_length === 256000 && JSON.stringify(chat.endpoints) === '["chat"]'
757
+ && embed?.context_length === 128000 && embed.finetuned === false;
758
+ })),
759
+ done('cohere.models.filter_by_endpoint', 'models', 'GET /v1/models?endpoint=: filters to models serving that endpoint', 'api', 'common', () => withRoot(async (h) => {
760
+ const all = await h({ m: 'GET', p: '/v1/models' });
761
+ const rerank = await h({ m: 'GET', p: '/v1/models?endpoint=rerank' });
762
+ const chat = await h({ m: 'GET', p: '/v1/models?endpoint=chat' });
763
+ const allN = all.body.models.length;
764
+ const rr = rerank.body.models;
765
+ const ch = chat.body.models;
766
+ // A real filter: strictly fewer than the whole catalog, disjoint from the other endpoint,
767
+ // and every row genuinely serves it.
768
+ return rr.length > 0 && rr.length < allN && rr.every((m) => m.endpoints.includes('rerank'))
769
+ && ch.length > 0 && ch.every((m) => m.endpoints.includes('chat'))
770
+ && !rr.some((m) => ch.some((c) => c.name === m.name));
771
+ })),
772
+ done('cohere.models.get', 'models', 'GET /v1/models/{name}: one card, 404 for an unknown name', 'api', 'core', () => withRoot(async (h) => {
773
+ const one = await h({ m: 'GET', p: '/v1/models/rerank-v3.5' });
774
+ const missing = await h({ m: 'GET', p: '/v1/models/not-a-model' });
775
+ const b = one.body;
776
+ return ok(one) && b.name === 'rerank-v3.5' && b.context_length === 4000
777
+ && String(b.tokenizer_url).startsWith('https://')
778
+ && bareError(missing, 404) && message(missing).includes("model 'not-a-model' not found");
779
+ })),
780
+ done('cohere.models.closed_endpoint_set', 'models', "every SERVED model's `endpoints` is in Cohere's closed CompatibleEndpoint set", 'api', 'common', () => withRoot(async (h) => {
781
+ // The claim is about what the twin SERVES, so the catalog is read back off the wire rather
782
+ // than out of the module. An earlier version asserted over the imported `COHERE_MODELS`
783
+ // array and had no request on its path at all — the mutation gate reported it as a SURVIVOR,
784
+ // correctly: it would have stayed green with the whole handler deleted.
785
+ const listed = await h({ m: 'GET', p: '/v1/models' });
786
+ if (!ok(listed))
787
+ return false;
788
+ const models = listed.body.models;
789
+ if (!Array.isArray(models) || models.length === 0)
790
+ return false;
791
+ // A LITERAL of the vendor's documented set, written here rather than imported from the models
792
+ // module — importing the constant the catalog is built from would be a tautology.
793
+ const documented = new Set(['chat', 'embed', 'classify', 'summarize', 'rerank', 'rate', 'generate']);
794
+ for (const m of models) {
795
+ if (!Array.isArray(m.endpoints) || m.endpoints.length === 0)
796
+ return false;
797
+ for (const e of m.endpoints)
798
+ if (!documented.has(String(e)))
799
+ return false;
800
+ }
801
+ // Every documented endpoint the twin's catalog actually uses is FILTERABLE, and one it does
802
+ // not use returns an empty list rather than the whole catalog — so the served `endpoints`
803
+ // values and the filter agree, in both directions.
804
+ const served = new Set(models.flatMap((m) => m.endpoints));
805
+ for (const e of served) {
806
+ const filtered = await h({ m: 'GET', p: `/v1/models?endpoint=${e}` });
807
+ const got = filtered.body.models;
808
+ if (got.length === 0 || got.length >= models.length)
809
+ return false;
810
+ if (!got.every((m) => m.endpoints.includes(e)))
811
+ return false;
812
+ }
813
+ for (const e of [...documented].filter((d) => !served.has(d))) {
814
+ if ((await h({ m: 'GET', p: `/v1/models?endpoint=${e}` })).body.models.length !== 0)
815
+ return false;
816
+ }
817
+ // …and the module's own exported set bijects with the documented one, so a future addition to
818
+ // either side is caught rather than silently diverging.
819
+ return [...COHERE_ENDPOINTS].sort().join(',') === [...documented].sort().join(',');
820
+ })),
821
+ todo('cohere.models.pagination', 'models', 'GET /v1/models: real `page_token` cursor pagination', 'api', 'niche'),
822
+ todo('cohere.models.finetuned_in_catalog', 'models', 'GET /v1/models: finetuned models appear with finetuned:true and default_endpoints', 'api', 'common'),
823
+ todo('cohere.models.default_only', 'models', 'GET /v1/models?default_only=true filtering', 'api', 'niche'),
824
+ // ══ DATASETS (stateful) ═══════════════════════════════════════════════════════════════
825
+ done('cohere.datasets.create_read', 'datasets', 'datasets: create → get, with the create answering ONLY `{id}`', 'api', 'core', () => withRoot(async (h) => {
826
+ const created = await h({ m: 'POST', p: '/v1/datasets?name=ds-one&type=embed-input', b: { content: 'a\nb' } });
827
+ if (!ok(created))
828
+ return false;
829
+ // The vendor's `DatasetsCreateResponse` is `{ id }` and nothing else — a twin returning the
830
+ // whole dataset here would be more helpful and less faithful.
831
+ if (Object.keys(created.body).join(',') !== 'id')
832
+ return false;
833
+ const id = field(created, 'id');
834
+ const got = await h({ m: 'GET', p: `/v1/datasets/${id}` });
835
+ const d = got.body.dataset;
836
+ // The dataset is NESTED under `dataset` — `DatasetsGetResponse` is `{ dataset }`.
837
+ return ok(got) && got.body.id === undefined
838
+ && d?.id === id && d.name === 'ds-one' && d.dataset_type === 'embed-input'
839
+ && d.validation_status === 'validated' && d.created_at === PINNED_AT;
840
+ })),
841
+ done('cohere.datasets.closed_type_set', 'datasets', "datasets: `type` biject with Cohere's closed DatasetType set", 'api', 'common', () => withRoot(async (h) => {
842
+ // The vendor's documented set as a LITERAL — the oracle that makes "the twin serves surface
843
+ // the vendor does not have" checkable in the ACCEPT direction too, not just the reject one.
844
+ const documented = ['embed-input', 'embed-result', 'cluster-result', 'cluster-outliers', 'reranker-finetune-input', 'single-label-classification-finetune-input', 'chat-finetune-input', 'multi-label-classification-finetune-input', 'batch-chat-input', 'batch-openai-chat-input', 'batch-embed-v2-input', 'batch-chat-v2-input'];
845
+ for (const t of documented) {
846
+ if (!ok(await h({ m: 'POST', p: `/v1/datasets?name=x&type=${t}`, b: DATA_FILE })))
847
+ return false;
848
+ }
849
+ const bad = await h({ m: 'POST', p: '/v1/datasets?name=x&type=not-a-real-type', b: DATA_FILE });
850
+ const noType = await h({ m: 'POST', p: '/v1/datasets?name=x', b: DATA_FILE });
851
+ const noName = await h({ m: 'POST', p: '/v1/datasets?type=embed-input', b: DATA_FILE });
852
+ // …and the multipart `data` file the vendor's own client always appends is REQUIRED, so the
853
+ // closed-set oracle above is not resting on a lenient path the vendor would 400
854
+ // (§9 round 1, finding 6).
855
+ const noFile = await h({ m: 'POST', p: '/v1/datasets?name=x&type=embed-input' });
856
+ return bareError(bad, 400) && message(bad).includes('type must be one of')
857
+ && bareError(noType, 400) && bareError(noName, 400)
858
+ && bareError(noFile, 400) && message(noFile) === 'invalid request: the data file is required';
859
+ })),
860
+ done('cohere.datasets.list_filter', 'datasets', 'datasets: list, filtered by datasetType / validationStatus, with limit+offset', 'api', 'common', () => withRoot(async (h) => {
861
+ await h({ m: 'POST', p: '/v1/datasets?name=a&type=embed-input', b: DATA_FILE });
862
+ await h({ m: 'POST', p: '/v1/datasets?name=b&type=chat-finetune-input', b: DATA_FILE });
863
+ await h({ m: 'POST', p: '/v1/datasets?name=c&type=embed-input', b: DATA_FILE });
864
+ const all = await h({ m: 'GET', p: '/v1/datasets' });
865
+ const embed = await h({ m: 'GET', p: '/v1/datasets?datasetType=embed-input' });
866
+ const paged = await h({ m: 'GET', p: '/v1/datasets?limit=1&offset=1' });
867
+ const badStatus = await h({ m: 'GET', p: '/v1/datasets?validationStatus=nonsense' });
868
+ // The LIST filter honours the same closed DatasetType set the CREATE path does. An earlier
869
+ // version applied `datasetType` raw and answered `200 {datasets:[]}` for a value the vendor
870
+ // rejects — reporting an empty account for what is actually a refused request, and leaving
871
+ // the two paths asymmetric for no reason (§9 round two, MINOR 9).
872
+ const badType = await h({ m: 'GET', p: '/v1/datasets?datasetType=not-a-real-type' });
873
+ if (!bareError(badType, 400) || !message(badType).includes('datasetType must be one of'))
874
+ return false;
875
+ const names = (r) => r.body.datasets.map((d) => d.name);
876
+ return names(all).join(',') === 'a,b,c'
877
+ && names(embed).join(',') === 'a,c'
878
+ && names(paged).join(',') === 'b'
879
+ && bareError(badStatus, 400);
880
+ })),
881
+ done('cohere.datasets.usage', 'datasets', 'datasets: GET /v1/datasets/usage folds real stored bytes (and is not shadowed by /{id})', 'api', 'common', () => withRoot(async (h) => {
882
+ const empty = await h({ m: 'GET', p: '/v1/datasets/usage' });
883
+ if (!ok(empty) || field(empty, 'organization_usage') !== 0)
884
+ return false;
885
+ await h({ m: 'POST', p: '/v1/datasets?name=a&type=embed-input', b: { content: '12345' } });
886
+ await h({ m: 'POST', p: '/v1/datasets?name=b&type=embed-input', b: { content: '123' } });
887
+ const used = await h({ m: 'GET', p: '/v1/datasets/usage' });
888
+ // A real fold over stored state, not a constant — and `usage` is a literal sibling of
889
+ // `/{id}`, so this also pins the route-ordering that keeps it from being shadowed.
890
+ return ok(used) && field(used, 'organization_usage') === 8 && used.body.dataset === undefined;
891
+ })),
892
+ done('cohere.datasets.delete', 'datasets', 'datasets: delete answers `{}` and the row really leaves the list', 'api', 'core', () => withRoot(async (h) => {
893
+ const created = await h({ m: 'POST', p: '/v1/datasets?name=gone&type=embed-input', b: DATA_FILE });
894
+ const id = field(created, 'id');
895
+ const del = await h({ m: 'DELETE', p: `/v1/datasets/${id}` });
896
+ // Cohere's delete answers an EMPTY object, not the `{deleted:true}` envelope most vendors
897
+ // send — and the row must actually be gone, which a status-only assertion would not catch.
898
+ if (!ok(del) || Object.keys(del.body).length !== 0)
899
+ return false;
900
+ const after = await h({ m: 'GET', p: `/v1/datasets/${id}` });
901
+ const list = await h({ m: 'GET', p: '/v1/datasets' });
902
+ const delAgain = await h({ m: 'DELETE', p: `/v1/datasets/${id}` });
903
+ return bareError(after, 404) && list.body.datasets.length === 0 && bareError(delAgain, 404);
904
+ })),
905
+ done('cohere.datasets.id_survives_delete', 'datasets', 'DIRTY STATE: a deleted dataset\'s id is never re-issued to a new one', 'api', 'core', () => withRoot(async (h) => {
906
+ // The count-mint bug three packs' §9 reviews each found: delete a row, create a new one, and
907
+ // a row-count-derived id lands back on the tombstone. Only a build-up-then-assert verify can
908
+ // see it; a fresh-root one structurally cannot.
909
+ const a = field(await h({ m: 'POST', p: '/v1/datasets?name=a&type=embed-input', b: DATA_FILE }), 'id');
910
+ const b = field(await h({ m: 'POST', p: '/v1/datasets?name=b&type=embed-input', b: DATA_FILE }), 'id');
911
+ await h({ m: 'DELETE', p: `/v1/datasets/${b}` });
912
+ await h({ m: 'DELETE', p: `/v1/datasets/${a}` });
913
+ const c = field(await h({ m: 'POST', p: '/v1/datasets?name=c&type=embed-input', b: DATA_FILE }), 'id');
914
+ const d = field(await h({ m: 'POST', p: '/v1/datasets?name=d&type=embed-input', b: DATA_FILE }), 'id');
915
+ if (c === a || c === b || d === a || d === b || c === d)
916
+ return false;
917
+ // …and the live row really is the new one, not a resurrected tombstone.
918
+ const got = await h({ m: 'GET', p: `/v1/datasets/${c}` });
919
+ return ok(got) && got.body.dataset.name === 'c';
920
+ })),
921
+ todo('cohere.datasets.validation_pipeline', 'datasets', 'datasets: real upload validation (queued → processing → validated/failed) with row errors', 'api', 'core'),
922
+ todo('cohere.datasets.parts', 'datasets', 'datasets: `dataset_parts` splits (train/eval) and their row counts', 'api', 'common'),
923
+ todo('cohere.datasets.metrics', 'datasets', 'datasets: the `metrics` block (label distribution, token counts)', 'api', 'niche'),
924
+ todo('cohere.datasets.date_filters', 'datasets', 'datasets: the `before` / `after` timestamp list filters', 'api', 'niche'),
925
+ todo('cohere.datasets.csv_and_separators', 'datasets', 'datasets: csv_delimiter / text_separator / keep_fields upload options', 'api', 'niche'),
926
+ // ══ CONNECTORS (Cohere's RAG connector registry) ══════════════════════════════════════
927
+ done('cohere.connectors.create_read', 'connectors', 'connectors: create → get, both NESTED under `connector`', 'api', 'core', () => withRoot(async (h) => {
928
+ const created = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'search', url: 'https://e.test/s', excludes: ['secret'], description: 'd' } });
929
+ if (!ok(created))
930
+ return false;
931
+ const c = created.body.connector;
932
+ // `CreateConnectorResponse` is `{ connector }` — a bare object would break every SDK caller.
933
+ if (created.body.id !== undefined || c === undefined)
934
+ return false;
935
+ if (c.name !== 'search' || c.url !== 'https://e.test/s' || c.description !== 'd')
936
+ return false;
937
+ // `auth_type`/`auth_status` are DERIVED server-side, not caller-supplied.
938
+ if (c.auth_type !== 'none' || c.auth_status !== 'valid' || c.active !== true)
939
+ return false;
940
+ const got = await h({ m: 'GET', p: `/v1/connectors/${c.id}` });
941
+ return ok(got) && got.body.connector?.id === c.id && JSON.stringify(got.body.connector.excludes) === '["secret"]';
942
+ })),
943
+ done('cohere.connectors.list_total_count', 'connectors', 'connectors: list carries `total_count`, and limit/offset page it', 'api', 'common', () => withRoot(async (h) => {
944
+ for (const n of ['a', 'b', 'c'])
945
+ await h({ m: 'POST', p: '/v1/connectors', b: { name: n, url: `https://e.test/${n}` } });
946
+ const all = await h({ m: 'GET', p: '/v1/connectors' });
947
+ const paged = await h({ m: 'GET', p: '/v1/connectors?limit=1&offset=1' });
948
+ // `total_count` is the UNPAGED total — a twin returning the page size here would be wrong in
949
+ // exactly the way that breaks a paginating client.
950
+ return all.body.connectors.length === 3 && all.body.total_count === 3
951
+ && paged.body.connectors.length === 1
952
+ && paged.body.connectors[0].name === 'b'
953
+ && paged.body.total_count === 3;
954
+ })),
955
+ done('cohere.connectors.update', 'connectors', 'connectors: PATCH is a partial update — untouched fields survive', 'api', 'core', () => withRoot(async (h) => {
956
+ const created = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'orig', url: 'https://e.test/s', excludes: ['x'] } });
957
+ const id = created.body.connector.id;
958
+ const patched = await h({ m: 'PATCH', p: `/v1/connectors/${id}`, b: { name: 'renamed', active: false } });
959
+ const c = patched.body.connector;
960
+ // A whole-row replace would lose `url` and `excludes` — the failure a status-only assertion
961
+ // would sail past.
962
+ if (c.name !== 'renamed' || c.active !== false || c.url !== 'https://e.test/s' || JSON.stringify(c.excludes) !== '["x"]')
963
+ return false;
964
+ const reread = await h({ m: 'GET', p: `/v1/connectors/${id}` });
965
+ const missing = await h({ m: 'PATCH', p: '/v1/connectors/nope', b: { name: 'x' } });
966
+ return reread.body.connector.name === 'renamed' && bareError(missing, 404);
967
+ })),
968
+ done('cohere.connectors.update_revert_is_not_a_replay', 'connectors', 'A PATCH reverting a field under a FROZEN clock is a real write, not a swallowed replay', 'api', 'core', () => withRoot(async (h) => {
969
+ // §9 round 1, finding 4. `applyTwinWrite`'s action id is (content + `occurredAt` millisecond).
970
+ // A world under a frozen clock (TWIN_WORLD_CLOCK_FILE) gives every request ONE occurredAt, so
971
+ // A → B → A makes the third action byte-identical to the first: the kernel drops it as
972
+ // `replayed` while the handler answers 200 carrying B, the value the caller did not ask for.
973
+ // Every request below shares the same pinned instant, which is exactly that world.
974
+ const created = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'A', url: 'https://e.test/s' } });
975
+ const id = created.body.connector.id;
976
+ // THE SEQUENCE IS ODD-LENGTH ON PURPOSE. `B → A → B` is the shortest revisit whose deduped
977
+ // outcome DIFFERS from its correct one: the third update is byte-identical to the first, so
978
+ // a twin without the ordinal drops it as `replayed` and the projection stays at A, while a
979
+ // correct twin lands B. An EVEN-length cycle (B → A → B → A) ends at A either way — which is
980
+ // precisely how the first version of this pin came out HOLLOW in the revert matrix: its cell
981
+ // stayed green with the ordinal removed, because the assertion could not tell the two apart.
982
+ const toB = await h({ m: 'PATCH', p: `/v1/connectors/${id}`, b: { name: 'B' } });
983
+ if (toB.body.connector.name !== 'B')
984
+ return false;
985
+ const backToA = await h({ m: 'PATCH', p: `/v1/connectors/${id}`, b: { name: 'A' } });
986
+ if (backToA.body.connector.name !== 'A')
987
+ return false;
988
+ const againB = await h({ m: 'PATCH', p: `/v1/connectors/${id}`, b: { name: 'B' } });
989
+ // The reply must say B…
990
+ if (againB.body.connector.name !== 'B')
991
+ return false;
992
+ // …and so must the STORED state. Reply-and-state disagreeing is the failure mode, and only
993
+ // the re-read can see it.
994
+ const reread = await h({ m: 'GET', p: `/v1/connectors/${id}` });
995
+ if (reread.body.connector.name !== 'B')
996
+ return false;
997
+ // A longer odd cycle, so the ordinal is shown to keep MOVING rather than merely alternating
998
+ // between two values that would themselves collide on the next revisit.
999
+ for (const n of ['A', 'B', 'A'])
1000
+ await h({ m: 'PATCH', p: `/v1/connectors/${id}`, b: { name: n } });
1001
+ const final = await h({ m: 'GET', p: `/v1/connectors/${id}` });
1002
+ // The ordinal is twin bookkeeping and must never reach the wire.
1003
+ return final.body.connector.name === 'A' && final.body.connector._rev === undefined;
1004
+ })),
1005
+ done('cohere.connectors.oauth_authorize', 'connectors', 'connectors: oauth/authorize builds a real redirect, and refuses a non-oauth connector', 'api', 'common', () => withRoot(async (h) => {
1006
+ const plain = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'plain', url: 'https://e.test/s' } });
1007
+ const plainId = plain.body.connector.id;
1008
+ const refused = await h({ m: 'POST', p: `/v1/connectors/${plainId}/oauth/authorize` });
1009
+ // A connector with no OAuth configuration has nothing to authorize. Answering a fabricated
1010
+ // redirect URL would be a fake success on a path the vendor refuses.
1011
+ if (!bareError(refused, 400) || !message(refused).includes('not configured for oauth'))
1012
+ return false;
1013
+ const oauth = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'oauth', url: 'https://e.test/o', oauth: { client_id: 'cid-9', client_secret: 's', authorize_url: 'https://auth.test/go', token_url: 'https://auth.test/tok' } } });
1014
+ const oc = oauth.body.connector;
1015
+ if (oc.auth_type !== 'oauth' || oc.auth_status !== 'expired')
1016
+ return false;
1017
+ const authz = await h({ m: 'POST', p: `/v1/connectors/${oc.id}/oauth/authorize?after_token_redirect=https://app.test/done` });
1018
+ const url = field(authz, 'redirect_url');
1019
+ // The redirect is built from the connector's OWN stored configuration, not a constant.
1020
+ return ok(authz) && url.startsWith('https://auth.test/go?')
1021
+ && url.includes('client_id=cid-9')
1022
+ && url.includes('after_token_redirect=https%3A%2F%2Fapp.test%2Fdone')
1023
+ && (await h({ m: 'POST', p: '/v1/connectors/nope/oauth/authorize' })).status === 404;
1024
+ })),
1025
+ done('cohere.connectors.delete', 'connectors', 'connectors: delete answers `{}` and the row really leaves the list', 'api', 'common', () => withRoot(async (h) => {
1026
+ const created = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'gone', url: 'https://e.test/s' } });
1027
+ const id = created.body.connector.id;
1028
+ const del = await h({ m: 'DELETE', p: `/v1/connectors/${id}` });
1029
+ if (!ok(del) || Object.keys(del.body).length !== 0)
1030
+ return false;
1031
+ const after = await h({ m: 'GET', p: `/v1/connectors/${id}` });
1032
+ const list = await h({ m: 'GET', p: '/v1/connectors' });
1033
+ return bareError(after, 404) && list.body.total_count === 0;
1034
+ })),
1035
+ done('cohere.connectors.validation', 'connectors', 'connectors: name and url are both required', 'api', 'common', () => withRoot(async (h) => {
1036
+ const noName = await h({ m: 'POST', p: '/v1/connectors', b: { url: 'https://e.test' } });
1037
+ const noUrl = await h({ m: 'POST', p: '/v1/connectors', b: { name: 'x' } });
1038
+ return bareError(noName, 400) && message(noName) === 'invalid request: name is required'
1039
+ && bareError(noUrl, 400) && message(noUrl) === 'invalid request: url is required';
1040
+ })),
1041
+ todo('cohere.connectors.service_auth', 'connectors', 'connectors: `service_auth` bearer/basic configuration and its auth_status', 'api', 'common'),
1042
+ todo('cohere.connectors.oauth_token_exchange', 'connectors', 'connectors: the OAuth callback token exchange that flips auth_status to valid', 'api', 'common'),
1043
+ todo('cohere.connectors.search_invocation', 'connectors', 'connectors: the twin CALLING a connector\'s search URL during a v1 chat', 'api', 'common'),
1044
+ todo('cohere.connectors.continue_on_failure', 'connectors', 'connectors: `continue_on_failure` semantics when a connector search errors', 'api', 'niche'),
1045
+ // ══ EMBED JOBS (stateful) ═════════════════════════════════════════════════════════════
1046
+ done('cohere.embed_jobs.create_read', 'embed_jobs', 'embed jobs: create answers `{job_id, meta}`; the job reads back with NO `id`', 'api', 'core', () => withRoot(async (h) => {
1047
+ const ds = field(await h({ m: 'POST', p: '/v1/datasets?name=in&type=embed-input', b: DATA_FILE }), 'id');
1048
+ const created = await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: ds, input_type: 'search_document', name: 'j1' } });
1049
+ if (!ok(created))
1050
+ return false;
1051
+ const b = created.body;
1052
+ // A DIFFERENT create envelope again: `job_id`, not `id`, and a `meta` alongside.
1053
+ if (typeof b.job_id !== 'string' || b.id !== undefined || b.meta === undefined)
1054
+ return false;
1055
+ const got = await h({ m: 'GET', p: `/v1/embed-jobs/${b.job_id}` });
1056
+ const j = got.body;
1057
+ // The vendor's EmbedJob schema has NO `id` key at all; emitting one would be invented
1058
+ // surface, and a connector subjecting on `.id` would collapse the whole collection.
1059
+ return ok(got) && j.job_id === b.job_id && j.id === undefined
1060
+ && j.status === 'processing' && j.input_dataset_id === ds && j.model === 'embed-english-v3.0'
1061
+ && j.truncate === 'END' && j.name === 'j1' && j.created_at === PINNED_AT;
1062
+ })),
1063
+ done('cohere.embed_jobs.requires_real_dataset', 'embed_jobs', 'embed jobs: `dataset_id` must reference a dataset that exists', 'api', 'core', () => withRoot(async (h) => {
1064
+ const missing = await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: 'does-not-exist', input_type: 'search_document' } });
1065
+ if (!bareError(missing, 404) || !message(missing).includes("dataset 'does-not-exist' not found"))
1066
+ return false;
1067
+ const ds = field(await h({ m: 'POST', p: '/v1/datasets?name=in&type=embed-input', b: DATA_FILE }), 'id');
1068
+ // …and once the dataset EXISTS the same call succeeds — so the refusal is about the missing
1069
+ // reference, not about the endpoint being broken.
1070
+ const okJob = await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: ds, input_type: 'search_document' } });
1071
+ // A DELETED dataset must fail the same way a never-created one does.
1072
+ await h({ m: 'DELETE', p: `/v1/datasets/${ds}` });
1073
+ const afterDelete = await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: ds, input_type: 'search_document' } });
1074
+ return ok(okJob) && bareError(afterDelete, 404);
1075
+ })),
1076
+ done('cohere.embed_jobs.cancel_state_machine', 'embed_jobs', 'embed jobs: cancel moves processing → cancelling, and a terminal job is refused', 'api', 'core', () => withRoot(async (h) => {
1077
+ const ds = field(await h({ m: 'POST', p: '/v1/datasets?name=in&type=embed-input', b: DATA_FILE }), 'id');
1078
+ const job = field(await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: ds, input_type: 'search_document' } }), 'job_id');
1079
+ const cancel = await h({ m: 'POST', p: `/v1/embed-jobs/${job}/cancel` });
1080
+ // `embedJobs.cancel` is declared `-> void`: an empty body — and the STATE must have moved,
1081
+ // which a status-only assertion would not catch.
1082
+ if (!ok(cancel) || Object.keys(cancel.body).length !== 0)
1083
+ return false;
1084
+ const after = await h({ m: 'GET', p: `/v1/embed-jobs/${job}` });
1085
+ if (after.body.status !== 'cancelling')
1086
+ return false;
1087
+ const again = await h({ m: 'POST', p: `/v1/embed-jobs/${job}/cancel` });
1088
+ const missing = await h({ m: 'POST', p: '/v1/embed-jobs/nope/cancel' });
1089
+ return bareError(again, 400) && message(again).includes('cannot be cancelled') && bareError(missing, 404);
1090
+ })),
1091
+ done('cohere.embed_jobs.validation', 'embed_jobs', 'embed jobs: model / dataset_id / input_type required, closed enums enforced', 'api', 'common', () => withRoot(async (h) => {
1092
+ const ds = field(await h({ m: 'POST', p: '/v1/datasets?name=in&type=embed-input', b: DATA_FILE }), 'id');
1093
+ const base = { model: 'embed-english-v3.0', dataset_id: ds, input_type: 'search_document' };
1094
+ const noModel = await h({ m: 'POST', p: '/v1/embed-jobs', b: { dataset_id: ds, input_type: 'search_document' } });
1095
+ const noDataset = await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', input_type: 'search_document' } });
1096
+ const noInput = await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: ds } });
1097
+ const badInput = await h({ m: 'POST', p: '/v1/embed-jobs', b: { ...base, input_type: 'search' } });
1098
+ const badTrunc = await h({ m: 'POST', p: '/v1/embed-jobs', b: { ...base, truncate: 'middle' } });
1099
+ const chatModel = await h({ m: 'POST', p: '/v1/embed-jobs', b: { ...base, model: 'command-a-03-2025' } });
1100
+ return bareError(noModel, 400) && bareError(noDataset, 400) && bareError(noInput, 400)
1101
+ && bareError(badInput, 400) && bareError(badTrunc, 400) && bareError(chatModel, 404);
1102
+ })),
1103
+ done('cohere.embed_jobs.list', 'embed_jobs', 'embed jobs: list under the `embed_jobs` key (not `data`)', 'api', 'common', () => withRoot(async (h) => {
1104
+ const empty = await h({ m: 'GET', p: '/v1/embed-jobs' });
1105
+ if (!ok(empty) || JSON.stringify(empty.body.embed_jobs) !== '[]' || empty.body.data !== undefined)
1106
+ return false;
1107
+ const ds = field(await h({ m: 'POST', p: '/v1/datasets?name=in&type=embed-input', b: DATA_FILE }), 'id');
1108
+ const job = field(await h({ m: 'POST', p: '/v1/embed-jobs', b: { model: 'embed-english-v3.0', dataset_id: ds, input_type: 'search_document' } }), 'job_id');
1109
+ const list = await h({ m: 'GET', p: '/v1/embed-jobs' });
1110
+ const jobs = list.body.embed_jobs;
1111
+ return jobs.length === 1 && jobs[0].job_id === job && jobs[0].id === undefined;
1112
+ })),
1113
+ todo('cohere.embed_jobs.completion', 'embed_jobs', 'embed jobs: a job actually completing and minting its `output_dataset_id`', 'api', 'common'),
1114
+ todo('cohere.embed_jobs.failure', 'embed_jobs', 'embed jobs: the `failed` terminal state and its error reporting', 'api', 'niche'),
1115
+ // ══ SURFACE THE TWIN DOES NOT SERVE (real vendor endpoints, honestly filed) ═══════════
1116
+ todo('cohere.generate.create', 'generate', 'POST /v1/generate: the legacy completion endpoint (deprecated but still served)', 'api', 'niche'),
1117
+ todo('cohere.generate.stream', 'generate', 'POST /v1/generate with stream: the GenerateStreamedResponse wire', 'api', 'niche'),
1118
+ todo('cohere.summarize.create', 'summarize', 'POST /v1/summarize: the legacy summarization endpoint (deprecated but still served)', 'api', 'niche'),
1119
+ todo('cohere.parse.create', 'parse', 'POST /v2/parse: document parsing into structured output', 'api', 'common'),
1120
+ todo('cohere.audio.transcriptions', 'audio', 'POST /v2/audio/transcriptions: multipart audio → transcript', 'api', 'common'),
1121
+ todo('cohere.batches.create', 'batches', 'POST /v2/batches: submit a batch of chat/embed requests', 'api', 'common'),
1122
+ todo('cohere.batches.list', 'batches', 'GET /v2/batches: list batches with their status counts', 'api', 'common'),
1123
+ todo('cohere.batches.retrieve', 'batches', 'GET /v2/batches/{id}: one batch with its output file references', 'api', 'common'),
1124
+ todo('cohere.batches.cancel', 'batches', 'POST /v2/batches/{id}:cancel — note the COLON verb suffix, not a path segment', 'api', 'common'),
1125
+ todo('cohere.finetuning.create', 'finetuning', 'POST /v1/finetuning/finetuned-models: start a finetune from a dataset', 'api', 'common'),
1126
+ todo('cohere.finetuning.list', 'finetuning', 'GET /v1/finetuning/finetuned-models: list finetuned models', 'api', 'common'),
1127
+ todo('cohere.finetuning.get', 'finetuning', 'GET /v1/finetuning/finetuned-models/{id}: one finetuned model and its status', 'api', 'common'),
1128
+ todo('cohere.finetuning.update', 'finetuning', 'PATCH /v1/finetuning/finetuned-models/{id}: rename / re-point a finetune', 'api', 'niche'),
1129
+ todo('cohere.finetuning.delete', 'finetuning', 'DELETE /v1/finetuning/finetuned-models/{id}', 'api', 'niche'),
1130
+ todo('cohere.finetuning.events', 'finetuning', 'GET /v1/finetuning/finetuned-models/{id}/events: the training event log', 'api', 'niche'),
1131
+ todo('cohere.finetuning.metrics', 'finetuning', 'GET /v1/finetuning/finetuned-models/{id}/training-step-metrics', 'api', 'niche'),
1132
+ // ══ ERRORS / AUTH / READ-ONLY ═════════════════════════════════════════════════════════
1133
+ done('cohere.auth.check_api_key', 'auth', 'POST /v1/check-api-key: a POST despite the name, answering {valid, organization_id, owner_id}', 'api', 'common', () => withRoot(async (h) => {
1134
+ // §9 round two, MAJOR 2: this endpoint was served, probed by conformance, driven through the
1135
+ // real SDK and headlined in the README's "asserted by a named capability" table — with NO
1136
+ // manifest entry and no area. The area census could not catch it, because it asserts a
1137
+ // bijection between COHERE_AREAS and the manifest's areas: a surface missing from BOTH sides
1138
+ // passes silently. That is the census's documented blind spot, found live.
1139
+ const r = await h({ m: 'POST', p: '/v1/check-api-key' });
1140
+ if (!ok(r))
1141
+ return false;
1142
+ const b = r.body;
1143
+ if (b.valid !== true || typeof b.organization_id !== 'string' || typeof b.owner_id !== 'string')
1144
+ return false;
1145
+ // THE VERB IS THE POINT. `checkApiKey()` sends `method: "POST"` in cohere-ai's Client.js —
1146
+ // the name invites a GET, and a twin that served one would break every real caller.
1147
+ const asGet = await h({ m: 'GET', p: '/v1/check-api-key' });
1148
+ if (!bareError(asGet, 404))
1149
+ return false;
1150
+ // …and it is auth-gated like every other endpoint when an auth surface is present.
1151
+ return bareError(await h({ m: 'POST', p: '/v1/check-api-key', h: {} }), 401);
1152
+ })),
1153
+ done('cohere.errors.bare_message_envelope', 'errors', "every error body is Cohere's BARE `{message}` — one key, no wrapper", 'api', 'core', () => withRoot(async (h) => {
1154
+ // Sample every distinct failure the twin can produce and assert the SHAPE of each. A single
1155
+ // spot check would not notice one path drifting to the OpenAI `{error:{...}}` envelope.
1156
+ const cases = [
1157
+ await h({ m: 'POST', p: '/v2/chat', b: {} }),
1158
+ await h({ m: 'POST', p: '/v2/chat', b: CHAT({ model: 'nope' }) }),
1159
+ await h({ m: 'GET', p: '/v1/models/nope' }),
1160
+ await h({ m: 'GET', p: '/v1/datasets/nope' }),
1161
+ await h({ m: 'GET', p: '/v1/nowhere' }),
1162
+ await h({ m: 'GET', p: '/v1/models', h: {} }),
1163
+ await h({ m: 'POST', p: '/v2/chat', b: CHAT(), ro: true }),
1164
+ ];
1165
+ for (const r of cases) {
1166
+ if (r.status < 400)
1167
+ return false;
1168
+ if (!r.body || typeof r.body !== 'object')
1169
+ return false;
1170
+ if (Object.keys(r.body).join(',') !== 'message')
1171
+ return false;
1172
+ if (typeof r.body.message !== 'string' || r.body.message === '')
1173
+ return false;
1174
+ }
1175
+ // …and the statuses really are the vendor's, not all one code.
1176
+ return cases.map((r) => r.status).join(',') === '400,404,404,404,404,401,405';
1177
+ })),
1178
+ done('cohere.errors.auth_401', 'errors', 'auth: a request with an auth SURFACE but no usable bearer token 401s', 'api', 'core', () => withRoot(async (h) => {
1179
+ const none = await h({ m: 'GET', p: '/v1/models', h: {} });
1180
+ const empty = await h({ m: 'GET', p: '/v1/models', h: { authorization: 'Bearer ' } });
1181
+ const sentinel = await h({ m: 'GET', p: '/v1/models', h: { authorization: 'Bearer invalid' } });
1182
+ const good = await h({ m: 'GET', p: '/v1/models', h: { authorization: 'Bearer sk-anything' } });
1183
+ // The twin cannot validate real keys, so the modeled failure is the CHECKABLE
1184
+ // missing/sentinel case — and a plausible token must still be ACCEPTED, or the twin would be
1185
+ // unusable rather than faithful.
1186
+ return bareError(none, 401) && bareError(empty, 401) && bareError(sentinel, 401) && ok(good);
1187
+ })),
1188
+ done('cohere.errors.read_only_405', 'errors', 'readOnly: every POST/PATCH/DELETE is refused 405 while reads still serve', 'api', 'core', () => withRoot(async (h) => {
1189
+ // Seed with writes ENABLED, then prove the same reads still work read-only while every
1190
+ // mutating VERB is refused. Note the refusal is method-based, so the write-free inference
1191
+ // POSTs (`/v2/chat`, `/v1/tokenize`) are refused too — a read-only Cohere world cannot chat.
1192
+ // That is a defensible D3 reading of "no POSTs" but it is NOT "every mutation", which is why
1193
+ // the title says POST/PATCH/DELETE rather than over-claiming (§9 round 1, finding 8).
1194
+ const ds = field(await h({ m: 'POST', p: '/v1/datasets?name=a&type=embed-input', b: DATA_FILE }), 'id');
1195
+ const writes = [
1196
+ { m: 'POST', p: '/v2/chat', b: CHAT(), ro: true },
1197
+ { m: 'POST', p: '/v1/datasets?name=b&type=embed-input', ro: true },
1198
+ { m: 'DELETE', p: `/v1/datasets/${ds}`, ro: true },
1199
+ { m: 'PATCH', p: '/v1/connectors/x', b: { name: 'y' }, ro: true },
1200
+ { m: 'POST', p: '/v1/tokenize', b: { text: 'x', model: 'command-a-03-2025' }, ro: true },
1201
+ ];
1202
+ for (const w of writes) {
1203
+ const r = await h(w);
1204
+ if (!bareError(r, 405))
1205
+ return false;
1206
+ }
1207
+ const read = await h({ m: 'GET', p: '/v1/datasets', ro: true });
1208
+ return ok(read) && read.body.datasets.length === 1;
1209
+ })),
1210
+ done('cohere.errors.unmodeled_ops_404', 'errors', 'unmodeled operations fail like the vendor (404), never a fake success', 'api', 'core', () => withRoot(async (h) => {
1211
+ // Real Cohere endpoints this twin does NOT model. Each must 404 rather than fake-succeed —
1212
+ // and each is filed as a `todo` above, so the manifest and the handler agree.
1213
+ const unmodeled = [
1214
+ { m: 'POST', p: '/v1/generate', b: { prompt: 'x' } },
1215
+ { m: 'POST', p: '/v1/summarize', b: { text: 'x' } },
1216
+ { m: 'POST', p: '/v2/parse', b: {} },
1217
+ { m: 'POST', p: '/v2/audio/transcriptions', b: {} },
1218
+ { m: 'GET', p: '/v2/batches' },
1219
+ { m: 'POST', p: '/v2/batches' },
1220
+ { m: 'GET', p: '/v1/finetuning/finetuned-models' },
1221
+ { m: 'POST', p: '/v1/finetuning/finetuned-models', b: {} },
1222
+ ];
1223
+ for (const u of unmodeled) {
1224
+ const r = await h(u);
1225
+ if (!bareError(r, 404))
1226
+ return false;
1227
+ }
1228
+ // …and a method the twin does not serve on a path it DOES is equally a 404, not a silent
1229
+ // fall-through to the GET branch.
1230
+ const wrongMethod = await h({ m: 'DELETE', p: '/v1/models/rerank-v3.5' });
1231
+ return bareError(wrongMethod, 404);
1232
+ })),
1233
+ done('cohere.errors.malformed_body', 'errors', 'a malformed JSON body is refused, never treated as an empty object', 'api', 'common', () => {
1234
+ const root = mkdtempSync(join(tmpdir(), 'cohere-cap-'));
1235
+ return verifyBoundary('cohere.malformed', async () => {
1236
+ try {
1237
+ const r = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: '{not json', root, occurredAt: PINNED_AT });
1238
+ // An unparseable body yields no `model`, so the vendor-shaped required-field refusal is
1239
+ // the correct answer — and a 200 here would mean the twin generated from nothing.
1240
+ return bareError(r, 400) && message(r) === 'invalid request: model is required';
1241
+ }
1242
+ finally {
1243
+ rmSync(root, { recursive: true, force: true });
1244
+ }
1245
+ });
1246
+ }),
1247
+ // ══ DETERMINISM — the serve-path invariant ════════════════════════════════════════════
1248
+ done('cohere.determinism.replay_two_roots', 'determinism', 'the served response is byte-identical across two INDEPENDENT state roots', 'api', 'core', () => {
1249
+ const a = mkdtempSync(join(tmpdir(), 'cohere-det-a-'));
1250
+ const b = mkdtempSync(join(tmpdir(), 'cohere-det-b-'));
1251
+ return verifyBoundary('cohere.determinism', async () => {
1252
+ try {
1253
+ const requests = [
1254
+ { m: 'POST', p: '/v2/chat', b: CHAT() },
1255
+ { m: 'POST', p: '/v2/chat', b: CHAT({ tools: [TOOL] }) },
1256
+ { m: 'POST', p: '/v1/chat', b: { message: 'v1 det' } },
1257
+ { m: 'POST', p: '/v2/embed', b: { model: 'embed-v4.0', input_type: 'search_query', texts: ['det'], embedding_types: ['float', 'int8', 'base64'] } },
1258
+ { m: 'POST', p: '/v2/rerank', b: { model: 'rerank-v3.5', query: 'q', documents: ['a q', 'b'] } },
1259
+ { m: 'POST', p: '/v1/classify', b: { inputs: ['x'], examples: [{ text: 'a', label: 'p' }, { text: 'b', label: 'n' }] } },
1260
+ { m: 'POST', p: '/v1/tokenize', b: { text: 'det tokens here', model: 'command-a-03-2025' } },
1261
+ ];
1262
+ const run = async (root) => {
1263
+ const out = [];
1264
+ for (const s of requests) {
1265
+ const r = await handleCohereTwinRequest({ method: s.m, path: s.p, root, occurredAt: PINNED_AT, ...(s.b === undefined ? {} : { body: JSON.stringify(s.b) }) });
1266
+ out.push(`${r.status} ${JSON.stringify(r.body)}`);
1267
+ }
1268
+ return out;
1269
+ };
1270
+ const first = await run(a);
1271
+ const second = await run(b);
1272
+ // Two independent roots, same requests, byte-identical answers — and the payloads are
1273
+ // non-trivial, so this cannot pass on a twin that answers `{}` to everything.
1274
+ if (first.join('\n') !== second.join('\n'))
1275
+ return false;
1276
+ if (first.some((s) => s.length < 40))
1277
+ return false;
1278
+ // Replaying the FIRST root a second time must also be identical: the stored state grew
1279
+ // (the tokenize wrote rows) without perturbing any answer.
1280
+ const third = await run(a);
1281
+ return third.join('\n') === first.join('\n');
1282
+ }
1283
+ finally {
1284
+ rmSync(a, { recursive: true, force: true });
1285
+ rmSync(b, { recursive: true, force: true });
1286
+ }
1287
+ });
1288
+ }),
1289
+ done('cohere.determinism.no_wall_clock', 'determinism', 'no wall-clock or randomness in served content: an unpinned run is stable, and TIMESTAMPS are pinned', 'api', 'core', () => {
1290
+ const root = mkdtempSync(join(tmpdir(), 'cohere-det-c-'));
1291
+ return verifyBoundary('cohere.determinism_clock', async () => {
1292
+ try {
1293
+ // NOTHING here threads `occurredAt`, so anything reading `Date.now()` or `Math.random()` on
1294
+ // the serve path differs between calls.
1295
+ const one = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: JSON.stringify(CHAT()), root });
1296
+ await new Promise((r) => setTimeout(r, 5));
1297
+ const two = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: JSON.stringify(CHAT()), root });
1298
+ if (JSON.stringify(one.body) !== JSON.stringify(two.body))
1299
+ return false;
1300
+ // A DIFFERENT prompt must give a different answer, so "identical" is not trivially true.
1301
+ const other = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: JSON.stringify(CHAT({ messages: [{ role: 'user', content: 'different' }] })), root });
1302
+ if (JSON.stringify(other.body) === JSON.stringify(one.body))
1303
+ return false;
1304
+ // THE HALF THAT ACTUALLY REFUTES THE CLAIM (§9 round 1, finding 1). `/v2/chat` carries no
1305
+ // timestamp at all, so the three calls above would stay green with `nowIso` rewritten to
1306
+ // `new Date().toISOString()` — the pack's own headline invariant had a surviving mutant.
1307
+ // Datasets are the endpoint that DOES stamp a clock, so an unpinned pair of creates is
1308
+ // where a wall clock becomes visible. Both halves matter: the two timestamps must AGREE
1309
+ // across a real 5ms gap, and they must equal the pinned instant written here as a LITERAL
1310
+ // (importing the handler's own constant could not catch it drifting).
1311
+ const mk = (name) => handleCohereTwinRequest({ method: 'POST', path: `/v1/datasets?name=${name}&type=embed-input`, body: JSON.stringify({ content: 'x' }), root });
1312
+ const a = await mk('clock-a');
1313
+ await new Promise((r) => setTimeout(r, 5));
1314
+ const b = await mk('clock-b');
1315
+ const read = async (r) => (await handleCohereTwinRequest({ method: 'GET', path: `/v1/datasets/${r.body.id}`, root })).body;
1316
+ const rowA = await read(a);
1317
+ const rowB = await read(b);
1318
+ const stamped = rowA.dataset?.created_at;
1319
+ if (typeof stamped !== 'string' || stamped !== rowB.dataset?.created_at)
1320
+ return false;
1321
+ if (stamped !== '2027-01-15T08:00:00.000Z')
1322
+ return false;
1323
+ if (rowA.dataset?.updated_at !== stamped)
1324
+ return false;
1325
+ // …and an EXPLICIT occurredAt still wins, so the pin is a default rather than a hardcode.
1326
+ const pinned = await handleCohereTwinRequest({ method: 'POST', path: '/v1/datasets?name=clock-c&type=embed-input', body: JSON.stringify({ content: 'x' }), root, occurredAt: PINNED_AT });
1327
+ const rowC = await read(pinned);
1328
+ return rowC.dataset?.created_at === PINNED_AT;
1329
+ }
1330
+ finally {
1331
+ rmSync(root, { recursive: true, force: true });
1332
+ }
1333
+ });
1334
+ }),
1335
+ done('cohere.determinism.stream_matches_unary', 'determinism', 'the streamed and unary answers to the same request agree exactly', 'api', 'common', () => withStream('/v2/chat', CHAT({ stream: true, tools: [TOOL] }), (events, final) => {
1336
+ const end = events.find((e) => e.data?.type === 'message-end')?.data;
1337
+ const start = events.find((e) => e.data?.type === 'message-start')?.data;
1338
+ const f = final.body;
1339
+ // Ids and usage must be the SAME object the unary path would have produced — a separate
1340
+ // generation for the stream would show up here.
1341
+ return start?.id === f.id && end?.id === f.id
1342
+ && JSON.stringify(end?.delta?.usage) === JSON.stringify(f.usage)
1343
+ && end?.delta?.finish_reason === f.finish_reason;
1344
+ })),
1345
+ // ══ CONNECTOR (the twin's pull/push plane) ════════════════════════════════════════════
1346
+ done('cohere.connector.pull_all_collections', 'connector', 'Connector: pull folds datasets + connectors + embed jobs into the projection', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1347
+ const res = await syncCohereFromReal(execute, { root, occurredAt: PINNED_AT });
1348
+ if (res.observed !== 3 || res.deltasAppended !== 3)
1349
+ return false;
1350
+ // Every modeled collection is actually fetched — a pull that quietly skipped one would still
1351
+ // report a plausible count without this.
1352
+ if (calls.map((c) => `${c.method} ${c.path}`).sort().join('|') !== 'GET /v1/connectors|GET /v1/datasets|GET /v1/embed-jobs')
1353
+ return false;
1354
+ // …and the pulled rows are SERVABLE through the twin's own read paths under the VENDOR's ids.
1355
+ const ds = await handleCohereTwinRequest({ method: 'GET', path: '/v1/datasets/ds-real-1', root });
1356
+ const conn = await handleCohereTwinRequest({ method: 'GET', path: '/v1/connectors/conn-real-1', root });
1357
+ const job = await handleCohereTwinRequest({ method: 'GET', path: '/v1/embed-jobs/job-real-1', root });
1358
+ return ds.body.dataset?.name === 'real-dataset'
1359
+ && conn.body.connector?.auth_type === 'oauth'
1360
+ && job.body.job_id === 'job-real-1' && job.body.input_dataset_id === 'ds-real-1';
1361
+ })),
1362
+ done('cohere.connector.pull_idempotent', 'connector', 'Connector: re-pulling identical state appends NOTHING (shadow-diff)', 'connector', 'core', () => withConnector(async (execute, _calls, root) => {
1363
+ const first = await syncCohereFromReal(execute, { root, occurredAt: PINNED_AT });
1364
+ const second = await syncCohereFromReal(execute, { root, occurredAt: '2026-08-31T13:00:00.000Z' });
1365
+ if (first.deltasAppended !== 3 || second.deltasAppended !== 0 || second.observed !== 3)
1366
+ return false;
1367
+ // The projection still serves exactly one row per collection — a re-pull that duplicated
1368
+ // would show up here rather than in the delta count.
1369
+ const list = await handleCohereTwinRequest({ method: 'GET', path: '/v1/datasets', root });
1370
+ return list.body.datasets.length === 1;
1371
+ })),
1372
+ done('cohere.connector.pull_refuses_error_envelope', 'connector', "Connector: a REFUSED pull throws — it is never an empty account", 'connector', 'core', () => {
1373
+ const root = mkdtempSync(join(tmpdir(), 'cohere-refuse-'));
1374
+ return verifyBoundary('cohere.pull_refuses', async () => {
1375
+ try {
1376
+ // Each executor is built INLINE rather than through `withConnector`, because the outcome
1377
+ // under test is a THROW: `verifyBoundary` converts a non-infrastructure throw into a
1378
+ // `false`, so a nested helper would swallow the very rejection being asserted.
1379
+ const executorFor = (reply) => async (method, path) => reply(method, path);
1380
+ // 1. Cohere answers a failure with its bare `{message}` envelope. Mapping that to "no
1381
+ // resources" would fold an EMPTY account over real observed state and delete the mirror.
1382
+ let refusalMsg = '';
1383
+ try {
1384
+ await syncCohereFromReal(executorFor(() => ({ message: 'rate limited' })), { root, occurredAt: PINNED_AT });
1385
+ }
1386
+ catch (e) {
1387
+ refusalMsg = e.message;
1388
+ }
1389
+ if (!refusalMsg.includes('pull /v1/datasets failed') || !refusalMsg.includes('rate limited'))
1390
+ return false;
1391
+ // 2. An UNRECOGNIZED envelope (no error, but no collection key either) is also a throw,
1392
+ // not a zero-row pull — "I do not understand this response" is not "the account is
1393
+ // empty", and only the throw keeps the two apart.
1394
+ let unknownMsg = '';
1395
+ try {
1396
+ await syncCohereFromReal(executorFor(() => ({ unexpected: [] })), { root, occurredAt: PINNED_AT });
1397
+ }
1398
+ catch (e) {
1399
+ unknownMsg = e.message;
1400
+ }
1401
+ if (!unknownMsg.includes('no "datasets" key'))
1402
+ return false;
1403
+ // 3. …but an EXPLICIT `null` genuinely means empty ON THE COLLECTIONS WHOSE SCHEMA SAYS SO,
1404
+ // and must NOT throw. Without this half the check would pass on a connector that threw
1405
+ // on everything. Nullability is read PER COLLECTION from the vendor's own serializers:
1406
+ // `DatasetsListResponse.datasets` and `ListEmbedJobResponse.embed_jobs` are
1407
+ // `?: Raw[] | null`, so null means empty there.
1408
+ const empty = await syncCohereFromReal(executorFor((m, p) => (m === 'GET' && p === '/v1/datasets' ? { datasets: null } : m === 'GET' && p === '/v1/connectors' ? { connectors: [], total_count: 0 } : { embed_jobs: null })), { root, occurredAt: PINNED_AT });
1409
+ if (empty.observed !== 0 || empty.deltasAppended !== 0)
1410
+ return false;
1411
+ // 3b. …and `ListConnectorsResponse.connectors` is declared REQUIRED and NON-nullable, so a
1412
+ // null THERE is a response the vendor says cannot occur. Treating it as an empty
1413
+ // account would fold an empty list over real observed connector state — the exact
1414
+ // hazard this whole check exists to close, admitted through a door that an earlier
1415
+ // version justified with a premise that was false for this one collection
1416
+ // (§9 round 1, connector m1).
1417
+ let nullConnMsg = '';
1418
+ try {
1419
+ await syncCohereFromReal(executorFor((m, p) => (m === 'GET' && p === '/v1/datasets' ? { datasets: [] } : m === 'GET' && p === '/v1/connectors' ? { connectors: null } : { embed_jobs: [] })), { root, occurredAt: PINNED_AT });
1420
+ }
1421
+ catch (e) {
1422
+ nullConnMsg = e.message;
1423
+ }
1424
+ if (!nullConnMsg.includes('required and non-nullable'))
1425
+ return false;
1426
+ // 4. And a NON-list under the key is a throw too, not a coerced empty.
1427
+ let badListMsg = '';
1428
+ try {
1429
+ await syncCohereFromReal(executorFor(() => ({ datasets: 'nope' })), { root, occurredAt: PINNED_AT });
1430
+ }
1431
+ catch (e) {
1432
+ badListMsg = e.message;
1433
+ }
1434
+ return badListMsg.includes('is not a list');
1435
+ }
1436
+ finally {
1437
+ rmSync(root, { recursive: true, force: true });
1438
+ }
1439
+ });
1440
+ }),
1441
+ done('cohere.connector.map_shapes', 'connector', 'Connector: the mappers carry every REQUIRED vendor field, and key embed jobs on `job_id`', 'connector', 'core', () => verifyBoundary('cohere.map_shapes', async () => {
1442
+ const d = mapDataset(REAL_DATASET);
1443
+ const c = mapConnector(REAL_CONNECTOR);
1444
+ const j = mapEmbedJob(REAL_EMBED_JOB);
1445
+ if (d.type !== 'dataset' || d.id !== 'ds-real-1')
1446
+ return false;
1447
+ // Every key the vendor's `Dataset` schema declares REQUIRED — a pulled row missing one is
1448
+ // unparseable by the official SDK the moment the twin serves it back.
1449
+ for (const k of ['name', 'created_at', 'updated_at', 'dataset_type', 'validation_status']) {
1450
+ if (d.fields[k] === undefined || d.fields[k] === null)
1451
+ return false;
1452
+ }
1453
+ if (c.type !== 'connector' || c.id !== 'conn-real-1' || c.fields.auth_type !== 'oauth')
1454
+ return false;
1455
+ for (const k of ['name', 'url', 'created_at', 'updated_at'])
1456
+ if (c.fields[k] === undefined || c.fields[k] === null)
1457
+ return false;
1458
+ // THE EMBED-JOB TRAP: the vendor's schema has NO `id` — subjecting on `.id` would land every
1459
+ // pulled job under the string "undefined" and collapse the collection onto one row.
1460
+ if (j.type !== 'embed_job' || j.id !== 'job-real-1' || j.fields.job_id !== 'job-real-1')
1461
+ return false;
1462
+ // A row with `updated_at` MISSING must fall back rather than emit null: both vendor schemas
1463
+ // declare it required-without-default.
1464
+ const noUpdated = mapDataset({ ...REAL_DATASET, updated_at: undefined });
1465
+ return noUpdated.fields.updated_at === REAL_DATASET.created_at;
1466
+ })),
1467
+ done('cohere.connector.push_create_uses_vendor_id', 'connector', 'Connector: push confirms under the VENDOR-minted id, per-type envelope', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1468
+ const created = await handleCohereTwinRequest({ method: 'POST', path: '/v1/connectors', body: JSON.stringify({ name: 'local', url: 'https://e.test/s' }), root, occurredAt: PINNED_AT });
1469
+ const localId = created.body.connector.id;
1470
+ const push = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1471
+ if (push.pushed !== 1)
1472
+ return false;
1473
+ // The create envelope is NESTED (`{connector:{id}}`) — a generic `res.id` read would fall
1474
+ // back to the local id here and silently serve one account row as two after the next pull.
1475
+ const external = Object.values(push.externalIds)[0];
1476
+ if (external !== 'conn-vendor-minted' || external === localId)
1477
+ return false;
1478
+ if (calls[0].method !== 'POST' || calls[0].path !== '/v1/connectors')
1479
+ return false;
1480
+ // The payload is the vendor's CREATE schema — derived fields the endpoint does not accept
1481
+ // must not be replayed.
1482
+ if (calls[0].body.name !== 'local' || calls[0].body.auth_type !== undefined || calls[0].body.auth_status !== undefined)
1483
+ return false;
1484
+ // The row now lives under the VENDOR's id, and the superseded local id is tombstoned so the
1485
+ // next mint can never re-issue it.
1486
+ const atVendor = await handleCohereTwinRequest({ method: 'GET', path: '/v1/connectors/conn-vendor-minted', root });
1487
+ const atLocal = await handleCohereTwinRequest({ method: 'GET', path: `/v1/connectors/${localId}`, root });
1488
+ const list = await handleCohereTwinRequest({ method: 'GET', path: '/v1/connectors', root });
1489
+ if (!ok(atVendor) || atLocal.status !== 404 || list.body.total_count !== 1)
1490
+ return false;
1491
+ // A 404 is equally true of a row that is simply ABSENT, which is what projection suppression
1492
+ // alone produces — so the 404 cannot distinguish "tombstoned" from "gone", and tombstoned is
1493
+ // the whole property (§9 round 1, m4).
1494
+ //
1495
+ // The check that CAN tell them apart reads the PROJECTION, where a tombstone is visible and an
1496
+ // absence is not — and asserts the SUPERSEDE LINK, which is the tombstone's actual value:
1497
+ // an auditable record that this local id became that vendor id. (The revert matrix is what
1498
+ // forced this to be honest: a first attempt asserted that the next mint does not re-issue
1499
+ // `localId`, and its cell stayed GREEN — because `nextId`'s ordinal only ever moves UPWARD
1500
+ // from the row-set size, so the superseded id is not a candidate either way. That claim was
1501
+ // over-stated; this one is the property the tombstone genuinely carries.)
1502
+ const rows = projectResources('cohere', root).filter((r) => r.type === 'connector');
1503
+ const tomb = rows.find((r) => r.id === localId);
1504
+ if (tomb === undefined)
1505
+ return false; // suppressed, not tombstoned
1506
+ if (tomb._deleted !== true)
1507
+ return false; // present but not marked dead
1508
+ if (tomb._superseded_by !== 'conn-vendor-minted')
1509
+ return false; // no provenance link
1510
+ // …and the tombstone is genuinely invisible to every READ path, not just to the id lookup.
1511
+ const listed = list.body.connectors.map((c) => c.id);
1512
+ return !listed.includes(localId) && listed.includes('conn-vendor-minted');
1513
+ })),
1514
+ done('cohere.connector.push_embed_job_key', 'connector', "Connector: an embed-job push reads the vendor id from `job_id`, and renames the dataset FK to the write shape", 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1515
+ // The dataset is PULLED, so it is vendor-known under its own id. (An earlier version created
1516
+ // it locally and asserted the twin-minted id went out in `dataset_id` — §9 round two found it
1517
+ // was pinning the bug rather than the behaviour.)
1518
+ await syncCohereFromReal(execute, { root, occurredAt: PINNED_AT });
1519
+ await handleCohereTwinRequest({ method: 'POST', path: '/v1/embed-jobs', body: JSON.stringify({ model: 'embed-english-v3.0', dataset_id: 'ds-real-1', input_type: 'search_document' }), root, occurredAt: PINNED_AT });
1520
+ const push = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1521
+ if (push.pushed !== 1 || push.refused.length !== 0)
1522
+ return false;
1523
+ if (Object.values(push.externalIds)[0] !== 'job-vendor-minted')
1524
+ return false;
1525
+ const jobCall = calls.find((c) => c.method === 'POST' && c.path === '/v1/embed-jobs');
1526
+ // The CREATE schema's field is `dataset_id`; the READ schema's is `input_dataset_id`. A
1527
+ // connector replaying the stored read-shape would send a field the endpoint does not declare.
1528
+ return jobCall.body.dataset_id === 'ds-real-1' && jobCall.body.input_dataset_id === undefined
1529
+ && jobCall.body.input_type === 'search_document';
1530
+ })),
1531
+ done('cohere.connector.push_refuses_twin_minted_foreign_key', 'connector', 'Connector: a payload that REFERENCES a twin-minted id is refused, not posted', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1532
+ // §9 round two, MAJOR. The identity guard covers `subject.id` — and a FOREIGN KEY carries an
1533
+ // id just as capably. `dataset.create` is an un-pushable multipart gap, so a locally created
1534
+ // dataset is PERMANENTLY vendor-unknown; the embed-job create copied its `input_dataset_id`
1535
+ // straight into the vendor's `dataset_id`, so `{"dataset_id":"<twin-uuid>"}` went to the REAL
1536
+ // account, where Cohere rejects the unknown dataset and the batch wedges exactly as B1 did.
1537
+ const ds = await handleCohereTwinRequest({ method: 'POST', path: '/v1/datasets?name=local&type=embed-input', body: JSON.stringify(DATA_FILE), root, occurredAt: PINNED_AT });
1538
+ const dsId = ds.body.id;
1539
+ await handleCohereTwinRequest({ method: 'POST', path: '/v1/embed-jobs', body: JSON.stringify({ model: 'embed-english-v3.0', dataset_id: dsId, input_type: 'search_document' }), root, occurredAt: PINNED_AT });
1540
+ const push = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1541
+ // Both the dataset create (filed multipart gap) and the embed job (twin-minted FK) refuse.
1542
+ if (push.pushed !== 0 || push.refused.length !== 2)
1543
+ return false;
1544
+ const fk = push.refused.find((r) => r.operation === 'embed_job.create');
1545
+ if (!fk || !fk.reason.includes(`references dataset '${dsId}'`))
1546
+ return false;
1547
+ // NOT ONE REQUEST went out, and the twin-minted id appears nowhere — not in a path, and not
1548
+ // in a BODY, which is the half a path-only assertion cannot see.
1549
+ if (calls.length !== 0)
1550
+ return false;
1551
+ return !JSON.stringify(calls).includes(dsId);
1552
+ })),
1553
+ done('cohere.connector.push_refuses_idless_create_response', 'connector', 'Connector: a create response with NO vendor id is an error — never confirmed under the twin\'s own id', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1554
+ // §9 round two, m-R2.1. Falling back to the local id would MANUFACTURE a vendor identity:
1555
+ // no supersede tombstone is written, so `vendorIdentity` would afterwards report that id as
1556
+ // vendor-known and every later mutation would push the twin's own UUID at the real account —
1557
+ // re-opening the BLOCKER through a side door.
1558
+ await handleCohereTwinRequest({ method: 'POST', path: '/v1/connectors', body: JSON.stringify({ name: 'x', url: 'https://e.test/s' }), root, occurredAt: PINNED_AT });
1559
+ let msg = '';
1560
+ try {
1561
+ await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1562
+ }
1563
+ catch (e) {
1564
+ msg = e.message;
1565
+ }
1566
+ if (!msg.includes('carried no vendor id') || !msg.includes("refusing to confirm under the twin's own id"))
1567
+ return false;
1568
+ // The malformed create WAS sent (this is a response-shape failure, not a refusal to call)…
1569
+ if (calls.length !== 1)
1570
+ return false;
1571
+ // …and nothing was confirmed, so the action is still pending rather than silently "done".
1572
+ const { pendingActions } = await import('@volter/world-core');
1573
+ return pendingActions('cohere', root).length === 1;
1574
+ }, (m, p) => (m === 'POST' && p === '/v1/connectors' ? { connector: { name: 'x' } } : {}))),
1575
+ done('cohere.connector.push_refuses_unknown_op', 'connector', 'Connector: an operation nobody reasoned about STOPS the run (never a silent skip)', 'connector', 'core', () => withConnector(async (execute) => {
1576
+ const { pushCohereAction } = await import("./cohere-connector.js");
1577
+ let msg = '';
1578
+ try {
1579
+ await pushCohereAction(execute, { operation: 'connector.archive', subject: { type: 'connector', id: 'c1' }, fields: {} });
1580
+ }
1581
+ catch (e) {
1582
+ msg = e.message;
1583
+ }
1584
+ // The SPECIFIC refusal, not merely "something threw" — a dead connector seam's own throw
1585
+ // would otherwise read as a pass and the capability would survive sabotage.
1586
+ if (!msg.includes("unsupported operation 'connector.archive'") || !msg.includes('refusing to silently drop'))
1587
+ return false;
1588
+ // A FILED gap answers with ITS OWN reason instead of the generic one, so a caller can tell a
1589
+ // thought-about gap from a hole nobody has looked at.
1590
+ let filed = '';
1591
+ try {
1592
+ await pushCohereAction(execute, { operation: 'dataset.create', subject: { type: 'dataset', id: 'd1' }, fields: {} });
1593
+ }
1594
+ catch (e) {
1595
+ filed = e.message;
1596
+ }
1597
+ return filed.includes('cannot faithfully push') && filed.includes('multipart/form-data');
1598
+ })),
1599
+ done('cohere.connector.token_type_unpushable', 'connector', 'Connector: the tokenizer vocabulary is refused push-wide, by TYPE not by verb', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1600
+ // Tokenize writes `token.observe` rows. A verb-keyed refusal would let a hypothetical
1601
+ // `token.delete` through, and the `/v1/${type}s` fallback would then fire `DELETE
1602
+ // /v1/tokens/<id>` — an endpoint Cohere does not have — at a REAL account.
1603
+ await handleCohereTwinRequest({ method: 'POST', path: '/v1/tokenize', body: JSON.stringify({ text: 'push me', model: 'command-a-03-2025' }), root, occurredAt: PINNED_AT });
1604
+ const push = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1605
+ if (push.pushed !== 0 || push.refused.length === 0)
1606
+ return false;
1607
+ if (!push.refused.every((r) => r.reason.includes('no vendor endpoint')))
1608
+ return false;
1609
+ // NOT ONE REQUEST went out. "It refused" is not proof; the count is what shows nothing
1610
+ // reached the vendor.
1611
+ if (calls.length !== 0)
1612
+ return false;
1613
+ // …and the type-wide rule holds for a verb that IS otherwise pushable.
1614
+ return unpushableReason('token.delete', 'token') !== undefined && unpushableReason('token.create', 'token') !== undefined;
1615
+ })),
1616
+ done('cohere.connector.push_request_shape', 'connector', 'Connector: the REST (method, path) for each pushable verb is the vendor\'s', 'connector', 'common', () => verifyBoundary('cohere.request_shape', async () => {
1617
+ const at = (operation, type, id) => cohereRequestForAction({ operation, subject: { type, id } });
1618
+ const create = at('connector.create', 'connector', 'c1');
1619
+ const update = at('connector.update', 'connector', 'c1');
1620
+ const del = at('dataset.delete', 'dataset', 'd1');
1621
+ const cancel = at('embed_job.cancel', 'embed_job', 'j1');
1622
+ return create.method === 'POST' && create.path === '/v1/connectors'
1623
+ && update.method === 'PATCH' && update.path === '/v1/connectors/c1'
1624
+ && del.method === 'DELETE' && del.path === '/v1/datasets/d1'
1625
+ && cancel.method === 'POST' && cancel.path === '/v1/embed-jobs/j1/cancel';
1626
+ })),
1627
+ done('cohere.connector.full_sync_converges', 'connector', 'Connector: push→pull converges — a second full sync is a total no-op', 'connector', 'core', () => withConnector(async (execute, _calls, root) => {
1628
+ await handleCohereTwinRequest({ method: 'POST', path: '/v1/connectors', body: JSON.stringify({ name: 'local', url: 'https://e.test/s' }), root, occurredAt: PINNED_AT });
1629
+ const first = await fullSyncCohere(execute, { root, occurredAt: PINNED_AT });
1630
+ if (first.pushed !== 1 || first.collections !== 3)
1631
+ return false;
1632
+ const second = await fullSyncCohere(execute, { root, occurredAt: '2026-08-31T14:00:00.000Z' });
1633
+ // Nothing pending and identical real state ⇒ a complete no-op. A push that did not confirm,
1634
+ // or a pull that double-counted, both show up right here.
1635
+ if (second.pushed !== 0 || second.deltasAppended !== 0)
1636
+ return false;
1637
+ const list = await handleCohereTwinRequest({ method: 'GET', path: '/v1/connectors', root });
1638
+ // ONE row, not two: the locally-created connector and the pulled vendor row are the same
1639
+ // account object and must not both be served.
1640
+ return list.body.total_count === 1 && list.body.connectors[0].id === 'conn-real-1';
1641
+ }, (m, p) => (m === 'GET' && p === '/v1/datasets' ? { datasets: [] } : m === 'GET' && p === '/v1/connectors' ? { connectors: [REAL_CONNECTOR], total_count: 1 } : m === 'GET' ? { embed_jobs: [] } : m === 'POST' && p === '/v1/connectors' ? { connector: REAL_CONNECTOR } : {}))),
1642
+ done('cohere.connector.pull_timestamp_moves', 'connector', 'Connector: the default poll timestamp MOVES (a pinned one hides reverting values)', 'connector', 'common', () => verifyBoundary('cohere.poll_timestamp', async () => {
1643
+ const a = pollTimestamp();
1644
+ const b = pollTimestamp();
1645
+ const c = pollTimestamp();
1646
+ // Strictly increasing WITHIN the process, even when the wall clock has not ticked: the
1647
+ // kernel hashes an observed event over (occurredAt + post-state), so under a fixed poll time
1648
+ // a vendor value that reverts A→B→A collides with its own earlier observation and syncPull
1649
+ // reports a phantom delta while the projection keeps serving the stale value.
1650
+ return a < b && b < c;
1651
+ })),
1652
+ done('cohere.connector.budget_refuses_before_calling', 'connector', 'Budget: the ceiling THROWS instead of calling, with the fake\'s count unchanged', 'connector', 'core', () => verifyBoundary('cohere.budget_ceiling', async () => {
1653
+ const ledger = join(mkdtempSync(join(tmpdir(), 'cohere-budget-')), 'ledger.json');
1654
+ let calls = 0;
1655
+ const fetchImpl = (async () => { calls++; return new Response('{}', { status: 200, headers: { 'content-type': 'application/json' } }); });
1656
+ // The ledger path is INJECTED: a suite that spent against the operator's real
1657
+ // ~/.volter/cohere file would poison every later run on this machine.
1658
+ const budget = new CohereBudget({ path: ledger, now: () => 1_800_000_000_000 });
1659
+ const execute = liveCohereExecute('k', 'https://api.cohere.com', { fetchImpl, budget });
1660
+ // Ceiling 20 at the tokenize weight of 1 ⇒ exactly 20 calls fit.
1661
+ for (let i = 0; i < 20; i++)
1662
+ await execute('POST', '/v1/tokenize', {});
1663
+ if (calls !== 20)
1664
+ return false;
1665
+ let threw = false;
1666
+ try {
1667
+ await execute('POST', '/v1/tokenize', {});
1668
+ }
1669
+ catch (e) {
1670
+ threw = e instanceof CohereBudgetError;
1671
+ }
1672
+ // "It threw" is NOT the proof. The COUNT is what shows nothing reached the vendor.
1673
+ return threw && calls === 20;
1674
+ })),
1675
+ done('cohere.connector.budget_prices_by_endpoint', 'connector', "Budget: weights reproduce Cohere's own per-endpoint scarcity", 'connector', 'core', () => verifyBoundary('cohere.budget_weights', async () => {
1676
+ // The published per-minute allowances (trial key) that these weights encode:
1677
+ // embed-jobs 5, rerank 10, chat 20, tokenize 100 — so the prices must be strictly ordered
1678
+ // the other way round.
1679
+ const embedJob = cohereCallWeight('POST', '/v1/embed-jobs');
1680
+ const rerank = cohereCallWeight('POST', '/v2/rerank');
1681
+ const chat = cohereCallWeight('POST', '/v2/chat');
1682
+ const tokenize = cohereCallWeight('POST', '/v1/tokenize');
1683
+ if (!(embedJob > rerank && rerank > chat && chat > tokenize))
1684
+ return false;
1685
+ // An UNCLASSIFIED endpoint is never free — it costs the default.
1686
+ if (cohereCallWeight('POST', '/v1/anything-else') !== chat)
1687
+ return false;
1688
+ // NORMALIZATION: a lower-case method and a trailing slash are input variations, not attacks,
1689
+ // and either would otherwise slip an expensive call past an anchored rule at the read price.
1690
+ return cohereCallWeight('post', '/v1/embed-jobs') === embedJob
1691
+ && cohereCallWeight('POST', '/v1/embed-jobs/') === embedJob
1692
+ && cohereCallWeight('POST', '/v1/embed-jobs?x=1') === embedJob
1693
+ // …and a LONGER path must not borrow the anchored rule's price.
1694
+ && cohereCallWeight('POST', '/v1/embed-jobs/j1/cancel') === chat;
1695
+ })),
1696
+ done('cohere.connector.budget_guard_cannot_be_swapped', 'connector', 'Budget: a duck-typed / subclassed / proxied budget is REFUSED at construction', 'connector', 'core', () => verifyBoundary('cohere.budget_guard', async () => {
1697
+ const fetchImpl = (async () => new Response('{}', { status: 200 }));
1698
+ const refuses = (budget) => {
1699
+ try {
1700
+ liveCohereExecute('k', 'https://api.cohere.com', { fetchImpl, budget: budget });
1701
+ return false;
1702
+ }
1703
+ catch {
1704
+ return true;
1705
+ }
1706
+ };
1707
+ const duck = { checkBudget: () => ({}), recordCall: () => { } };
1708
+ class Loose extends CohereBudget {
1709
+ checkBudget() { return undefined; }
1710
+ }
1711
+ const proxied = new Proxy(new CohereBudget({ path: join(mkdtempSync(join(tmpdir(), 'cb-')), 'l.json') }), { get: (t, k) => (k === 'checkBudget' ? () => ({}) : Reflect.get(t, k)) });
1712
+ // Each is a one-liner that would otherwise hand back a client with NO ceiling.
1713
+ if (!refuses(duck) || !refuses(new Loose({ path: join(mkdtempSync(join(tmpdir(), 'cb-')), 'l.json') })) || !refuses(proxied))
1714
+ return false;
1715
+ // …and an UNMODIFIED budget is still accepted, so the guard is not simply refusing
1716
+ // everything.
1717
+ const real = new CohereBudget({ path: join(mkdtempSync(join(tmpdir(), 'cb-')), 'l.json') });
1718
+ return typeof liveCohereExecute('k', 'https://api.cohere.com', { fetchImpl, budget: real }) === 'function';
1719
+ })),
1720
+ done('cohere.connector.push_remaps_to_vendor_id', 'connector', 'Connector: a create-then-UPDATE push addresses the VENDOR id, never the twin-minted one', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1721
+ // §9 round 1 BLOCKER. Create locally, PATCH locally, push once. The create confirms under the
1722
+ // vendor's id — but the QUEUED update still carries the twin-minted id, and the twin's ids are
1723
+ // UUID-SHAPED, so `PATCH /v1/connectors/<twin-uuid>` fired at the REAL account is
1724
+ // indistinguishable from a legitimate request in an operator's logs. Real Cohere 404s, the
1725
+ // batch aborts mid-run, and the update stays PENDING — so every later push re-issues the same
1726
+ // doomed request forever.
1727
+ const created = await handleCohereTwinRequest({ method: 'POST', path: '/v1/connectors', body: JSON.stringify({ name: 'local', url: 'https://e.test/s' }), root, occurredAt: PINNED_AT });
1728
+ const localId = created.body.connector.id;
1729
+ await handleCohereTwinRequest({ method: 'PATCH', path: `/v1/connectors/${localId}`, body: JSON.stringify({ name: 'renamed' }), root, occurredAt: PINNED_AT });
1730
+ const push = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1731
+ if (push.pushed !== 2 || push.refused.length !== 0)
1732
+ return false;
1733
+ const paths = calls.map((c) => `${c.method} ${c.path}`);
1734
+ // THE ASSERTION: the PATCH went to the vendor's id.
1735
+ if (paths[0] !== 'POST /v1/connectors' || paths[1] !== 'PATCH /v1/connectors/conn-vendor-minted')
1736
+ return false;
1737
+ // …and the twin-minted id was NEVER put on the wire, in any request.
1738
+ if (calls.some((c) => c.path.includes(localId)))
1739
+ return false;
1740
+ // The PATCH payload is the vendor's UPDATE schema — the twin's own bookkeeping never rides.
1741
+ const patch = calls[1].body;
1742
+ return patch.name === 'renamed' && patch._twin_minted === undefined && patch._rev === undefined && patch.auth_status === undefined;
1743
+ })),
1744
+ done('cohere.connector.push_identity_survives_an_aborted_batch', 'connector', 'Connector: the vendor-id mapping is DURABLE — a second push after an abort still addresses the vendor', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1745
+ // §9 ROUND TWO, BLOCKER — the two round-one fixes destroying each other. `confirmAction`
1746
+ // suppresses the confirmed create's projection, and the supersede tombstone carries only
1747
+ // `{_deleted,_superseded_by}` — so `_twin_minted` VANISHES with the create it lived on. The
1748
+ // in-loop map was then the only guard, and it dies with the batch:
1749
+ // push #1 confirms the create, the PATCH throws (a budget refusal, a retry-after past the
1750
+ // cap, a network blip, any vendor `{message}`) → the batch aborts, the PATCH stays pending
1751
+ // → push #2 has an EMPTY map and a marker-less tombstone → the twin's own UUID goes to the
1752
+ // real account, every run, forever.
1753
+ // Neither the B1 capability nor its revert-matrix cell could see this: both are single-batch.
1754
+ const created = await handleCohereTwinRequest({ method: 'POST', path: '/v1/connectors', body: JSON.stringify({ name: 'local', url: 'https://e.test/s' }), root, occurredAt: PINNED_AT });
1755
+ const localId = created.body.connector.id;
1756
+ await handleCohereTwinRequest({ method: 'PATCH', path: `/v1/connectors/${localId}`, body: JSON.stringify({ name: 'renamed' }), root, occurredAt: PINNED_AT });
1757
+ // PUSH #1 — the create succeeds, then the PATCH throws, aborting the batch mid-run.
1758
+ let aborted = false;
1759
+ const failingOnPatch = async (method, path, body) => {
1760
+ if (method === 'PATCH')
1761
+ throw new Error('simulated mid-batch failure');
1762
+ return execute(method, path, body);
1763
+ };
1764
+ try {
1765
+ await pushPendingCohereActions(failingOnPatch, { root, occurredAt: PINNED_AT });
1766
+ }
1767
+ catch {
1768
+ aborted = true;
1769
+ }
1770
+ if (!aborted)
1771
+ return false;
1772
+ // The create really did land, and the update really is still pending.
1773
+ const afterFirst = calls.filter((c) => c.method === 'POST' && c.path === '/v1/connectors');
1774
+ if (afterFirst.length !== 1)
1775
+ return false;
1776
+ // PUSH #2 — a FRESH call, so the in-memory map is empty. The durable supersede tombstone is
1777
+ // the only thing that can resolve the identity now.
1778
+ calls.length = 0;
1779
+ const second = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1780
+ if (second.pushed !== 1 || second.refused.length !== 0)
1781
+ return false;
1782
+ // THE ASSERTION: the vendor's id, and the twin-minted id NOWHERE on the wire.
1783
+ if (calls.length !== 1 || calls[0].path !== '/v1/connectors/conn-vendor-minted')
1784
+ return false;
1785
+ return !JSON.stringify(calls).includes(localId);
1786
+ })),
1787
+ done('cohere.connector.push_refuses_subject_with_no_vendor_id', 'connector', 'Connector: an action on a subject the vendor has never seen is REFUSED, not fired at the account', 'connector', 'core', () => withConnector(async (execute, calls, root) => {
1788
+ // §9 round 1 MAJOR, and the sharpest "what did the fix make newly REACHABLE" case in the pack.
1789
+ // `dataset.create` is a FILED multipart gap, so it is skipped rather than aborting the run —
1790
+ // and skipping it is precisely what made the following delete reachable:
1791
+ // `DELETE /v1/datasets/<twin-minted-uuid>` went to the REAL account, addressing whatever (if
1792
+ // anything) happens to carry that id there. Aborting would have prevented it; the skip did not.
1793
+ const ds = await handleCohereTwinRequest({ method: 'POST', path: '/v1/datasets?name=doomed&type=embed-input', body: JSON.stringify(DATA_FILE), root, occurredAt: PINNED_AT });
1794
+ const dsId = ds.body.id;
1795
+ await handleCohereTwinRequest({ method: 'DELETE', path: `/v1/datasets/${dsId}`, root, occurredAt: PINNED_AT });
1796
+ const push = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1797
+ // BOTH are refused by name, and NOT ONE REQUEST went out. "It refused" is not the proof; the
1798
+ // call count is what shows nothing reached the vendor.
1799
+ if (push.pushed !== 0 || push.refused.length !== 2 || calls.length !== 0)
1800
+ return false;
1801
+ const del = push.refused.find((r) => r.operation === 'dataset.delete');
1802
+ if (!del || !del.reason.includes('minted by this twin') || del.subjectId !== dsId)
1803
+ return false;
1804
+ // …and the run does NOT abort: the filed create is still reported alongside it.
1805
+ if (!push.refused.some((r) => r.operation === 'dataset.create' && r.reason.includes('multipart')))
1806
+ return false;
1807
+ // THE OTHER DIRECTION, so this is not just "the connector refuses deletes": a row that came
1808
+ // from a PULL is vendor-known under its own id, and a mutation on it pushes normally.
1809
+ await syncCohereFromReal(execute, { root, occurredAt: PINNED_AT });
1810
+ await handleCohereTwinRequest({ method: 'PATCH', path: '/v1/connectors/conn-real-1', body: JSON.stringify({ name: 'renamed' }), root, occurredAt: PINNED_AT });
1811
+ const second = await pushPendingCohereActions(execute, { root, occurredAt: PINNED_AT });
1812
+ return second.pushed === 1 && calls.some((c) => c.method === 'PATCH' && c.path === '/v1/connectors/conn-real-1');
1813
+ })),
1814
+ todo('cohere.connector.pull_finetuned_models', 'connector', 'Connector: pull finetuned models (needs the finetuning endpoints first)', 'connector', 'common'),
1815
+ todo('cohere.connector.pull_batches', 'connector', 'Connector: pull batch jobs (needs the /v2/batches endpoints first)', 'connector', 'common'),
1816
+ todo('cohere.connector.push_dataset_multipart', 'connector', 'Connector: push a dataset create as the multipart/form-data upload the endpoint requires', 'connector', 'common'),
1817
+ todo('cohere.connector.pull_dataset_parts', 'connector', 'Connector: pull a dataset\'s PARTS and validation errors, not just the dataset row', 'connector', 'niche'),
1818
+ todo('cohere.connector.push_connector_oauth', 'connector', 'Connector: push a connector\'s oauth/service_auth configuration on create', 'connector', 'common'),
1819
+ // ══ CONFORMANCE ══════════════════════════════════════════════════════════════════════
1820
+ done('cohere.conformance.probes', 'conformance', 'Conformance: every claimed endpoint is probed for a live OUTCOME, not just a dispatch', 'api', 'core', async () => verifyBoundary('cohere.conformance', async () => {
1821
+ const report = await checkCohereConformance();
1822
+ return report.ok && report.claimed === 27 && report.checksRun >= 58 && report.violations.length === 0;
1823
+ })),
1824
+ done('cohere.conformance.scenario_engine_is_the_kernel', 'conformance', 'Scenario scripting runs on THE kernel engine with a pack adapter (never a bespoke one)', 'api', 'common', () => verifyBoundary('cohere.scenario_kernel', async () => {
1825
+ const engine = createCohereScenarioEngine();
1826
+ const remove = engine.use({ on: { userTextIncludes: 'refund' }, respond: { text: 'scripted refund reply' } });
1827
+ const root = mkdtempSync(join(tmpdir(), 'cohere-scn-'));
1828
+ try {
1829
+ const hit = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: JSON.stringify(CHAT({ messages: [{ role: 'user', content: 'I need a refund' }] })), root, occurredAt: PINNED_AT, scenarioEngine: engine });
1830
+ const miss = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: JSON.stringify(CHAT()), root, occurredAt: PINNED_AT, scenarioEngine: engine });
1831
+ remove();
1832
+ const after = await handleCohereTwinRequest({ method: 'POST', path: '/v2/chat', body: JSON.stringify(CHAT({ messages: [{ role: 'user', content: 'I need a refund' }] })), root, occurredAt: PINNED_AT, scenarioEngine: engine });
1833
+ const text = (r) => String(r.body.message?.content?.[0]?.text ?? '');
1834
+ // The scripted turn fires; an unmatched one falls back to the labeled stub AND ledgers the
1835
+ // miss with its features; removing the handler restores the stub.
1836
+ const status = engine.status();
1837
+ return text(hit) === 'scripted refund reply'
1838
+ && text(miss).includes('[twin-stub:') && text(miss).includes('twin-scenario miss')
1839
+ && text(after).includes('[twin-stub:')
1840
+ && status.vendor === 'cohere'
1841
+ // Two misses: the unmatched request, and the refund request AFTER the handler was
1842
+ // removed. The handler row is gone from the status, and it fired exactly once.
1843
+ && status.misses === 2 && status.handlers.length === 0;
1844
+ }
1845
+ finally {
1846
+ rmSync(root, { recursive: true, force: true });
1847
+ }
1848
+ })),
1849
+ ];
1850
+ export function cohereCapabilities() {
1851
+ return checkCapabilities('cohere', COHERE_CAPABILITIES);
1852
+ }