@cat-factory/mcp-server 0.44.0 → 0.46.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.
package/dist/server.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { type CatFactoryMcpOptions } from './config.ts';
3
3
  import { type CatFactoryTool } from './tools.generated.ts';
4
4
  /** The npm version, stamped into the SDK's `User-Agent` so a deployment can attribute calls. */
5
- export declare const MCP_SERVER_VERSION = "0.44.0";
5
+ export declare const MCP_SERVER_VERSION = "0.46.0";
6
6
  /** The name this server reports to a host. */
7
7
  export declare const MCP_SERVER_NAME = "cat-factory";
8
8
  export interface CatFactoryMcpServer {
package/dist/server.js CHANGED
@@ -19,7 +19,7 @@ import { CAT_FACTORY_TOOLS } from './tools.generated.js';
19
19
  // has been round-tripped through a second type system, and every gap in that conversion becomes a
20
20
  // tool that misdescribes its own input.
21
21
  /** The npm version, stamped into the SDK's `User-Agent` so a deployment can attribute calls. */
22
- export const MCP_SERVER_VERSION = '0.44.0';
22
+ export const MCP_SERVER_VERSION = '0.46.0';
23
23
  /** The name this server reports to a host. */
24
24
  export const MCP_SERVER_NAME = 'cat-factory';
25
25
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"tools.generated.d.ts","sourceRoot":"","sources":["../src/tools.generated.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAA;IACnB,8FAA8F;IAC9F,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAA;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACnC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5B,oBAAoB,EAAE,KAAK,CAAA;KAC5B,CAAA;IACD;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACpC,CAAA;IACD,kDAAkD;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACtF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAuID,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAwzCtD,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,EAAE,SAAS,0BAA0B,EAmB/E,CAAA;AAED,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBpE,CAAA"}
1
+ {"version":3,"file":"tools.generated.d.ts","sourceRoot":"","sources":["../src/tools.generated.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAA;IACnB,8FAA8F;IAC9F,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAA;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACnC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5B,oBAAoB,EAAE,KAAK,CAAA;KAC5B,CAAA;IACD;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,QAAQ,CAAA;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACpC,CAAA;IACD,kDAAkD;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACtF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAuID,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAm0CtD,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,EAAE,SAAS,0BAA0B,EAmB/E,CAAA;AAED,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBpE,CAAA"}
@@ -179,7 +179,7 @@ export const CAT_FACTORY_TOOLS = [
179
179
  readOnly: false,
180
180
  description: 'Create a service\n\nCreate a board service, optionally backed by a repository from `GET /api/v1/repos`. The repository link is what makes the service runnable: execution resolves a task’s repository by walking up to its enclosing service frame, so a service with none holds tasks and can start none of them. A whole-repo repository that already backs a service in this account is MOUNTED rather than duplicated; a monorepo service must name its subdirectory. The board lays the service out itself: this surface publishes no coordinates. Requires an `admin` key.\n\nCalls `POST /api/v1/services` (operation `createPublicService`).',
181
181
  inputSchema: { "type": "object", "properties": { "body": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 2000 }, "repo": { "type": "object", "properties": { "directory": { "type": "string", "maxLength": 400 }, "monorepo": { "type": "boolean" }, "repoId": { "type": "number" } }, "required": ["repoId"] }, "title": { "type": "string", "minLength": 1, "maxLength": 200 }, "type": { "type": "string", "enum": ["service", "frontend", "library", "document"] } }, "description": "The request body." } }, "additionalProperties": false },
182
- outputSchema: { "type": "object", "properties": { "description": { "type": "string" }, "provisioning": { "description": "Discriminated by `type` (kubernetes | custom). A newer deployment may report a variant not in this list." }, "serviceId": { "type": "string" }, "status": { "type": "string", "description": "One of: planned, ready, in_progress, blocked, pr_ready, done. A newer deployment may report a member not in this list." }, "title": { "type": "string" }, "type": { "type": "string", "description": "One of: frontend, service, library, document, api, database, queue, integration, external, environment. A newer deployment may report a member not in this list." } } },
182
+ outputSchema: { "type": "object", "properties": { "description": { "type": "string" }, "provisioning": { "description": "Discriminated by `type` (kubernetes | infraless | custom). A newer deployment may report a variant not in this list." }, "serviceId": { "type": "string" }, "status": { "type": "string", "description": "One of: planned, ready, in_progress, blocked, pr_ready, done. A newer deployment may report a member not in this list." }, "title": { "type": "string" }, "type": { "type": "string", "description": "One of: frontend, service, library, document, api, database, queue, integration, external, environment. A newer deployment may report a member not in this list." } } },
183
183
  invoke: (client, args) => client.services.create(args.body),
184
184
  },
185
185
  {
@@ -201,7 +201,7 @@ export const CAT_FACTORY_TOOLS = [
201
201
  readOnly: true,
202
202
  description: 'List the workspace\'s services\n\nList the board service frames in the key’s workspace, so a caller can discover the serviceId to create/list tasks under.\n\nCalls `GET /api/v1/services` (operation `listPublicServices`).',
203
203
  inputSchema: { "type": "object", "properties": {}, "additionalProperties": false },
204
- outputSchema: { "type": "object", "properties": { "services": { "type": "array", "items": { "type": "object", "properties": { "description": { "type": "string" }, "provisioning": { "description": "Discriminated by `type` (kubernetes | custom). A newer deployment may report a variant not in this list." }, "serviceId": { "type": "string" }, "status": { "type": "string", "description": "One of: planned, ready, in_progress, blocked, pr_ready, done. A newer deployment may report a member not in this list." }, "title": { "type": "string" }, "type": { "type": "string", "description": "One of: frontend, service, library, document, api, database, queue, integration, external, environment. A newer deployment may report a member not in this list." } } } } } },
204
+ outputSchema: { "type": "object", "properties": { "services": { "type": "array", "items": { "type": "object", "properties": { "description": { "type": "string" }, "provisioning": { "description": "Discriminated by `type` (kubernetes | infraless | custom). A newer deployment may report a variant not in this list." }, "serviceId": { "type": "string" }, "status": { "type": "string", "description": "One of: planned, ready, in_progress, blocked, pr_ready, done. A newer deployment may report a member not in this list." }, "title": { "type": "string" }, "type": { "type": "string", "description": "One of: frontend, service, library, document, api, database, queue, integration, external, environment. A newer deployment may report a member not in this list." } } } } } },
205
205
  invoke: (client, args) => client.services.list(),
206
206
  },
207
207
  {
@@ -210,9 +210,9 @@ export const CAT_FACTORY_TOOLS = [
210
210
  group: 'services',
211
211
  operationId: 'updatePublicService',
212
212
  readOnly: false,
213
- description: 'Patch a service, including where its per-run manifests live\n\nChange a service’s authored fields, and declare its `provisioning`: where the manifests for a per-run environment are read from. That second half is what a connected cluster alone cannot supply, because the platform keeps “which cluster” (one per workspace) apart from “which manifests” (one set per service). An omitted `provisioning` leaves the stored one alone rather than clearing it. Board coordinates are deliberately absent, as they are on service creation.\n\nCalls `PATCH /api/v1/services/{serviceId}` (operation `updatePublicService`).',
214
- inputSchema: { "type": "object", "properties": { "serviceId": { "type": "string", "description": "Path parameter `serviceId`." }, "body": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 2000 }, "provisioning": { "anyOf": [{ "type": "object", "properties": { "manifestSource": { "anyOf": [{ "type": "object", "properties": { "path": { "type": "string", "minLength": 1, "maxLength": 500 }, "renderer": { "type": "string", "enum": ["raw", "kustomize"] }, "type": { "const": "colocated" } }, "required": ["path", "type"] }, { "type": "object", "properties": { "path": { "type": "string", "minLength": 1, "maxLength": 500 }, "ref": { "type": "string", "minLength": 1 }, "renderer": { "type": "string", "enum": ["raw", "kustomize"] }, "repo": { "type": "string" }, "type": { "const": "separate" } }, "required": ["path", "repo", "type"] }], "description": "Discriminated by `type` (colocated | separate)." }, "type": { "const": "kubernetes" } }, "required": ["manifestSource", "type"] }, { "type": "object", "properties": { "manifestId": { "type": "string", "minLength": 1, "maxLength": 64 }, "manifestPath": { "type": "string", "maxLength": 500 }, "type": { "const": "custom" } }, "required": ["manifestId", "type"] }], "description": "Discriminated by `type` (kubernetes | custom)." }, "title": { "type": "string", "minLength": 1, "maxLength": 200 } }, "description": "The request body." } }, "additionalProperties": false, "required": ["serviceId"] },
215
- outputSchema: { "type": "object", "properties": { "description": { "type": "string" }, "provisioning": { "description": "Discriminated by `type` (kubernetes | custom). A newer deployment may report a variant not in this list." }, "serviceId": { "type": "string" }, "status": { "type": "string", "description": "One of: planned, ready, in_progress, blocked, pr_ready, done. A newer deployment may report a member not in this list." }, "title": { "type": "string" }, "type": { "type": "string", "description": "One of: frontend, service, library, document, api, database, queue, integration, external, environment. A newer deployment may report a member not in this list." } } },
213
+ description: 'Patch a service, including where its per-run manifests live\n\nChange a service’s authored fields, and declare its `provisioning`: where the manifests for a per-run environment are read from. That second half is what a connected cluster alone cannot supply, because the platform keeps “which cluster” (one per workspace) apart from “which manifests” (one set per service). An omitted `provisioning` leaves the stored one alone rather than clearing it, so correcting a title cannot un-deploy a service; send `provisioning: { "type": "infraless" }` to take the pin BACK, which leaves the service with no environment to provision and reads back with no `provisioning` at all. Board coordinates are deliberately absent, as they are on service creation.\n\nCalls `PATCH /api/v1/services/{serviceId}` (operation `updatePublicService`).',
214
+ inputSchema: { "type": "object", "properties": { "serviceId": { "type": "string", "description": "Path parameter `serviceId`." }, "body": { "type": "object", "properties": { "description": { "type": "string", "maxLength": 2000 }, "provisioning": { "anyOf": [{ "type": "object", "properties": { "manifestSource": { "anyOf": [{ "type": "object", "properties": { "path": { "type": "string", "minLength": 1, "maxLength": 500 }, "renderer": { "type": "string", "enum": ["raw", "kustomize"] }, "type": { "const": "colocated" } }, "required": ["path", "type"] }, { "type": "object", "properties": { "path": { "type": "string", "minLength": 1, "maxLength": 500 }, "ref": { "type": "string", "minLength": 1 }, "renderer": { "type": "string", "enum": ["raw", "kustomize"] }, "repo": { "type": "string" }, "type": { "const": "separate" } }, "required": ["path", "repo", "type"] }], "description": "Discriminated by `type` (colocated | separate)." }, "type": { "const": "kubernetes" } }, "required": ["manifestSource", "type"] }, { "type": "object", "properties": { "type": { "const": "infraless" } }, "required": ["type"] }, { "type": "object", "properties": { "manifestId": { "type": "string", "minLength": 1, "maxLength": 64 }, "manifestPath": { "type": "string", "maxLength": 500 }, "type": { "const": "custom" } }, "required": ["manifestId", "type"] }], "description": "Discriminated by `type` (kubernetes | infraless | custom)." }, "title": { "type": "string", "minLength": 1, "maxLength": 200 } }, "description": "The request body." } }, "additionalProperties": false, "required": ["serviceId"] },
215
+ outputSchema: { "type": "object", "properties": { "description": { "type": "string" }, "provisioning": { "description": "Discriminated by `type` (kubernetes | infraless | custom). A newer deployment may report a variant not in this list." }, "serviceId": { "type": "string" }, "status": { "type": "string", "description": "One of: planned, ready, in_progress, blocked, pr_ready, done. A newer deployment may report a member not in this list." }, "title": { "type": "string" }, "type": { "type": "string", "description": "One of: frontend, service, library, document, api, database, queue, integration, external, environment. A newer deployment may report a member not in this list." } } },
216
216
  invoke: (client, args) => client.services.update(str(args, 'serviceId'), args.body),
217
217
  },
218
218
  {
@@ -376,7 +376,7 @@ export const CAT_FACTORY_TOOLS = [
376
376
  readOnly: true,
377
377
  description: 'Get a task\'s run (rich projection)\n\nRead a task’s run in detail: per-step status/progress/subtasks, the failure kind and message, and the PR (url + branch).\n\nCalls `GET /api/v1/tasks/{taskId}/run` (operation `getPublicRun`).',
378
378
  inputSchema: { "type": "object", "properties": { "taskId": { "type": "string", "description": "Path parameter `taskId`." } }, "additionalProperties": false, "required": ["taskId"] },
379
- outputSchema: { "type": "object", "properties": { "createdAt": { "type": "number" }, "currentStep": { "type": "number" }, "error": { "anyOf": [{ "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } } }, { "type": "null" }] }, "externalIdentity": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "externalIdentityWithheld": { "type": "boolean" }, "pullRequest": { "anyOf": [{ "type": "object", "properties": { "branch": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "url": { "type": "string" } } }, { "type": "null" }] }, "runId": { "type": "string" }, "status": { "type": "string", "description": "One of: running, blocked, paused, done, failed. A newer deployment may report a member not in this list." }, "steps": { "type": "array", "items": { "type": "object", "properties": { "agentKind": { "type": "string" }, "data": { "anyOf": [{}, { "type": "null" }] }, "output": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "progress": { "type": "number" }, "state": { "type": "string", "description": "One of: pending, working, waiting_decision, done. A newer deployment may report a member not in this list." }, "subtasks": { "anyOf": [{ "type": "object", "properties": { "completed": { "type": "number" }, "inProgress": { "type": "number" }, "total": { "type": "number" } } }, { "type": "null" }] }, "truncated": { "type": "boolean" } } } }, "taskId": { "type": "string" } } },
379
+ outputSchema: { "type": "object", "properties": { "createdAt": { "type": "number" }, "currentStep": { "type": "number" }, "error": { "anyOf": [{ "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" } } }, { "type": "null" }] }, "externalIdentity": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "externalIdentityWithheld": { "type": "boolean" }, "pullRequest": { "anyOf": [{ "type": "object", "properties": { "branch": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "url": { "type": "string" } } }, { "type": "null" }] }, "runId": { "type": "string" }, "status": { "type": "string", "description": "One of: running, blocked, paused, done, failed. A newer deployment may report a member not in this list." }, "steps": { "type": "array", "items": { "type": "object", "properties": { "agentKind": { "type": "string" }, "data": { "anyOf": [{}, { "type": "null" }] }, "output": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "progress": { "type": "number" }, "skipped": { "type": "boolean" }, "state": { "type": "string", "description": "One of: pending, working, waiting_decision, done. A newer deployment may report a member not in this list." }, "subtasks": { "anyOf": [{ "type": "object", "properties": { "completed": { "type": "number" }, "inProgress": { "type": "number" }, "total": { "type": "number" } } }, { "type": "null" }] }, "truncated": { "type": "boolean" } } } }, "taskId": { "type": "string" } } },
380
380
  invoke: (client, args) => client.tasks.getRun(str(args, 'taskId')),
381
381
  },
382
382
  {
@@ -569,6 +569,17 @@ export const CAT_FACTORY_TOOLS = [
569
569
  outputSchema: { "type": "object", "properties": { "connections": { "type": "array", "items": { "type": "object", "properties": { "acceptsManifestId": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "backendKind": { "type": "string" }, "connectedAt": { "type": "number" }, "endpoint": { "type": "string" }, "engine": { "type": "string" }, "label": { "type": "string" }, "manifestId": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "provisionType": { "type": "string" }, "secretKeys": { "type": "array", "items": { "type": "string" } } } } } } },
570
570
  invoke: (client, args) => client.environments.listConnections(),
571
571
  },
572
+ {
573
+ name: 'environments_list_manifest_types',
574
+ title: 'List the custom manifest types a service can pin',
575
+ group: 'environments',
576
+ operationId: 'listPublicEnvironmentManifestTypes',
577
+ readOnly: true,
578
+ description: 'List the custom manifest types a service can pin\n\nEvery custom-manifest-type id a service’s `custom` provisioning may name, with the label and default manifest path of each, and whether the deployment registered it in code (`registered`) or the workspace defined it (`workspace`). Those two are fixed by different people, which is why the source is reported. The read exists because a pin is checked against no registry on the way in: an id no handler serves is accepted and fails at the `deployer` step of a run already paid for, so a caller lists first and refuses before it spends.\n\nCalls `GET /api/v1/environments/manifest-types` (operation `listPublicEnvironmentManifestTypes`).',
579
+ inputSchema: { "type": "object", "properties": {}, "additionalProperties": false },
580
+ outputSchema: { "type": "object", "properties": { "manifestTypes": { "type": "array", "items": { "type": "object", "properties": { "defaultManifestPath": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, "label": { "type": "string" }, "manifestId": { "type": "string" }, "source": { "type": "string", "description": "One of: registered, workspace. A newer deployment may report a member not in this list." } } } } } },
581
+ invoke: (client, args) => client.environments.listManifestTypes(),
582
+ },
572
583
  {
573
584
  name: 'environments_test_connection',
574
585
  title: 'Probe a candidate cluster connection without saving it',
@@ -1494,7 +1505,7 @@ export const CAT_FACTORY_TOOL_GROUPS = {
1494
1505
  'task_types': 'What a task can be created AS in this workspace (the built-in kinds plus the operations the deployment registered), and the fields each one accepts.',
1495
1506
  'use_cases': 'The deployment\'s own non-container model operations: what it will generate for you, on which models, from which parameters, and running one. Each use case narrows the models it may run on and declares the form it accepts, so a wrapper renders a picker from the catalog rather than from a hard-coded copy; a model listed as unavailable says whether the deployment cannot serve it at all or has yet to configure the credential. Discovery takes a `read` key, invoking a `write` one: an invocation spends model tokens and returns text, and starts no run.',
1496
1507
  'notifications': 'The workspace\'s human-actionable inbox: list, act on, or dismiss a run tail.',
1497
- 'environments': 'The cluster this workspace provisions per-run environments onto: probe a candidate connection without saving it, or bind one. The credential is write-only, so a read reports which secret keys are stored and never their values.',
1508
+ 'environments': 'The cluster this workspace provisions per-run environments onto: probe a candidate connection without saving it, bind one, or list what is already bound. The credential is write-only, so a read reports which secret keys are stored and never their values. The manifest-type catalog is the read under a service\'s `custom` provisioning pin: the ids a pin may name, each saying whether the deployment registered it in code or the workspace defined it, so a caller checks an id before a run pays to discover it resolves to nothing.',
1498
1509
  'models': 'The models a run in this workspace could actually dispatch to, and why an unavailable one is unavailable: unconfigured, or refused by the account model-family policy. Those two need opposite fixes.',
1499
1510
  'vcs': 'The workspace\'s source-control connection: which account it talks to, how it authenticates, and whether it may create repositories and write workflow files. Both permissions are enforced by the provider at push time, so reading them beats discovering one missing halfway through an automated setup.',
1500
1511
  'tracker': 'What this workspace does to a task\'s LINKED tracker issue as its pull request progresses: comment when it opens, comment and close the issue when it merges, and post a headless run\'s parked review findings so the reporter can answer where they filed. The write MERGES, so turning one action on leaves the other two as they were. It is the writeback half of the workspace\'s tracker configuration; the filing selection (which tracker a tech-debt ticket is raised on) is not published yet.',