common-qa-mcp 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,7 +38,7 @@ export class RemoteMcpAdapter {
38
38
  async client() {
39
39
  if (!this.clientPromise) {
40
40
  this.clientPromise = (async () => {
41
- const client = new Client({ name: 'common-qa-mcp', version: '0.4.1' });
41
+ const client = new Client({ name: 'common-qa-mcp', version: '0.5.0' });
42
42
  // The `as Transport` cast bridges exactOptionalPropertyTypes: StreamableHTTPClientTransport
43
43
  // implements Transport, but the SDK's own .d.ts (built without EOPT) leaves its optional
44
44
  // callbacks (onclose?/onerror?/onmessage?) without `| undefined`, which this project's EOPT
@@ -22,6 +22,7 @@ export declare class SimplifyQaAdapter {
22
22
  private readonly http;
23
23
  private agentHop;
24
24
  private formulaCache;
25
+ private backlogDefaultsCache;
25
26
  constructor(cfg: ConnectedQaConfig, transport?: SimplifyQaTransport);
26
27
  private headers;
27
28
  private requireProjectId;
@@ -89,6 +90,23 @@ export declare class SimplifyQaAdapter {
89
90
  listDefects(q: DefectQuery): Promise<ListResult<DefectSummary>>;
90
91
  /** `POST /pm/task/search` — same searchFields protocol as defect/userstory search. */
91
92
  listTasks(q: TaskQuery): Promise<ListResult<TaskSummary>>;
93
+ /** Fetch the project's default `state` and `priority` for a backlog entity.
94
+ * parentId: 1 = Epic, 2 = Feature, 3 = User Story. Two-source resolution, in order:
95
+ *
96
+ * 1. `/pm/fields/:parentId?fieldType=defaultFld` — pick the field value marked `isDefault: true`;
97
+ * fall back to the first non-archived value (seed ships with `isDefault: false` everywhere
98
+ * until a customer configures one).
99
+ * 2. If either state or priority is still missing, hit the entity's `/search` endpoint for one
100
+ * existing row in the project and steal its state / priority. Real data is a more reliable
101
+ * signal than the fields config, which is customer-scoped for Epic/Feature (parentIds 1/2)
102
+ * and can be missing entirely on customers that pre-date the seeding step.
103
+ *
104
+ * Returns the value's `.key` (uppercase enum like `PROPOSED`, `MEDIUM`) — that is what the entity
105
+ * row stores; the field metadata declares `keyname: "key"` / `type: "KEY"` and the SQA UI binding
106
+ * (see epic-form.component.html: `keyname="key" type="KEY" [displayKeys]="{'field':'value'}"`) confirms
107
+ * key is stored, `.value` is only for display. Both sources are wrapped in try/catch: a transient
108
+ * upstream error must not block create; the backend surfaces its own error if invalid. */
109
+ private getBacklogDefaults;
92
110
  createStory(input: StoryInput): Promise<SavedRef>;
93
111
  updateStory(id: string, patch: StoryUpdate): Promise<SavedRef>;
94
112
  listEpics(q: EpicQuery): Promise<ListResult<EpicSummary>>;
@@ -411,21 +429,30 @@ export declare class SimplifyQaAdapter {
411
429
  startRun(target: RunTarget, opts: RunOptions): Promise<RunRef>;
412
430
  stopRun(runId: string): Promise<void>;
413
431
  listCloudRunners(): Promise<CloudRunner[]>;
432
+ /** Gather every identifier this process can claim: bare hostname, non-loopback MAC addresses,
433
+ * non-loopback IPs. Cached per-adapter — network interfaces do not change mid-session. */
434
+ private localIdsCache;
435
+ private getLocalIdentifiers;
436
+ /** Does a machineRegistration row belong to the machine this MCP is running on?
437
+ * A single positive match on hostname, MAC, or IP is enough — the local agent registers with
438
+ * ALL of these, but the surviving match on the SQA row depends on OS quirks (Windows writes a
439
+ * padded hostname, macOS writes `foo.local`, IPs shift on Wi-Fi handoff). Any one match is
440
+ * proof enough; we don't try to reconcile the others. */
441
+ private isThisMachine;
414
442
  listLocalAgents(): Promise<LocalAgent[]>;
415
443
  /**
416
- * Pick THE ACTING USER'S OWN active agent — never row [0] of a shared-tenant roster (which
417
- * would silently dispatch a local run to a teammate's box, and the run would sit queued until
418
- * TTL because it lands in a Redis key that no local agent on the caller's machine polls).
444
+ * Pick THE ACTING USER'S OWN agent — never row [0] of a shared-tenant roster (which would
445
+ * silently dispatch a local run to a teammate's box, and the run would sit queued until TTL
446
+ * because it lands in a Redis key that no local agent on the caller's machine polls).
419
447
  *
420
448
  * SQA's `machineRegistration` row carries no owner_user_id column (unlike walnut, which matches
421
- * the JWT `id` claim to `owner_user_id`), so we identify "your" agent by hostname: common-mcp
422
- * runs on the caller's own box in the typical MCP setup, and SQA `machineName` is either the
423
- * bare OS hostname or a bracketed display form (`USER.NAME [ Hostname.local ]`) — both contain
424
- * `os.hostname()`. Filter → active only → hostname substring match → return the single hit.
425
- * Zero/many matches refuse honestly; a silent guess would just repeat the exact bug we're fixing.
449
+ * the JWT `id` claim to `owner_user_id`), so we identify "your" agent by physical identity:
450
+ * hostname, MAC address, or IP — any one match against `os.networkInterfaces()` on the box this
451
+ * MCP is running on. When exactly one row is "this machine", pick it regardless of the DB
452
+ * `active` flag (that flag is stale by design — see listLocalAgents for the executionQueue bug).
426
453
  *
427
- * ponytail: hostname heuristic. Upgrade to owner-user-id match if the backend adds that column
428
- * to machineRegistration (mirror walnut's `resolveLocalAgentCredential` at that point).
454
+ * ponytail: multi-identifier heuristic. Upgrade to owner-user-id match if the backend adds that
455
+ * column to machineRegistration (mirror walnut's `resolveLocalAgentCredential` at that point).
429
456
  */
430
457
  private resolveLocalAgentId;
431
458
  private detectExecutionOS;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/simplifyqa/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/simplifyqa/adapter.ts"],"names":[],"mappings":"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"}
@@ -231,6 +231,9 @@ export class SimplifyQaAdapter {
231
231
  // (from the Promise.all in saveGeneratedIterations) all await the same fetch instead of each firing
232
232
  // their own /tm/syncFormulas/fetch before the cache is populated.
233
233
  this.formulaCache = null;
234
+ // Same rationale for the backlog default state/priority per parentId (1=Epic, 2=Feature, 3=Story).
235
+ // Fields config barely changes mid-session; cache the in-flight promise so parallel creates share it.
236
+ this.backlogDefaultsCache = new Map();
234
237
  // ---------------------------------------------------------------------- Automation resolvers
235
238
  /** POST /tm/action/search → per (technology, name) → row (id + objectRequired + objectTemplate).
236
239
  * Cached per adapter instance: the catalog is customer-wide and rarely changes during a session.
@@ -244,6 +247,9 @@ export class SimplifyQaAdapter {
244
247
  * formulaCache. Populated from `POST /tm/objectTemplate/search` (confirmed endpoint,
245
248
  * api-endpoints.ts `object.search`'s sibling `objectTemplate.search`). */
246
249
  this.objectTemplateCache = null;
250
+ /** Gather every identifier this process can claim: bare hostname, non-loopback MAC addresses,
251
+ * non-loopback IPs. Cached per-adapter — network interfaces do not change mid-session. */
252
+ this.localIdsCache = null;
247
253
  if (!cfg.baseUrl) {
248
254
  throw new Error('SimplifyQaAdapter requires a baseUrl — set QA_BASE_URL or use a JWT with a `url` claim.');
249
255
  }
@@ -738,12 +744,102 @@ export class SimplifyQaAdapter {
738
744
  const rows = pickArray(raw, 'data', 'content', 'tasks');
739
745
  return withTotal(rows.map(toTaskSummary), raw);
740
746
  }
747
+ // ---------------------------------------------------------------------- Backlog defaults
748
+ /** Fetch the project's default `state` and `priority` for a backlog entity.
749
+ * parentId: 1 = Epic, 2 = Feature, 3 = User Story. Two-source resolution, in order:
750
+ *
751
+ * 1. `/pm/fields/:parentId?fieldType=defaultFld` — pick the field value marked `isDefault: true`;
752
+ * fall back to the first non-archived value (seed ships with `isDefault: false` everywhere
753
+ * until a customer configures one).
754
+ * 2. If either state or priority is still missing, hit the entity's `/search` endpoint for one
755
+ * existing row in the project and steal its state / priority. Real data is a more reliable
756
+ * signal than the fields config, which is customer-scoped for Epic/Feature (parentIds 1/2)
757
+ * and can be missing entirely on customers that pre-date the seeding step.
758
+ *
759
+ * Returns the value's `.key` (uppercase enum like `PROPOSED`, `MEDIUM`) — that is what the entity
760
+ * row stores; the field metadata declares `keyname: "key"` / `type: "KEY"` and the SQA UI binding
761
+ * (see epic-form.component.html: `keyname="key" type="KEY" [displayKeys]="{'field':'value'}"`) confirms
762
+ * key is stored, `.value` is only for display. Both sources are wrapped in try/catch: a transient
763
+ * upstream error must not block create; the backend surfaces its own error if invalid. */
764
+ async getBacklogDefaults(parentId) {
765
+ const cached = this.backlogDefaultsCache.get(parentId);
766
+ if (cached)
767
+ return cached;
768
+ const projectId = this.requireProjectId();
769
+ const p = (async () => {
770
+ const out = {};
771
+ // Source 1: /pm/fields config.
772
+ try {
773
+ const raw = await this.http.getJson(`/pm/fields/${parentId}?fieldType=defaultFld&projectId=${projectId}`);
774
+ const fields = Array.isArray(raw) ? raw : pickArray(raw, 'data', 'content', 'fields');
775
+ const pick = (key) => {
776
+ const field = fields.find((f) => f?.key === key);
777
+ const values = Array.isArray(field?.values) ? field.values : [];
778
+ const chosen = values.find((v) => v?.isDefault === true && v?.archive !== true)
779
+ ?? values.find((v) => v?.archive !== true);
780
+ // Entity rows persist the uppercase enum (value.key). value.value is display-only.
781
+ const stored = str(chosen ?? {}, 'key', 'value');
782
+ return stored && stored.length > 0 ? stored : undefined;
783
+ };
784
+ const s = pick('state');
785
+ const pr = pick('priority');
786
+ if (s)
787
+ out.state = s;
788
+ if (pr)
789
+ out.priority = pr;
790
+ }
791
+ catch { /* fall through to Source 2 */ }
792
+ // Source 2: fall back to state/priority from an existing entity of the same kind in this project.
793
+ // Epic has no priority field, so we only need state for parentId=1.
794
+ const needsPriority = parentId !== 1 && !out.priority;
795
+ if (!out.state || needsPriority) {
796
+ try {
797
+ const path = parentId === 1 ? '/pm/epic/search'
798
+ : parentId === 2 ? '/pm/feature/search'
799
+ : '/pm/userstory/search';
800
+ // Story rows carry a scalar `projectId`; Epic/Feature rows carry an array `projectIds`.
801
+ const filters = [
802
+ { column: 'deleted', value: false },
803
+ parentId === 3
804
+ ? { column: 'projectId', value: projectId }
805
+ : { column: 'projectIds', value: projectId },
806
+ ];
807
+ const body = this.searchBody(filters, { startIndex: 0, limit: 1 });
808
+ const raw = await this.http.postJson(path, body);
809
+ const rows = pickArray(raw, 'data', 'content');
810
+ const row = rows[0];
811
+ if (row) {
812
+ if (!out.state) {
813
+ const s = str(row, 'state', 'status');
814
+ if (s)
815
+ out.state = s;
816
+ }
817
+ if (needsPriority) {
818
+ const pr = str(row, 'priority');
819
+ if (pr)
820
+ out.priority = pr;
821
+ }
822
+ }
823
+ }
824
+ catch { /* leave out.state / out.priority absent; caller can override */ }
825
+ }
826
+ return out;
827
+ })();
828
+ this.backlogDefaultsCache.set(parentId, p);
829
+ return p;
830
+ }
741
831
  // ---------------------------------------------------------------------- Stories (write)
742
832
  async createStory(input) {
833
+ const defaults = await this.getBacklogDefaults(3);
834
+ const state = input.state ?? defaults.state;
835
+ const priority = input.priority ?? defaults.priority;
743
836
  const body = {
744
837
  ...input,
745
838
  // SQA userstory expects a singular numeric projectId; fill from the connected project when omitted.
746
839
  projectId: input.projectId ?? this.requireProjectId(),
840
+ ...(state ? { state } : {}),
841
+ ...(priority ? { priority } : {}),
842
+ customFields: input.customFields ?? {},
747
843
  };
748
844
  const raw = await this.http.postJson('/pm/userstory', body);
749
845
  return toSavedRef(raw, true);
@@ -791,9 +887,13 @@ export class SimplifyQaAdapter {
791
887
  return toEpic(doc && typeof doc === 'object' ? doc : {});
792
888
  }
793
889
  async createEpic(input) {
890
+ const defaults = await this.getBacklogDefaults(1);
891
+ const state = input.state ?? defaults.state;
794
892
  const body = {
795
893
  ...input,
796
894
  projectIds: input.projectIds ?? [this.requireProjectId()],
895
+ ...(state ? { state } : {}),
896
+ customFields: input.customFields ?? {},
797
897
  };
798
898
  const raw = await this.http.postJson('/pm/epic', body);
799
899
  return toSavedRef(raw, true);
@@ -855,9 +955,15 @@ export class SimplifyQaAdapter {
855
955
  return toFeature(doc && typeof doc === 'object' ? doc : {});
856
956
  }
857
957
  async createFeature(input) {
958
+ const defaults = await this.getBacklogDefaults(2);
959
+ const state = input.state ?? defaults.state;
960
+ const priority = input.priority ?? defaults.priority;
858
961
  const body = {
859
962
  ...input,
860
963
  projectIds: input.projectIds ?? [this.requireProjectId()],
964
+ ...(state ? { state } : {}),
965
+ ...(priority ? { priority } : {}),
966
+ customFields: input.customFields ?? {},
861
967
  };
862
968
  const raw = await this.http.postJson('/pm/feature', body);
863
969
  return toSavedRef(raw, true);
@@ -2955,6 +3061,46 @@ export class SimplifyQaAdapter {
2955
3061
  };
2956
3062
  });
2957
3063
  }
3064
+ getLocalIdentifiers() {
3065
+ if (this.localIdsCache)
3066
+ return this.localIdsCache;
3067
+ const hostFull = os.hostname().toLowerCase();
3068
+ const hostBare = hostFull.replace(/\.(local|lan|localdomain)$/, '').split('.')[0] ?? hostFull;
3069
+ const macs = new Set();
3070
+ const ips = new Set();
3071
+ const ifaces = os.networkInterfaces();
3072
+ for (const list of Object.values(ifaces)) {
3073
+ if (!list)
3074
+ continue;
3075
+ for (const iface of list) {
3076
+ if (iface.internal)
3077
+ continue;
3078
+ if (iface.mac && iface.mac !== '00:00:00:00:00:00')
3079
+ macs.add(iface.mac.toLowerCase());
3080
+ if (iface.address)
3081
+ ips.add(iface.address);
3082
+ }
3083
+ }
3084
+ this.localIdsCache = { hostBare, macs, ips };
3085
+ return this.localIdsCache;
3086
+ }
3087
+ /** Does a machineRegistration row belong to the machine this MCP is running on?
3088
+ * A single positive match on hostname, MAC, or IP is enough — the local agent registers with
3089
+ * ALL of these, but the surviving match on the SQA row depends on OS quirks (Windows writes a
3090
+ * padded hostname, macOS writes `foo.local`, IPs shift on Wi-Fi handoff). Any one match is
3091
+ * proof enough; we don't try to reconcile the others. */
3092
+ isThisMachine(row, ids = this.getLocalIdentifiers()) {
3093
+ const name = (str(row, 'machineName', 'name', 'host') ?? '').toLowerCase();
3094
+ if (ids.hostBare.length > 0 && name.length > 0 && name.includes(ids.hostBare))
3095
+ return true;
3096
+ const mac = (str(row, 'macAddress') ?? '').toLowerCase();
3097
+ if (mac.length > 0 && ids.macs.has(mac))
3098
+ return true;
3099
+ const ip = str(row, 'ipAddress', 'hostAddress') ?? '';
3100
+ if (ip.length > 0 && ids.ips.has(ip))
3101
+ return true;
3102
+ return false;
3103
+ }
2958
3104
  async listLocalAgents() {
2959
3105
  // ponytail: no projectId filter — machine_registration.projectId is never written by
2960
3106
  // test-management/services/machine_registration.service.js (create only stamps
@@ -2963,50 +3109,43 @@ export class SimplifyQaAdapter {
2963
3109
  const body = this.searchBody([{ column: 'deleted', value: false }], { limit: 1000 });
2964
3110
  const raw = await this.http.postJson('/tm/machineRegistration/search', body);
2965
3111
  const rows = pickArray(raw, 'data', 'content', 'agents', 'machines');
2966
- // ponytail: hostname override, same trick sqa-ui uses at
2967
- // sqa-ui/.../machine-registration.component.ts:169. The DB `active` flag is only
2968
- // written to `true` on first registration (fire-and-forget in executions/services/
2969
- // executionQueue.service.js:49) and back to `false` by a 7s-stale cron. Every other poll
2970
- // is a no-op, so a still-polling agent frequently shows `active:false`. When the row's
2971
- // machineName matches THIS box's hostname, MCP is running on the same machine as the
2972
- // agent — trust that over the stale DB flag. Upgrade path: if the backend adds a live
2973
- // Redis-presence endpoint (ZSCORE SQAAGENTTRACKER), consult that here instead.
2974
- const hostFull = os.hostname().toLowerCase();
2975
- // Bare hostname: strip trailing .local/.lan/.localdomain AND take the first label. Handles
2976
- // both directions of "short vs FQDN" mismatch — the agent may register as `Pratiks-MBP`
2977
- // while os.hostname() returns `pratiks-mbp.local`, or vice-versa.
2978
- const hostBare = hostFull.replace(/\.(local|lan|localdomain)$/, '').split('.')[0] ?? hostFull;
3112
+ // ponytail: mirror sqa-ui/machine-registration.component.ts:169. The DB `active` flag is only
3113
+ // written to `true` on FIRST registration (fire-and-forget in executions/services/
3114
+ // executionQueue.service.js:49) and back to `false` by a 7s-stale cron. Every subsequent poll
3115
+ // is a no-op for the DB — a still-polling agent frequently shows `active:false`. Executions
3116
+ // service is off-limits for the fix, so when the row belongs to THIS machine (any of hostname
3117
+ // / MAC / IP matches), trust that over the stale DB flag.
3118
+ const ids = this.getLocalIdentifiers();
2979
3119
  return rows.map((n) => {
2980
3120
  const id = str(n, 'id', '_id', 'agentId') ?? '';
2981
3121
  const agentName = str(n, 'machineName', 'name', 'host');
2982
3122
  const owner = str(n, 'owner', 'userName', 'createdBy');
2983
3123
  const hostAddr = str(n, 'macAddress', 'hostAddress');
2984
3124
  const dbActive = typeof n?.active === 'boolean' ? n.active : false;
2985
- const nameLc = agentName?.toLowerCase() ?? '';
2986
- const isMyBox = nameLc.length > 0 && hostBare.length > 0 && nameLc.includes(hostBare);
3125
+ const isMyBox = this.isThisMachine(n, ids);
2987
3126
  return {
2988
3127
  id,
2989
3128
  ...(agentName ? { name: agentName } : {}),
2990
3129
  online: dbActive || isMyBox,
3130
+ ...(isMyBox ? { isThisMachine: true } : {}),
2991
3131
  ...(owner ? { owner } : {}),
2992
3132
  ...(hostAddr ? { host: hostAddr } : {}),
2993
3133
  };
2994
3134
  });
2995
3135
  }
2996
3136
  /**
2997
- * Pick THE ACTING USER'S OWN active agent — never row [0] of a shared-tenant roster (which
2998
- * would silently dispatch a local run to a teammate's box, and the run would sit queued until
2999
- * TTL because it lands in a Redis key that no local agent on the caller's machine polls).
3137
+ * Pick THE ACTING USER'S OWN agent — never row [0] of a shared-tenant roster (which would
3138
+ * silently dispatch a local run to a teammate's box, and the run would sit queued until TTL
3139
+ * because it lands in a Redis key that no local agent on the caller's machine polls).
3000
3140
  *
3001
3141
  * SQA's `machineRegistration` row carries no owner_user_id column (unlike walnut, which matches
3002
- * the JWT `id` claim to `owner_user_id`), so we identify "your" agent by hostname: common-mcp
3003
- * runs on the caller's own box in the typical MCP setup, and SQA `machineName` is either the
3004
- * bare OS hostname or a bracketed display form (`USER.NAME [ Hostname.local ]`) — both contain
3005
- * `os.hostname()`. Filter → active only → hostname substring match → return the single hit.
3006
- * Zero/many matches refuse honestly; a silent guess would just repeat the exact bug we're fixing.
3142
+ * the JWT `id` claim to `owner_user_id`), so we identify "your" agent by physical identity:
3143
+ * hostname, MAC address, or IP — any one match against `os.networkInterfaces()` on the box this
3144
+ * MCP is running on. When exactly one row is "this machine", pick it regardless of the DB
3145
+ * `active` flag (that flag is stale by design — see listLocalAgents for the executionQueue bug).
3007
3146
  *
3008
- * ponytail: hostname heuristic. Upgrade to owner-user-id match if the backend adds that column
3009
- * to machineRegistration (mirror walnut's `resolveLocalAgentCredential` at that point).
3147
+ * ponytail: multi-identifier heuristic. Upgrade to owner-user-id match if the backend adds that
3148
+ * column to machineRegistration (mirror walnut's `resolveLocalAgentCredential` at that point).
3010
3149
  */
3011
3150
  async resolveLocalAgentId(preferred) {
3012
3151
  if (preferred && preferred.length > 0)
@@ -3016,24 +3155,25 @@ export class SimplifyQaAdapter {
3016
3155
  throw new Error('startRun (LOCAL): no local agent registered. Register a machine in the SimplifyQA UI ' +
3017
3156
  'first, or pass mode: "cloud" if a cloud runner is provisioned.');
3018
3157
  }
3019
- const active = agents.filter((a) => a.online);
3020
- if (active.length === 0) {
3021
- throw new Error('startRun (LOCAL): no local agent is currently active (polling). Launch your SimplifyQA ' +
3022
- 'desktop agent and retry — or pass `agentId` explicitly if you know the credential id.');
3023
- }
3024
- const hostFull = os.hostname().toLowerCase();
3025
- // Same short-vs-FQDN handling as listLocalAgents — see the ponytail note there.
3026
- const host = hostFull.replace(/\.(local|lan|localdomain)$/, '').split('.')[0] ?? hostFull;
3027
- const mine = active.filter((a) => host.length > 0 && (a.name ?? '').toLowerCase().includes(host));
3158
+ // Priority 1: rows that physically match this machine. Ignore the DB `active` flag — a running
3159
+ // agent frequently shows `active:false` between the 5s stale-cron and the next heartbeat, and
3160
+ // the executions service is off-limits for the real fix.
3161
+ const mine = agents.filter((a) => a.isThisMachine);
3028
3162
  if (mine.length === 1)
3029
3163
  return mine[0].id;
3030
- const listing = (arr) => arr.map((a) => ` - ${a.name ?? a.id} \`${a.id}\``).join('\n');
3031
3164
  if (mine.length > 1) {
3032
- throw new Error(`startRun (LOCAL): multiple active agents match this machine (${host}). Pass \`agentId\` ` +
3033
- `to pick one:\n${listing(mine)}`);
3034
- }
3035
- throw new Error(`startRun (LOCAL): could not auto-pick your local agent — no active agent's name matches ` +
3036
- `this hostname (${host}). Pass \`agentId\` explicitly. Active agents:\n${listing(active)}`);
3165
+ const listing = mine.map((a) => ` - ${a.name ?? a.id} \`${a.id}\``).join('\n');
3166
+ throw new Error(`startRun (LOCAL): multiple agents registered from this machine. Pass \`agentId\` to ` +
3167
+ `pick one:\n${listing}`);
3168
+ }
3169
+ // No physical match — fall back to the old online-only pool (roster shared across teammates).
3170
+ // No physical match for this machine. Refuse to guess — dispatching to a teammate's agent is
3171
+ // the exact silent-misroute bug isThisMachine was written to prevent. Surface the roster so
3172
+ // the caller can pass `agentId` explicitly.
3173
+ const listing = agents.map((a) => ` - ${a.name ?? a.id} \`${a.id}\`${a.online ? '' : ' (offline)'}`).join('\n');
3174
+ throw new Error(`startRun (LOCAL): no agent registered from this machine (hostname / MAC / IP did not match ` +
3175
+ `any row). Launch the SimplifyQA desktop agent on this box, or pass \`agentId\` explicitly. ` +
3176
+ `Registered agents:\n${listing}`);
3037
3177
  }
3038
3178
  detectExecutionOS() {
3039
3179
  if (process.platform === 'win32')