@ours.network/fleet 2.3.0 → 2.3.2

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 (113) hide show
  1. package/README.md +1 -1
  2. package/dist/application/harness-capabilities.d.ts +60 -0
  3. package/dist/application/harness-capabilities.js +96 -0
  4. package/dist/application/model-catalog.d.ts +17 -0
  5. package/dist/application/model-catalog.js +32 -9
  6. package/dist/application/preset-provenance.d.ts +1 -1
  7. package/dist/application/preset-provenance.js +18 -3
  8. package/dist/application/role-creation-service.d.ts +3 -1
  9. package/dist/application/role-creation-service.js +4 -1
  10. package/dist/application/task-room-service.d.ts +1 -1
  11. package/dist/application/task-room-service.js +2 -2
  12. package/dist/build-info.json +4 -4
  13. package/dist/harness/claude-code.js +7 -0
  14. package/dist/harness/codex.js +7 -0
  15. package/dist/harness/hermes.js +2 -0
  16. package/dist/harness/types.d.ts +20 -0
  17. package/dist/init-wizard.d.ts +19 -12
  18. package/dist/init-wizard.js +122 -104
  19. package/dist/rooms-tasks/add-member.d.ts +15 -1
  20. package/dist/rooms-tasks/add-member.js +27 -4
  21. package/dist/rooms-tasks/task-state.js +7 -2
  22. package/dist/web/fleet-config-service.d.ts +8 -0
  23. package/dist/web/fleet-config-service.js +23 -8
  24. package/dist/web/resource-views.d.ts +2 -0
  25. package/dist/web/resource-views.js +26 -15
  26. package/dist/web/server.js +58 -24
  27. package/package.json +1 -1
  28. package/presets/README.md +38 -18
  29. package/presets/brain-catalog.json +19 -19
  30. package/presets/legacy/generated-brains-rev4.json +497 -0
  31. package/presets/manifest.json +1 -1
  32. package/presets/fleet/brains/claude-fable-5-1-high.yaml +0 -5
  33. package/presets/fleet/brains/claude-fable-5-1-low.yaml +0 -5
  34. package/presets/fleet/brains/claude-fable-5-1-max.yaml +0 -5
  35. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +0 -5
  36. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +0 -5
  37. package/presets/fleet/brains/claude-fable-5-high.yaml +0 -5
  38. package/presets/fleet/brains/claude-fable-5-low.yaml +0 -5
  39. package/presets/fleet/brains/claude-fable-5-max.yaml +0 -5
  40. package/presets/fleet/brains/claude-fable-5-medium.yaml +0 -5
  41. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +0 -5
  42. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +0 -4
  43. package/presets/fleet/brains/claude-opus-5-5-high.yaml +0 -5
  44. package/presets/fleet/brains/claude-opus-5-5-low.yaml +0 -5
  45. package/presets/fleet/brains/claude-opus-5-5-max.yaml +0 -5
  46. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +0 -5
  47. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +0 -5
  48. package/presets/fleet/brains/claude-opus-5-high.yaml +0 -5
  49. package/presets/fleet/brains/claude-opus-5-low.yaml +0 -5
  50. package/presets/fleet/brains/claude-opus-5-max.yaml +0 -5
  51. package/presets/fleet/brains/claude-opus-5-medium.yaml +0 -5
  52. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +0 -5
  53. package/presets/fleet/brains/claude-sonnet-5-high.yaml +0 -5
  54. package/presets/fleet/brains/claude-sonnet-5-low.yaml +0 -5
  55. package/presets/fleet/brains/claude-sonnet-5-max.yaml +0 -5
  56. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +0 -5
  57. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +0 -5
  58. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +0 -5
  59. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +0 -5
  60. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +0 -5
  61. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +0 -5
  62. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +0 -5
  63. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +0 -5
  64. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +0 -5
  65. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +0 -5
  66. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +0 -5
  67. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +0 -5
  68. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +0 -5
  69. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +0 -5
  70. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +0 -5
  71. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +0 -5
  72. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +0 -5
  73. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +0 -5
  74. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +0 -5
  75. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +0 -5
  76. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +0 -5
  77. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +0 -5
  78. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +0 -5
  79. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +0 -5
  80. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +0 -5
  81. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +0 -5
  82. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +0 -5
  83. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +0 -5
  84. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +0 -5
  85. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +0 -5
  86. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +0 -5
  87. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +0 -5
  88. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +0 -5
  89. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +0 -5
  90. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +0 -5
  91. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +0 -5
  92. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +0 -5
  93. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +0 -5
  94. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +0 -5
  95. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +0 -5
  96. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +0 -5
  97. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +0 -5
  98. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +0 -5
  99. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +0 -5
  100. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +0 -5
  101. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +0 -5
  102. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +0 -5
  103. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +0 -5
  104. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +0 -5
  105. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +0 -5
  106. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +0 -5
  107. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +0 -5
  108. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +0 -5
  109. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +0 -5
  110. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +0 -5
  111. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +0 -5
  112. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +0 -5
  113. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +0 -5
@@ -7,15 +7,13 @@ import { registerConversationStream } from './conversation-stream.js';
7
7
  import { conversationHasAttachment } from '../application/conversation-history.js';
8
8
  import { readDeliveredFile } from '../file-delivery/store.js';
9
9
  import { WorkspaceDeviceAuthError } from './workspace-devices.js';
10
- import { readFileSync } from 'node:fs';
11
- import { packagedPresetRoot } from '../preset-bootstrap.js';
12
- import { validateCatalog } from '../init-wizard.js';
10
+ import { PURPOSE_BRAINS, PurposeBrainConflictError } from '../init-wizard.js';
11
+ import { harnessCapabilities, validateBrainChoice } from '../application/harness-capabilities.js';
13
12
  import { getAdapter } from '../harness/registry.js';
14
13
  import { storeAgentAttachment, attachmentPrompt, MAX_ATTACHMENT_BODY, readAgentAttachment, prepareAttachmentPresentation, presentAttachmentEvent } from './agent-attachments.js';
15
14
  import { readChatIdle } from '../temp-idle.js';
16
15
  import { agentDir } from '../paths.js';
17
16
  import { SupervisorOursTools } from '../application/supervisor-ours-tools.js';
18
- import { join } from 'node:path';
19
17
  import Fastify from 'fastify';
20
18
  import fastifyWebsocket from '@fastify/websocket';
21
19
  import { createHmac, randomBytes } from 'node:crypto';
@@ -215,12 +213,12 @@ export async function buildWebServer(services, boundary, options = {}) {
215
213
  return { harness, ok: false, checks: [{ name: 'availability', ok: false, detail: 'Harness checks unavailable' }] };
216
214
  }
217
215
  }));
218
- const catalog = validateCatalog(JSON.parse(readFileSync(join(packagedPresetRoot(), 'brain-catalog.json'), 'utf8')));
219
- // Codex models are offered only when the runtime itself listed them for the active account.
220
- // When it could not be asked, none is offered and the reason is reported.
221
- const codexModels = services.codexModels ? await services.codexModels() : undefined;
222
- const offered = (model) => model.harness !== 'codex' || !codexModels || (codexModels.state === 'known' && codexModels.models.includes(model.model));
223
- const payload = { harnesses, catalog: catalog.models.filter(offered), ...(codexModels ? { codexModels: codexModels.state === 'known' ? { state: 'known' } : codexModels } : {}), providers: services.subscriptions ? await services.subscriptions.list() : [], coordinator: 'FleetCoordinator', configured: onboardingConfigured() };
216
+ // The catalog is each adapter's maintained models, narrowed to what the active Codex account offers.
217
+ const capabilities = await harnessCapabilities({ harnesses: ['codex', 'claude-code'], codexModels: services.codexModels, checkReadiness: false });
218
+ const codex = capabilities.harnesses.find(item => item.harness === 'codex');
219
+ const catalog = capabilities.harnesses.flatMap(item => item.models.filter(model => model.available && model.efforts !== null)
220
+ .map(model => ({ harness: item.harness, session: 'acp', model: model.id, label: model.label, efforts: model.efforts })));
221
+ const payload = { harnesses, catalog, ...(codex?.discovery ? { codexModels: codex.discovery } : {}), providers: services.subscriptions ? await services.subscriptions.list() : [], coordinator: 'FleetCoordinator', configured: onboardingConfigured() };
224
222
  if (revision === services.configuration?.read().revision) {
225
223
  onboardingObserved = { owner: browser.id, revision, payload };
226
224
  events.publish('onboarding.changed', {});
@@ -245,15 +243,25 @@ export async function buildWebServer(services, boundary, options = {}) {
245
243
  if (!services.configuration || !services.onboardingSetup)
246
244
  throw new FleetError('capability_unavailable', 'first-time Fleet setup is unavailable');
247
245
  const requested = request.body?.models;
248
- const codexModels = services.codexModels ? await services.codexModels() : undefined;
249
- const supported = validateCatalog(JSON.parse(readFileSync(join(packagedPresetRoot(), 'brain-catalog.json'), 'utf8'))).models
250
- .filter(model => model.harness !== 'codex' || !codexModels || (codexModels.state === 'known' && codexModels.models.includes(model.model)));
246
+ const capabilities = await harnessCapabilities({ harnesses: ['codex', 'claude-code'], codexModels: services.codexModels, checkReadiness: false });
251
247
  const models = {};
252
248
  for (const work of ONBOARDING_WORK) {
253
- const matches = supported.filter(model => model.harness === requested?.[work]?.harness && model.model === requested?.[work]?.model);
254
- if (matches.length !== 1)
255
- throw new FleetError('invalid_request', `choose a supported model for ${work}`);
256
- models[work] = matches[0];
249
+ const choice = requested?.[work];
250
+ const label = PURPOSE_BRAINS[work].label;
251
+ if (!choice || typeof choice !== 'object' || !('effort' in choice))
252
+ throw new FleetError('invalid_request', `choose a harness, model and effort for the ${label} Brain`);
253
+ const { harness, model, effort } = choice;
254
+ if (typeof harness !== 'string' || typeof model !== 'string' || (effort !== null && typeof effort !== 'string'))
255
+ throw new FleetError('invalid_request', `choose a harness, model and effort for the ${label} Brain`);
256
+ const check = validateBrainChoice(capabilities, { harness, session: 'acp', model, effort });
257
+ // Setup offers the adapters' maintained models only, each with an explicit effort when it has one.
258
+ if (!check.ok)
259
+ throw new FleetError('invalid_request', `${label} Brain: ${check.message}`);
260
+ if (!check.model || check.model.source !== 'adapter')
261
+ throw new FleetError('invalid_request', `${label} Brain: choose a supported model`);
262
+ if (check.model.efforts?.length && effort === null)
263
+ throw new FleetError('invalid_request', `${label} Brain: choose an effort for ${check.model.label} (${check.model.efforts.join(', ')})`);
264
+ models[work] = { harness: harness, session: 'acp', model, effort: effort };
257
265
  }
258
266
  const chosen = Object.values(models);
259
267
  const subscriptions = [...new Set(chosen.map(model => model.harness === 'codex' ? 'codex' : 'claude'))];
@@ -264,31 +272,49 @@ export async function buildWebServer(services, boundary, options = {}) {
264
272
  if (onboardingConfigured())
265
273
  throw new FleetError('conflict', 'Fleet is already set up; change its models in the configuration');
266
274
  try {
267
- await setup({ subscriptions, assignmentStrategy: oneModel ? 'one-model' : 'per-job', models, reasoning: 'balanced' });
275
+ await setup({ subscriptions, assignmentStrategy: oneModel ? 'one-model' : 'per-job', models });
268
276
  }
269
277
  catch (error) {
278
+ if (error instanceof PurposeBrainConflictError)
279
+ throw new FleetError('conflict', error.message);
270
280
  throw new FleetError('backend_failure', `Fleet setup did not complete: ${error.message}`);
271
281
  }
272
- // Setup preserves files it finds, so confirm the published models are the ones this request chose.
273
- // The prepared agents reference packaged Brain presets, so resolve what each of them now points at:
274
- // a preserved file of a packaged name may hold another model, session or reasoning than its name says.
282
+ // Setup preserves files it finds, so confirm each prepared agent now resolves to exactly the chosen triple.
275
283
  const published = configuration.read(true).model, brains = published.brains ?? {};
276
284
  const brainOf = (holder) => brains[String(holder?.brain?.ref ?? '')];
277
285
  const assigned = { coordination: brainOf(published.agents.FleetCoordinator), development: brainOf(published.agent_templates?.Developer), review: brainOf(published.agent_templates?.Critic) };
278
286
  for (const work of ONBOARDING_WORK)
279
- if (assigned[work]?.harness !== models[work].harness || assigned[work]?.model !== models[work].model || assigned[work]?.session !== models[work].session || assigned[work]?.effort !== 'medium')
287
+ if (assigned[work]?.harness !== models[work].harness || assigned[work]?.model !== models[work].model || assigned[work]?.session !== models[work].session || (assigned[work]?.effort ?? null) !== models[work].effort)
280
288
  throw new FleetError('conflict', 'Fleet was set up with different models; review its configuration');
281
289
  return { configured: true };
282
290
  });
283
291
  onboardingSetupQueue = run.catch(() => { });
284
292
  return run;
285
293
  });
294
+ app.get('/api/v1/harness-capabilities', async (request) => {
295
+ auth.authenticate(request);
296
+ return harnessCapabilities({ codexModels: services.codexModels });
297
+ });
286
298
  app.get('/api/v1/creation-capabilities', async (request) => {
287
299
  auth.authenticate(request);
288
300
  return services.creation.capabilities();
289
301
  });
302
+ // A new agent's own harness/model/effort must be one its adapter supports; saved Brains are used as they are.
303
+ const checkBrainChoice = async (brain) => {
304
+ if (!brain || typeof brain !== 'object')
305
+ return;
306
+ const value = brain;
307
+ const check = validateBrainChoice(await harnessCapabilities({ codexModels: services.codexModels, checkReadiness: false }), {
308
+ harness: String(value.harness), session: value.session,
309
+ model: value.model, effort: value.effort
310
+ });
311
+ if (!check.ok)
312
+ throw new FleetError('invalid_request', `Brain: ${check.message}`);
313
+ };
314
+ const checkInlineBrain = (creation) => checkBrainChoice(creation?.brain?.inline);
290
315
  app.post('/api/v1/roles/preview', async (request) => {
291
316
  auth.authenticate(request, true);
317
+ await checkInlineBrain(request.body);
292
318
  return services.creation.preview(request.body);
293
319
  });
294
320
  app.post('/api/v1/roles', async (request, reply) => {
@@ -297,7 +323,7 @@ export async function buildWebServer(services, boundary, options = {}) {
297
323
  const idempotencyKey = String(request.headers['idempotency-key'] ?? '');
298
324
  if (!body?.request || !body.previewHash)
299
325
  throw new FleetError('invalid_request', 'request and previewHash are required');
300
- const action = await services.creation.create(body.request, body.previewHash, idempotencyKey, session.id);
326
+ const action = await services.creation.create(body.request, body.previewHash, idempotencyKey, session.id, checkInlineBrain);
301
327
  events.publish('creation.changed', action, action.roleId);
302
328
  reply.header('Location', `/api/v1/creation-actions/${encodeURIComponent(action.actionId)}`);
303
329
  reply.code(202);
@@ -398,6 +424,9 @@ export async function buildWebServer(services, boundary, options = {}) {
398
424
  const project = async (descriptor, signal, owner = '') => {
399
425
  signal.throwIfAborted();
400
426
  services.invalidateResourceCaches?.();
427
+ // Role projections load the configuration: fence this capture on its external inputs too.
428
+ if (['directory', 'roles', 'previews'].includes(descriptor.resource))
429
+ services.configuration?.observeValidationInputs();
401
430
  switch (descriptor.resource) {
402
431
  case 'task-layout':
403
432
  try {
@@ -702,7 +731,12 @@ export async function buildWebServer(services, boundary, options = {}) {
702
731
  auth.authenticate(request, true);
703
732
  const body = request.body;
704
733
  try {
705
- const result = await taskApi(() => requireTaskRooms().addMember(taskRef(request), body));
734
+ // A new manual harness/model/effort must be one the adapter supports; nothing is substituted.
735
+ // A retry of an accepted request returns its receipt even if the account's models changed since.
736
+ const result = await taskApi(() => requireTaskRooms().addMember(taskRef(request), body, async (member) => {
737
+ if (typeof member.brain === 'object')
738
+ await checkBrainChoice(member.brain.inline);
739
+ }));
706
740
  reply.code(result.state === 'running' ? 202 : 200);
707
741
  return result;
708
742
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/fleet",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "Harness-agnostic fleet of persistent, identity-bound AI agents. Declarative fleet.yaml, managed native/ACP sessions, supervision, and ours.network messaging.",
5
5
  "type": "module",
6
6
  "license": "FSL-1.1-Apache-2.0",
package/presets/README.md CHANGED
@@ -1,26 +1,48 @@
1
- # Predefined Brains
1
+ # Models, efforts and Brains
2
2
 
3
- `brain-catalog.json` is the source for generated `fleet/brains/*.yaml` files.
4
- Run `node scripts/generate-brain-presets.mjs` after changing it, and run the same
5
- command with `--check` to verify generated files. An empty `efforts` array generates
6
- one `-default` preset with no `effort` field. Bootstrap adds missing presets and
7
- preserves existing user files. Existing model presets remain available.
3
+ `brain-catalog.json` is the model catalog maintained with the Claude Code and
4
+ Codex harness adapters: each exact model ID, its label, and the efforts it
5
+ supports (an empty `efforts` list means the model has no effort setting). The
6
+ adapters expose it through `modelCapabilities()`, and Fleet serves it, narrowed
7
+ to the models the active Codex account offers, at `GET /api/v1/harness-capabilities`.
8
+ Onboarding, Settings and agent launch flows use that one source. Hermes models
9
+ come from the provider configured in the role home, so Hermes lists none and
10
+ sets no effort.
11
+
12
+ Setup no longer installs a Brain per model and effort. It creates three
13
+ editable purpose Brains from the choices made during setup:
14
+
15
+ | Brain | Used by |
16
+ | --- | --- |
17
+ | `development` | Developer, Engineer |
18
+ | `critic` | Critic |
19
+ | `coordination` | LocalCoordinator, FleetCoordinator |
20
+
21
+ Users change these or add more in Settings > Brains. An agent can also be
22
+ launched with a one-off harness, model and effort; that choice is kept with the
23
+ agent and saves no Brain.
24
+
25
+ Existing installations keep every Brain file and reference. The values of the
26
+ Brain presets earlier releases generated per model and effort are frozen in
27
+ `legacy/generated-brains-rev4.json`; configuration provenance reports an
28
+ untouched one as `legacy` and an edited one as `changed`. Nothing deletes them.
29
+ `fleet/brains/claude-default.yaml` (the Claude Code default model) still ships
30
+ for packaged templates and existing references; setup does not install it.
8
31
 
9
32
  ## GPT-6.1 Sol (added 2026-09-29)
10
33
 
11
- The Codex presets `codex-gpt-6-1-sol-{low,medium,high,xhigh,max,ultra}`
12
- use the exact model ID `gpt-6.1-sol` with ACP sessions. The init wizard offers
34
+ The Codex catalog entry uses the exact model ID `gpt-6.1-sol` with ACP sessions. The init wizard offers
13
35
  GPT-6.1 Sol for development, review, and coordination.
14
36
 
15
37
  [Official OpenAI documentation](https://developers.openai.com/api/docs/models/gpt-6.1-sol)
16
38
  supports low, medium, high, xhigh, and max API reasoning efforts. The local
17
39
  Codex `models_cache.json` inspected on 2026-09-29 additionally advertises
18
- `ultra`, a Codex harness mode. These presets reflect that six-effort Codex
40
+ `ultra`, a Codex harness mode. The catalog reflects that six-effort Codex
19
41
  catalog; no inference or ACP launch was performed for this addition.
20
42
 
21
43
  ## Current model additions (verified 2026-09-24)
22
44
 
23
- | Harness | Exact model ID | Preset efforts |
45
+ | Harness | Exact model ID | Efforts |
24
46
  | --- | --- | --- |
25
47
  | Codex | `gpt-6-sol` | low, medium, high, xhigh, max, ultra |
26
48
  | Codex | `gpt-6-luna` | low, medium, high, xhigh, max |
@@ -29,23 +51,21 @@ catalog; no inference or ACP launch was performed for this addition.
29
51
  | Claude Code (retained) | `claude-sonnet-5` | low, medium, high, xhigh, max |
30
52
  | Claude Code | `claude-haiku-4-5-20251001` | default, with no effort setting |
31
53
 
32
- For example, select `codex-gpt-6-sol-ultra`, `claude-opus-5-5-max`, or
33
- `claude-haiku-4-5-20251001-default` as a Brain reference. The init wizard offers
34
- models supporting its Quick/Balanced/Thorough (low/medium/high) choices; use the
35
- named Brain directly for Haiku, which does not support effort.
54
+ Setup asks for an effort only among the efforts a model supports; Haiku gets
55
+ none.
36
56
 
37
57
  ### Runtime requirements and evidence
38
58
 
39
59
  Codex CLI **0.155.0** freshly queried through `app-server` `initialize` then
40
60
  `model/list` advertised the GPT rows above. A previously populated
41
61
  `~/.codex/models_cache.json` did not contain these models; refresh runtime discovery
42
- before concluding a model is unavailable. `ours-fleet doctor` compares presets to
62
+ before concluding a model is unavailable. `ours-fleet doctor` compares configured Codex Brains to
43
63
  the local cache. The catalog is not an account entitlement guarantee.
44
64
 
45
65
  The [Sol](https://developers.openai.com/api/docs/models/gpt-6-sol) and
46
66
  [Luna](https://developers.openai.com/api/docs/models/gpt-6-luna) API model pages
47
67
  also support `none`, but the verified Codex runtime does not advertise it.
48
- Consequently there are no `none` presets. Sol's `ultra` is an advertised Codex
68
+ Consequently the catalog lists no `none` effort. Sol's `ultra` is an advertised Codex
49
69
  harness mode, not an additional API reasoning level; Luna does not advertise it.
50
70
 
51
71
  Claude Code **2.1.281** was verified using the Agent SDK `supportedModels()`
@@ -56,13 +76,13 @@ not asserted minimum versions. Provider references:
56
76
  [model IDs](https://platform.claude.com/docs/en/models/overview) and
57
77
  [Claude Code effort support](https://code.claude.com/docs/en/model-config#adjust-effort-level).
58
78
 
59
- **Check the executable used by ACP before selecting the new Claude presets.**
79
+ **Check the executable used by ACP before selecting the new Claude models.**
60
80
  The inspected `claude-agent-acp` **0.63.0** installation bundles Agent SDK
61
81
  **0.3.220**, whose default executable reports older models. To use the verified
62
82
  installed Claude CLI, set `CLAUDE_CODE_EXECUTABLE` to its absolute path in the
63
83
  launch environment (for example `/usr/bin/claude` on the verification host).
64
84
  Otherwise use a bundled SDK whose runtime advertises these models and efforts.
65
- The presets do not change your executable or restart agents. An older bundled
85
+ The catalog does not change your executable or restart agents. An older bundled
66
86
  runtime alone is not evidence of support for the new models.
67
87
 
68
88
  No-prompt ACP startup and `session/set_config_option` probes also verified all
@@ -1,23 +1,23 @@
1
1
  {
2
- "schema_version": 1,
3
- "catalog_revision": 4,
2
+ "schema_version": 2,
3
+ "catalog_revision": 5,
4
4
  "models": [
5
- { "harness": "codex", "session": "acp", "model": "gpt-6-astra", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
6
- { "harness": "codex", "session": "acp", "model": "gpt-5.6-sol", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
7
- { "harness": "codex", "session": "acp", "model": "gpt-5.6-terra", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
8
- { "harness": "codex", "session": "acp", "model": "gpt-5.6-luna", "efforts": ["low", "medium", "high", "xhigh", "max"] },
9
- { "harness": "codex", "session": "acp", "model": "gpt-5.5", "efforts": ["low", "medium", "high", "xhigh"] },
10
- { "harness": "codex", "session": "acp", "model": "gpt-5.4", "efforts": ["low", "medium", "high", "xhigh"] },
11
- { "harness": "codex", "session": "acp", "model": "gpt-5.4-mini", "efforts": ["low", "medium", "high", "xhigh"] },
12
- { "harness": "codex", "session": "acp", "model": "gpt-5.3-codex-spark", "efforts": ["low", "medium", "high", "xhigh"] },
13
- { "harness": "claude-code", "session": "acp", "model": "claude-fable-5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
14
- { "harness": "claude-code", "session": "acp", "model": "claude-opus-5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
15
- { "harness": "claude-code", "session": "acp", "model": "claude-sonnet-5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
16
- { "harness": "codex", "session": "acp", "model": "gpt-6.1-sol", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
17
- { "harness": "codex", "session": "acp", "model": "gpt-6-sol", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
18
- { "harness": "codex", "session": "acp", "model": "gpt-6-luna", "efforts": ["low", "medium", "high", "xhigh", "max"] },
19
- { "harness": "claude-code", "session": "acp", "model": "claude-fable-5-1", "efforts": ["low", "medium", "high", "xhigh", "max"] },
20
- { "harness": "claude-code", "session": "acp", "model": "claude-opus-5-5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
21
- { "harness": "claude-code", "session": "acp", "model": "claude-haiku-4-5-20251001", "efforts": [] }
5
+ { "harness": "codex", "session": "acp", "model": "gpt-6-astra", "label": "GPT-6 Astra", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
6
+ { "harness": "codex", "session": "acp", "model": "gpt-5.6-sol", "label": "GPT-5.6 Sol", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
7
+ { "harness": "codex", "session": "acp", "model": "gpt-5.6-terra", "label": "GPT-5.6 Terra", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
8
+ { "harness": "codex", "session": "acp", "model": "gpt-5.6-luna", "label": "GPT-5.6 Luna", "efforts": ["low", "medium", "high", "xhigh", "max"] },
9
+ { "harness": "codex", "session": "acp", "model": "gpt-5.5", "label": "GPT-5.5", "efforts": ["low", "medium", "high", "xhigh"] },
10
+ { "harness": "codex", "session": "acp", "model": "gpt-5.4", "label": "GPT-5.4", "efforts": ["low", "medium", "high", "xhigh"] },
11
+ { "harness": "codex", "session": "acp", "model": "gpt-5.4-mini", "label": "GPT-5.4 Mini", "efforts": ["low", "medium", "high", "xhigh"] },
12
+ { "harness": "codex", "session": "acp", "model": "gpt-5.3-codex-spark", "label": "GPT-5.3 Codex Spark", "efforts": ["low", "medium", "high", "xhigh"] },
13
+ { "harness": "claude-code", "session": "acp", "model": "claude-fable-5", "label": "Claude Fable 5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
14
+ { "harness": "claude-code", "session": "acp", "model": "claude-opus-5", "label": "Claude Opus 5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
15
+ { "harness": "claude-code", "session": "acp", "model": "claude-sonnet-5", "label": "Claude Sonnet 5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
16
+ { "harness": "codex", "session": "acp", "model": "gpt-6.1-sol", "label": "GPT-6.1 Sol", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
17
+ { "harness": "codex", "session": "acp", "model": "gpt-6-sol", "label": "GPT-6 Sol", "efforts": ["low", "medium", "high", "xhigh", "max", "ultra"] },
18
+ { "harness": "codex", "session": "acp", "model": "gpt-6-luna", "label": "GPT-6 Luna", "efforts": ["low", "medium", "high", "xhigh", "max"] },
19
+ { "harness": "claude-code", "session": "acp", "model": "claude-fable-5-1", "label": "Claude Fable 5.1", "efforts": ["low", "medium", "high", "xhigh", "max"] },
20
+ { "harness": "claude-code", "session": "acp", "model": "claude-opus-5-5", "label": "Claude Opus 5.5", "efforts": ["low", "medium", "high", "xhigh", "max"] },
21
+ { "harness": "claude-code", "session": "acp", "model": "claude-haiku-4-5-20251001", "label": "Claude Haiku 4.5", "efforts": [] }
22
22
  ]
23
23
  }