@pome-sh/cli 0.23.19 → 0.23.21

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "pome-sh",
3
- "version": "0.23.19",
4
- "git_sha": "62e2d8e1a3de3ad4c5648e36fefb3b62a5085a2b",
5
- "build_time": "2026-08-12T13:50:55.793Z"
3
+ "version": "0.23.21",
4
+ "git_sha": "d43a18c54ee2082774e8a8fc9a60cd57e3dad784",
5
+ "build_time": "2026-08-12T15:48:56.168Z"
6
6
  }
@@ -183,7 +183,7 @@ async function checkTwinReachable(_configDir) {
183
183
  });
184
184
  let harness;
185
185
  try {
186
- const { bootTwin } = await import('./twinHarness-FNALWW53.js');
186
+ const { bootTwin } = await import('./twinHarness-XWT46NM5.js');
187
187
  harness = await bootTwin({
188
188
  twin: "github",
189
189
  seedState: void 0,
@@ -2,7 +2,7 @@ import { criterionSchema, finalizeResponseSchema, HostedDiscardRefusedError, Hos
2
2
  import { seedSchema, parseSeed, defaultSeedState as defaultSeedState$2 } from './chunk-KIUIKAVU.js';
3
3
  import { gmailSeedSchema, defaultSeedState } from './chunk-NJ246QPJ.js';
4
4
  import { linearSeedSchema, defaultSeedState as defaultSeedState$1 } from './chunk-ZKID2HS3.js';
5
- import { isTwinName, TWIN_REGISTRY } from './chunk-ZC42N2J7.js';
5
+ import { isTwinName, TWIN_REGISTRY } from './chunk-N4FVASOY.js';
6
6
  import { toTwinHttpEventRow } from './chunk-OW7VVW6X.js';
7
7
  import { redactEvent, redactSecrets } from './chunk-SG6ZTIMT.js';
8
8
  import { mkdir, appendFile, writeFile, readFile } from 'node:fs/promises';
@@ -1,4 +1,4 @@
1
- import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-ZC42N2J7.js';
1
+ import { TWIN_NAMES, isTwinName, TWIN_REGISTRY } from './chunk-N4FVASOY.js';
2
2
  import { createFileBackedRecorderStore, createRecorderStore } from './chunk-OW7VVW6X.js';
3
3
 
4
4
  // src/recorder/recorder.ts
@@ -84,9 +84,9 @@ var TWIN_REGISTRY = {
84
84
  envName: "STRIPE",
85
85
  defaultPort: 3333,
86
86
  version: package_default3.version,
87
- defaultSeed: async () => (await import('./src-E6TRTNLF.js')).defaultSeed(),
87
+ defaultSeed: async () => (await import('./src-6JNLHNYE.js')).defaultSeed(),
88
88
  async boot({ seedState, runId, recorder, twinBaseUrl }) {
89
- const stripeTwin = await import('./src-E6TRTNLF.js');
89
+ const stripeTwin = await import('./src-6JNLHNYE.js');
90
90
  const { createApp } = await import('./server-KOR7UHEP.js');
91
91
  const {
92
92
  applySeed: applyStripeSeed,
@@ -149,7 +149,7 @@ var TWIN_REGISTRY = {
149
149
  portEnvName: "LINEAR_TWIN_PORT",
150
150
  tokenEnvName: "POME_LINEAR_TOKEN",
151
151
  version: package_default5.version,
152
- defaultSeed: async () => (await import('./src-ZC7YOHIQ.js')).defaultSeedState(),
152
+ defaultSeed: async () => (await import('./src-UVXZQZGN.js')).defaultSeedState(),
153
153
  async boot({ seedState, runId, recorder }) {
154
154
  const {
155
155
  createLinearTwinApp,
@@ -157,7 +157,7 @@ var TWIN_REGISTRY = {
157
157
  LinearDomain,
158
158
  openLinearTwinDatabase,
159
159
  parseSeed
160
- } = await import('./src-ZC7YOHIQ.js');
160
+ } = await import('./src-UVXZQZGN.js');
161
161
  const db = openLinearTwinDatabase(":memory:");
162
162
  const seed = parseSeed(seedState);
163
163
  const domain = new LinearDomain(db);
@@ -1,5 +1,5 @@
1
1
  import { readManifest, normalizeManifestTwins } from './chunk-ABM3CMQB.js';
2
- import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-QZKP4252.js';
2
+ import { createHostedClient, perTwinReturnedByCloud, parseTaskFile, runAgentCommand, writeRunArtifactsCore, toTwinHttpEvent, redactJsonl, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, evaluationCounts } from './chunk-3E3DQ65T.js';
3
3
  import { MOUNTED_TWINS, HostedAuthError, HostedDiscardRefusedError, HostedQuotaError, HostedOrchError, HostedTrialError, agentResponseSchema } from './chunk-X66JOOO7.js';
4
4
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
5
5
  import { existsSync } from 'node:fs';
@@ -1,7 +1,7 @@
1
1
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
2
2
  import { buildEgressAllowlist, readBlockedEgress } from './chunk-CBFKZZBR.js';
3
- import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-QZKP4252.js';
4
- import { createRecorder, bootTwin } from './chunk-XGTPMFIH.js';
3
+ import { parseTaskFile, seedStateForTwin, runAgentCommand, writeRunArtifactsCore } from './chunk-3E3DQ65T.js';
4
+ import { createRecorder, bootTwin } from './chunk-E33L264J.js';
5
5
  import { eventSchema } from './chunk-VBATFCWR.js';
6
6
  import { redactSecrets, redactEvent } from './chunk-SG6ZTIMT.js';
7
7
  import { serve } from '@hono/node-server';
@@ -1,16 +1,16 @@
1
1
  import { newGroupId, reassuranceBox, twinReadyLine, trialsHeaderLine, trialLine, summaryLines, evaluatingLine, criterionPhrase } from './chunk-RGZBC7NF.js';
2
2
  import { DemoCapacityError, capacityLabel, parseCapacityMarker, capacityKindFrom } from './chunk-ZX4WNSZ5.js';
3
- import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-GZ3KWK4E.js';
3
+ import { runTask, demoTaskPath, DEMO_TASK_NAME, DEMO_REPO } from './chunk-UBZLAZLA.js';
4
4
  import { getAvailablePort } from './chunk-XDU6TD4O.js';
5
5
  import './chunk-CBFKZZBR.js';
6
- import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-QZKP4252.js';
6
+ import { createHostedClient, parseTaskFile, uploadRunBlobs, scoreFromFinalizeResponse, scoreStatus, outcomeOf } from './chunk-3E3DQ65T.js';
7
7
  import './chunk-NW7HGA2K.js';
8
8
  import { HostedQuotaError, HostedOrchError } from './chunk-X66JOOO7.js';
9
9
  import './chunk-KIUIKAVU.js';
10
10
  import './chunk-NJ246QPJ.js';
11
11
  import './chunk-ZKID2HS3.js';
12
- import { bootTwin } from './chunk-XGTPMFIH.js';
13
- import './chunk-ZC42N2J7.js';
12
+ import { bootTwin } from './chunk-E33L264J.js';
13
+ import './chunk-N4FVASOY.js';
14
14
  import './chunk-OW7VVW6X.js';
15
15
  import './chunk-VBATFCWR.js';
16
16
  import './chunk-SG6ZTIMT.js';
@@ -1,13 +1,13 @@
1
1
  import { newGroupId, criterionPhrase } from './chunk-RGZBC7NF.js';
2
- import { runTaskHosted, resolveRunAgentIdentity } from './chunk-6KLIACJO.js';
2
+ import { runTaskHosted, resolveRunAgentIdentity } from './chunk-SUXYXBA4.js';
3
3
  import './chunk-ABM3CMQB.js';
4
- import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-QZKP4252.js';
4
+ import { createHostedClient, parseTaskFile, outcomeOf } from './chunk-3E3DQ65T.js';
5
5
  import './chunk-NW7HGA2K.js';
6
6
  import { HostedQuotaError, HostedTrialError } from './chunk-X66JOOO7.js';
7
7
  import './chunk-KIUIKAVU.js';
8
8
  import './chunk-NJ246QPJ.js';
9
9
  import './chunk-ZKID2HS3.js';
10
- import './chunk-ZC42N2J7.js';
10
+ import './chunk-N4FVASOY.js';
11
11
  import './chunk-OW7VVW6X.js';
12
12
  import './chunk-VBATFCWR.js';
13
13
  import './chunk-SG6ZTIMT.js';
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, VERDICT_ARTIFACT_VERSION, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-6KLIACJO.js';
2
+ import { DEFAULT_CONTROL_PLANE_URL, DEFAULT_DASHBOARD_URL, clearLocalCredentials, friendlyHostedError, runSessionCreate, runSessionList, runSessionStop, resolveCredentials, runTaskHosted, discoverRunSet, VERDICT_ARTIFACT_VERSION, persistCredentialsAfterLogin, DEFAULT_DOCS_SITE_ORIGIN, resolveSeams, resolveCachedAgentId, readLinkCache, postAgentResolver, writeLinkCache, ensurePomeGitignored } from '../../chunk-SUXYXBA4.js';
3
3
  import { readManifest, writeManifest, MANIFEST_JSON, readRequiredManifest, normalizeManifestTwins } from '../../chunk-ABM3CMQB.js';
4
- import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-GZ3KWK4E.js';
4
+ import { assetPath, runTask, resolvePackageRoot, DEMO_TASK_NAME, demoTaskPath } from '../../chunk-UBZLAZLA.js';
5
5
  import '../../chunk-XDU6TD4O.js';
6
6
  import '../../chunk-CBFKZZBR.js';
7
- import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, markerFor, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-QZKP4252.js';
7
+ import { parseTaskFile, scoreStatus, runScoreLine, readLatestRun, readMetaSummary, outcomeOf, readConfigTwins, scoreCountsSummary, markerFor, criterionMarkerLabel, twinSkipSuffix, readCodeCriteria, createHostedClient, toTwinHttpEvent, redactJsonl, scoreFromFinalizeResponse, parseGitHubSeedState, uploadRunBlobs, isPreSatisfied } from '../../chunk-3E3DQ65T.js';
8
8
  import '../../chunk-NW7HGA2K.js';
9
9
  import { MOUNTED_TWINS, deriveAgentSlug, exitCodeFor, HostedUsageError, HostedOrchError, HostedAuthError, HostedQuotaError } from '../../chunk-X66JOOO7.js';
10
10
  import { TAPE_ASSERTABLE_TOOLS } from '../../chunk-FKZZWWYC.js';
@@ -15,8 +15,8 @@ import '../../chunk-NJ246QPJ.js';
15
15
  import { LINEAR_CHECKS } from '../../chunk-XBT6ZLBG.js';
16
16
  import '../../chunk-ZKID2HS3.js';
17
17
  import { oneOf, defineCheck, repoRef, VACUITY_SENTINEL_NUMBER, childStatePath, VACUITY_SENTINEL, statePath, templateSlots, renderCheck, checksDigest, checkPattern, checkNearMissPattern } from '../../chunk-JWJYNAWI.js';
18
- import '../../chunk-XGTPMFIH.js';
19
- import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-ZC42N2J7.js';
18
+ import '../../chunk-E33L264J.js';
19
+ import { TWIN_NAME_LIST, isTwinName, createGitHubSmokeApp } from '../../chunk-N4FVASOY.js';
20
20
  import '../../chunk-OW7VVW6X.js';
21
21
  import { isLegacyEventRow, eventSchema } from '../../chunk-VBATFCWR.js';
22
22
  import { redactEvent, redactSecrets } from '../../chunk-SG6ZTIMT.js';
@@ -4541,7 +4541,7 @@ var DEFAULT_AGENT_COMMAND = `node ${DEFAULT_AGENT_FILE}`;
4541
4541
  var MANIFEST_SCHEMA_URL = "https://pome.sh/schemas/v1/pome.json";
4542
4542
  var MAX_UNREADABLE_PATHS_SHOWN = 5;
4543
4543
  function readPackageVersion() {
4544
- if ("0.23.19".length > 0) return "0.23.19";
4544
+ if ("0.23.21".length > 0) return "0.23.21";
4545
4545
  try {
4546
4546
  const here = dirname(fileURLToPath(import.meta.url));
4547
4547
  const candidates = [
@@ -4996,7 +4996,7 @@ function createProgram() {
4996
4996
  return;
4997
4997
  }
4998
4998
  {
4999
- const { runDoctorChecks } = await import('../../checks-HBR53PBQ.js');
4999
+ const { runDoctorChecks } = await import('../../checks-3GNDXCIP.js');
5000
5000
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5001
5001
  const doctorReport = await runDoctorChecks({ mode: useLocal ? "full" : "hosted" });
5002
5002
  if (!doctorReport.ok) {
@@ -5034,7 +5034,7 @@ function createProgram() {
5034
5034
  taskForRuns.config.runs
5035
5035
  );
5036
5036
  if (k > 1) {
5037
- const { runTrialGroup } = await import('../../runTrialGroup-JROYRFVK.js');
5037
+ const { runTrialGroup } = await import('../../runTrialGroup-3YUZBWVX.js');
5038
5038
  const fileForRerun = relative(process.cwd(), file);
5039
5039
  const rerunCommand = defaultTask ? options.trials !== void 0 ? `pome run -n ${k}` : "pome run" : `pome run ${fileForRerun && !fileForRerun.startsWith("..") ? fileForRerun : file} -n ${k}`;
5040
5040
  const groupResult = await runTrialGroup({
@@ -5128,7 +5128,7 @@ function createProgram() {
5128
5128
  process.exitCode = 5;
5129
5129
  return;
5130
5130
  }
5131
- const { runDemo } = await import('../../runDemo-N44J2NHJ.js');
5131
+ const { runDemo } = await import('../../runDemo-6B353L3B.js');
5132
5132
  const result = await runDemo({
5133
5133
  apiBase: opts.apiUrl.replace(/\/$/, ""),
5134
5134
  dashboardBase: process.env.POME_DASHBOARD_URL ?? DEFAULT_DASHBOARD_URL,
@@ -5146,7 +5146,7 @@ function createProgram() {
5146
5146
  program.command("doctor").description(
5147
5147
  "Check the agent\u2194twin wiring: pome.json (or pome.yaml) present + valid, the local twin boots + serves, requests routed to the twin (not a hardcoded production host), egress floor active. On failure prints one named cause (file:line where knowable) + one concrete fix and exits non-zero."
5148
5148
  ).action(async () => {
5149
- const { runDoctorChecks } = await import('../../checks-HBR53PBQ.js');
5149
+ const { runDoctorChecks } = await import('../../checks-3GNDXCIP.js');
5150
5150
  const { renderDoctorReport } = await import('../../render-ZQQ4UMNO.js');
5151
5151
  const report = await runDoctorChecks();
5152
5152
  for (const line of renderDoctorReport(report, { passNote: true })) console.error(line);
@@ -5322,7 +5322,7 @@ function createProgram() {
5322
5322
  ).description(
5323
5323
  "Start a standalone twin as a long-lived foreground server (Ctrl-C to stop)"
5324
5324
  ).action(async (name, options) => {
5325
- const { runTwinStartCommand } = await import('../../twinStart-AXCVJWZQ.js');
5325
+ const { runTwinStartCommand } = await import('../../twinStart-FU7LXQAA.js');
5326
5326
  await runTwinStartCommand(name, options);
5327
5327
  });
5328
5328
  twin.command("reset").argument("[name]", "Twin name (default: github)", "github").description("Reset standalone twin state").action(async (name) => {
@@ -2782,6 +2782,11 @@ function flattenCreated(created2) {
2782
2782
  }
2783
2783
  return out;
2784
2784
  }
2785
+
2786
+ // ../packages/twin-stripe/dist/src/upstream-types.js
2787
+ var STRIPE_REFUND_REASONS = ["duplicate", "fraudulent", "requested_by_customer"];
2788
+
2789
+ // ../packages/twin-stripe/dist/src/route-inputs.js
2785
2790
  var declareInputs = routeInputDeclarer("refuse");
2786
2791
  var ID_PATH = { id: z.string().min(1) };
2787
2792
  var LIST_QUERY = {
@@ -2818,7 +2823,7 @@ var CONFIRM_PAYMENT_INTENT_BODY = { payment_method: z.string().optional() };
2818
2823
  var CREATE_REFUND_BODY = {
2819
2824
  charge: z.string().optional(),
2820
2825
  amount: z.coerce.number().optional(),
2821
- reason: z.string().nullish()
2826
+ reason: z.enum(STRIPE_REFUND_REASONS).nullish()
2822
2827
  };
2823
2828
  var CUSTOMER_FIELDS_BODY = {
2824
2829
  name: z.string().nullish(),
@@ -3957,8 +3962,8 @@ var mcp_tools_list_meta_default = {
3957
3962
  method: "tools/list",
3958
3963
  protocol: "JSON-RPC 2.0 over Streamable HTTP",
3959
3964
  protocolVersion: "2025-06-18",
3960
- captureDate: "2026-08-06",
3961
- rawFileSha256: "7bb87c5d6d99fea8dad1069a501f9801811e42c7cf81723b6b3d4e75aacc5bba",
3965
+ captureDate: "2026-08-12",
3966
+ rawFileSha256: "5ce7a3dcecd7a2093bb3986472461f713a48b5c14e82163151ca4b108e4fa520",
3962
3967
  liveToolCount: 26,
3963
3968
  liveToolOrder: [
3964
3969
  "create_payment_intent",
@@ -3989,14 +3994,14 @@ var mcp_tools_list_meta_default = {
3989
3994
  "list_events"
3990
3995
  ],
3991
3996
  transcription: {
3992
- readFrom: "twin-stripe's own tools/list, booted on defaultSeed() and driven through Hono's app.request, read immediately before this table became fixture-driven (F-1325)",
3997
+ readFrom: "twin-stripe's own tools/list, booted on defaultSeed() and driven through Hono's app.request, read immediately before this table became fixture-driven (F-1325). Re-projected on 2026-08-12 for F-1484: every tool's inputSchema was rewritten from stripeToolInputSchema() of its zod schema \u2014 a no-op for 25 of the 26, and create_refund.reason's enum for the one. Names, descriptions and ordering are unchanged, and test/mcp-tool-fixture.test.ts boots the twin and asserts it serves exactly these bytes.",
3993
3998
  contentOrigin: "packages/twin-stripe/src/tools.ts \u2014 a hand-written TypeScript array of 26 tools. Each inputSchema is z.toJSONSchema() of that tool's zod schema, frozen here verbatim including the $schema key it emits.",
3994
3999
  comparedToUpstream: "never, and not comparable today. @stripe/mcp is a stdio-to-HTTP proxy that declares no tools of its own and the served listing is a function of the caller's Restricted API Key, so F-1326 recorded stripe as not-captured (fixtures/mcp-tools-list/stripe.status.json) rather than inventing a deployment-invariant table."
3995
4000
  },
3996
4001
  notes: [
3997
4002
  "Seeded from the code table rather than from upstream on purpose. F-1325 is name-neutral by construction: every byte this twin serves is identical before and after it."
3998
4003
  ],
3999
- canonicalFileSha256: "76d0bafab29a0ccc15730b7ee4d754bcec75d655891e3a2a21a11b4e7cfc8211",
4004
+ canonicalFileSha256: "6a294341065eb90138f26654ad00bf7b0b3750ee6c2f12df82a38fb91df7854f",
4000
4005
  files: {
4001
4006
  raw: "mcp-tools-list.raw.json",
4002
4007
  canonical: "mcp-tools-list.canonical.json"
@@ -4004,7 +4009,7 @@ var mcp_tools_list_meta_default = {
4004
4009
  };
4005
4010
 
4006
4011
  // ../packages/twin-stripe/dist/fixtures/mcp-tools-list.raw.json
4007
- var mcp_tools_list_raw_default = { jsonrpc: "2.0", id: 1, result: { tools: [{ name: "create_payment_intent", description: "Create a PaymentIntent: crypto-deposit (the x402 entry point) or card (optionally with payment_method / customer / confirm).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { amount: { type: "integer", exclusiveMinimum: 0, maximum: 9007199254740991 }, currency: { type: "string", minLength: 1 }, payment_method_types: { minItems: 1, maxItems: 1, type: "array", items: { type: "string", enum: ["crypto", "card"] } }, payment_method_options: { type: "object", properties: { crypto: { type: "object", properties: { mode: { type: "string", const: "deposit" }, deposit_options: { type: "object", properties: { networks: { minItems: 1, type: "array", items: { type: "string" } } }, additionalProperties: false } }, required: ["mode"], additionalProperties: false } }, required: ["crypto"], additionalProperties: false }, payment_method: { type: "string" }, customer: { type: "string" }, confirm: { type: "boolean" }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { type: "string" } }, capture_method: { type: "string" }, confirmation_method: { type: "string" } }, required: ["amount", "currency", "payment_method_types"], additionalProperties: false } }, { name: "retrieve_payment_intent", description: "Retrieve a PaymentIntent by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_payment_intents", description: "List PaymentIntents with optional filters.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] } }, additionalProperties: false } }, { name: "confirm_payment_intent", description: "Confirm a PaymentIntent. Card PIs attempt the charge synchronously (magic test PMs decline); crypto-deposit PIs are idempotent here.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, payment_method: { type: "string" } }, required: ["id"], additionalProperties: false } }, { name: "update_payment_intent", description: "Update a non-terminal PaymentIntent (amount, metadata, payment_method, customer). The card retry step: attach a new PM after a decline, then confirm again.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, amount: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { anyOf: [{ type: "string" }, { type: "null" }] } }, payment_method: { type: "string" }, customer: { type: "string" } }, required: ["id"], additionalProperties: false } }, { name: "cancel_payment_intent", description: "Cancel a PaymentIntent. Refused once succeeded.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "simulate_crypto_deposit", description: "Test helper: drive a crypto-deposit PI from requires_action through processing to succeeded.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "retrieve_charge", description: "Retrieve a Charge by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_charges", description: "List charges with optional payment_intent / customer / created filters.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, payment_intent: { type: "string" }, customer: { type: "string" } }, additionalProperties: false } }, { name: "create_refund", description: "Refund a charge, fully or partially. Stripe refuses a refund on a charge that is already fully refunded, or one that would exceed the remaining refundable amount.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { charge: { type: "string", minLength: 1 }, amount: { type: "integer", exclusiveMinimum: 0, maximum: 9007199254740991 }, reason: { type: "string" } }, required: ["charge"], additionalProperties: false } }, { name: "retrieve_refund", description: "Retrieve a Refund by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_refunds", description: "List refunds, optionally filtered by charge or payment_intent.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, charge: { type: "string" }, payment_intent: { type: "string" } }, additionalProperties: false } }, { name: "create_customer", description: "Create a customer. All fields optional, like real Stripe.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { name: { type: "string" }, email: { type: "string" }, description: { type: "string" }, phone: { type: "string" }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { type: "string" } } }, additionalProperties: false } }, { name: "retrieve_customer", description: "Retrieve a Customer by id. Deleted customers return the {deleted: true} stub.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "update_customer", description: "Update a customer's fields. Metadata merges per-key; a null or empty value unsets the key.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, name: { type: "string" }, email: { type: "string" }, description: { type: "string" }, phone: { type: "string" }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { anyOf: [{ type: "string" }, { type: "null" }] } } }, required: ["id"], additionalProperties: false } }, { name: "delete_customer", description: "Delete a customer (soft delete; its payment methods are detached).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_customers", description: "List customers with optional email / created filters.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, email: { type: "string" } }, additionalProperties: false } }, { name: "list_customer_payment_methods", description: "List the payment methods attached to a customer.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { customer: { type: "string", minLength: 1 }, type: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 100 } }, required: ["customer"], additionalProperties: false } }, { name: "create_payment_method", description: "Create a card payment method from test card details (e.g. number 4242424242424242).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { type: { type: "string", const: "card" }, card: { type: "object", properties: { number: { type: "string", minLength: 1 }, exp_month: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, exp_year: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, cvc: { type: "string" } }, required: ["number", "exp_month", "exp_year"], additionalProperties: false } }, required: ["type", "card"], additionalProperties: false } }, { name: "retrieve_payment_method", description: "Retrieve a PaymentMethod by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "attach_payment_method", description: "Attach a payment method to a customer. One customer per PM; a detached PM cannot be reattached.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, customer: { type: "string", minLength: 1 } }, required: ["id", "customer"], additionalProperties: false } }, { name: "detach_payment_method", description: "Detach a payment method from its customer.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "retrieve_balance", description: "Retrieve the current balance (available + pending per currency).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: {}, additionalProperties: false } }, { name: "list_balance_transactions", description: "List balance transactions (charges, refunds, fees).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, type: { type: "string" } }, additionalProperties: false } }, { name: "retrieve_event", description: "Retrieve an event by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_events", description: "List events. Filter by type and created.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, type: { type: "string" } }, additionalProperties: false } }] } };
4012
+ var mcp_tools_list_raw_default = { jsonrpc: "2.0", id: 1, result: { tools: [{ name: "create_payment_intent", description: "Create a PaymentIntent: crypto-deposit (the x402 entry point) or card (optionally with payment_method / customer / confirm).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { amount: { type: "integer", exclusiveMinimum: 0, maximum: 9007199254740991 }, currency: { type: "string", minLength: 1 }, payment_method_types: { minItems: 1, maxItems: 1, type: "array", items: { type: "string", enum: ["crypto", "card"] } }, payment_method_options: { type: "object", properties: { crypto: { type: "object", properties: { mode: { type: "string", const: "deposit" }, deposit_options: { type: "object", properties: { networks: { minItems: 1, type: "array", items: { type: "string" } } }, additionalProperties: false } }, required: ["mode"], additionalProperties: false } }, required: ["crypto"], additionalProperties: false }, payment_method: { type: "string" }, customer: { type: "string" }, confirm: { type: "boolean" }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { type: "string" } }, capture_method: { type: "string" }, confirmation_method: { type: "string" } }, required: ["amount", "currency", "payment_method_types"], additionalProperties: false } }, { name: "retrieve_payment_intent", description: "Retrieve a PaymentIntent by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_payment_intents", description: "List PaymentIntents with optional filters.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] } }, additionalProperties: false } }, { name: "confirm_payment_intent", description: "Confirm a PaymentIntent. Card PIs attempt the charge synchronously (magic test PMs decline); crypto-deposit PIs are idempotent here.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, payment_method: { type: "string" } }, required: ["id"], additionalProperties: false } }, { name: "update_payment_intent", description: "Update a non-terminal PaymentIntent (amount, metadata, payment_method, customer). The card retry step: attach a new PM after a decline, then confirm again.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, amount: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { anyOf: [{ type: "string" }, { type: "null" }] } }, payment_method: { type: "string" }, customer: { type: "string" } }, required: ["id"], additionalProperties: false } }, { name: "cancel_payment_intent", description: "Cancel a PaymentIntent. Refused once succeeded.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "simulate_crypto_deposit", description: "Test helper: drive a crypto-deposit PI from requires_action through processing to succeeded.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "retrieve_charge", description: "Retrieve a Charge by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_charges", description: "List charges with optional payment_intent / customer / created filters.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, payment_intent: { type: "string" }, customer: { type: "string" } }, additionalProperties: false } }, { name: "create_refund", description: "Refund a charge, fully or partially. Stripe refuses a refund on a charge that is already fully refunded, or one that would exceed the remaining refundable amount.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { charge: { type: "string", minLength: 1 }, amount: { type: "integer", exclusiveMinimum: 0, maximum: 9007199254740991 }, reason: { type: "string", enum: ["duplicate", "fraudulent", "requested_by_customer"] } }, required: ["charge"], additionalProperties: false } }, { name: "retrieve_refund", description: "Retrieve a Refund by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_refunds", description: "List refunds, optionally filtered by charge or payment_intent.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, charge: { type: "string" }, payment_intent: { type: "string" } }, additionalProperties: false } }, { name: "create_customer", description: "Create a customer. All fields optional, like real Stripe.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { name: { type: "string" }, email: { type: "string" }, description: { type: "string" }, phone: { type: "string" }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { type: "string" } } }, additionalProperties: false } }, { name: "retrieve_customer", description: "Retrieve a Customer by id. Deleted customers return the {deleted: true} stub.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "update_customer", description: "Update a customer's fields. Metadata merges per-key; a null or empty value unsets the key.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, name: { type: "string" }, email: { type: "string" }, description: { type: "string" }, phone: { type: "string" }, metadata: { type: "object", propertyNames: { type: "string" }, additionalProperties: { anyOf: [{ type: "string" }, { type: "null" }] } } }, required: ["id"], additionalProperties: false } }, { name: "delete_customer", description: "Delete a customer (soft delete; its payment methods are detached).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_customers", description: "List customers with optional email / created filters.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, email: { type: "string" } }, additionalProperties: false } }, { name: "list_customer_payment_methods", description: "List the payment methods attached to a customer.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { customer: { type: "string", minLength: 1 }, type: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 100 } }, required: ["customer"], additionalProperties: false } }, { name: "create_payment_method", description: "Create a card payment method from test card details (e.g. number 4242424242424242).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { type: { type: "string", const: "card" }, card: { type: "object", properties: { number: { type: "string", minLength: 1 }, exp_month: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, exp_year: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, cvc: { type: "string" } }, required: ["number", "exp_month", "exp_year"], additionalProperties: false } }, required: ["type", "card"], additionalProperties: false } }, { name: "retrieve_payment_method", description: "Retrieve a PaymentMethod by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "attach_payment_method", description: "Attach a payment method to a customer. One customer per PM; a detached PM cannot be reattached.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 }, customer: { type: "string", minLength: 1 } }, required: ["id", "customer"], additionalProperties: false } }, { name: "detach_payment_method", description: "Detach a payment method from its customer.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "retrieve_balance", description: "Retrieve the current balance (available + pending per currency).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: {}, additionalProperties: false } }, { name: "list_balance_transactions", description: "List balance transactions (charges, refunds, fees).", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, type: { type: "string" } }, additionalProperties: false } }, { name: "retrieve_event", description: "Retrieve an event by id.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { id: { type: "string", minLength: 1 } }, required: ["id"], additionalProperties: false } }, { name: "list_events", description: "List events. Filter by type and created.", inputSchema: { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { limit: { type: "integer", minimum: 1, maximum: 100 }, created: { anyOf: [{ type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, { type: "object", properties: { gt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, gte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lt: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 }, lte: { type: "integer", minimum: -9007199254740991, maximum: 9007199254740991 } }, additionalProperties: false }] }, type: { type: "string" } }, additionalProperties: false } }] } };
4008
4013
 
4009
4014
  // ../packages/twin-stripe/dist/src/tools.js
4010
4015
  var stripeToolFixture = loadMcpToolFixture({ raw: mcp_tools_list_raw_default, meta: mcp_tools_list_meta_default });
@@ -4108,7 +4113,10 @@ var toolArgumentSchemas = [
4108
4113
  schema: z.object({
4109
4114
  charge: z.string().min(1),
4110
4115
  amount: z.coerce.number().int().positive().optional(),
4111
- reason: z.string().optional()
4116
+ // F-1484 — Stripe's closed set, not a free string. `.optional()` is kept:
4117
+ // the vendor does not require the field, and narrowing the arity as well
4118
+ // as the value would refuse every refund the corpus actually makes.
4119
+ reason: z.enum(STRIPE_REFUND_REASONS).optional()
4112
4120
  })
4113
4121
  },
4114
4122
  {
@@ -2703,25 +2703,25 @@ function resolveLinearCredential(db, token2, nowIso) {
2703
2703
  // ../packages/twin-linear/dist/fixtures/mcp-tools-list.meta.json
2704
2704
  var mcp_tools_list_meta_default = {
2705
2705
  twin: "linear",
2706
- substrate: "twin-authored-from-vendor-docs",
2707
- endpoint: "in-process://twin-linear/s/:sid/mcp",
2706
+ substrate: "upstream-capture-projection",
2707
+ endpoint: "https://mcp.linear.app/mcp",
2708
2708
  method: "tools/list",
2709
- protocol: "JSON-RPC 2.0 over Streamable HTTP",
2709
+ protocol: "JSON-RPC 2.0 over HTTP",
2710
2710
  protocolVersion: "2025-06-18",
2711
- captureDate: "2026-08-06",
2712
- rawFileSha256: "f764e11486c25738b1952b6e83e4919fcb84c3c36cd36ef801b326fb40ed111d",
2711
+ captureDate: "2026-08-10",
2712
+ rawFileSha256: "9bd5195130a072b1b60d11d567b035bb34e77e099b41e55dca2faa920f3109c4",
2713
2713
  liveToolCount: 22,
2714
2714
  liveToolOrder: [
2715
- "list_issues",
2716
- "get_issue",
2717
- "save_issue",
2718
2715
  "list_comments",
2719
2716
  "save_comment",
2720
2717
  "delete_comment",
2721
- "list_teams",
2722
- "get_team",
2723
- "list_users",
2724
- "get_user",
2718
+ "list_cycles",
2719
+ "get_document",
2720
+ "list_documents",
2721
+ "save_document",
2722
+ "get_issue",
2723
+ "list_issues",
2724
+ "save_issue",
2725
2725
  "list_issue_statuses",
2726
2726
  "get_issue_status",
2727
2727
  "list_issue_labels",
@@ -2729,33 +2729,94 @@ var mcp_tools_list_meta_default = {
2729
2729
  "list_projects",
2730
2730
  "get_project",
2731
2731
  "save_project",
2732
- "list_cycles",
2733
- "search_documentation",
2734
- "list_documents",
2735
- "get_document",
2736
- "save_document"
2732
+ "list_teams",
2733
+ "get_team",
2734
+ "list_users",
2735
+ "get_user",
2736
+ "search_documentation"
2737
2737
  ],
2738
- transcription: {
2739
- readFrom: "twin-linear's own tools/list, booted on defaultSeedState() and driven through Hono's app.request, read immediately before this table became fixture-driven (F-1325)",
2740
- contentOrigin: "the tool NAMES come from Linear's published MCP launch documentation; the inputSchemas are twin-owned Gate-1 fixtures, as this fixture's own notes have always admitted. The pre-F-1325 provenance read `source: documented_official_linear_mcp_launch_set`, which reads like a capture. It was never one.",
2741
- comparedToUpstream: "never. https://mcp.linear.app/mcp is OAuth-gated, so F-1326 recorded the upstream golden as deferred (fixtures/mcp-tools-list/linear.status.json). Re-sourcing this table needs that token and belongs to F-1329, not here."
2742
- },
2743
2738
  notes: [
2744
- "Gate-1 Wave 4 expands Gate 0's 18-tool freeze: delete_comment plus documents list/get/save; save_issue estimate/parentId/relations; save_comment parentId.",
2745
- "Documents, initiatives and milestones beyond this minimal set stay named gaps.",
2746
- "GraphQL keeps issueCreate/issueUpdate for SDK parity; MCP follows the documented listing.",
2747
- "This listing carries the generic outputSchema the twin serves on every tool. The pre-F-1325 canonical omitted it, so the committed oracle described less than the wire did.",
2748
- "Seeded from the served table rather than from upstream on purpose. F-1325 is name-neutral by construction: every byte this twin serves is identical before and after it."
2739
+ "These rows are Linear's, not this twin's. Until F-1480 the fixture was `twin-authored-from-vendor-docs`: the tool NAMES came from Linear's published documentation and every description and inputSchema was ours. It is the same shape F-1468 retired on twin-github, one step further from the vendor \u2014 github at least transcribed a table it served, this one was authored from prose \u2014 and it is the EASIER of the two to fix, because these 22 names are a STRICT SUBSET of the golden's 58 (`twin_only` is 0, measured), so the producer can only ever SUBTRACT.",
2740
+ "The 22 are the captured surface's 58 minus 36 this twin does not model. Every dropped name gives its reason in `projection.dropped`, grouped by CAPABILITY rather than by tool: each family is one absence, and modelling any member means building the thing all of them read from. The producer enforces the list \u2014 a dropped name the capture does not carry fails, because a typo there suppresses nothing while the real divergence goes on failing elsewhere. `projection.carried` is EMPTY, which is the strong form: every row this twin serves is the capture's. twin-github needs a carried door because two of its tools are feature-flag-gated upstream; nothing here is.",
2741
+ "What this file does NOT say is what the twin ACCEPTS. These are Linear's advertised schemas; the twin's own validators are what admit or refuse an examinee's call, and the two can disagree. Reading this fixture as a statement about behaviour is the mistake it exists to make visible.",
2742
+ "Linear declares no `outputSchema` on any of its 58 tools, so since F-1480 neither does this twin, and `tools/call` carries its payload as JSON text in `content[0]` rather than in `result.structuredContent` \u2014 MCP only permits the structured field for a tool that declares an output schema. The generic outputSchema the pre-F-1480 fixture put on every row is where that field came from; it was ours, not Linear's. test/_mcpPayload.ts is the reader, and it re-asserts the absence at every call site.",
2743
+ "`configuration` is the SOURCE capture's, carried through verbatim \u2014 its `completeness: exact` and its `matchesExaminee: 58 tools` describe the golden this was projected from, not what this twin serves. GraphQL keeps issueCreate/issueUpdate for SDK parity; the MCP surface follows Linear's captured listing."
2749
2744
  ],
2750
- canonicalFileSha256: "ff65fdd9e6085e255066e1cf0935993634131d862068d82e0f349c5e7882ff91",
2745
+ canonicalFileSha256: "d1dc15827ff6a95a19e5f710cb648658dbbe736318c32775766eff05ed1737fc",
2751
2746
  files: {
2752
2747
  raw: "mcp-tools-list.raw.json",
2753
2748
  canonical: "mcp-tools-list.canonical.json"
2749
+ },
2750
+ configuration: {
2751
+ auth: "bearer",
2752
+ grantedScopes: "read write",
2753
+ responseFraming: "text/event-stream",
2754
+ deploymentSelector: "the authorising Linear workspace. Captured 2026-08-10 from a throwaway workspace under an OAuth grant carrying BOTH scopes mcp.linear.app grants a tool surface for (scopes_supported: read, write, openid, email \u2014 the other two are OIDC identity claims and gate no tool). The grant was minted, used for exactly one tools/list, and revoked.",
2755
+ responseFramingNote: "linear is the only one of the five that answers the tools/list POST as SSE rather than application/json. raw.json holds the unwrapped `data:` payload, because the consumer parses and hashes it; the framing is recorded here so the fact is kept rather than lost.",
2756
+ matchesExaminee: "58 tools, and an examinee pointing an MCP client at this URL under a read+write grant gets exactly them. THE SCOPE SET IS NOT INVARIANT HERE, AND THIS IS THE MEASUREMENT RATHER THAN AN ARGUMENT (F-1394): the same endpoint, captured the same day, answered 36 tools under `read` and 58 under `read write`. The 22 the write scope adds are every write Linear has and nothing else \u2014 prepare_attachment_upload, create_attachment_from_upload, create_attachment, delete_attachment, save_comment, delete_comment, save_document, save_issue, create_issue_label, save_project, save_release, save_release_note, save_diff_comment, resolve_diff_thread, delete_diff_comment, submit_diff_review, merge_diff, save_milestone, save_initiative, create_initiative_label, save_status_update, delete_status_update. Nothing was REMOVED: the read listing is a strict subset, so a narrower grant can only ever under-report. A later capture may therefore never be read-only.",
2757
+ completeness: "exact",
2758
+ completenessBasis: "the axis that moves an OAuth-gated listing is the grant, and this one is now maximal: `read` and `write` are the only scopes mcp.linear.app gates tools behind, and holding both was measured to return 22 more tools than holding `read` alone, with none withheld. The count is corroborated from outside the capture \u2014 a live Linear MCP connector on a separate credential exposes the same 58 names.",
2759
+ unguardedDirection: "the authorising WORKSPACE. This is a throwaway workspace, and nothing here reads a second one, so a listing that varied by Linear plan tier would be invisible from this golden. The reason that is judged shut rather than merely unmeasured is Linear's own grant model: the OAuth surface offers `read`/`write` and no plan-scoped or preview scope, which is the same argument SECRETS.md makes for capturing this twin from a throwaway at all \u2014 and it is the opposite of stripe, where preview tool groups ARE granted per account and the class is `credential-scoped` because of it.",
2760
+ requestHeaders: {
2761
+ "content-type": "application/json",
2762
+ accept: "application/json, text/event-stream"
2763
+ },
2764
+ requestBody: {
2765
+ method: "tools/list",
2766
+ jsonrpc: "2.0",
2767
+ id: 1
2768
+ }
2769
+ },
2770
+ projection: {
2771
+ sourceFixture: "fixtures/mcp-tools-list/linear.raw.json",
2772
+ sourceRawFileSha256: "c737b527fec275abf693f3718db22875bdae0e9c4f207884af6790b0b4e6465a",
2773
+ sourceCaptureDate: "2026-08-10",
2774
+ sourceSubstrate: "live-wire-oauth",
2775
+ producer: "packages/twin-linear/scripts/adopt-upstream-mcp-fixture.ts \u2014 re-derive and diff with `npm run gate:mcp-fixture -w @pome-sh/twin-linear`",
2776
+ dropped: {
2777
+ get_attachment: "out of modeled scope: the twin models no attachments. There is no upload endpoint, no blob store and no file identity behind an issue, so every one of these reads or writes an object that does not exist here.",
2778
+ create_attachment: "out of modeled scope: the twin models no attachments. There is no upload endpoint, no blob store and no file identity behind an issue, so every one of these reads or writes an object that does not exist here.",
2779
+ create_attachment_from_upload: "out of modeled scope: the twin models no attachments. There is no upload endpoint, no blob store and no file identity behind an issue, so every one of these reads or writes an object that does not exist here.",
2780
+ prepare_attachment_upload: "out of modeled scope: the twin models no attachments. There is no upload endpoint, no blob store and no file identity behind an issue, so every one of these reads or writes an object that does not exist here.",
2781
+ delete_attachment: "out of modeled scope: the twin models no attachments. There is no upload endpoint, no blob store and no file identity behind an issue, so every one of these reads or writes an object that does not exist here.",
2782
+ extract_images: "out of modeled scope: the twin models no attachments. There is no upload endpoint, no blob store and no file identity behind an issue, so every one of these reads or writes an object that does not exist here.",
2783
+ list_agent_skills: "out of modeled scope: Linear's agent-skill registry is a feature of Linear's own agent platform, not of the issue tracker this twin models.",
2784
+ get_agent_skill: "out of modeled scope: Linear's agent-skill registry is a feature of Linear's own agent platform, not of the issue tracker this twin models.",
2785
+ list_release_pipelines: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2786
+ list_releases: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2787
+ get_release: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2788
+ save_release: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2789
+ list_release_notes: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2790
+ get_release_note: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2791
+ save_release_note: "out of modeled scope: the twin models no releases, release pipelines or release notes. Nothing in its schema associates an issue with a shipped version.",
2792
+ get_diff: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2793
+ list_diffs: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2794
+ get_diff_threads: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2795
+ save_diff_comment: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2796
+ resolve_diff_thread: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2797
+ delete_diff_comment: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2798
+ submit_diff_review: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2799
+ merge_diff: "out of modeled scope: Linear's code-review surface. The twin models no diffs, no review threads and no merge, and an examinee reviewing code in Linear is exercising a capability that lives in twin-github here.",
2800
+ list_milestones: "out of modeled scope: project milestones are not modeled. The twin's projects carry issues and no milestone layer between them.",
2801
+ get_milestone: "out of modeled scope: project milestones are not modeled. The twin's projects carry issues and no milestone layer between them.",
2802
+ save_milestone: "out of modeled scope: project milestones are not modeled. The twin's projects carry issues and no milestone layer between them.",
2803
+ list_initiatives: "out of modeled scope: initiatives are the layer ABOVE projects, and the twin's hierarchy stops at project. Modelling one member means adding that layer and everything that hangs off it.",
2804
+ get_initiative: "out of modeled scope: initiatives are the layer ABOVE projects, and the twin's hierarchy stops at project. Modelling one member means adding that layer and everything that hangs off it.",
2805
+ save_initiative: "out of modeled scope: initiatives are the layer ABOVE projects, and the twin's hierarchy stops at project. Modelling one member means adding that layer and everything that hangs off it.",
2806
+ list_initiative_labels: "out of modeled scope: initiatives are the layer ABOVE projects, and the twin's hierarchy stops at project. Modelling one member means adding that layer and everything that hangs off it.",
2807
+ create_initiative_label: "out of modeled scope: initiatives are the layer ABOVE projects, and the twin's hierarchy stops at project. Modelling one member means adding that layer and everything that hangs off it.",
2808
+ get_status_updates: "out of modeled scope: project and initiative status updates are not modeled \u2014 the twin has no periodic-update object attached to either.",
2809
+ save_status_update: "out of modeled scope: project and initiative status updates are not modeled \u2014 the twin has no periodic-update object attached to either.",
2810
+ delete_status_update: "out of modeled scope: project and initiative status updates are not modeled \u2014 the twin has no periodic-update object attached to either.",
2811
+ get_workspace: "out of modeled scope: the twin serves ONE implicit workspace and has no workspace object to read. This is also why the initiative and status-update families above have nothing to hang from.",
2812
+ list_project_labels: "out of modeled scope: labels on PROJECTS are a separate taxonomy from labels on issues, which the twin does model (`list_issue_labels`, `create_issue_label`). Adding it is a second label namespace, not a second endpoint on the first."
2813
+ },
2814
+ carried: {}
2754
2815
  }
2755
2816
  };
2756
2817
 
2757
2818
  // ../packages/twin-linear/dist/fixtures/mcp-tools-list.raw.json
2758
- var mcp_tools_list_raw_default = { jsonrpc: "2.0", id: 1, result: { tools: [{ name: "list_issues", description: 'List issues in the Linear workspace. For my issues, use "me" as the assignee.', inputSchema: { type: "object", properties: { team: { type: "string", description: "Team key or id" }, assignee: { type: "string", description: 'User email, id, or "me"' }, state: { type: "string", description: "Workflow state name or id" }, limit: { type: "number", description: "Max results (default 50, max 250)" }, cursor: { type: "string", description: "Pagination cursor" }, query: { type: "string", description: "Title/description search" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "get_issue", description: "Retrieve detailed information about an issue by ID or identifier (e.g. ENG-1).", inputSchema: { type: "object", properties: { id: { type: "string", description: "Issue id or identifier" } }, required: ["id"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "save_issue", description: "Create or update a Linear issue. Omit id to create (title and team required); provide id for a partial update. Relation arrays (blocks/blockedBy/relatedTo) are append-only.", inputSchema: { type: "object", properties: { id: { type: "string", description: "Issue id or identifier (update)" }, title: { type: "string" }, team: { type: "string" }, description: { type: "string" }, assignee: { type: "string" }, state: { type: "string" }, priority: { type: "number" }, estimate: { type: ["number", "null"], description: "Estimate points; null clears on update" }, labels: { type: "array", items: { type: "string" } }, project: { type: "string" }, cycle: { type: "string" }, parentId: { type: ["string", "null"], description: "Parent issue id/identifier; null removes" }, blocks: { type: "array", items: { type: "string" }, description: "Append-only blocked issues" }, blockedBy: { type: "array", items: { type: "string" }, description: "Append-only blockers" }, relatedTo: { type: "array", items: { type: "string" }, description: "Append-only related issues" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_comments", description: "List comments for a specific Linear issue.", inputSchema: { type: "object", properties: { issueId: { type: "string" }, limit: { type: "number" }, cursor: { type: "string" } }, required: ["issueId"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "save_comment", description: "Create or update a comment on a Linear issue. Provide id to edit. To reply in a thread, pass parentId (issueId optional when replying).", inputSchema: { type: "object", properties: { id: { type: "string", description: "Comment id (edit)" }, issueId: { type: "string" }, parentId: { type: "string", description: "Parent comment id for threaded replies" }, body: { type: "string" } }, required: ["body"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "delete_comment", description: "Delete a Linear comment by id.", inputSchema: { type: "object", properties: { id: { type: "string", description: "Comment ID" } }, required: ["id"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_teams", description: "List teams in the user's Linear workspace.", inputSchema: { type: "object", properties: { limit: { type: "number" }, cursor: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "get_team", description: "Retrieve details of a specific Linear team.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Team id, key, or name" } }, required: ["query"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_users", description: "Retrieve users in the Linear workspace.", inputSchema: { type: "object", properties: { limit: { type: "number" }, cursor: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "get_user", description: "Retrieve details of a specific Linear user.", inputSchema: { type: "object", properties: { query: { type: "string", description: "User id, email, or name" } }, required: ["query"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_issue_statuses", description: "List available issue statuses in a Linear team.", inputSchema: { type: "object", properties: { team: { type: "string" } }, required: ["team"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "get_issue_status", description: "Retrieve detailed information about an issue status by name or ID.", inputSchema: { type: "object", properties: { id: { type: "string" }, name: { type: "string" }, team: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_issue_labels", description: "List available issue labels in a Linear workspace or team.", inputSchema: { type: "object", properties: { team: { type: "string" }, limit: { type: "number" }, cursor: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "create_issue_label", description: "Create a new Linear issue label.", inputSchema: { type: "object", properties: { name: { type: "string" }, color: { type: "string" }, description: { type: "string" }, team: { type: "string" } }, required: ["name"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_projects", description: "List projects in the user's Linear workspace.", inputSchema: { type: "object", properties: { team: { type: "string" }, limit: { type: "number" }, cursor: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "get_project", description: "Retrieve details of a specific Linear project.", inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "save_project", description: "Create or update a Linear project. Omit id to create (name required); provide id for a partial update.", inputSchema: { type: "object", properties: { id: { type: "string" }, name: { type: "string" }, team: { type: "string" }, description: { type: "string" }, state: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_cycles", description: "Retrieve cycles for a specific Linear team.", inputSchema: { type: "object", properties: { teamId: { type: "string" }, limit: { type: "number" }, cursor: { type: "string" } }, required: ["teamId"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "search_documentation", description: "Search Linear's documentation to learn about features and usage.", inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "list_documents", description: "List documents in the user's Linear workspace.", inputSchema: { type: "object", properties: { projectId: { type: "string" }, teamId: { type: "string" }, query: { type: "string" }, limit: { type: "number" }, cursor: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "get_document", description: "Retrieve a Linear document by ID or slug.", inputSchema: { type: "object", properties: { id: { type: "string", description: "Document ID or slug" } }, required: ["id"], additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }, { name: "save_document", description: "Create or update a Linear document. Omit id to create (title + exactly one parent required); provide id for a partial update.", inputSchema: { type: "object", properties: { id: { type: "string" }, title: { type: "string" }, content: { type: "string" }, project: { type: "string" }, team: { type: "string" }, issue: { type: "string" }, cycle: { type: "string" }, icon: { type: "string" }, color: { type: "string" } }, additionalProperties: false }, outputSchema: { type: "object", additionalProperties: true } }] } };
2819
+ var mcp_tools_list_raw_default = { jsonrpc: "2.0", id: 1, result: { tools: [{ name: "list_comments", title: "List comments", description: "List comments on a Linear issue, project, initiative, document, project milestone, or project/initiative status update. Provide exactly one of `issueId`, `projectId`, `initiativeId`, `documentId`, `milestoneId`, or `statusUpdateId`. For issues, projects, and initiatives this returns both top-level discussion threads and inline description comments. Inline (anchored) comments carry a non-null `quotedText` set to the snippet of description text they reference.", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 250)", type: "number", maximum: 250 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, issueId: { description: "Issue ID or identifier (e.g., LIN-123) (provide exactly one parent)", type: "string" }, projectId: { description: "Project name, ID, identifier (e.g., PROJ-123), or slug (provide exactly one parent)", type: "string" }, initiativeId: { description: "Initiative name, ID, identifier (e.g., INIT-123), or slug (provide exactly one parent)", type: "string" }, documentId: { description: "Document ID or slug (provide exactly one parent)", type: "string" }, milestoneId: { description: "Milestone UUID (provide exactly one parent). Resolve milestone names via `list_milestones` first.", type: "string" }, statusUpdateId: { description: "Status update UUID (provide exactly one parent). Resolve status updates via `get_status_updates` first.", type: "string" }, statusUpdateType: { description: "Type of status update named by `statusUpdateId`, as returned by `get_status_updates`. Only valid together with `statusUpdateId`; omit to check both project and initiative status updates.", type: "string", enum: ["project", "initiative"] } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "save_comment", title: "Save comment", description: "Create or update a comment on a Linear issue, project, initiative, document, project milestone, or project/initiative status update. If `id` is provided, updates the existing comment; otherwise creates a new one. To start a new thread, pass `body` and exactly one of `issueId`, `projectId`, `initiativeId`, `documentId`, `milestoneId`, or `statusUpdateId` \u2014 comments on issues/projects/initiatives become top-level discussion threads; comments on documents/milestones become description comments. A status update holds a single thread, so a comment on an update that already has one is added to it as a reply. To reply to an existing thread, pass `parentId` and `body`; the reply inherits the parent's thread type, so no entity reference is needed. Parent reference fields are ignored when `id` or `parentId` is provided (`statusUpdateType` is rejected instead).", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { description: "Comment ID. If provided, updates the existing comment", type: "string" }, issueId: { description: "Issue ID or identifier (e.g., LIN-123) (provide exactly one parent)", type: "string" }, projectId: { description: "Project name, ID, identifier (e.g., PROJ-123), or slug (provide exactly one parent)", type: "string" }, initiativeId: { description: "Initiative name, ID, identifier (e.g., INIT-123), or slug (provide exactly one parent)", type: "string" }, documentId: { description: "Document ID or slug (provide exactly one parent)", type: "string" }, milestoneId: { description: "Milestone UUID (provide exactly one parent). Resolve milestone names via `list_milestones` first.", type: "string" }, statusUpdateId: { description: "Status update UUID (provide exactly one parent). Resolve status updates via `get_status_updates` first.", type: "string" }, statusUpdateType: { description: "Type of status update named by `statusUpdateId`, as returned by `get_status_updates`. Only valid together with `statusUpdateId`; omit to check both project and initiative status updates.", type: "string", enum: ["project", "initiative"] }, parentId: { description: "Parent comment ID (for replies, only when creating)", type: "string" }, body: { type: "string", description: "Content as Markdown. Do not escape the string \u2014 use literal newlines and special characters, not escape sequences. To mention a user, use @displayName (e.g., @johndoe)" } }, required: ["body"], additionalProperties: false }, annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } }, { name: "delete_comment", title: "Delete comment", description: "Delete a Linear comment. Inline description comments (those with non-null `quotedText`) anchor a mark in the editor, so their root cannot be deleted \u2014 delete the replies individually or resolve the thread instead.", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { type: "string", description: "Comment ID" } }, required: ["id"], additionalProperties: false }, annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } }, { name: "list_cycles", title: "List cycles", description: "Retrieve cycles for a specific Linear team", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { teamId: { type: "string", description: "Team ID" }, type: { description: "Filter: current, previous, next, or all", type: "string", enum: ["current", "previous", "next"] } }, required: ["teamId"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "get_document", title: "Get document", description: "Retrieve a Linear document by ID or slug", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { type: "string", description: "Document ID or slug" } }, required: ["id"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "list_documents", title: "List documents", description: "List documents in the user's Linear workspace", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 250)", type: "number", maximum: 250 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, query: { description: "Search query", type: "string" }, projectId: { description: "Filter by project ID", type: "string" }, initiativeId: { description: "Filter by initiative ID", type: "string" }, teamId: { description: "Filter by team ID", type: "string" }, creatorId: { description: "Filter by creator ID", type: "string" }, createdAt: { description: "Created after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, updatedAt: { description: "Updated after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, includeArchived: { default: false, description: "Include archived items", type: "boolean" }, fields: { description: "Fields to include in each result. `id` is always included. Omit or pass an empty array for the default response.", type: "array", items: { type: "string", enum: ["id", "title", "content", "url", "createdAt", "updatedAt", "archivedAt", "creator", "updatedBy", "project", "initiative", "team", "issue"] } } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "save_document", title: "Save document", description: "Create or update a Linear document. If `id` is provided, updates the existing document; otherwise creates a new one. When creating, `title` is required and exactly one parent (`project`, `issue`, `initiative`, `cycle`, or `team`) must be specified. On update, passing a parent reparents the document. To change parts of the content without resending all of it, pass `patch` instead of `content`.", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { description: "Document ID or slug to update. Omit to create a new document.", type: "string" }, title: { description: "Document title (required when creating)", type: "string" }, content: { description: "Content as Markdown. Do not escape the string \u2014 use literal newlines and special characters, not escape sequences. To mention a user, use @displayName (e.g., @johndoe)", type: "string" }, patch: { description: "Partial edits applied to the current content, in order and atomically (one failing operation aborts the whole save). Every anchor string must match the current content exactly once. Only valid on update, in place of the full content/description field", minItems: 1, maxItems: 50, type: "array", items: { oneOf: [{ type: "object", properties: { op: { type: "string", const: "replace" }, old_string: { type: "string", minLength: 1, description: "Exact text to replace. Must match the current content exactly once" }, new_string: { type: "string", description: "Replacement text. Empty string deletes the match" }, replace_all: { description: "Replace every occurrence instead of requiring a unique match", type: "boolean" } }, required: ["op", "old_string", "new_string"] }, { type: "object", properties: { op: { type: "string", const: "insert_before" }, anchor: { type: "string", minLength: 1, description: "Exact text to insert before. Must match the current content exactly once" }, text: { type: "string", minLength: 1, description: 'Text to insert directly before the anchor. Include separators (e.g. "\\n\\n")' } }, required: ["op", "anchor", "text"] }, { type: "object", properties: { op: { type: "string", const: "insert_after" }, anchor: { type: "string", minLength: 1, description: "Exact text to insert after. Must match the current content exactly once" }, text: { type: "string", minLength: 1, description: 'Text to insert directly after the anchor. Include separators (e.g. "\\n\\n")' } }, required: ["op", "anchor", "text"] }, { type: "object", properties: { op: { type: "string", const: "prepend" }, text: { type: "string", minLength: 1, description: "Text to insert at the very start of the content" } }, required: ["op", "text"] }, { type: "object", properties: { op: { type: "string", const: "append" }, text: { type: "string", minLength: 1, description: "Text to insert at the very end of the content" } }, required: ["op", "text"] }, { type: "object", properties: { op: { type: "string", const: "replace_range" }, from: { type: "string", minLength: 1, description: "Exact text where the range starts (inclusive). Must match exactly once" }, to: { type: "string", minLength: 1, description: "Exact text where the range ends (exclusive, stays in place). Must match exactly once after `from`" }, new_string: { type: "string", description: "Text replacing the range. Empty string deletes it" } }, required: ["op", "from", "to", "new_string"] }] } }, project: { description: "Project name, ID, identifier (e.g., PROJ-123), or slug", type: "string" }, issue: { description: "Issue ID or identifier (e.g., LIN-123)", type: "string" }, initiative: { description: "Initiative name, ID, identifier (e.g., INIT-123), or slug", type: "string" }, cycle: { description: "Cycle name, number, or ID. When passing a name or number, also pass `team` to disambiguate.", type: "string" }, team: { description: "Team name or ID. Attaches the document to the team, unless `cycle` is also passed, in which case it disambiguates the cycle.", type: "string" }, icon: { description: 'Icon name or emoji code (e.g. "Rocket" or ":eagle:"), not a raw Unicode emoji', type: "string" }, color: { description: "Hex color", type: "string" } }, additionalProperties: false }, annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } }, { name: "get_issue", title: "Get issue", description: "Retrieve detailed information about an issue by ID, including attachments, git branch name, and active Triage Intelligence suggestions when the issue is in triage", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { type: "string", description: "Issue ID or identifier (e.g., LIN-123)" }, includeRelations: { default: false, description: "Include blocking/related/duplicate relations", type: "boolean" }, includeCustomerNeeds: { default: false, description: "Include associated customer needs", type: "boolean" }, includeReleases: { default: false, description: "Include associated releases", type: "boolean" } }, required: ["id"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "list_issues", title: "List issues", description: `List issues in the user's Linear workspace, including active Triage Intelligence suggestions for issues in triage. For my issues, use "me" as the assignee. Use "null" for no assignee.`, inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 250)", type: "number", maximum: 250 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, query: { description: "Search issue title or description", type: "string" }, team: { description: "Team name or ID", type: "string" }, state: { description: "State type, name, or ID", type: "string" }, cycle: { description: "Cycle name, number, or ID", type: "string" }, label: { description: "Label name or ID", type: "string" }, assignee: { description: 'User ID, name, email, or "me"', anyOf: [{ type: "string" }, { type: "null" }] }, delegate: { description: 'Agent name or ID. When the user asks to delegate to "Linear" or "the Linear agent", this refers to the "Linear" app user specifically', type: "string" }, project: { description: "Project name, ID, identifier (e.g., PROJ-123), or slug", type: "string" }, release: { description: "Release ID or slug", type: "string" }, priority: { description: "0=None, 1=Urgent, 2=High, 3=Medium, 4=Low", type: "number" }, parentId: { description: "Parent issue ID or identifier (e.g., LIN-123)", type: "string" }, fields: { description: "Fields to include in each result. `id` is always included. Omit or pass an empty array for the default response.", type: "array", items: { type: "string", enum: ["id", "title", "description", "projectMilestone", "priority", "estimate", "url", "gitBranchName", "createdAt", "updatedAt", "archivedAt", "completedAt", "startedAt", "canceledAt", "dueDate", "slaStartedAt", "slaMediumRiskAt", "slaHighRiskAt", "slaBreachesAt", "slaType", "status", "statusType", "labels", "triageIntel", "createdBy", "createdById", "assignee", "assigneeId", "delegate", "delegateId", "project", "projectId", "parentId", "team", "teamId", "cycleId"] } }, createdAt: { description: "Created after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, updatedAt: { description: "Updated after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, includeArchived: { default: true, description: "Include archived items", type: "boolean" } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "save_issue", title: "Save issue", description: 'Create or update a Linear issue. If `id` is provided, updates the existing issue; otherwise creates a new one. When creating, `title` and `team` are required. Note: use `assignee` (not `assigneeId`) to set the assignee \u2014 it accepts a user ID, name, email, or "me".', inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { description: "Only for updating an existing issue. Pass the issue ID or identifier (e.g., LIN-123). Do NOT pass this parameter when creating a new issue.", type: "string" }, title: { description: "Issue title (required when creating)", type: "string" }, description: { description: "Content as Markdown. Do not escape the string \u2014 use literal newlines and special characters, not escape sequences. To mention a user, use @displayName (e.g., @johndoe)", type: "string" }, patch: { description: "Partial edits applied to the current content, in order and atomically (one failing operation aborts the whole save). Every anchor string must match the current content exactly once. Only valid on update, in place of the full content/description field", minItems: 1, maxItems: 50, type: "array", items: { oneOf: [{ type: "object", properties: { op: { type: "string", const: "replace" }, old_string: { type: "string", minLength: 1, description: "Exact text to replace. Must match the current content exactly once" }, new_string: { type: "string", description: "Replacement text. Empty string deletes the match" }, replace_all: { description: "Replace every occurrence instead of requiring a unique match", type: "boolean" } }, required: ["op", "old_string", "new_string"] }, { type: "object", properties: { op: { type: "string", const: "insert_before" }, anchor: { type: "string", minLength: 1, description: "Exact text to insert before. Must match the current content exactly once" }, text: { type: "string", minLength: 1, description: 'Text to insert directly before the anchor. Include separators (e.g. "\\n\\n")' } }, required: ["op", "anchor", "text"] }, { type: "object", properties: { op: { type: "string", const: "insert_after" }, anchor: { type: "string", minLength: 1, description: "Exact text to insert after. Must match the current content exactly once" }, text: { type: "string", minLength: 1, description: 'Text to insert directly after the anchor. Include separators (e.g. "\\n\\n")' } }, required: ["op", "anchor", "text"] }, { type: "object", properties: { op: { type: "string", const: "prepend" }, text: { type: "string", minLength: 1, description: "Text to insert at the very start of the content" } }, required: ["op", "text"] }, { type: "object", properties: { op: { type: "string", const: "append" }, text: { type: "string", minLength: 1, description: "Text to insert at the very end of the content" } }, required: ["op", "text"] }, { type: "object", properties: { op: { type: "string", const: "replace_range" }, from: { type: "string", minLength: 1, description: "Exact text where the range starts (inclusive). Must match exactly once" }, to: { type: "string", minLength: 1, description: "Exact text where the range ends (exclusive, stays in place). Must match exactly once after `from`" }, new_string: { type: "string", description: "Text replacing the range. Empty string deletes it" } }, required: ["op", "from", "to", "new_string"] }] } }, team: { description: "Team name or ID (required when creating)", type: "string" }, cycle: { description: "Cycle name, number, or ID. Null to remove", anyOf: [{ type: "string" }, { type: "null" }] }, milestone: { description: "Milestone name or ID", type: "string" }, priority: { description: "0=None, 1=Urgent, 2=High, 3=Medium, 4=Low", type: "number" }, project: { description: "Project name, ID, identifier (e.g., PROJ-123), or slug. Null to remove", anyOf: [{ type: "string" }, { type: "null" }] }, state: { description: "State type, name, or ID", type: "string" }, assignee: { description: 'User ID, name, email, or "me". Null to remove', anyOf: [{ type: "string" }, { type: "null" }] }, delegate: { description: 'Agent name or ID. When the user asks to delegate to "Linear" or "the Linear agent", this refers to the "Linear" app user specifically. Null to remove', anyOf: [{ type: "string" }, { type: "null" }] }, labels: { description: 'Label names or IDs as a JSON array of strings (e.g. ["Bug", "Urgent"]). Replaces the full label set; existing labels not included are removed. Omit to leave labels unchanged', type: "array", items: { type: "string" } }, dueDate: { description: "Due date (ISO format). On update, pass null to remove the due date", anyOf: [{ type: "string" }, { type: "null" }] }, slaBreachesAt: { description: "ISO-8601 timestamp when the SLA will breach. On update, pass null to remove the SLA", anyOf: [{ type: "string", format: "date-time", pattern: "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, { type: "null" }] }, slaType: { description: 'SLA day counting type: "all" or "onlyBusinessDays". Only use with slaBreachesAt; null means unset', anyOf: [{ type: "string", enum: ["all", "onlyBusinessDays"] }, { type: "null" }] }, parentId: { description: "Parent issue ID or identifier (e.g., LIN-123). Null to remove", anyOf: [{ type: "string" }, { type: "null" }] }, estimate: { description: "Issue estimate value. On create, pass null or omit for no estimate. On update, pass null to clear the estimate; omitting leaves it unchanged. 0 is a real estimate only on teams that allow zero estimates.", anyOf: [{ type: "number" }, { type: "null" }] }, links: { description: "Link attachments to add [{url, title}]. Append-only; existing links are never removed", type: "array", items: { type: "object", properties: { url: { type: "string", format: "uri" }, title: { type: "string", minLength: 1 } }, required: ["url", "title"] } }, setReleases: { description: "Replace all releases on the issue with these. Cannot be combined with addReleases/removeReleases", type: "array", items: { type: "string" } }, addReleases: { description: "Release IDs or slugs to add. Append-only; existing releases are never removed", type: "array", items: { type: "string" } }, removeReleases: { description: "Release IDs or slugs to remove. Only valid when updating an existing issue", type: "array", items: { type: "string" } }, blocks: { description: "Issue IDs/identifiers this blocks. Append-only; existing relations are never removed", type: "array", items: { type: "string" } }, blockedBy: { description: "Issue IDs/identifiers blocking this. Append-only; existing relations are never removed", type: "array", items: { type: "string" } }, relatedTo: { description: "Related issue IDs/identifiers. Append-only; existing relations are never removed", type: "array", items: { type: "string" } }, duplicateOf: { description: "Duplicate of issue ID/identifier. Null to remove", anyOf: [{ type: "string" }, { type: "null" }] }, removeBlocks: { description: "Issue IDs/identifiers to stop blocking", type: "array", items: { type: "string" } }, removeBlockedBy: { description: "Issue IDs/identifiers to remove as blockers of this issue", type: "array", items: { type: "string" } }, removeRelatedTo: { description: "Related issue IDs/identifiers to remove", type: "array", items: { type: "string" } } }, additionalProperties: false }, annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } }, { name: "list_issue_statuses", title: "List issue statuses", description: "List available issue statuses in a Linear team", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { team: { type: "string", description: "Team name or ID" } }, required: ["team"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "get_issue_status", title: "Get issue status", description: "Retrieve detailed information about an issue status in Linear by name or ID", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { type: "string", description: "Status ID" }, name: { type: "string", description: "Status name" }, team: { type: "string", description: "Team name or ID" } }, required: ["id", "name", "team"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "list_issue_labels", title: "List issue labels", description: "List available issue labels in a Linear workspace or team", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 250)", type: "number", maximum: 250 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, name: { description: "Filter by name", type: "string" }, team: { description: "Team name or ID", type: "string" } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "create_issue_label", title: "Create issue label", description: "Create a new Linear issue label", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { name: { type: "string", description: "Label name" }, description: { description: "Label description", type: "string" }, color: { description: "Hex color code", type: "string" }, teamId: { description: "Team UUID (omit for workspace label)", type: "string" }, parent: { description: "Parent label group name", type: "string" }, isGroup: { default: false, description: "Is label group (not directly applicable)", type: "boolean" } }, required: ["name"], additionalProperties: false }, annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false } }, { name: "list_projects", title: "List projects", description: "List projects in the user's Linear workspace", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 50)", type: "number", maximum: 50 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, query: { description: "Search project name", type: "string" }, state: { description: "State type, name, or ID", type: "string" }, initiative: { description: "Initiative name, ID, identifier (e.g., INIT-123), or slug", type: "string" }, team: { description: "Team name or ID", type: "string" }, member: { description: 'User ID, name, email, or "me"', type: "string" }, label: { description: "Label name or ID", type: "string" }, createdAt: { description: "Created after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, updatedAt: { description: "Updated after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, includeMilestones: { default: false, description: "Include milestones", type: "boolean" }, includeMembers: { default: false, description: "Include project members", type: "boolean" }, includeArchived: { default: false, description: "Include archived items", type: "boolean" }, fields: { description: "Fields to include in each result. `id` is always included. Omit or pass an empty array for the default response.", type: "array", items: { type: "string", enum: ["id", "name", "summary", "description", "url", "trashed", "createdAt", "updatedAt", "startedAt", "completedAt", "canceledAt", "startDate", "startDateResolution", "targetDate", "targetDateResolution", "priority", "labels", "initiatives", "lead", "status", "teams", "members", "milestones"] } } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "get_project", title: "Get project", description: "Retrieve details of a specific project in Linear", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { query: { type: "string", description: "Project name, ID, identifier (e.g., PROJ-123), or slug" }, includeMilestones: { default: false, description: "Include milestones", type: "boolean" }, includeMembers: { default: false, description: "Include project members", type: "boolean" }, includeResources: { default: false, description: "Include resources (documents, links, attachments)", type: "boolean" } }, required: ["query"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "save_project", title: "Save project", description: "Create or update a Linear project. If `id` is provided, updates the existing project; otherwise creates a new one. When creating, `name` and at least one team (via `addTeams` or `setTeams`) are required. To change parts of the description without resending all of it, pass `patch` instead of `description`.", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { id: { description: "Project name, ID, identifier (e.g., PROJ-123), or slug. If provided, updates the existing project", type: "string" }, name: { description: "Project name (required when creating)", type: "string" }, icon: { description: 'Icon name or emoji code (e.g. "Rocket" or ":eagle:"), not a raw Unicode emoji', type: "string" }, color: { description: "Hex color", type: "string" }, summary: { description: "Short summary (max 255 chars)", type: "string" }, description: { description: "Content as Markdown. Do not escape the string \u2014 use literal newlines and special characters, not escape sequences. To mention a user, use @displayName (e.g., @johndoe)", type: "string" }, patch: { description: "Partial edits applied to the current content, in order and atomically (one failing operation aborts the whole save). Every anchor string must match the current content exactly once. Only valid on update, in place of the full content/description field", minItems: 1, maxItems: 50, type: "array", items: { oneOf: [{ type: "object", properties: { op: { type: "string", const: "replace" }, old_string: { type: "string", minLength: 1, description: "Exact text to replace. Must match the current content exactly once" }, new_string: { type: "string", description: "Replacement text. Empty string deletes the match" }, replace_all: { description: "Replace every occurrence instead of requiring a unique match", type: "boolean" } }, required: ["op", "old_string", "new_string"] }, { type: "object", properties: { op: { type: "string", const: "insert_before" }, anchor: { type: "string", minLength: 1, description: "Exact text to insert before. Must match the current content exactly once" }, text: { type: "string", minLength: 1, description: 'Text to insert directly before the anchor. Include separators (e.g. "\\n\\n")' } }, required: ["op", "anchor", "text"] }, { type: "object", properties: { op: { type: "string", const: "insert_after" }, anchor: { type: "string", minLength: 1, description: "Exact text to insert after. Must match the current content exactly once" }, text: { type: "string", minLength: 1, description: 'Text to insert directly after the anchor. Include separators (e.g. "\\n\\n")' } }, required: ["op", "anchor", "text"] }, { type: "object", properties: { op: { type: "string", const: "prepend" }, text: { type: "string", minLength: 1, description: "Text to insert at the very start of the content" } }, required: ["op", "text"] }, { type: "object", properties: { op: { type: "string", const: "append" }, text: { type: "string", minLength: 1, description: "Text to insert at the very end of the content" } }, required: ["op", "text"] }, { type: "object", properties: { op: { type: "string", const: "replace_range" }, from: { type: "string", minLength: 1, description: "Exact text where the range starts (inclusive). Must match exactly once" }, to: { type: "string", minLength: 1, description: "Exact text where the range ends (exclusive, stays in place). Must match exactly once after `from`" }, new_string: { type: "string", description: "Text replacing the range. Empty string deletes it" } }, required: ["op", "from", "to", "new_string"] }] } }, state: { description: "Project state", type: "string" }, startDate: { description: "Start date (ISO format). Pair with startDateResolution to indicate precision (e.g. month, quarter)", type: "string" }, startDateResolution: { description: "Start date resolution", type: "string", enum: ["halfYear", "month", "quarter", "year"] }, targetDate: { description: "Target date (ISO format). Pair with targetDateResolution to indicate precision (e.g. month, quarter)", type: "string" }, targetDateResolution: { description: "Target date resolution", type: "string", enum: ["halfYear", "month", "quarter", "year"] }, priority: { description: "0=None, 1=Urgent, 2=High, 3=Medium, 4=Low", type: "integer", minimum: 0, maximum: 4 }, addTeams: { description: "Team name or ID to add", type: "array", items: { type: "string" } }, removeTeams: { description: "Team name or ID to remove", type: "array", items: { type: "string" } }, setTeams: { description: "Replace all teams with these. Cannot combine with addTeams/removeTeams", type: "array", items: { type: "string" } }, labels: { description: 'Label names or IDs as a JSON array of strings (e.g. ["Bug", "Urgent"]). Replaces the full label set; existing labels not included are removed. Omit to leave labels unchanged', type: "array", items: { type: "string" } }, lead: { description: 'User ID, name, email, or "me". Null to remove', anyOf: [{ type: "string" }, { type: "null" }] }, addInitiatives: { description: "Initiatives to add. Initiative name, ID, identifier (e.g., INIT-123), or slug", type: "array", items: { type: "string" } }, removeInitiatives: { description: "Initiatives to remove. Initiative name, ID, identifier (e.g., INIT-123), or slug", type: "array", items: { type: "string" } }, setInitiatives: { description: "Replace all initiatives with these. Initiative name, ID, identifier (e.g., INIT-123), or slug. Cannot combine with addInitiatives/removeInitiatives", type: "array", items: { type: "string" } }, links: { description: "External resource links to add [{url, title}]. Append-only; existing links are never removed", type: "array", items: { type: "object", properties: { url: { type: "string", format: "uri" }, title: { type: "string", minLength: 1 } }, required: ["url", "title"] } } }, additionalProperties: false }, annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } }, { name: "list_teams", title: "List teams", description: "List teams in the user's Linear workspace", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 250)", type: "number", maximum: 250 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, query: { description: "Search query", type: "string" }, includeArchived: { default: false, description: "Include archived items", type: "boolean" }, createdAt: { description: "Created after: ISO-8601 date/duration (e.g., -P1D)", type: "string" }, updatedAt: { description: "Updated after: ISO-8601 date/duration (e.g., -P1D)", type: "string" } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "get_team", title: "Get team", description: "Retrieve details of a specific Linear team", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { query: { type: "string", description: "Team UUID, key, or name" } }, required: ["query"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "list_users", title: "List users", description: "Retrieve users in the Linear workspace", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { limit: { default: 50, description: "Max results (default 50, max 250)", type: "number", maximum: 250 }, cursor: { description: "Next page cursor", type: "string" }, orderBy: { default: "updatedAt", description: "Sort: createdAt | updatedAt", type: "string", enum: ["createdAt", "updatedAt"] }, query: { description: "Filter by name or email", type: "string" }, team: { description: "Team name or ID", type: "string" } }, additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "get_user", title: "Get user", description: "Retrieve details of a specific Linear user", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { query: { type: "string", description: 'User ID, name, email, or "me"' } }, required: ["query"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }, { name: "search_documentation", title: "Search documentation", description: "Search Linear's documentation to learn about features and usage", inputSchema: { type: "object", $schema: "https://json-schema.org/draft/2020-12/schema", properties: { query: { type: "string", description: "Search query" }, page: { default: 0, description: "Page number", type: "number" } }, required: ["query"], additionalProperties: false }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } }] } };
2759
2820
 
2760
2821
  // ../packages/twin-linear/dist/src/identity.js
2761
2822
  function actorFromSession(session) {
@@ -0,0 +1,5 @@
1
+ export { UnsupportedTwinError, bootTwin } from './chunk-E33L264J.js';
2
+ export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-N4FVASOY.js';
3
+ import './chunk-OW7VVW6X.js';
4
+ import './chunk-VBATFCWR.js';
5
+ import './chunk-SG6ZTIMT.js';
@@ -1,5 +1,5 @@
1
- import { bootTwin } from './chunk-XGTPMFIH.js';
2
- import { isTwinName, TWIN_NAMES, defaultPortFor, TWIN_REGISTRY } from './chunk-ZC42N2J7.js';
1
+ import { bootTwin } from './chunk-E33L264J.js';
2
+ import { isTwinName, TWIN_NAMES, defaultPortFor, TWIN_REGISTRY } from './chunk-N4FVASOY.js';
3
3
  import './chunk-OW7VVW6X.js';
4
4
  import './chunk-VBATFCWR.js';
5
5
  import './chunk-SG6ZTIMT.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pome-sh/cli",
3
- "version": "0.23.19",
3
+ "version": "0.23.21",
4
4
  "description": "Digital-twin testing for AI agents \u2014 run tasks against resettable local or hosted twins and record tool-call traces for evaluation on pome.sh.",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,5 +0,0 @@
1
- export { UnsupportedTwinError, bootTwin } from './chunk-XGTPMFIH.js';
2
- export { STRIPE_LOCAL_ACCOUNT_ID } from './chunk-ZC42N2J7.js';
3
- import './chunk-OW7VVW6X.js';
4
- import './chunk-VBATFCWR.js';
5
- import './chunk-SG6ZTIMT.js';