@amistio/cli 0.1.55 → 0.1.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +958 -687
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
5
- import { writeFile as writeFile12 } from "node:fs/promises";
6
- import os9 from "node:os";
7
- import path19 from "node:path";
4
+ import { createHash as createHash9, randomUUID as randomUUID4 } from "node:crypto";
5
+ import { writeFile as writeFile13 } from "node:fs/promises";
6
+ import os10 from "node:os";
7
+ import path20 from "node:path";
8
8
  import { Command } from "commander";
9
9
 
10
10
  // ../shared/src/schemas.ts
11
11
  import { z } from "zod";
12
+ var runnerMaxConcurrentWorkLimit = 8;
12
13
  var isoDateTimeSchema = z.string().datetime({ offset: true });
13
14
  var itemTypeSchema = z.enum([
14
15
  "account",
@@ -948,8 +949,8 @@ var runnerHeartbeatItemSchema = baseItemSchema.extend({
948
949
  supportedExecutionEnvironmentProfiles: z.array(runnerExecutionEnvironmentProfileSchema).optional(),
949
950
  currentExecutionEnvironmentProfile: runnerExecutionEnvironmentProfileSchema.optional(),
950
951
  environmentReadiness: runnerEnvironmentReadinessSchema.optional(),
951
- maxConcurrentWork: z.number().int().min(1).max(4).optional(),
952
- activeClaimLaneIds: z.array(runnerClaimLaneIdSchema).max(4).optional(),
952
+ maxConcurrentWork: z.number().int().min(1).max(runnerMaxConcurrentWorkLimit).optional(),
953
+ activeClaimLaneIds: z.array(runnerClaimLaneIdSchema).max(runnerMaxConcurrentWorkLimit).optional(),
953
954
  currentWorkItemId: z.string().min(1).optional(),
954
955
  currentImplementationScopeId: z.string().min(1).optional(),
955
956
  currentWorktreeKey: z.string().min(1).optional(),
@@ -3302,8 +3303,8 @@ var toolSessionMutationSchema = z3.object({
3302
3303
  });
3303
3304
  function resolveApiUrl(apiUrl, urlPath) {
3304
3305
  const base = apiUrl.endsWith("/") ? apiUrl.slice(0, -1) : apiUrl;
3305
- const path20 = urlPath.startsWith("/") ? urlPath : `/${urlPath}`;
3306
- return new URL(`${base}${path20}`);
3306
+ const path21 = urlPath.startsWith("/") ? urlPath : `/${urlPath}`;
3307
+ return new URL(`${base}${path21}`);
3307
3308
  }
3308
3309
 
3309
3310
  // src/orchestrator.ts
@@ -6258,6 +6259,191 @@ async function checkRunnerWatchGitPreflight(options) {
6258
6259
  return { status: "blocked", exitCode: 1, message, readiness: readiness2 };
6259
6260
  }
6260
6261
 
6262
+ // src/runner-active-claims.ts
6263
+ import { randomUUID as randomUUID3 } from "node:crypto";
6264
+ import { chmod as chmod3, mkdir as mkdir9, readFile as readFile9, rm as rm3, stat as stat4, writeFile as writeFile9 } from "node:fs/promises";
6265
+ import os6 from "node:os";
6266
+ import path11 from "node:path";
6267
+ var activeClaimLockStaleMs = 3e4;
6268
+ var activeClaimLockRetryMs = 20;
6269
+ var activeClaimLockAttempts = 50;
6270
+ var maxStoredActiveClaims = 100;
6271
+ var LocalRunnerActiveClaimStore = class {
6272
+ constructor(filePath = defaultActiveClaimStorePath()) {
6273
+ this.filePath = filePath;
6274
+ }
6275
+ filePath;
6276
+ operation = Promise.resolve();
6277
+ async reserve(input) {
6278
+ return this.withLockedStore(async () => {
6279
+ const now = /* @__PURE__ */ new Date();
6280
+ const data = normalizeActiveClaimFile(await this.read());
6281
+ data.activeClaims = pruneExpiredClaims(data.activeClaims, now.getTime());
6282
+ const conflict = data.activeClaims.find((record2) => activeClaimConflicts(record2, input));
6283
+ if (conflict) {
6284
+ return { status: "blocked", reason: activeClaimConflictReason(conflict, input), existing: conflict };
6285
+ }
6286
+ const record = {
6287
+ ...input,
6288
+ reservationId: `runner_claim_${randomUUID3()}`,
6289
+ processId: process.pid,
6290
+ reservedAt: now.toISOString(),
6291
+ updatedAt: now.toISOString()
6292
+ };
6293
+ data.activeClaims = [...data.activeClaims, record].slice(-maxStoredActiveClaims);
6294
+ await this.write(data);
6295
+ return { status: "reserved", record };
6296
+ });
6297
+ }
6298
+ async release(reservationId) {
6299
+ await this.withLockedStore(async () => {
6300
+ const data = normalizeActiveClaimFile(await this.read());
6301
+ const activeClaims = data.activeClaims.filter((record) => record.reservationId !== reservationId);
6302
+ if (activeClaims.length === data.activeClaims.length) {
6303
+ return;
6304
+ }
6305
+ await this.write({ activeClaims });
6306
+ });
6307
+ }
6308
+ async listActive(now = Date.now()) {
6309
+ return this.withLockedStore(async () => {
6310
+ const data = normalizeActiveClaimFile(await this.read());
6311
+ const activeClaims = pruneExpiredClaims(data.activeClaims, now);
6312
+ if (activeClaims.length !== data.activeClaims.length) {
6313
+ await this.write({ activeClaims });
6314
+ }
6315
+ return activeClaims;
6316
+ });
6317
+ }
6318
+ async withLockedStore(operation) {
6319
+ return this.withProcessLock(async () => {
6320
+ const release = await this.acquireFileLock();
6321
+ try {
6322
+ return await operation();
6323
+ } finally {
6324
+ await release();
6325
+ }
6326
+ });
6327
+ }
6328
+ async withProcessLock(operation) {
6329
+ const previous = this.operation;
6330
+ let releaseProcessLock = () => void 0;
6331
+ this.operation = new Promise((resolve) => {
6332
+ releaseProcessLock = resolve;
6333
+ });
6334
+ await previous.catch(() => void 0);
6335
+ try {
6336
+ return await operation();
6337
+ } finally {
6338
+ releaseProcessLock();
6339
+ }
6340
+ }
6341
+ async acquireFileLock() {
6342
+ const lockPath = `${this.filePath}.lock`;
6343
+ await mkdir9(path11.dirname(this.filePath), { recursive: true });
6344
+ for (let attempt = 0; attempt < activeClaimLockAttempts; attempt += 1) {
6345
+ try {
6346
+ await mkdir9(lockPath);
6347
+ return async () => {
6348
+ await rm3(lockPath, { recursive: true, force: true });
6349
+ };
6350
+ } catch (error) {
6351
+ if (!isNodeErrorCode(error, "EEXIST")) {
6352
+ throw error;
6353
+ }
6354
+ await removeStaleLock(lockPath, Date.now());
6355
+ await delay(activeClaimLockRetryMs);
6356
+ }
6357
+ }
6358
+ throw new Error("Could not acquire local runner active-claim lock.");
6359
+ }
6360
+ async read() {
6361
+ try {
6362
+ return JSON.parse(await readFile9(this.filePath, "utf8"));
6363
+ } catch {
6364
+ return { activeClaims: [] };
6365
+ }
6366
+ }
6367
+ async write(data) {
6368
+ await mkdir9(path11.dirname(this.filePath), { recursive: true });
6369
+ await writeFile9(this.filePath, JSON.stringify(data, null, 2), { encoding: "utf8", mode: 384 });
6370
+ await chmod3(this.filePath, 384);
6371
+ }
6372
+ };
6373
+ var defaultRunnerActiveClaimStore = new LocalRunnerActiveClaimStore();
6374
+ function activeClaimConflictMessage(result) {
6375
+ if (result.reason === "sameLane") {
6376
+ return `Runner lane ${result.existing.claimLaneId} is already working on ${result.existing.workItemId}.`;
6377
+ }
6378
+ if (result.reason === "sameWorktree") {
6379
+ return `Runner worktree ${result.existing.worktreeKey} is already reserved by lane ${result.existing.claimLaneId}.`;
6380
+ }
6381
+ return `Runner work item ${result.existing.workItemId} is already reserved by lane ${result.existing.claimLaneId}.`;
6382
+ }
6383
+ function defaultActiveClaimStorePath() {
6384
+ return path11.join(os6.homedir(), ".config", "amistio", "active-runner-claims.json");
6385
+ }
6386
+ function normalizeActiveClaimFile(value) {
6387
+ if (!value || typeof value !== "object" || !("activeClaims" in value)) {
6388
+ return { activeClaims: [] };
6389
+ }
6390
+ const activeClaims = value.activeClaims;
6391
+ if (!Array.isArray(activeClaims)) {
6392
+ return { activeClaims: [] };
6393
+ }
6394
+ return {
6395
+ activeClaims: activeClaims.filter(isRunnerActiveClaimRecord)
6396
+ };
6397
+ }
6398
+ function isRunnerActiveClaimRecord(value) {
6399
+ if (!value || typeof value !== "object") return false;
6400
+ const record = value;
6401
+ return typeof record.reservationId === "string" && typeof record.accountId === "string" && typeof record.projectId === "string" && typeof record.repositoryLinkId === "string" && typeof record.runnerId === "string" && typeof record.claimLaneId === "string" && typeof record.workItemId === "string" && typeof record.attempt === "number" && typeof record.expiresAt === "string" && typeof record.reservedAt === "string" && typeof record.updatedAt === "string" && typeof record.processId === "number";
6402
+ }
6403
+ function pruneExpiredClaims(records, now) {
6404
+ return records.filter((record) => {
6405
+ const expiresAt = Date.parse(record.expiresAt);
6406
+ return Number.isFinite(expiresAt) && expiresAt > now;
6407
+ });
6408
+ }
6409
+ function activeClaimConflicts(record, input) {
6410
+ if (record.accountId !== input.accountId || record.projectId !== input.projectId || record.repositoryLinkId !== input.repositoryLinkId) {
6411
+ return false;
6412
+ }
6413
+ if (record.runnerId === input.runnerId && record.claimLaneId === input.claimLaneId) {
6414
+ return true;
6415
+ }
6416
+ if (record.workItemId === input.workItemId) {
6417
+ return true;
6418
+ }
6419
+ return Boolean(record.worktreeKey && input.worktreeKey && record.worktreeKey === input.worktreeKey);
6420
+ }
6421
+ function activeClaimConflictReason(record, input) {
6422
+ if (record.runnerId === input.runnerId && record.claimLaneId === input.claimLaneId) {
6423
+ return "sameLane";
6424
+ }
6425
+ if (record.workItemId === input.workItemId) {
6426
+ return "sameWorkItem";
6427
+ }
6428
+ return "sameWorktree";
6429
+ }
6430
+ async function removeStaleLock(lockPath, now) {
6431
+ try {
6432
+ const lockStat = await stat4(lockPath);
6433
+ if (now - lockStat.mtimeMs > activeClaimLockStaleMs) {
6434
+ await rm3(lockPath, { recursive: true, force: true });
6435
+ }
6436
+ } catch {
6437
+ return;
6438
+ }
6439
+ }
6440
+ function isNodeErrorCode(error, code) {
6441
+ return typeof error === "object" && error !== null && error.code === code;
6442
+ }
6443
+ function delay(ms) {
6444
+ return new Promise((resolve) => setTimeout(resolve, ms));
6445
+ }
6446
+
6261
6447
  // src/runner-patch-drift.ts
6262
6448
  var patchDriftPatterns = [
6263
6449
  { signature: "applyPatchVerificationFailed", pattern: /apply_patch\s+verification\s+failed/i },
@@ -6320,9 +6506,9 @@ ${options.detail}`);
6320
6506
  // src/runner-service.ts
6321
6507
  import { spawn as spawn3 } from "node:child_process";
6322
6508
  import { createHash as createHash5 } from "node:crypto";
6323
- import { mkdir as mkdir9, readFile as readFile9, rm as rm3, writeFile as writeFile9 } from "node:fs/promises";
6324
- import os6 from "node:os";
6325
- import path11 from "node:path";
6509
+ import { mkdir as mkdir10, readFile as readFile10, rm as rm4, writeFile as writeFile10 } from "node:fs/promises";
6510
+ import os7 from "node:os";
6511
+ import path12 from "node:path";
6326
6512
  function detectRunnerServicePlatform(platform = process.platform) {
6327
6513
  if (platform === "darwin") return "launchd";
6328
6514
  if (platform === "linux") return "systemd";
@@ -6333,19 +6519,19 @@ function createRunnerServiceDescriptor(input) {
6333
6519
  if (platform === "unsupported") {
6334
6520
  throw new Error("Startup services are supported for user-level launchd on macOS and systemd user services on Linux.");
6335
6521
  }
6336
- const homeDir = input.homeDir ?? os6.homedir();
6522
+ const homeDir = input.homeDir ?? os7.homedir();
6337
6523
  const serviceName = runnerServiceName(input);
6338
6524
  const serviceFilePath = runnerServiceFilePath(platform, serviceName, homeDir);
6339
6525
  const now = (/* @__PURE__ */ new Date()).toISOString();
6340
6526
  const command = [input.executablePath ?? process.execPath, input.scriptPath ?? process.argv[1], ...input.args];
6341
- const logPath = path11.join(input.metadataDir ?? defaultRunnerMetadataDir(), `${runnerServiceKey(input)}.service.log`);
6527
+ const logPath = path12.join(input.metadataDir ?? defaultRunnerMetadataDir(), `${runnerServiceKey(input)}.service.log`);
6342
6528
  const metadata = {
6343
6529
  schemaVersion: 1,
6344
6530
  accountId: input.accountId,
6345
6531
  projectId: input.projectId,
6346
6532
  repositoryLinkId: input.repositoryLinkId,
6347
6533
  runnerId: input.runnerId,
6348
- rootDir: path11.resolve(input.rootDir),
6534
+ rootDir: path12.resolve(input.rootDir),
6349
6535
  apiUrl: input.apiUrl,
6350
6536
  serviceName,
6351
6537
  serviceFilePath,
@@ -6362,9 +6548,9 @@ function createRunnerServiceDescriptor(input) {
6362
6548
  }
6363
6549
  async function installRunnerService(input, options = {}) {
6364
6550
  const descriptor = createRunnerServiceDescriptor(input);
6365
- await mkdir9(path11.dirname(descriptor.metadata.serviceFilePath), { recursive: true });
6366
- await mkdir9(input.metadataDir ?? defaultRunnerMetadataDir(), { recursive: true });
6367
- await writeFile9(descriptor.metadata.serviceFilePath, descriptor.content, { encoding: "utf8", mode: 384 });
6551
+ await mkdir10(path12.dirname(descriptor.metadata.serviceFilePath), { recursive: true });
6552
+ await mkdir10(input.metadataDir ?? defaultRunnerMetadataDir(), { recursive: true });
6553
+ await writeFile10(descriptor.metadata.serviceFilePath, descriptor.content, { encoding: "utf8", mode: 384 });
6368
6554
  await writeRunnerServiceMetadata(descriptor.metadata, input.metadataDir);
6369
6555
  if (options.activate !== false) {
6370
6556
  const activation = await activateRunnerService(descriptor.metadata);
@@ -6380,13 +6566,13 @@ async function removeRunnerService(input) {
6380
6566
  return void 0;
6381
6567
  }
6382
6568
  await deactivateRunnerService(metadata).catch(() => void 0);
6383
- await rm3(metadata.serviceFilePath, { force: true });
6384
- await rm3(runnerServiceMetadataPath(input, input.metadataDir ?? defaultRunnerMetadataDir()), { force: true });
6569
+ await rm4(metadata.serviceFilePath, { force: true });
6570
+ await rm4(runnerServiceMetadataPath(input, input.metadataDir ?? defaultRunnerMetadataDir()), { force: true });
6385
6571
  return { ...metadata, status: "removed", updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
6386
6572
  }
6387
6573
  async function readRunnerServiceMetadata(input, metadataDir = defaultRunnerMetadataDir()) {
6388
6574
  try {
6389
- const parsed = JSON.parse(await readFile9(runnerServiceMetadataPath(input, metadataDir), "utf8"));
6575
+ const parsed = JSON.parse(await readFile10(runnerServiceMetadataPath(input, metadataDir), "utf8"));
6390
6576
  if (parsed.schemaVersion !== 1 || !parsed.serviceName || !parsed.serviceFilePath) {
6391
6577
  return void 0;
6392
6578
  }
@@ -6396,8 +6582,8 @@ async function readRunnerServiceMetadata(input, metadataDir = defaultRunnerMetad
6396
6582
  }
6397
6583
  }
6398
6584
  async function writeRunnerServiceMetadata(metadata, metadataDir = defaultRunnerMetadataDir()) {
6399
- await mkdir9(metadataDir, { recursive: true });
6400
- await writeFile9(runnerServiceMetadataPath(metadata, metadataDir), JSON.stringify(metadata, null, 2), { encoding: "utf8", mode: 384 });
6585
+ await mkdir10(metadataDir, { recursive: true });
6586
+ await writeFile10(runnerServiceMetadataPath(metadata, metadataDir), JSON.stringify(metadata, null, 2), { encoding: "utf8", mode: 384 });
6401
6587
  }
6402
6588
  async function runnerServiceRuntimeStatus(metadata) {
6403
6589
  if (metadata.platform === "launchd") {
@@ -6480,12 +6666,12 @@ WantedBy=default.target
6480
6666
  }
6481
6667
  function runnerServiceFilePath(platform, serviceName, homeDir) {
6482
6668
  if (platform === "launchd") {
6483
- return path11.join(homeDir, "Library", "LaunchAgents", `${serviceName}.plist`);
6669
+ return path12.join(homeDir, "Library", "LaunchAgents", `${serviceName}.plist`);
6484
6670
  }
6485
- return path11.join(homeDir, ".config", "systemd", "user", `${serviceName}.service`);
6671
+ return path12.join(homeDir, ".config", "systemd", "user", `${serviceName}.service`);
6486
6672
  }
6487
6673
  function runnerServiceMetadataPath(input, metadataDir) {
6488
- return path11.join(metadataDir, `${runnerServiceKey(input)}.service.json`);
6674
+ return path12.join(metadataDir, `${runnerServiceKey(input)}.service.json`);
6489
6675
  }
6490
6676
  function runnerServiceName(input) {
6491
6677
  return `com.amistio.runner.${runnerServiceKey(input).slice(0, 20)}`;
@@ -6820,8 +7006,8 @@ function createSmokeSession({ now, status, lastActivityAt }) {
6820
7006
  // src/sync.ts
6821
7007
  import { execFile as execFile3 } from "node:child_process";
6822
7008
  import { createHash as createHash6 } from "node:crypto";
6823
- import { mkdir as mkdir10, readdir as readdir5, readFile as readFile10, stat as stat4, writeFile as writeFile10 } from "node:fs/promises";
6824
- import path12 from "node:path";
7009
+ import { mkdir as mkdir11, readdir as readdir5, readFile as readFile11, stat as stat5, writeFile as writeFile11 } from "node:fs/promises";
7010
+ import path13 from "node:path";
6825
7011
  import { promisify as promisify3 } from "node:util";
6826
7012
  var execFileAsync3 = promisify3(execFile3);
6827
7013
  var legacySyncRoots = ["architecture", "context", "decisions", "features", "memory", "plans", "prompts", "workflows"];
@@ -6917,7 +7103,7 @@ async function readLocalSyncedDocuments(rootDir) {
6917
7103
  const documentFiles = await findBrainDocumentFiles(rootDir);
6918
7104
  const documents = [];
6919
7105
  for (const fullPath of documentFiles) {
6920
- const raw = await readFile10(fullPath, "utf8");
7106
+ const raw = await readFile11(fullPath, "utf8");
6921
7107
  const repoPath = toRepoPath(rootDir, fullPath);
6922
7108
  const parsed = parseSyncedDocument(raw, repoPath);
6923
7109
  if (!parsed) {
@@ -6967,8 +7153,8 @@ async function materializeBrainDocuments(rootDir, documents, options = {}) {
6967
7153
  result.skipped.push(document.repoPath);
6968
7154
  continue;
6969
7155
  }
6970
- await mkdir10(path12.dirname(fullPath), { recursive: true });
6971
- await writeFile10(fullPath, createSyncedDocumentContent(document), "utf8");
7156
+ await mkdir11(path13.dirname(fullPath), { recursive: true });
7157
+ await writeFile11(fullPath, createSyncedDocumentContent(document), "utf8");
6972
7158
  result.written.push(document.repoPath);
6973
7159
  }
6974
7160
  return result;
@@ -7097,7 +7283,7 @@ function parseSyncedHtml(content) {
7097
7283
  }
7098
7284
  async function readExistingSyncedDocument(fullPath) {
7099
7285
  try {
7100
- const raw = await readFile10(fullPath, "utf8");
7286
+ const raw = await readFile11(fullPath, "utf8");
7101
7287
  const parsed = parseSyncedDocument(raw, fullPath);
7102
7288
  if (!parsed) {
7103
7289
  return { exists: true };
@@ -7122,7 +7308,7 @@ async function readExistingSyncedDocument(fullPath) {
7122
7308
  async function findBrainDocumentFiles(rootDir) {
7123
7309
  const files = [];
7124
7310
  for (const syncRoot of [...syncRoots, htmlSyncRoot]) {
7125
- const fullRoot = path12.join(rootDir, syncRoot);
7311
+ const fullRoot = path13.join(rootDir, syncRoot);
7126
7312
  if (!await exists2(fullRoot)) {
7127
7313
  continue;
7128
7314
  }
@@ -7132,7 +7318,7 @@ async function findBrainDocumentFiles(rootDir) {
7132
7318
  }
7133
7319
  async function walkBrainDocumentFiles(directory, files) {
7134
7320
  for (const entry of await readdir5(directory, { withFileTypes: true })) {
7135
- const fullPath = path12.join(directory, entry.name);
7321
+ const fullPath = path13.join(directory, entry.name);
7136
7322
  if (entry.isDirectory()) {
7137
7323
  await walkBrainDocumentFiles(fullPath, files);
7138
7324
  } else if (entry.isFile() && /\.(md|mdx|html?)$/i.test(entry.name)) {
@@ -7141,23 +7327,23 @@ async function walkBrainDocumentFiles(directory, files) {
7141
7327
  }
7142
7328
  }
7143
7329
  function safeRepoPath(rootDir, repoPath) {
7144
- if (path12.isAbsolute(repoPath)) {
7330
+ if (path13.isAbsolute(repoPath)) {
7145
7331
  throw new Error(`Refusing to use absolute repo path: ${repoPath}`);
7146
7332
  }
7147
- const normalized = path12.normalize(repoPath);
7148
- if (normalized === ".." || normalized.startsWith(`..${path12.sep}`)) {
7333
+ const normalized = path13.normalize(repoPath);
7334
+ if (normalized === ".." || normalized.startsWith(`..${path13.sep}`)) {
7149
7335
  throw new Error(`Refusing to use path outside the repository: ${repoPath}`);
7150
7336
  }
7151
- const root = path12.resolve(rootDir);
7152
- const fullPath = path12.resolve(root, normalized);
7153
- if (!fullPath.startsWith(`${root}${path12.sep}`)) {
7337
+ const root = path13.resolve(rootDir);
7338
+ const fullPath = path13.resolve(root, normalized);
7339
+ if (!fullPath.startsWith(`${root}${path13.sep}`)) {
7154
7340
  throw new Error(`Refusing to use path outside the repository: ${repoPath}`);
7155
7341
  }
7156
7342
  return fullPath;
7157
7343
  }
7158
7344
  function isControlPlanePath(repoPath) {
7159
- const normalized = path12.normalize(repoPath);
7160
- return syncRoots.some((syncRoot) => normalized === syncRoot || normalized.startsWith(`${syncRoot}${path12.sep}`)) || normalized === htmlSyncRoot || normalized.startsWith(`${htmlSyncRoot}${path12.sep}`);
7345
+ const normalized = path13.normalize(repoPath);
7346
+ return syncRoots.some((syncRoot) => normalized === syncRoot || normalized.startsWith(`${syncRoot}${path13.sep}`)) || normalized === htmlSyncRoot || normalized.startsWith(`${htmlSyncRoot}${path13.sep}`);
7161
7347
  }
7162
7348
  function canonicalControlPlaneRepoPath(repoPath) {
7163
7349
  const normalized = repoPath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/+/, "");
@@ -7168,16 +7354,16 @@ function canonicalControlPlaneRepoPath(repoPath) {
7168
7354
  return normalized;
7169
7355
  }
7170
7356
  function toRepoPath(rootDir, fullPath) {
7171
- return path12.relative(rootDir, fullPath).split(path12.sep).join("/");
7357
+ return path13.relative(rootDir, fullPath).split(path13.sep).join("/");
7172
7358
  }
7173
7359
  function inferTitle(content, repoPath) {
7174
7360
  const heading = content.split("\n").find((line) => line.startsWith("# "))?.replace(/^#\s+/, "").trim();
7175
7361
  if (heading) return heading;
7176
7362
  const htmlHeading = content.match(/<h1\b[^>]*>([\s\S]*?)<\/h1>/i)?.[1]?.replace(/<[^>]+>/g, "").trim();
7177
- return htmlHeading || path12.basename(repoPath, path12.extname(repoPath));
7363
+ return htmlHeading || path13.basename(repoPath, path13.extname(repoPath));
7178
7364
  }
7179
7365
  async function collectExternalBrainDocumentsForPush(rootDir, metadata, existingDocuments, options) {
7180
- const root = path12.resolve(rootDir);
7366
+ const root = path13.resolve(rootDir);
7181
7367
  const maxBytes = (options.maxFileKb ?? defaultAutoSyncMaxFileKb) * 1024;
7182
7368
  const syncedAt = options.syncedAt ?? (/* @__PURE__ */ new Date()).toISOString();
7183
7369
  const existingById = new Map(existingDocuments.map((document) => [document.documentId, document]));
@@ -7193,7 +7379,7 @@ async function collectExternalBrainDocumentsForPush(rootDir, metadata, existingD
7193
7379
  continue;
7194
7380
  }
7195
7381
  const fullPath = safeRepoPath(root, normalizedRepoPath);
7196
- const fileStat = await stat4(fullPath).catch(() => void 0);
7382
+ const fileStat = await stat5(fullPath).catch(() => void 0);
7197
7383
  if (!fileStat?.isFile()) {
7198
7384
  skipped.push({ repoPath: normalizedRepoPath, reason: "unreadable" });
7199
7385
  continue;
@@ -7202,7 +7388,7 @@ async function collectExternalBrainDocumentsForPush(rootDir, metadata, existingD
7202
7388
  skipped.push({ repoPath: normalizedRepoPath, reason: "tooLarge" });
7203
7389
  continue;
7204
7390
  }
7205
- const content = await readFile10(fullPath, "utf8").catch(() => void 0);
7391
+ const content = await readFile11(fullPath, "utf8").catch(() => void 0);
7206
7392
  if (content === void 0) {
7207
7393
  skipped.push({ repoPath: normalizedRepoPath, reason: "unreadable" });
7208
7394
  continue;
@@ -7267,7 +7453,7 @@ async function listAutoSyncCandidatePaths(rootDir) {
7267
7453
  }
7268
7454
  const files = [];
7269
7455
  for (const syncRoot of [...syncRoots, htmlSyncRoot, ...legacySyncRoots]) {
7270
- const fullRoot = path12.join(rootDir, syncRoot);
7456
+ const fullRoot = path13.join(rootDir, syncRoot);
7271
7457
  if (await exists2(fullRoot)) {
7272
7458
  await walkAutoSyncFiles(rootDir, fullRoot, files);
7273
7459
  }
@@ -7276,8 +7462,8 @@ async function listAutoSyncCandidatePaths(rootDir) {
7276
7462
  }
7277
7463
  async function walkAutoSyncFiles(rootDir, directory, files) {
7278
7464
  for (const entry of await readdir5(directory, { withFileTypes: true }).catch(() => [])) {
7279
- const fullPath = path12.join(directory, entry.name);
7280
- const repoPath = normalizeRepoPath3(path12.relative(rootDir, fullPath));
7465
+ const fullPath = path13.join(directory, entry.name);
7466
+ const repoPath = normalizeRepoPath3(path13.relative(rootDir, fullPath));
7281
7467
  if (entry.isDirectory()) {
7282
7468
  if (!autoSyncExcludedDirectoryNames.has(entry.name)) {
7283
7469
  await walkAutoSyncFiles(rootDir, fullPath, files);
@@ -7331,7 +7517,7 @@ function parseFrontmatterFromSyncedDocument(frontmatter) {
7331
7517
  }
7332
7518
  async function exists2(filePath) {
7333
7519
  try {
7334
- await stat4(filePath);
7520
+ await stat5(filePath);
7335
7521
  return true;
7336
7522
  } catch {
7337
7523
  return false;
@@ -7339,9 +7525,9 @@ async function exists2(filePath) {
7339
7525
  }
7340
7526
 
7341
7527
  // src/tool-session-store.ts
7342
- import { mkdir as mkdir11, readFile as readFile11, writeFile as writeFile11 } from "node:fs/promises";
7343
- import os7 from "node:os";
7344
- import path13 from "node:path";
7528
+ import { mkdir as mkdir12, readFile as readFile12, writeFile as writeFile12 } from "node:fs/promises";
7529
+ import os8 from "node:os";
7530
+ import path14 from "node:path";
7345
7531
  var LocalToolSessionStore = class {
7346
7532
  constructor(filePath = defaultSessionStorePath()) {
7347
7533
  this.filePath = filePath;
@@ -7355,12 +7541,12 @@ var LocalToolSessionStore = class {
7355
7541
  async setProviderSessionId(toolSessionId, toolName, providerSessionId) {
7356
7542
  const data = await this.read();
7357
7543
  data[toolSessionId] = { toolName, providerSessionId, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
7358
- await mkdir11(path13.dirname(this.filePath), { recursive: true });
7359
- await writeFile11(this.filePath, JSON.stringify(data, null, 2), "utf8");
7544
+ await mkdir12(path14.dirname(this.filePath), { recursive: true });
7545
+ await writeFile12(this.filePath, JSON.stringify(data, null, 2), "utf8");
7360
7546
  }
7361
7547
  async read() {
7362
7548
  try {
7363
- return JSON.parse(await readFile11(this.filePath, "utf8"));
7549
+ return JSON.parse(await readFile12(this.filePath, "utf8"));
7364
7550
  } catch {
7365
7551
  return {};
7366
7552
  }
@@ -7368,16 +7554,16 @@ var LocalToolSessionStore = class {
7368
7554
  };
7369
7555
  function defaultSessionStorePath() {
7370
7556
  if (process.platform === "darwin") {
7371
- return path13.join(os7.homedir(), "Library", "Application Support", "Amistio", "tool-sessions.json");
7557
+ return path14.join(os8.homedir(), "Library", "Application Support", "Amistio", "tool-sessions.json");
7372
7558
  }
7373
7559
  if (process.platform === "win32") {
7374
- return path13.join(process.env.APPDATA ?? os7.homedir(), "Amistio", "tool-sessions.json");
7560
+ return path14.join(process.env.APPDATA ?? os8.homedir(), "Amistio", "tool-sessions.json");
7375
7561
  }
7376
- return path13.join(process.env.XDG_STATE_HOME ?? path13.join(os7.homedir(), ".local", "state"), "amistio", "tool-sessions.json");
7562
+ return path14.join(process.env.XDG_STATE_HOME ?? path14.join(os8.homedir(), ".local", "state"), "amistio", "tool-sessions.json");
7377
7563
  }
7378
7564
 
7379
7565
  // src/work-runner.ts
7380
- import path14 from "node:path";
7566
+ import path15 from "node:path";
7381
7567
  var generationResultStart = "AMISTIO_BRAIN_GENERATION_RESULT_START";
7382
7568
  var generationResultEnd = "AMISTIO_BRAIN_GENERATION_RESULT_END";
7383
7569
  var assistantAnswerStart = "AMISTIO_ASSISTANT_ANSWER_START";
@@ -8971,15 +9157,15 @@ function normalizeProjectContextRepoPath(value, options) {
8971
9157
  if (!trimmed || /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(trimmed) || /^file:/i.test(trimmed) || /^[A-Za-z]:($|[^\\/])/.test(trimmed)) {
8972
9158
  throwUnsafeProjectContextPath();
8973
9159
  }
8974
- const absolute = trimmed.startsWith("/") || trimmed.startsWith("\\\\") || path14.isAbsolute(trimmed) || path14.win32.isAbsolute(trimmed);
9160
+ const absolute = trimmed.startsWith("/") || trimmed.startsWith("\\\\") || path15.isAbsolute(trimmed) || path15.win32.isAbsolute(trimmed);
8975
9161
  if (!absolute) {
8976
9162
  return normalizeRelativeProjectContextPath(trimmed);
8977
9163
  }
8978
9164
  if (!options.repositoryRoot) {
8979
9165
  throwUnsafeProjectContextPath();
8980
9166
  }
8981
- const useWindowsPathRules = path14.win32.isAbsolute(trimmed) && !trimmed.startsWith("/");
8982
- const relativePath = useWindowsPathRules ? path14.win32.relative(path14.win32.resolve(options.repositoryRoot), path14.win32.resolve(trimmed)) : path14.relative(path14.resolve(options.repositoryRoot), path14.resolve(trimmed));
9167
+ const useWindowsPathRules = path15.win32.isAbsolute(trimmed) && !trimmed.startsWith("/");
9168
+ const relativePath = useWindowsPathRules ? path15.win32.relative(path15.win32.resolve(options.repositoryRoot), path15.win32.resolve(trimmed)) : path15.relative(path15.resolve(options.repositoryRoot), path15.resolve(trimmed));
8983
9169
  return normalizeRelativeProjectContextPath(relativePath);
8984
9170
  }
8985
9171
  function normalizeRelativeProjectContextPath(value) {
@@ -9063,15 +9249,15 @@ function stripJsonFence(value) {
9063
9249
  }
9064
9250
 
9065
9251
  // src/runner-resources.ts
9066
- import os8 from "node:os";
9252
+ import os9 from "node:os";
9067
9253
  var defaultRuntime = {
9068
9254
  nowMs: () => Date.now(),
9069
9255
  memoryUsage: () => process.memoryUsage(),
9070
9256
  uptime: () => process.uptime(),
9071
9257
  cpuUsage: () => process.cpuUsage(),
9072
- totalmem: () => os8.totalmem(),
9073
- freemem: () => os8.freemem(),
9074
- loadavg: () => os8.loadavg()
9258
+ totalmem: () => os9.totalmem(),
9259
+ freemem: () => os9.freemem(),
9260
+ loadavg: () => os9.loadavg()
9075
9261
  };
9076
9262
  var previousRunnerResourceSample;
9077
9263
  function sampleCurrentRunnerResourceUsage() {
@@ -9184,8 +9370,8 @@ function roundNumber(value, digits) {
9184
9370
  // src/importer.ts
9185
9371
  import { execFile as execFile4 } from "node:child_process";
9186
9372
  import { createHash as createHash7 } from "node:crypto";
9187
- import { readdir as readdir6, readFile as readFile12, stat as stat5 } from "node:fs/promises";
9188
- import path15 from "node:path";
9373
+ import { readdir as readdir6, readFile as readFile13, stat as stat6 } from "node:fs/promises";
9374
+ import path16 from "node:path";
9189
9375
  import { promisify as promisify4 } from "node:util";
9190
9376
  var execFileAsync4 = promisify4(execFile4);
9191
9377
  var defaultMaxFileKb = 256;
@@ -9206,12 +9392,12 @@ var documentFolderByType = {
9206
9392
  workflow: "docs/workflows"
9207
9393
  };
9208
9394
  async function inspectLocalRepository(rootDir, defaultBranch) {
9209
- const requestedRoot = path15.resolve(rootDir);
9395
+ const requestedRoot = path16.resolve(rootDir);
9210
9396
  const root = await runGit2(["-C", requestedRoot, "rev-parse", "--show-toplevel"]).catch(() => requestedRoot);
9211
9397
  const detectedBranch = await runGit2(["-C", root, "symbolic-ref", "--quiet", "--short", "HEAD"]).catch(() => defaultBranch);
9212
9398
  const originUrl = await runGit2(["-C", root, "remote", "get-url", "origin"]).catch(() => void 0);
9213
9399
  const parsedCloneUrl = originUrl ? parseOptionalOriginCloneUrl(originUrl) : void 0;
9214
- const repoName = (parsedCloneUrl?.repoName ?? path15.basename(root)) || "repository";
9400
+ const repoName = (parsedCloneUrl?.repoName ?? path16.basename(root)) || "repository";
9215
9401
  const fingerprintSeed = parsedCloneUrl ? `origin:${parsedCloneUrl.normalizedKey}` : `repo:${repoName}:${detectedBranch || defaultBranch}`;
9216
9402
  return {
9217
9403
  rootDir: root,
@@ -9223,7 +9409,7 @@ async function inspectLocalRepository(rootDir, defaultBranch) {
9223
9409
  };
9224
9410
  }
9225
9411
  async function scanLegacyDocuments(options) {
9226
- const rootDir = path15.resolve(options.rootDir);
9412
+ const rootDir = path16.resolve(options.rootDir);
9227
9413
  const maxBytes = (options.maxFileKb ?? defaultMaxFileKb) * 1024;
9228
9414
  const skipped = [];
9229
9415
  const candidates = [];
@@ -9243,8 +9429,8 @@ async function scanLegacyDocuments(options) {
9243
9429
  skipped.push({ repoPath, reason: "excluded" });
9244
9430
  continue;
9245
9431
  }
9246
- const fullPath = path15.join(rootDir, ...repoPath.split("/"));
9247
- const fileStat = await stat5(fullPath).catch(() => void 0);
9432
+ const fullPath = path16.join(rootDir, ...repoPath.split("/"));
9433
+ const fileStat = await stat6(fullPath).catch(() => void 0);
9248
9434
  if (!fileStat?.isFile()) {
9249
9435
  skipped.push({ repoPath, reason: "unreadable" });
9250
9436
  continue;
@@ -9253,7 +9439,7 @@ async function scanLegacyDocuments(options) {
9253
9439
  skipped.push({ repoPath, reason: "tooLarge" });
9254
9440
  continue;
9255
9441
  }
9256
- const content = await readFile12(fullPath, "utf8").catch(() => void 0);
9442
+ const content = await readFile13(fullPath, "utf8").catch(() => void 0);
9257
9443
  if (content === void 0) {
9258
9444
  skipped.push({ repoPath, reason: "unreadable" });
9259
9445
  continue;
@@ -9345,8 +9531,8 @@ async function listRepositoryPaths(rootDir) {
9345
9531
  async function walkRepository(rootDir, directory, files) {
9346
9532
  const entries = await readdir6(directory, { withFileTypes: true }).catch(() => []);
9347
9533
  for (const entry of entries) {
9348
- const fullPath = path15.join(directory, entry.name);
9349
- const repoPath = normalizeRepoPath4(path15.relative(rootDir, fullPath));
9534
+ const fullPath = path16.join(directory, entry.name);
9535
+ const repoPath = normalizeRepoPath4(path16.relative(rootDir, fullPath));
9350
9536
  if (entry.isDirectory()) {
9351
9537
  if (!excludedDirectoryNames.has(entry.name)) {
9352
9538
  await walkRepository(rootDir, fullPath, files);
@@ -9414,9 +9600,9 @@ function uniqueDestinationPath(basePath, sourcePath, usedPaths) {
9414
9600
  usedPaths.add(basePath);
9415
9601
  return basePath;
9416
9602
  }
9417
- const extension = path15.posix.extname(basePath) || ".md";
9418
- const directory = path15.posix.dirname(basePath);
9419
- const basename = path15.posix.basename(basePath, extension);
9603
+ const extension = path16.posix.extname(basePath) || ".md";
9604
+ const directory = path16.posix.dirname(basePath);
9605
+ const basename = path16.posix.basename(basePath, extension);
9420
9606
  const uniquePath = `${directory}/${basename}-${hashText(sourcePath, 8)}${extension}`;
9421
9607
  usedPaths.add(uniquePath);
9422
9608
  return uniquePath;
@@ -9489,7 +9675,7 @@ function inferTitle2(content, repoPath) {
9489
9675
  if (heading) return heading;
9490
9676
  const htmlHeading = body.match(/<h1\b[^>]*>([\s\S]*?)<\/h1>/i)?.[1]?.replace(/<[^>]+>/g, "").trim();
9491
9677
  if (htmlHeading) return htmlHeading;
9492
- const basename = path15.posix.basename(repoPath, path15.posix.extname(repoPath)).replace(/[-_]+/g, " ").trim();
9678
+ const basename = path16.posix.basename(repoPath, path16.posix.extname(repoPath)).replace(/[-_]+/g, " ").trim();
9493
9679
  return titleCase(basename || "Imported Document");
9494
9680
  }
9495
9681
  function stripFrontmatter(content) {
@@ -9530,7 +9716,7 @@ async function runGit2(args) {
9530
9716
 
9531
9717
  // src/runner-actions.ts
9532
9718
  import { spawn as spawn4 } from "node:child_process";
9533
- import path16 from "node:path";
9719
+ import path17 from "node:path";
9534
9720
  function buildBackgroundRunnerArgs(options) {
9535
9721
  const args = [
9536
9722
  "run",
@@ -9540,7 +9726,7 @@ function buildBackgroundRunnerArgs(options) {
9540
9726
  "--runner-id",
9541
9727
  options.runnerId,
9542
9728
  "--root",
9543
- path16.resolve(options.root),
9729
+ path17.resolve(options.root),
9544
9730
  "--session",
9545
9731
  options.session,
9546
9732
  "--interval-seconds",
@@ -9664,8 +9850,8 @@ function truncateProcessOutput(value) {
9664
9850
 
9665
9851
  // src/git-worktree.ts
9666
9852
  import { execFile as execFile5 } from "node:child_process";
9667
- import { copyFile, lstat, mkdir as mkdir12, readdir as readdir7, stat as stat6 } from "node:fs/promises";
9668
- import path17 from "node:path";
9853
+ import { copyFile, lstat, mkdir as mkdir13, readdir as readdir7, stat as stat7 } from "node:fs/promises";
9854
+ import path18 from "node:path";
9669
9855
  import { promisify as promisify5 } from "node:util";
9670
9856
  var execFileAsync5 = promisify5(execFile5);
9671
9857
  var exactLocalEnvironmentFiles = /* @__PURE__ */ new Set([".env", ".env.local", ".env.development", ".env.development.local", ".env.test", ".env.test.local", ".env.production", ".env.production.local"]);
@@ -9700,7 +9886,7 @@ async function prepareGitWorktreeIsolation(rootDir, workItem) {
9700
9886
  return { ...identity, baseRevision, worktreePath, ...preparedLocalEnvironmentFileCount2 ? { preparedLocalEnvironmentFileCount: preparedLocalEnvironmentFileCount2 } : {} };
9701
9887
  }
9702
9888
  await repairMissingRegisteredWorktree(repoRoot, worktreePath, identity.branch, identity.worktreeKey);
9703
- await mkdir12(path17.dirname(worktreePath), { recursive: true });
9889
+ await mkdir13(path18.dirname(worktreePath), { recursive: true });
9704
9890
  const branchExists = await gitCommandSucceeds(repoRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${identity.branch}`]);
9705
9891
  const worktreeArgs = branchExists ? ["worktree", "add", worktreePath, identity.branch] : ["worktree", "add", "-b", identity.branch, worktreePath, baseRevision];
9706
9892
  await gitOutput(repoRoot, worktreeArgs).catch((error) => {
@@ -9718,9 +9904,9 @@ async function resolveExistingGitWorktreeIsolation(rootDir, workItem) {
9718
9904
  return { ...identity, baseRevision, worktreePath };
9719
9905
  }
9720
9906
  function localWorktreePath(repoRoot, worktreeKey) {
9721
- const repoName = path17.basename(repoRoot);
9907
+ const repoName = path18.basename(repoRoot);
9722
9908
  const worktreeSlug = worktreeKey.split("/").filter(Boolean).pop() ?? "work";
9723
- return path17.join(path17.dirname(repoRoot), `${repoName}.worktrees`, worktreeSlug);
9909
+ return path18.join(path18.dirname(repoRoot), `${repoName}.worktrees`, worktreeSlug);
9724
9910
  }
9725
9911
  async function assertExistingWorktree(worktreePath, branch) {
9726
9912
  await gitOutput(worktreePath, ["rev-parse", "--is-inside-work-tree"]);
@@ -9783,7 +9969,7 @@ function parseRegisteredGitWorktrees(output) {
9783
9969
  return worktrees;
9784
9970
  }
9785
9971
  function normalizeGitWorktreePath(value) {
9786
- const resolved = path17.resolve(value);
9972
+ const resolved = path18.resolve(value);
9787
9973
  return resolved.startsWith("/private/var/") ? resolved.replace("/private/var/", "/var/") : resolved;
9788
9974
  }
9789
9975
  async function assertBaseRevision(repoRoot, baseRevision, currentHead) {
@@ -9803,8 +9989,8 @@ async function prepareLocalWorktreeEnvironment(repoRoot, worktreePath) {
9803
9989
  const candidates = await localEnvironmentFileCandidates(repoRoot);
9804
9990
  let preparedCount = 0;
9805
9991
  for (const candidate of candidates) {
9806
- const sourcePath = path17.join(repoRoot, candidate);
9807
- const targetPath = path17.join(worktreePath, candidate);
9992
+ const sourcePath = path18.join(repoRoot, candidate);
9993
+ const targetPath = path18.join(worktreePath, candidate);
9808
9994
  if (await pathExists(targetPath)) {
9809
9995
  continue;
9810
9996
  }
@@ -9835,7 +10021,7 @@ async function localEnvironmentFileCandidates(repoRoot) {
9835
10021
  if (!isRootFileName(name)) {
9836
10022
  continue;
9837
10023
  }
9838
- const source = await lstat(path17.join(repoRoot, name)).catch(() => void 0);
10024
+ const source = await lstat(path18.join(repoRoot, name)).catch(() => void 0);
9839
10025
  if (source?.isFile()) {
9840
10026
  candidates.push(name);
9841
10027
  }
@@ -9846,7 +10032,7 @@ function isAllowedLocalEnvironmentFile(name) {
9846
10032
  return exactLocalEnvironmentFiles.has(name) || localEnvironmentFilePattern.test(name);
9847
10033
  }
9848
10034
  function isRootFileName(name) {
9849
- return name === path17.basename(name) && !name.includes("/") && !name.includes("\\");
10035
+ return name === path18.basename(name) && !name.includes("/") && !name.includes("\\");
9850
10036
  }
9851
10037
  async function gitOutput(cwd, args) {
9852
10038
  const { stdout } = await execFileAsync5("git", args, { cwd, maxBuffer: 1024 * 1024 });
@@ -9856,7 +10042,7 @@ async function gitCommandSucceeds(cwd, args) {
9856
10042
  return execFileAsync5("git", args, { cwd }).then(() => true, () => false);
9857
10043
  }
9858
10044
  async function pathExists(value) {
9859
- return stat6(value).then(() => true, () => false);
10045
+ return stat7(value).then(() => true, () => false);
9860
10046
  }
9861
10047
  function workIsolationSlug(scopeId, title) {
9862
10048
  const scopeSlug = slugify(scopeId);
@@ -9879,7 +10065,7 @@ function safeFileError(error) {
9879
10065
 
9880
10066
  // src/implementation-handoff.ts
9881
10067
  import { execFile as execFile6 } from "node:child_process";
9882
- import path18 from "node:path";
10068
+ import path19 from "node:path";
9883
10069
  import { promisify as promisify6 } from "node:util";
9884
10070
  var execFileAsync6 = promisify6(execFile6);
9885
10071
  var DEFAULT_IMPLEMENTATION_EXPECTED_OUTCOME = "sourceImplementation";
@@ -10333,7 +10519,7 @@ async function cleanupWorktree(run, input) {
10333
10519
  return { status: "failed", message: "Cleanup skipped because the worktree is not clean after PR handoff." };
10334
10520
  }
10335
10521
  try {
10336
- await gitOutput2(run, input.primaryRepoRoot || path18.dirname(input.worktreePath), ["worktree", "remove", input.worktreePath]);
10522
+ await gitOutput2(run, input.primaryRepoRoot || path19.dirname(input.worktreePath), ["worktree", "remove", input.worktreePath]);
10337
10523
  return { status: "completed" };
10338
10524
  } catch (error) {
10339
10525
  return { status: "failed", message: `Cleanup failed: ${safeErrorMessage(error)}` };
@@ -11036,7 +11222,7 @@ var DEFAULT_MAX_PREFLIGHT_ATTEMPTS = 3;
11036
11222
  var DEFAULT_TOOL_TIMEOUT_SECONDS = 30 * 60;
11037
11223
  var RUNNER_WORK_LEASE_SECONDS = 300;
11038
11224
  var RUNNER_WORK_LEASE_RENEWAL_MS = 12e4;
11039
- var MAX_CONCURRENT_RUNNER_WORK = 4;
11225
+ var MAX_CONCURRENT_RUNNER_WORK = runnerMaxConcurrentWorkLimit;
11040
11226
  var runnerSupportedWorkKinds = ["brainGeneration", "implementation", "promptBatch", "planRevision", "assistantQuestion", "impactPreview", "issueDiagnosis", "securityPostureScan", "appEvaluationScan", "brainConsolidationScan", "projectContextRefresh", "implementationVerification", "testQualityScan", "implementationTestGate"];
11041
11227
  program.name("amistio").description("Amistio project brain CLI").version(CLI_VERSION);
11042
11228
  program.command("init").description("Create Amistio control-plane folders for a new project").option("--root <path>", "Repository root", defaultRoot).action(async (options) => {
@@ -11151,7 +11337,7 @@ program.command("import").description("Pair an existing checkout and import lega
11151
11337
  });
11152
11338
  program.command("pair").description("Pair this repository with an Amistio web project").requiredOption("--account <accountId>", "Amistio account ID").requiredOption("--project <projectId>", "Amistio project ID").option("--repository-link <repositoryLinkId>", "Existing repository link ID").option("--default-branch <branch>", "Default branch", "main").option("--api-url <url>", apiUrlOptionDescription, defaultApiUrl()).option("--pairing-code <code>", "Short-lived pairing code from the Amistio app").option("--token <token>", "Runner/device credential to store outside the repository").option("--root <path>", "Repository root", defaultRoot).action(async (options, command) => {
11153
11339
  const pairingRoot = await resolvePairingRoot(options.root, { explicitRoot: command.getOptionValueSource("root") === "cli" });
11154
- let repositoryLinkId = options.repositoryLink ?? `repo_${randomUUID3()}`;
11340
+ let repositoryLinkId = options.repositoryLink ?? `repo_${randomUUID4()}`;
11155
11341
  let credential = options.token;
11156
11342
  if (options.pairingCode) {
11157
11343
  const pairing = await new ApiClient({
@@ -11292,7 +11478,7 @@ sync.command("watch").description("Watch repository brain folders and auto-sync
11292
11478
  console.log(`Auto-sync watcher stopped after ${iterations} polling attempt${iterations === 1 ? "" : "s"}.`);
11293
11479
  return;
11294
11480
  }
11295
- await delay(options.intervalSeconds * 1e3);
11481
+ await delay2(options.intervalSeconds * 1e3);
11296
11482
  }
11297
11483
  });
11298
11484
  var work = program.command("work").description("Inspect approved work items");
@@ -11337,7 +11523,7 @@ work.command("prompt").description("Print or write an approved work prompt witho
11337
11523
  }
11338
11524
  const prompt = await createRunnerWorkPrompt(context.client, context.metadata.amistioProjectId, workItem);
11339
11525
  if (options.out) {
11340
- await writeFile12(options.out, prompt, "utf8");
11526
+ await writeFile13(options.out, prompt, "utf8");
11341
11527
  console.log(`Wrote work prompt to ${options.out}.`);
11342
11528
  } else {
11343
11529
  console.log(prompt);
@@ -11447,7 +11633,7 @@ program.command("orchestrate").description("Update the Amistio control plane thr
11447
11633
  ...options.toolCommand ? { toolCommand: options.toolCommand } : {},
11448
11634
  ...localModelConfig,
11449
11635
  streamOutput: options.stream,
11450
- ...sessionPolicy === "none" ? {} : { session: { toolSessionId: `local_orchestration_${randomUUID3()}`, policy: sessionPolicy, decision: localSessionDecision(sessionPolicy) } }
11636
+ ...sessionPolicy === "none" ? {} : { session: { toolSessionId: `local_orchestration_${randomUUID4()}`, policy: sessionPolicy, decision: localSessionDecision(sessionPolicy) } }
11451
11637
  });
11452
11638
  if (!options.stream && result.stdout.trim()) {
11453
11639
  console.log(result.stdout.trim());
@@ -11488,7 +11674,7 @@ program.command("run").description("Claim and run approved Amistio work locally"
11488
11674
  projectId: context.metadata.amistioProjectId,
11489
11675
  repositoryLinkId: context.metadata.repositoryLinkId,
11490
11676
  runnerId,
11491
- rootDir: path19.resolve(options.root),
11677
+ rootDir: path20.resolve(options.root),
11492
11678
  apiUrl: options.apiUrl,
11493
11679
  args: buildBackgroundRunnerArgs(resolvedOptions)
11494
11680
  });
@@ -11558,7 +11744,7 @@ program.command("run").description("Claim and run approved Amistio work locally"
11558
11744
  console.log(`Runner stopped after ${iterations} polling attempt${iterations === 1 ? "" : "s"}.`);
11559
11745
  return;
11560
11746
  }
11561
- await delay(options.intervalSeconds * 1e3);
11747
+ await delay2(options.intervalSeconds * 1e3);
11562
11748
  }
11563
11749
  } finally {
11564
11750
  process.off("SIGINT", handleShutdownSignal);
@@ -11717,7 +11903,7 @@ runnerService.command("install").description("Install a user-level startup servi
11717
11903
  projectId: context.metadata.amistioProjectId,
11718
11904
  repositoryLinkId: context.metadata.repositoryLinkId,
11719
11905
  runnerId,
11720
- rootDir: path19.resolve(options.root),
11906
+ rootDir: path20.resolve(options.root),
11721
11907
  apiUrl: options.apiUrl,
11722
11908
  args,
11723
11909
  platform
@@ -12006,612 +12192,696 @@ async function runNextWorkItem({
12006
12192
  }
12007
12193
  return { status: "idle", exitCode: 0, nextAction, message };
12008
12194
  }
12009
- const prompt = await createRunnerWorkPrompt(apiClient, projectId, result.workItem);
12010
- await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12011
- status: "running",
12012
- summary: "Prepared local runner execution prompt.",
12013
- idempotencyKey: `runner_milestone_prompt_${result.workItem.workItemId}_${result.workItem.attempt}`,
12014
- metadata: { workKind: result.workItem.workKind ?? "implementation", attempt: result.workItem.attempt }
12015
- });
12016
- if (dryRun || toolConfig.tool === "none") {
12017
- console.log(prompt);
12018
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12019
- return { status: "preview", exitCode: 0 };
12020
- }
12021
- const worktreeIsolation = await prepareWorktreeForClaimedItem({ apiClient, heartbeatConcurrency, maxPreflightAttempts, projectId, repositoryLinkId, root, runnerId, toolConfig, workItem: result.workItem });
12022
- if (worktreeIsolation.status !== "ready") {
12023
- return { status: worktreeIsolation.status === "failed" ? "failed" : "blocked", exitCode: 1, message: worktreeIsolation.message };
12024
- }
12025
- const executionRoot = worktreeIsolation.isolation?.worktreePath ?? root;
12026
- const isolationTelemetry = workItemIsolationTelemetry(result.workItem, worktreeIsolation.isolation);
12027
- const environmentReadiness = await checkRunnerExecutionEnvironment({
12028
- executionRoot,
12029
- primaryCheckoutRoot: root,
12030
- profile: executionProfile,
12031
- setupCommands: runnerEnvironmentSetupCommands(setupPackageManagerInstall),
12032
- ...result.workItem.workKind ? { workKind: result.workItem.workKind } : {},
12033
- env: process.env
12034
- });
12035
- if (environmentReadiness.profile === "dockerWorkspace" && environmentReadiness.status === "ready") {
12036
- environmentReadiness.status = "blocked";
12037
- environmentReadiness.summary = "Runner execution environment dockerWorkspace is blocked: containerized harness execution is not enabled in this runner build.";
12038
- environmentReadiness.blockers.push({ reason: "unsupportedProfile", summary: "Containerized harness execution is not enabled in this runner build.", remediation: "Select hostWorktree or hostWorktreeWithSetup until Docker workspace execution is enabled.", safePaths: [] });
12039
- environmentReadiness.checks.push({ checkId: "docker-harness", title: "Docker harness", status: "blocked", reason: "unsupportedProfile", summary: "Docker workspace envelope is valid, but this runner cannot execute the harness inside the container yet.", safePaths: [] });
12040
- }
12041
- if (environmentReadiness.status === "blocked") {
12042
- const statusResult2 = await apiClient.updateWorkStatus(projectId, result.workItem.workItemId, "blocked", `environment_blocked_${result.workItem.workItemId}_${result.workItem.attempt}_${randomUUID3()}`, runnerId, {
12043
- ...isolationTelemetry,
12044
- executionEnvironmentProfile: environmentReadiness.profile,
12045
- executionEnvironmentReadiness: environmentReadiness,
12046
- blockerReason: environmentReadiness.summary,
12047
- message: environmentReadiness.summary
12195
+ const localActiveClaim = await defaultRunnerActiveClaimStore.reserve(runnerActiveClaimInput({
12196
+ accountId: commandContext.accountId,
12197
+ claimLaneId,
12198
+ repositoryLinkId,
12199
+ runnerId,
12200
+ toolTimeoutMs,
12201
+ workItem: result.workItem
12202
+ }));
12203
+ if (localActiveClaim.status === "blocked") {
12204
+ return await releaseSkippedLocalClaim({
12205
+ apiClient,
12206
+ claimLaneId,
12207
+ conflict: localActiveClaim,
12208
+ projectId,
12209
+ repositoryLinkId,
12210
+ runnerId,
12211
+ workItem: result.workItem
12048
12212
  });
12049
- await recordRunnerMilestone(apiClient, projectId, statusResult2.workItem, runnerId, repositoryLinkId, {
12050
- status: "warning",
12051
- summary: environmentReadiness.summary,
12052
- idempotencyKey: `runner_milestone_environment_blocked_${result.workItem.workItemId}_${statusResult2.workItem.idempotencyKey}`,
12053
- metadata: { executionEnvironmentProfile: environmentReadiness.profile, blockerReasons: environmentReadiness.blockers.map((blocker) => blocker.reason) }
12213
+ }
12214
+ const releaseLocalActiveClaim = async () => {
12215
+ await defaultRunnerActiveClaimStore.release(localActiveClaim.record.reservationId).catch((error) => {
12216
+ console.error(`Could not release local Amistio active-claim reservation for ${result.workItem?.workItemId}: ${truncateLogExcerpt(errorDetail(error))}`);
12054
12217
  });
12055
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "blocked", {
12056
- ...runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency),
12057
- currentWorkItemId: result.workItem.workItemId,
12058
- currentExecutionEnvironmentProfile: environmentReadiness.profile,
12059
- environmentReadiness,
12060
- preferenceMessage: environmentReadiness.summary,
12061
- ...isolationTelemetry.implementationScopeId ? { currentImplementationScopeId: isolationTelemetry.implementationScopeId } : {},
12062
- ...isolationTelemetry.executionWorktreeKey ? { currentWorktreeKey: isolationTelemetry.executionWorktreeKey } : {},
12063
- ...isolationTelemetry.executionBranch ? { currentBranch: isolationTelemetry.executionBranch } : {}
12218
+ };
12219
+ try {
12220
+ const prompt = await createRunnerWorkPrompt(apiClient, projectId, result.workItem);
12221
+ await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12222
+ status: "running",
12223
+ summary: "Prepared local runner execution prompt.",
12224
+ idempotencyKey: `runner_milestone_prompt_${result.workItem.workItemId}_${result.workItem.attempt}`,
12225
+ metadata: { workKind: result.workItem.workKind ?? "implementation", attempt: result.workItem.attempt }
12064
12226
  });
12065
- console.error(environmentReadiness.summary);
12066
- return { status: "blocked", exitCode: 1, message: environmentReadiness.summary };
12067
- }
12068
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "running", {
12069
- ...runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency),
12070
- currentWorkItemId: result.workItem.workItemId,
12071
- currentExecutionEnvironmentProfile: environmentReadiness.profile,
12072
- environmentReadiness,
12073
- ...isolationTelemetry.implementationScopeId ? { currentImplementationScopeId: isolationTelemetry.implementationScopeId } : {},
12074
- ...isolationTelemetry.executionWorktreeKey ? { currentWorktreeKey: isolationTelemetry.executionWorktreeKey } : {},
12075
- ...isolationTelemetry.executionBranch ? { currentBranch: isolationTelemetry.executionBranch } : {}
12076
- });
12077
- if (isImplementationHandoffWork(result.workItem)) {
12078
- const repositoryLink = await loadWorkItemRepositoryLink(apiClient, projectId, result.workItem.repositoryLinkId ?? repositoryLinkId).catch(() => void 0);
12079
- const readinessHandoff = await checkImplementationHandoffReadiness({
12080
- primaryRepoRoot: root,
12081
- ...repositoryLink ? { repositoryLink } : {},
12082
- workItem: result.workItem,
12083
- ...worktreeIsolation.isolation ? { worktreeIsolation: worktreeIsolation.isolation } : {},
12084
- worktreePath: executionRoot
12227
+ if (dryRun || toolConfig.tool === "none") {
12228
+ console.log(prompt);
12229
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12230
+ return { status: "preview", exitCode: 0 };
12231
+ }
12232
+ const worktreeIsolation = await prepareWorktreeForClaimedItem({ apiClient, heartbeatConcurrency, maxPreflightAttempts, projectId, repositoryLinkId, root, runnerId, toolConfig, workItem: result.workItem });
12233
+ if (worktreeIsolation.status !== "ready") {
12234
+ return { status: worktreeIsolation.status === "failed" ? "failed" : "blocked", exitCode: 1, message: worktreeIsolation.message };
12235
+ }
12236
+ const executionRoot = worktreeIsolation.isolation?.worktreePath ?? root;
12237
+ const isolationTelemetry = workItemIsolationTelemetry(result.workItem, worktreeIsolation.isolation);
12238
+ const environmentReadiness = await checkRunnerExecutionEnvironment({
12239
+ executionRoot,
12240
+ primaryCheckoutRoot: root,
12241
+ profile: executionProfile,
12242
+ setupCommands: runnerEnvironmentSetupCommands(setupPackageManagerInstall),
12243
+ ...result.workItem.workKind ? { workKind: result.workItem.workKind } : {},
12244
+ env: process.env
12085
12245
  });
12086
- if (readinessHandoff) {
12087
- const message = readinessHandoff.message ?? "Implementation handoff readiness is blocked before local tool execution.";
12088
- const statusResult2 = await apiClient.updateWorkStatus(projectId, result.workItem.workItemId, "blocked", `handoff_readiness_blocked_${result.workItem.workItemId}_${result.workItem.attempt}_${randomUUID3()}`, runnerId, {
12246
+ if (environmentReadiness.profile === "dockerWorkspace" && environmentReadiness.status === "ready") {
12247
+ environmentReadiness.status = "blocked";
12248
+ environmentReadiness.summary = "Runner execution environment dockerWorkspace is blocked: containerized harness execution is not enabled in this runner build.";
12249
+ environmentReadiness.blockers.push({ reason: "unsupportedProfile", summary: "Containerized harness execution is not enabled in this runner build.", remediation: "Select hostWorktree or hostWorktreeWithSetup until Docker workspace execution is enabled.", safePaths: [] });
12250
+ environmentReadiness.checks.push({ checkId: "docker-harness", title: "Docker harness", status: "blocked", reason: "unsupportedProfile", summary: "Docker workspace envelope is valid, but this runner cannot execute the harness inside the container yet.", safePaths: [] });
12251
+ }
12252
+ if (environmentReadiness.status === "blocked") {
12253
+ const statusResult2 = await apiClient.updateWorkStatus(projectId, result.workItem.workItemId, "blocked", `environment_blocked_${result.workItem.workItemId}_${result.workItem.attempt}_${randomUUID4()}`, runnerId, {
12089
12254
  ...isolationTelemetry,
12090
- implementationHandoff: readinessHandoff,
12091
- blockerReason: message,
12092
- message,
12093
- ...readinessHandoff.error ? { error: readinessHandoff.error } : {}
12255
+ executionEnvironmentProfile: environmentReadiness.profile,
12256
+ executionEnvironmentReadiness: environmentReadiness,
12257
+ blockerReason: environmentReadiness.summary,
12258
+ message: environmentReadiness.summary
12094
12259
  });
12095
12260
  await recordRunnerMilestone(apiClient, projectId, statusResult2.workItem, runnerId, repositoryLinkId, {
12096
- status: "blocked",
12097
- summary: message,
12098
- idempotencyKey: `runner_milestone_handoff_readiness_blocked_${result.workItem.workItemId}_${statusResult2.workItem.idempotencyKey}`,
12099
- metadata: {
12100
- recoveryCategory: readinessHandoff.recovery?.category ?? "providerBlocked",
12101
- executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "",
12102
- executionBranch: isolationTelemetry.executionBranch ?? ""
12103
- }
12261
+ status: "warning",
12262
+ summary: environmentReadiness.summary,
12263
+ idempotencyKey: `runner_milestone_environment_blocked_${result.workItem.workItemId}_${statusResult2.workItem.idempotencyKey}`,
12264
+ metadata: { executionEnvironmentProfile: environmentReadiness.profile, blockerReasons: environmentReadiness.blockers.map((blocker) => blocker.reason) }
12104
12265
  });
12105
12266
  await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "blocked", {
12106
12267
  ...runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency),
12107
12268
  currentWorkItemId: result.workItem.workItemId,
12108
- preferenceMessage: message,
12269
+ currentExecutionEnvironmentProfile: environmentReadiness.profile,
12270
+ environmentReadiness,
12271
+ preferenceMessage: environmentReadiness.summary,
12109
12272
  ...isolationTelemetry.implementationScopeId ? { currentImplementationScopeId: isolationTelemetry.implementationScopeId } : {},
12110
12273
  ...isolationTelemetry.executionWorktreeKey ? { currentWorktreeKey: isolationTelemetry.executionWorktreeKey } : {},
12111
12274
  ...isolationTelemetry.executionBranch ? { currentBranch: isolationTelemetry.executionBranch } : {}
12112
12275
  });
12113
- console.error(message);
12114
- return { status: "blocked", exitCode: 1, message };
12276
+ console.error(environmentReadiness.summary);
12277
+ return { status: "blocked", exitCode: 1, message: environmentReadiness.summary };
12115
12278
  }
12116
- }
12117
- const resolvedModelConfig = toolConfigModelOptions(toolConfig);
12118
- const preparedHarnessRun = await builtinAmistioHarnessAdapter.createRunPreview({
12119
- rootDir: executionRoot,
12120
- prompt,
12121
- tool: toolConfig.tool,
12122
- invocationChannel: toolConfig.requestedInvocationChannel ?? "auto",
12123
- ...toolCommand ? { toolCommand } : {},
12124
- ...resolvedModelConfig,
12125
- executionPolicy: {
12126
- executionRoot,
12127
- mutationPolicy: harnessMutationPolicyForWorkItem(result.workItem),
12128
- claimLaneId
12129
- }
12130
- });
12131
- const preview = preparedHarnessRun.preview;
12132
- const sessionContext = await prepareToolSession({
12133
- apiClient,
12134
- projectId,
12135
- repositoryLinkId,
12136
- runnerId,
12137
- machineId: runnerMachineId(),
12138
- sessionPolicy: result.workItem.sessionPolicy ?? sessionPolicy,
12139
- toolName: preview.toolName,
12140
- ...toolConfig.model ? { model: toolConfig.model } : {},
12141
- supportsSessionReuse: preview.supportsSessionReuse,
12142
- resumabilityScope: preview.resumabilityScope,
12143
- workItem: result.workItem,
12144
- isolationTelemetry
12145
- });
12146
- console.log(`Claimed ${result.workItem.workItemId}. Running ${preview.toolName}: ${preview.displayCommand}`);
12147
- const autopilotClaimLine = formatAutopilotClaimLine(result.workItem);
12148
- if (autopilotClaimLine) {
12149
- console.log(autopilotClaimLine);
12150
- }
12151
- const promptBatchClaimLine = formatPromptBatchClaimLine(result.workItem);
12152
- if (promptBatchClaimLine) {
12153
- console.log(promptBatchClaimLine);
12154
- }
12155
- await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12156
- status: "running",
12157
- summary: `Local runner started ${preview.toolName} execution.`,
12158
- idempotencyKey: `runner_milestone_started_${result.workItem.workItemId}_${result.workItem.attempt}`,
12159
- metadata: {
12160
- tool: preview.toolName,
12161
- invocationChannel: toolConfig.requestedInvocationChannel ?? "auto",
12162
- claimLaneId: preparedHarnessRun.concurrency.claimLaneId,
12163
- harnessSupportsConcurrentRuns: preparedHarnessRun.concurrency.supportsConcurrentRuns,
12164
- harnessRequiresExclusiveRepository: preparedHarnessRun.concurrency.requiresExclusiveRepository,
12165
- harnessRequiresExclusiveProviderAuth: preparedHarnessRun.concurrency.requiresExclusiveProviderAuth,
12166
- harnessSerializedResourceKeys: preparedHarnessRun.concurrency.serializedResourceKeys
12279
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "running", {
12280
+ ...runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency),
12281
+ currentWorkItemId: result.workItem.workItemId,
12282
+ currentExecutionEnvironmentProfile: environmentReadiness.profile,
12283
+ environmentReadiness,
12284
+ ...isolationTelemetry.implementationScopeId ? { currentImplementationScopeId: isolationTelemetry.implementationScopeId } : {},
12285
+ ...isolationTelemetry.executionWorktreeKey ? { currentWorktreeKey: isolationTelemetry.executionWorktreeKey } : {},
12286
+ ...isolationTelemetry.executionBranch ? { currentBranch: isolationTelemetry.executionBranch } : {}
12287
+ });
12288
+ if (isImplementationHandoffWork(result.workItem)) {
12289
+ const repositoryLink = await loadWorkItemRepositoryLink(apiClient, projectId, result.workItem.repositoryLinkId ?? repositoryLinkId).catch(() => void 0);
12290
+ const readinessHandoff = await checkImplementationHandoffReadiness({
12291
+ primaryRepoRoot: root,
12292
+ ...repositoryLink ? { repositoryLink } : {},
12293
+ workItem: result.workItem,
12294
+ ...worktreeIsolation.isolation ? { worktreeIsolation: worktreeIsolation.isolation } : {},
12295
+ worktreePath: executionRoot
12296
+ });
12297
+ if (readinessHandoff) {
12298
+ const message = readinessHandoff.message ?? "Implementation handoff readiness is blocked before local tool execution.";
12299
+ const statusResult2 = await apiClient.updateWorkStatus(projectId, result.workItem.workItemId, "blocked", `handoff_readiness_blocked_${result.workItem.workItemId}_${result.workItem.attempt}_${randomUUID4()}`, runnerId, {
12300
+ ...isolationTelemetry,
12301
+ implementationHandoff: readinessHandoff,
12302
+ blockerReason: message,
12303
+ message,
12304
+ ...readinessHandoff.error ? { error: readinessHandoff.error } : {}
12305
+ });
12306
+ await recordRunnerMilestone(apiClient, projectId, statusResult2.workItem, runnerId, repositoryLinkId, {
12307
+ status: "blocked",
12308
+ summary: message,
12309
+ idempotencyKey: `runner_milestone_handoff_readiness_blocked_${result.workItem.workItemId}_${statusResult2.workItem.idempotencyKey}`,
12310
+ metadata: {
12311
+ recoveryCategory: readinessHandoff.recovery?.category ?? "providerBlocked",
12312
+ executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "",
12313
+ executionBranch: isolationTelemetry.executionBranch ?? ""
12314
+ }
12315
+ });
12316
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "blocked", {
12317
+ ...runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency),
12318
+ currentWorkItemId: result.workItem.workItemId,
12319
+ preferenceMessage: message,
12320
+ ...isolationTelemetry.implementationScopeId ? { currentImplementationScopeId: isolationTelemetry.implementationScopeId } : {},
12321
+ ...isolationTelemetry.executionWorktreeKey ? { currentWorktreeKey: isolationTelemetry.executionWorktreeKey } : {},
12322
+ ...isolationTelemetry.executionBranch ? { currentBranch: isolationTelemetry.executionBranch } : {}
12323
+ });
12324
+ console.error(message);
12325
+ return { status: "blocked", exitCode: 1, message };
12326
+ }
12167
12327
  }
12168
- });
12169
- const startedAt = Date.now();
12170
- const providerSessionStore = new LocalToolSessionStore();
12171
- const providerSessionId = sessionContext.toolSession ? await providerSessionStore.getProviderSessionId(sessionContext.toolSession.toolSessionId, preview.toolName) : void 0;
12172
- let toolResult;
12173
- const stopLeaseRenewal = startWorkLeaseRenewal({ apiClient, projectId, repositoryLinkId, runnerId, toolConfig, workItem: result.workItem, telemetry: isolationTelemetry, heartbeatConcurrency });
12174
- try {
12175
- toolResult = await builtinAmistioHarnessAdapter.executeRun({
12176
- preparedRun: preparedHarnessRun,
12328
+ const resolvedModelConfig = toolConfigModelOptions(toolConfig);
12329
+ const preparedHarnessRun = await builtinAmistioHarnessAdapter.createRunPreview({
12177
12330
  rootDir: executionRoot,
12178
12331
  prompt,
12179
12332
  tool: toolConfig.tool,
12180
12333
  invocationChannel: toolConfig.requestedInvocationChannel ?? "auto",
12181
12334
  ...toolCommand ? { toolCommand } : {},
12182
12335
  ...resolvedModelConfig,
12183
- streamOutput: stream,
12184
- timeoutMs: toolTimeoutMs,
12185
- ...sessionContext.toolSession ? {
12186
- session: {
12187
- toolSessionId: sessionContext.toolSession.toolSessionId,
12188
- policy: sessionContext.policy,
12189
- decision: sessionContext.decision,
12190
- ...providerSessionId ? { providerSessionId } : {}
12191
- }
12192
- } : {}
12336
+ executionPolicy: {
12337
+ executionRoot,
12338
+ mutationPolicy: harnessMutationPolicyForWorkItem(result.workItem),
12339
+ claimLaneId
12340
+ }
12193
12341
  });
12194
- } catch (error) {
12195
- stopLeaseRenewal();
12196
- const detail = truncateLogExcerpt(errorDetail(error));
12197
- const durationMs2 = Date.now() - startedAt;
12198
- const message = `${preview.toolName} failed before returning a result.`;
12199
- const settlements = await Promise.allSettled([
12200
- apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency)),
12201
- markToolSessionBlocked(apiClient, projectId, sessionContext.toolSession, errorMessage7(error)),
12202
- apiClient.updateWorkStatus(projectId, result.workItem.workItemId, "failed", `run_failed_${result.workItem.workItemId}_${result.workItem.attempt}_${runnerId}`, runnerId, {
12203
- ...isolationTelemetry,
12204
- tool: preview.toolName,
12205
- ...toolConfig.model ? { model: toolConfig.model } : {},
12206
- durationMs: durationMs2,
12207
- message,
12208
- error: detail,
12209
- ...result.workItem.workKind === "promptBatch" ? { promptBatch: finalizePromptBatchMetadata(result.workItem, "failed", detail) } : {},
12210
- ...sessionContext.toolSession ? { toolSessionId: sessionContext.toolSession.toolSessionId } : {},
12211
- sessionPolicy: sessionContext.policy,
12212
- sessionDecision: sessionContext.decision,
12213
- sessionDecisionReason: sessionContext.reason
12214
- }),
12215
- recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12216
- status: "failed",
12217
- summary: message,
12218
- idempotencyKey: `runner_milestone_tool_throw_${result.workItem.workItemId}_${result.workItem.attempt}`,
12219
- metadata: { tool: preview.toolName, error: detail }
12220
- })
12221
- ]);
12222
- logRejectedSettlements("record local tool failure", settlements);
12223
- if (verbose || !stream) {
12224
- console.error(detail);
12342
+ const preview = preparedHarnessRun.preview;
12343
+ const sessionContext = await prepareToolSession({
12344
+ apiClient,
12345
+ projectId,
12346
+ repositoryLinkId,
12347
+ runnerId,
12348
+ machineId: runnerMachineId(),
12349
+ sessionPolicy: result.workItem.sessionPolicy ?? sessionPolicy,
12350
+ toolName: preview.toolName,
12351
+ ...toolConfig.model ? { model: toolConfig.model } : {},
12352
+ supportsSessionReuse: preview.supportsSessionReuse,
12353
+ resumabilityScope: preview.resumabilityScope,
12354
+ workItem: result.workItem,
12355
+ isolationTelemetry
12356
+ });
12357
+ console.log(`Claimed ${result.workItem.workItemId}. Running ${preview.toolName}: ${preview.displayCommand}`);
12358
+ const autopilotClaimLine = formatAutopilotClaimLine(result.workItem);
12359
+ if (autopilotClaimLine) {
12360
+ console.log(autopilotClaimLine);
12225
12361
  }
12226
- return { status: "failed", exitCode: 1, message };
12227
- }
12228
- stopLeaseRenewal();
12229
- if (sessionContext.toolSession && toolResult.providerSessionId) {
12230
- await providerSessionStore.setProviderSessionId(sessionContext.toolSession.toolSessionId, preview.toolName, toolResult.providerSessionId);
12231
- }
12232
- if (!stream && toolResult.stdout.trim()) {
12233
- console.log(toolResult.stdout.trim());
12234
- }
12235
- if (!stream && toolResult.stderr.trim()) {
12236
- console.error(toolResult.stderr.trim());
12237
- }
12238
- if (result.workItem.workKind === "brainGeneration" || result.workItem.workKind === "planRevision") {
12239
- try {
12240
- return await finalizeBrainGenerationWork({
12241
- apiClient,
12242
- durationMs: Date.now() - startedAt,
12243
- projectId,
12244
- repositoryLinkId,
12245
- runnerId,
12246
- sessionContext,
12247
- toolConfig,
12248
- toolName: preview.toolName,
12249
- toolResult,
12250
- workItem: result.workItem
12251
- });
12252
- } catch (error) {
12253
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12362
+ const promptBatchClaimLine = formatPromptBatchClaimLine(result.workItem);
12363
+ if (promptBatchClaimLine) {
12364
+ console.log(promptBatchClaimLine);
12254
12365
  }
12255
- }
12256
- if (result.workItem.workKind === "assistantQuestion") {
12366
+ await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12367
+ status: "running",
12368
+ summary: `Local runner started ${preview.toolName} execution.`,
12369
+ idempotencyKey: `runner_milestone_started_${result.workItem.workItemId}_${result.workItem.attempt}`,
12370
+ metadata: {
12371
+ tool: preview.toolName,
12372
+ invocationChannel: toolConfig.requestedInvocationChannel ?? "auto",
12373
+ claimLaneId: preparedHarnessRun.concurrency.claimLaneId,
12374
+ harnessSupportsConcurrentRuns: preparedHarnessRun.concurrency.supportsConcurrentRuns,
12375
+ harnessRequiresExclusiveRepository: preparedHarnessRun.concurrency.requiresExclusiveRepository,
12376
+ harnessRequiresExclusiveProviderAuth: preparedHarnessRun.concurrency.requiresExclusiveProviderAuth,
12377
+ harnessSerializedResourceKeys: preparedHarnessRun.concurrency.serializedResourceKeys
12378
+ }
12379
+ });
12380
+ const startedAt = Date.now();
12381
+ const providerSessionStore = new LocalToolSessionStore();
12382
+ const providerSessionId = sessionContext.toolSession ? await providerSessionStore.getProviderSessionId(sessionContext.toolSession.toolSessionId, preview.toolName) : void 0;
12383
+ let toolResult;
12384
+ const stopLeaseRenewal = startWorkLeaseRenewal({ apiClient, projectId, repositoryLinkId, runnerId, toolConfig, workItem: result.workItem, telemetry: isolationTelemetry, heartbeatConcurrency });
12257
12385
  try {
12258
- return await finalizeAssistantQuestionWork({
12259
- apiClient,
12260
- durationMs: Date.now() - startedAt,
12261
- projectId,
12262
- repositoryLinkId,
12263
- runnerId,
12264
- sessionContext,
12265
- toolConfig,
12266
- toolName: preview.toolName,
12267
- toolResult,
12268
- workItem: result.workItem
12386
+ toolResult = await builtinAmistioHarnessAdapter.executeRun({
12387
+ preparedRun: preparedHarnessRun,
12388
+ rootDir: executionRoot,
12389
+ prompt,
12390
+ tool: toolConfig.tool,
12391
+ invocationChannel: toolConfig.requestedInvocationChannel ?? "auto",
12392
+ ...toolCommand ? { toolCommand } : {},
12393
+ ...resolvedModelConfig,
12394
+ streamOutput: stream,
12395
+ timeoutMs: toolTimeoutMs,
12396
+ ...sessionContext.toolSession ? {
12397
+ session: {
12398
+ toolSessionId: sessionContext.toolSession.toolSessionId,
12399
+ policy: sessionContext.policy,
12400
+ decision: sessionContext.decision,
12401
+ ...providerSessionId ? { providerSessionId } : {}
12402
+ }
12403
+ } : {}
12269
12404
  });
12270
12405
  } catch (error) {
12271
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12406
+ stopLeaseRenewal();
12407
+ const detail = truncateLogExcerpt(errorDetail(error));
12408
+ const durationMs2 = Date.now() - startedAt;
12409
+ const message = `${preview.toolName} failed before returning a result.`;
12410
+ const settlements = await Promise.allSettled([
12411
+ apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency)),
12412
+ markToolSessionBlocked(apiClient, projectId, sessionContext.toolSession, errorMessage7(error)),
12413
+ apiClient.updateWorkStatus(projectId, result.workItem.workItemId, "failed", `run_failed_${result.workItem.workItemId}_${result.workItem.attempt}_${runnerId}`, runnerId, {
12414
+ ...isolationTelemetry,
12415
+ tool: preview.toolName,
12416
+ ...toolConfig.model ? { model: toolConfig.model } : {},
12417
+ durationMs: durationMs2,
12418
+ message,
12419
+ error: detail,
12420
+ ...result.workItem.workKind === "promptBatch" ? { promptBatch: finalizePromptBatchMetadata(result.workItem, "failed", detail) } : {},
12421
+ ...sessionContext.toolSession ? { toolSessionId: sessionContext.toolSession.toolSessionId } : {},
12422
+ sessionPolicy: sessionContext.policy,
12423
+ sessionDecision: sessionContext.decision,
12424
+ sessionDecisionReason: sessionContext.reason
12425
+ }),
12426
+ recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12427
+ status: "failed",
12428
+ summary: message,
12429
+ idempotencyKey: `runner_milestone_tool_throw_${result.workItem.workItemId}_${result.workItem.attempt}`,
12430
+ metadata: { tool: preview.toolName, error: detail }
12431
+ })
12432
+ ]);
12433
+ logRejectedSettlements("record local tool failure", settlements);
12434
+ if (verbose || !stream) {
12435
+ console.error(detail);
12436
+ }
12437
+ return { status: "failed", exitCode: 1, message };
12272
12438
  }
12273
- }
12274
- if (result.workItem.workKind === "impactPreview") {
12275
- try {
12276
- return await finalizeImpactPreviewWork({
12277
- apiClient,
12278
- durationMs: Date.now() - startedAt,
12279
- projectId,
12280
- repositoryLinkId,
12281
- root,
12282
- runnerId,
12283
- sessionContext,
12284
- toolConfig,
12285
- toolName: preview.toolName,
12286
- toolResult,
12287
- workItem: result.workItem
12288
- });
12289
- } catch (error) {
12290
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12439
+ stopLeaseRenewal();
12440
+ if (sessionContext.toolSession && toolResult.providerSessionId) {
12441
+ await providerSessionStore.setProviderSessionId(sessionContext.toolSession.toolSessionId, preview.toolName, toolResult.providerSessionId);
12291
12442
  }
12292
- }
12293
- if (result.workItem.workKind === "issueDiagnosis") {
12294
- try {
12295
- return await finalizeIssueDiagnosisWork({
12296
- apiClient,
12297
- durationMs: Date.now() - startedAt,
12298
- projectId,
12299
- repositoryLinkId,
12300
- runnerId,
12301
- sessionContext,
12302
- toolConfig,
12303
- toolName: preview.toolName,
12304
- toolResult,
12305
- workItem: result.workItem
12306
- });
12307
- } catch (error) {
12308
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12443
+ if (!stream && toolResult.stdout.trim()) {
12444
+ console.log(toolResult.stdout.trim());
12309
12445
  }
12310
- }
12311
- if (result.workItem.workKind === "securityPostureScan") {
12312
- try {
12313
- return await finalizeSecurityPostureScanWork({
12314
- apiClient,
12315
- durationMs: Date.now() - startedAt,
12316
- projectId,
12317
- repositoryLinkId,
12318
- runnerId,
12319
- sessionContext,
12320
- toolConfig,
12321
- toolName: preview.toolName,
12322
- toolResult,
12323
- workItem: result.workItem
12324
- });
12325
- } catch (error) {
12326
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12446
+ if (!stream && toolResult.stderr.trim()) {
12447
+ console.error(toolResult.stderr.trim());
12327
12448
  }
12328
- }
12329
- if (result.workItem.workKind === "appEvaluationScan") {
12330
- try {
12331
- return await finalizeAppEvaluationScanWork({
12332
- apiClient,
12333
- durationMs: Date.now() - startedAt,
12334
- projectId,
12335
- repositoryLinkId,
12336
- runnerId,
12337
- sessionContext,
12338
- toolConfig,
12339
- toolName: preview.toolName,
12340
- toolResult,
12341
- workItem: result.workItem
12342
- });
12343
- } catch (error) {
12344
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12449
+ if (result.workItem.workKind === "brainGeneration" || result.workItem.workKind === "planRevision") {
12450
+ try {
12451
+ return await finalizeBrainGenerationWork({
12452
+ apiClient,
12453
+ durationMs: Date.now() - startedAt,
12454
+ projectId,
12455
+ repositoryLinkId,
12456
+ runnerId,
12457
+ sessionContext,
12458
+ toolConfig,
12459
+ toolName: preview.toolName,
12460
+ toolResult,
12461
+ workItem: result.workItem
12462
+ });
12463
+ } catch (error) {
12464
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12465
+ }
12345
12466
  }
12346
- }
12347
- if (result.workItem.workKind === "brainConsolidationScan") {
12348
- try {
12349
- return await finalizeBrainConsolidationScanWork({
12350
- apiClient,
12351
- durationMs: Date.now() - startedAt,
12352
- projectId,
12353
- repositoryLinkId,
12354
- runnerId,
12355
- sessionContext,
12356
- toolConfig,
12357
- toolName: preview.toolName,
12358
- toolResult,
12359
- workItem: result.workItem
12360
- });
12361
- } catch (error) {
12362
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12467
+ if (result.workItem.workKind === "assistantQuestion") {
12468
+ try {
12469
+ return await finalizeAssistantQuestionWork({
12470
+ apiClient,
12471
+ durationMs: Date.now() - startedAt,
12472
+ projectId,
12473
+ repositoryLinkId,
12474
+ runnerId,
12475
+ sessionContext,
12476
+ toolConfig,
12477
+ toolName: preview.toolName,
12478
+ toolResult,
12479
+ workItem: result.workItem
12480
+ });
12481
+ } catch (error) {
12482
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12483
+ }
12363
12484
  }
12364
- }
12365
- if (result.workItem.workKind === "projectContextRefresh") {
12366
- try {
12367
- return await finalizeProjectContextRefreshWork({
12368
- apiClient,
12369
- durationMs: Date.now() - startedAt,
12370
- executionRoot,
12371
- projectId,
12372
- repositoryLinkId,
12373
- runnerId,
12374
- sessionContext,
12375
- toolConfig,
12376
- toolName: preview.toolName,
12377
- toolResult,
12378
- workItem: result.workItem
12379
- });
12380
- } catch (error) {
12381
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12485
+ if (result.workItem.workKind === "impactPreview") {
12486
+ try {
12487
+ return await finalizeImpactPreviewWork({
12488
+ apiClient,
12489
+ durationMs: Date.now() - startedAt,
12490
+ projectId,
12491
+ repositoryLinkId,
12492
+ root,
12493
+ runnerId,
12494
+ sessionContext,
12495
+ toolConfig,
12496
+ toolName: preview.toolName,
12497
+ toolResult,
12498
+ workItem: result.workItem
12499
+ });
12500
+ } catch (error) {
12501
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12502
+ }
12382
12503
  }
12383
- }
12384
- if (result.workItem.workKind === "implementationVerification") {
12385
- try {
12386
- return await finalizeImplementationVerificationWork({
12387
- apiClient,
12388
- durationMs: Date.now() - startedAt,
12389
- projectId,
12390
- repositoryLinkId,
12391
- runnerId,
12392
- sessionContext,
12393
- toolConfig,
12394
- toolName: preview.toolName,
12395
- toolResult,
12396
- workItem: result.workItem
12504
+ if (result.workItem.workKind === "issueDiagnosis") {
12505
+ try {
12506
+ return await finalizeIssueDiagnosisWork({
12507
+ apiClient,
12508
+ durationMs: Date.now() - startedAt,
12509
+ projectId,
12510
+ repositoryLinkId,
12511
+ runnerId,
12512
+ sessionContext,
12513
+ toolConfig,
12514
+ toolName: preview.toolName,
12515
+ toolResult,
12516
+ workItem: result.workItem
12517
+ });
12518
+ } catch (error) {
12519
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12520
+ }
12521
+ }
12522
+ if (result.workItem.workKind === "securityPostureScan") {
12523
+ try {
12524
+ return await finalizeSecurityPostureScanWork({
12525
+ apiClient,
12526
+ durationMs: Date.now() - startedAt,
12527
+ projectId,
12528
+ repositoryLinkId,
12529
+ runnerId,
12530
+ sessionContext,
12531
+ toolConfig,
12532
+ toolName: preview.toolName,
12533
+ toolResult,
12534
+ workItem: result.workItem
12535
+ });
12536
+ } catch (error) {
12537
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12538
+ }
12539
+ }
12540
+ if (result.workItem.workKind === "appEvaluationScan") {
12541
+ try {
12542
+ return await finalizeAppEvaluationScanWork({
12543
+ apiClient,
12544
+ durationMs: Date.now() - startedAt,
12545
+ projectId,
12546
+ repositoryLinkId,
12547
+ runnerId,
12548
+ sessionContext,
12549
+ toolConfig,
12550
+ toolName: preview.toolName,
12551
+ toolResult,
12552
+ workItem: result.workItem
12553
+ });
12554
+ } catch (error) {
12555
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12556
+ }
12557
+ }
12558
+ if (result.workItem.workKind === "brainConsolidationScan") {
12559
+ try {
12560
+ return await finalizeBrainConsolidationScanWork({
12561
+ apiClient,
12562
+ durationMs: Date.now() - startedAt,
12563
+ projectId,
12564
+ repositoryLinkId,
12565
+ runnerId,
12566
+ sessionContext,
12567
+ toolConfig,
12568
+ toolName: preview.toolName,
12569
+ toolResult,
12570
+ workItem: result.workItem
12571
+ });
12572
+ } catch (error) {
12573
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12574
+ }
12575
+ }
12576
+ if (result.workItem.workKind === "projectContextRefresh") {
12577
+ try {
12578
+ return await finalizeProjectContextRefreshWork({
12579
+ apiClient,
12580
+ durationMs: Date.now() - startedAt,
12581
+ executionRoot,
12582
+ projectId,
12583
+ repositoryLinkId,
12584
+ runnerId,
12585
+ sessionContext,
12586
+ toolConfig,
12587
+ toolName: preview.toolName,
12588
+ toolResult,
12589
+ workItem: result.workItem
12590
+ });
12591
+ } catch (error) {
12592
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12593
+ }
12594
+ }
12595
+ if (result.workItem.workKind === "implementationVerification") {
12596
+ try {
12597
+ return await finalizeImplementationVerificationWork({
12598
+ apiClient,
12599
+ durationMs: Date.now() - startedAt,
12600
+ projectId,
12601
+ repositoryLinkId,
12602
+ runnerId,
12603
+ sessionContext,
12604
+ toolConfig,
12605
+ toolName: preview.toolName,
12606
+ toolResult,
12607
+ workItem: result.workItem
12608
+ });
12609
+ } catch (error) {
12610
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12611
+ }
12612
+ }
12613
+ if (result.workItem.workKind === "testQualityScan") {
12614
+ try {
12615
+ return await finalizeTestQualityScanWork({
12616
+ apiClient,
12617
+ durationMs: Date.now() - startedAt,
12618
+ projectId,
12619
+ repositoryLinkId,
12620
+ runnerId,
12621
+ sessionContext,
12622
+ toolConfig,
12623
+ toolName: preview.toolName,
12624
+ toolResult,
12625
+ workItem: result.workItem
12626
+ });
12627
+ } catch (error) {
12628
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12629
+ }
12630
+ }
12631
+ if (result.workItem.workKind === "implementationTestGate") {
12632
+ try {
12633
+ return await finalizeImplementationTestGateWork({
12634
+ apiClient,
12635
+ durationMs: Date.now() - startedAt,
12636
+ projectId,
12637
+ repositoryLinkId,
12638
+ runnerId,
12639
+ sessionContext,
12640
+ toolConfig,
12641
+ toolName: preview.toolName,
12642
+ toolResult,
12643
+ workItem: result.workItem
12644
+ });
12645
+ } catch (error) {
12646
+ return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12647
+ }
12648
+ }
12649
+ let finalStatus = toolResult.exitCode === 0 ? "completed" : "failed";
12650
+ const durationMs = Date.now() - startedAt;
12651
+ const promptBatchResult = result.workItem.workKind === "promptBatch" ? parsePromptBatchResultBestEffort(toolResult) : void 0;
12652
+ const promptBatchFinalStatus = promptBatchResult ? workStatusFromPromptBatchResult(promptBatchResult) : void 0;
12653
+ if (promptBatchFinalStatus && (toolResult.exitCode === 0 || promptBatchFinalStatus !== "completed")) {
12654
+ finalStatus = promptBatchFinalStatus;
12655
+ }
12656
+ const failureExcerpt = finalStatus === "completed" ? void 0 : truncateLogExcerpt(toolResult.stderr || toolResult.stdout);
12657
+ let implementationHandoff;
12658
+ let finalMessage = `${preview.toolName} exited with code ${toolResult.exitCode}.`;
12659
+ let finalError = failureExcerpt ?? promptBatchFailureReason(promptBatchResult);
12660
+ const patchDrift = finalStatus !== "completed" ? classifyPatchDriftToolResult(toolResult) : void 0;
12661
+ if (patchDrift) {
12662
+ finalStatus = "blocked";
12663
+ finalMessage = patchDrift.message;
12664
+ finalError = patchDrift.summary;
12665
+ implementationHandoff = {
12666
+ status: "blocked",
12667
+ cleanupStatus: "pending",
12668
+ message: patchDrift.message,
12669
+ error: patchDrift.summary,
12670
+ recovery: {
12671
+ category: "patchDrift",
12672
+ availableActions: ["requeueFreshAttempt", "exportHandoffDetails"],
12673
+ conflictFiles: [],
12674
+ summary: "The local patch did not match the current worktree context. Refresh context or queue a fresh linked attempt before retrying.",
12675
+ ...isolationTelemetry.executionWorktreeKey ? { worktreeKey: isolationTelemetry.executionWorktreeKey } : {}
12676
+ }
12677
+ };
12678
+ }
12679
+ if (promptBatchResult && finalStatus !== "completed" && toolResult.exitCode === 0) {
12680
+ finalMessage = "Prompt batch reported a failed or blocked child prompt.";
12681
+ }
12682
+ if (finalStatus === "completed" && isImplementationHandoffWork(result.workItem)) {
12683
+ await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12684
+ status: "running",
12685
+ summary: "Preparing GitHub PR handoff for implementation work.",
12686
+ idempotencyKey: `runner_milestone_handoff_started_${result.workItem.workItemId}_${result.workItem.attempt}`,
12687
+ metadata: { executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "", executionBranch: isolationTelemetry.executionBranch ?? "" }
12397
12688
  });
12398
- } catch (error) {
12399
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12689
+ const repositoryLink = await loadWorkItemRepositoryLink(apiClient, projectId, result.workItem.repositoryLinkId ?? repositoryLinkId);
12690
+ const approvedArtifacts = await apiClient.listBrainDocuments(projectId).then((response) => response.documents).catch((error) => {
12691
+ implementationHandoff = {
12692
+ status: "blocked",
12693
+ cleanupStatus: "pending",
12694
+ artifacts: { included: [], skipped: [], blocked: [] },
12695
+ message: "Implementation handoff is blocked because approved artifact metadata could not be loaded.",
12696
+ error: truncateLogExcerpt(errorDetail(error))
12697
+ };
12698
+ return void 0;
12699
+ });
12700
+ if (!implementationHandoff) {
12701
+ implementationHandoff = await completeImplementationHandoff({
12702
+ ...approvedArtifacts ? { approvedArtifacts } : {},
12703
+ primaryRepoRoot: root,
12704
+ ...repositoryLink ? { repositoryLink } : {},
12705
+ verificationSummary: "Local execution reported completion.",
12706
+ workItem: result.workItem,
12707
+ ...worktreeIsolation.isolation ? { worktreeIsolation: worktreeIsolation.isolation } : {},
12708
+ worktreePath: executionRoot
12709
+ });
12710
+ }
12711
+ finalStatus = workStatusFromImplementationHandoff(implementationHandoff);
12712
+ finalMessage = implementationHandoff.message ?? "Implementation handoff finished.";
12713
+ finalError = implementationHandoff.error;
12400
12714
  }
12401
- }
12402
- if (result.workItem.workKind === "testQualityScan") {
12715
+ const updatedToolSession = await finalizeToolSession({
12716
+ apiClient,
12717
+ projectId,
12718
+ status: toolResult.exitCode === 0 ? "completed" : "failed",
12719
+ runnerId,
12720
+ workItemId: result.workItem.workItemId,
12721
+ stdout: toolResult.stdout,
12722
+ ...sessionContext.toolSession ? { session: sessionContext.toolSession } : {},
12723
+ ...toolResult.messageCount !== void 0 ? { messageCount: toolResult.messageCount } : {},
12724
+ ...toolResult.tokensIn !== void 0 ? { tokensIn: toolResult.tokensIn } : {},
12725
+ ...toolResult.tokensOut !== void 0 ? { tokensOut: toolResult.tokensOut } : {},
12726
+ ...toolResult.costUsd !== void 0 ? { costUsd: toolResult.costUsd } : {}
12727
+ });
12728
+ let statusResult;
12729
+ const finalizationIdempotencyKey = `run_${result.workItem.workItemId}_${randomUUID4()}`;
12730
+ const finalizationTelemetry = {
12731
+ tool: preview.toolName,
12732
+ ...toolResult.model ? { model: toolResult.model } : {},
12733
+ durationMs,
12734
+ message: finalMessage,
12735
+ ...isolationTelemetry,
12736
+ ...finalStatus === "blocked" ? { blockerReason: finalMessage } : {},
12737
+ sessionPolicy: sessionContext.policy,
12738
+ sessionDecision: sessionContext.decision,
12739
+ sessionDecisionReason: sessionContext.reason,
12740
+ ...updatedToolSession ? { toolSessionId: updatedToolSession.toolSessionId } : {},
12741
+ ...updatedToolSession?.sessionGroupKey ? { sessionGroupKey: updatedToolSession.sessionGroupKey } : {},
12742
+ ...toolResult.tokensIn !== void 0 ? { tokensIn: toolResult.tokensIn } : {},
12743
+ ...toolResult.tokensOut !== void 0 ? { tokensOut: toolResult.tokensOut } : {},
12744
+ ...toolResult.costUsd !== void 0 ? { costUsd: toolResult.costUsd } : {},
12745
+ ...implementationHandoff ? { implementationHandoff } : {},
12746
+ ...result.workItem.workKind === "promptBatch" ? { promptBatch: finalizePromptBatchMetadata(result.workItem, finalStatus, finalError, promptBatchResult) } : {},
12747
+ ...finalError ? { error: finalError } : {}
12748
+ };
12403
12749
  try {
12404
- return await finalizeTestQualityScanWork({
12405
- apiClient,
12406
- durationMs: Date.now() - startedAt,
12750
+ const implementationFinalization = isNonMutatingImplementationOutcome(result.workItem) ? await submitNonMutatingImplementationCompletion(apiClient, {
12751
+ attempt: result.workItem.attempt,
12752
+ finalStatus,
12753
+ idempotencyKey: finalizationIdempotencyKey,
12407
12754
  projectId,
12408
- repositoryLinkId,
12409
12755
  runnerId,
12410
- sessionContext,
12411
- toolConfig,
12412
- toolName: preview.toolName,
12413
- toolResult,
12414
- workItem: result.workItem
12415
- });
12416
- } catch (error) {
12417
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12418
- }
12419
- }
12420
- if (result.workItem.workKind === "implementationTestGate") {
12421
- try {
12422
- return await finalizeImplementationTestGateWork({
12423
- apiClient,
12424
- durationMs: Date.now() - startedAt,
12756
+ telemetry: finalizationTelemetry,
12757
+ workItemId: result.workItem.workItemId
12758
+ }) : await submitStagedImplementationFinalization(apiClient, {
12759
+ accountId: commandContext.accountId,
12760
+ attempt: result.workItem.attempt,
12761
+ finalStatus,
12762
+ idempotencyKey: finalizationIdempotencyKey,
12425
12763
  projectId,
12426
12764
  repositoryLinkId,
12427
12765
  runnerId,
12428
- sessionContext,
12429
- toolConfig,
12430
- toolName: preview.toolName,
12431
- toolResult,
12432
- workItem: result.workItem
12766
+ telemetry: implementationFinalizationTelemetry(finalizationTelemetry),
12767
+ workItemId: result.workItem.workItemId,
12768
+ workKind: result.workItem.workKind === "promptBatch" ? "promptBatch" : "implementation"
12433
12769
  });
12770
+ if (implementationFinalization.status === "failed") {
12771
+ if (implementationFinalization.retryable) {
12772
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency)).catch(() => void 0);
12773
+ return { status: "blocked", exitCode: 0, message: implementationFinalization.message };
12774
+ }
12775
+ throw new Error(implementationFinalization.message);
12776
+ }
12777
+ if (implementationFinalization.status === "deferred") {
12778
+ const gateMessage = "Implementation test gate was queued and must pass before completion or PR handoff is finalized.";
12779
+ await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12780
+ status: "queued",
12781
+ summary: gateMessage,
12782
+ idempotencyKey: `runner_milestone_test_gate_required_${result.workItem.workItemId}_${result.workItem.attempt}`,
12783
+ metadata: { tool: preview.toolName, durationMs, executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "", executionBranch: isolationTelemetry.executionBranch ?? "" }
12784
+ });
12785
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12786
+ console.log(gateMessage);
12787
+ return { status: "blocked", exitCode: 0, message: gateMessage };
12788
+ }
12789
+ statusResult = { workItem: implementationFinalization.workItem };
12434
12790
  } catch (error) {
12435
- return recordFinalizationFailure({ apiClient, error, isolationTelemetry, projectId, repositoryLinkId, runnerId, sessionContext, toolConfig, toolName: preview.toolName, workItem: result.workItem, durationMs: Date.now() - startedAt });
12436
- }
12437
- }
12438
- let finalStatus = toolResult.exitCode === 0 ? "completed" : "failed";
12439
- const durationMs = Date.now() - startedAt;
12440
- const promptBatchResult = result.workItem.workKind === "promptBatch" ? parsePromptBatchResultBestEffort(toolResult) : void 0;
12441
- const promptBatchFinalStatus = promptBatchResult ? workStatusFromPromptBatchResult(promptBatchResult) : void 0;
12442
- if (promptBatchFinalStatus && (toolResult.exitCode === 0 || promptBatchFinalStatus !== "completed")) {
12443
- finalStatus = promptBatchFinalStatus;
12444
- }
12445
- const failureExcerpt = finalStatus === "completed" ? void 0 : truncateLogExcerpt(toolResult.stderr || toolResult.stdout);
12446
- let implementationHandoff;
12447
- let finalMessage = `${preview.toolName} exited with code ${toolResult.exitCode}.`;
12448
- let finalError = failureExcerpt ?? promptBatchFailureReason(promptBatchResult);
12449
- const patchDrift = finalStatus !== "completed" ? classifyPatchDriftToolResult(toolResult) : void 0;
12450
- if (patchDrift) {
12451
- finalStatus = "blocked";
12452
- finalMessage = patchDrift.message;
12453
- finalError = patchDrift.summary;
12454
- implementationHandoff = {
12455
- status: "blocked",
12456
- cleanupStatus: "pending",
12457
- message: patchDrift.message,
12458
- error: patchDrift.summary,
12459
- recovery: {
12460
- category: "patchDrift",
12461
- availableActions: ["requeueFreshAttempt", "exportHandoffDetails"],
12462
- conflictFiles: [],
12463
- summary: "The local patch did not match the current worktree context. Refresh context or queue a fresh linked attempt before retrying.",
12464
- ...isolationTelemetry.executionWorktreeKey ? { worktreeKey: isolationTelemetry.executionWorktreeKey } : {}
12791
+ if (error instanceof AmistioApiError && error.status === 409 && error.detail.includes("implementation_test_gate_required")) {
12792
+ const gateMessage = "Implementation test gate was queued and must pass before completion or PR handoff is finalized.";
12793
+ await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12794
+ status: "queued",
12795
+ summary: gateMessage,
12796
+ idempotencyKey: `runner_milestone_test_gate_required_${result.workItem.workItemId}_${result.workItem.attempt}`,
12797
+ metadata: { tool: preview.toolName, durationMs, executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "", executionBranch: isolationTelemetry.executionBranch ?? "" }
12798
+ });
12799
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12800
+ console.log(gateMessage);
12801
+ return { status: "blocked", exitCode: 0 };
12465
12802
  }
12466
- };
12467
- }
12468
- if (promptBatchResult && finalStatus !== "completed" && toolResult.exitCode === 0) {
12469
- finalMessage = "Prompt batch reported a failed or blocked child prompt.";
12470
- }
12471
- if (finalStatus === "completed" && isImplementationHandoffWork(result.workItem)) {
12803
+ throw error;
12804
+ }
12472
12805
  await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12473
- status: "running",
12474
- summary: "Preparing GitHub PR handoff for implementation work.",
12475
- idempotencyKey: `runner_milestone_handoff_started_${result.workItem.workItemId}_${result.workItem.attempt}`,
12476
- metadata: { executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "", executionBranch: isolationTelemetry.executionBranch ?? "" }
12477
- });
12478
- const repositoryLink = await loadWorkItemRepositoryLink(apiClient, projectId, result.workItem.repositoryLinkId ?? repositoryLinkId);
12479
- const approvedArtifacts = await apiClient.listBrainDocuments(projectId).then((response) => response.documents).catch((error) => {
12480
- implementationHandoff = {
12481
- status: "blocked",
12482
- cleanupStatus: "pending",
12483
- artifacts: { included: [], skipped: [], blocked: [] },
12484
- message: "Implementation handoff is blocked because approved artifact metadata could not be loaded.",
12485
- error: truncateLogExcerpt(errorDetail(error))
12486
- };
12487
- return void 0;
12806
+ status: finalStatus,
12807
+ summary: finalMessage,
12808
+ idempotencyKey: `runner_milestone_finished_${result.workItem.workItemId}_${statusResult.workItem.idempotencyKey}`,
12809
+ metadata: {
12810
+ tool: preview.toolName,
12811
+ durationMs,
12812
+ exitCode: toolResult.exitCode,
12813
+ verificationSummary: finalStatus === "completed" ? "Local execution reported completion." : "Local execution reported failure.",
12814
+ executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "",
12815
+ executionBranch: isolationTelemetry.executionBranch ?? "",
12816
+ ...implementationHandoff?.status ? { handoffStatus: implementationHandoff.status } : {},
12817
+ ...implementationHandoff?.prUrl ? { prUrl: implementationHandoff.prUrl } : {},
12818
+ ...implementationHandoff?.cleanupStatus ? { cleanupStatus: implementationHandoff.cleanupStatus } : {},
12819
+ ...implementationHandoff?.artifacts ? artifactHandoffMetadata(implementationHandoff.artifacts) : {}
12820
+ }
12488
12821
  });
12489
- if (!implementationHandoff) {
12490
- implementationHandoff = await completeImplementationHandoff({
12491
- ...approvedArtifacts ? { approvedArtifacts } : {},
12492
- primaryRepoRoot: root,
12493
- ...repositoryLink ? { repositoryLink } : {},
12494
- verificationSummary: "Local execution reported completion.",
12495
- workItem: result.workItem,
12496
- ...worktreeIsolation.isolation ? { worktreeIsolation: worktreeIsolation.isolation } : {},
12497
- worktreePath: executionRoot
12498
- });
12499
- }
12500
- finalStatus = workStatusFromImplementationHandoff(implementationHandoff);
12501
- finalMessage = implementationHandoff.message ?? "Implementation handoff finished.";
12502
- finalError = implementationHandoff.error;
12822
+ await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12823
+ const durationSeconds = Math.round(durationMs / 1e3);
12824
+ console.log(`Marked ${statusResult.workItem.workItemId} ${statusResult.workItem.status} after ${durationSeconds}s.`);
12825
+ return { status: finalStatus, exitCode: finalStatus === "completed" ? toolResult.exitCode : 1 };
12826
+ } finally {
12827
+ await releaseLocalActiveClaim();
12503
12828
  }
12504
- const updatedToolSession = await finalizeToolSession({
12505
- apiClient,
12506
- projectId,
12507
- status: toolResult.exitCode === 0 ? "completed" : "failed",
12829
+ }
12830
+ function runnerActiveClaimInput({ accountId, claimLaneId, repositoryLinkId, runnerId, toolTimeoutMs, workItem }) {
12831
+ const identity = needsGitWorktreeIsolation(workItem) ? resolveWorktreeIdentity(workItem) : void 0;
12832
+ const implementationScopeId = identity?.implementationScopeId ?? workItem.implementationScopeId;
12833
+ const worktreeKey = identity?.worktreeKey ?? workItem.executionWorktreeKey;
12834
+ const executionBranch = identity?.branch ?? workItem.executionBranch;
12835
+ const expiresAtMs = Date.now() + Math.max(toolTimeoutMs, RUNNER_WORK_LEASE_SECONDS * 1e3) + RUNNER_WORK_LEASE_SECONDS * 1e3;
12836
+ return {
12837
+ accountId,
12838
+ projectId: workItem.projectId,
12839
+ repositoryLinkId: workItem.repositoryLinkId ?? repositoryLinkId,
12508
12840
  runnerId,
12509
- workItemId: result.workItem.workItemId,
12510
- stdout: toolResult.stdout,
12511
- ...sessionContext.toolSession ? { session: sessionContext.toolSession } : {},
12512
- ...toolResult.messageCount !== void 0 ? { messageCount: toolResult.messageCount } : {},
12513
- ...toolResult.tokensIn !== void 0 ? { tokensIn: toolResult.tokensIn } : {},
12514
- ...toolResult.tokensOut !== void 0 ? { tokensOut: toolResult.tokensOut } : {},
12515
- ...toolResult.costUsd !== void 0 ? { costUsd: toolResult.costUsd } : {}
12516
- });
12517
- let statusResult;
12518
- const finalizationIdempotencyKey = `run_${result.workItem.workItemId}_${randomUUID3()}`;
12519
- const finalizationTelemetry = {
12520
- tool: preview.toolName,
12521
- ...toolResult.model ? { model: toolResult.model } : {},
12522
- durationMs,
12523
- message: finalMessage,
12524
- ...isolationTelemetry,
12525
- ...finalStatus === "blocked" ? { blockerReason: finalMessage } : {},
12526
- sessionPolicy: sessionContext.policy,
12527
- sessionDecision: sessionContext.decision,
12528
- sessionDecisionReason: sessionContext.reason,
12529
- ...updatedToolSession ? { toolSessionId: updatedToolSession.toolSessionId } : {},
12530
- ...updatedToolSession?.sessionGroupKey ? { sessionGroupKey: updatedToolSession.sessionGroupKey } : {},
12531
- ...toolResult.tokensIn !== void 0 ? { tokensIn: toolResult.tokensIn } : {},
12532
- ...toolResult.tokensOut !== void 0 ? { tokensOut: toolResult.tokensOut } : {},
12533
- ...toolResult.costUsd !== void 0 ? { costUsd: toolResult.costUsd } : {},
12534
- ...implementationHandoff ? { implementationHandoff } : {},
12535
- ...result.workItem.workKind === "promptBatch" ? { promptBatch: finalizePromptBatchMetadata(result.workItem, finalStatus, finalError, promptBatchResult) } : {},
12536
- ...finalError ? { error: finalError } : {}
12841
+ claimLaneId,
12842
+ workItemId: workItem.workItemId,
12843
+ ...workItem.claimLeaseId ? { claimLeaseId: workItem.claimLeaseId } : {},
12844
+ attempt: workItem.attempt,
12845
+ ...implementationScopeId ? { implementationScopeId } : {},
12846
+ ...worktreeKey ? { worktreeKey } : {},
12847
+ ...executionBranch ? { executionBranch } : {},
12848
+ expiresAt: new Date(expiresAtMs).toISOString()
12537
12849
  };
12538
- try {
12539
- const implementationFinalization = isNonMutatingImplementationOutcome(result.workItem) ? await submitNonMutatingImplementationCompletion(apiClient, {
12540
- attempt: result.workItem.attempt,
12541
- finalStatus,
12542
- idempotencyKey: finalizationIdempotencyKey,
12543
- projectId,
12850
+ }
12851
+ async function releaseSkippedLocalClaim({ apiClient, claimLaneId, conflict, projectId, repositoryLinkId, runnerId, workItem }) {
12852
+ const message = activeClaimConflictMessage(conflict);
12853
+ await apiClient.updateWorkStatus(projectId, workItem.workItemId, "approved", `local_claim_conflict_${workItem.workItemId}_${workItem.attempt}_${randomUUID4()}`, runnerId, {
12854
+ ...workItemIsolationTelemetry(workItem, void 0),
12855
+ claimLaneId,
12856
+ message,
12857
+ releaseClaim: true
12858
+ }).catch(async (error) => {
12859
+ await apiClient.recordRunnerLog(projectId, {
12544
12860
  runnerId,
12545
- telemetry: finalizationTelemetry,
12546
- workItemId: result.workItem.workItemId
12547
- }) : await submitStagedImplementationFinalization(apiClient, {
12548
- accountId: commandContext.accountId,
12549
- attempt: result.workItem.attempt,
12550
- finalStatus,
12551
- idempotencyKey: finalizationIdempotencyKey,
12552
- projectId,
12553
12861
  repositoryLinkId,
12554
- runnerId,
12555
- telemetry: implementationFinalizationTelemetry(finalizationTelemetry),
12556
- workItemId: result.workItem.workItemId,
12557
- workKind: result.workItem.workKind === "promptBatch" ? "promptBatch" : "implementation"
12558
- });
12559
- if (implementationFinalization.status === "failed") {
12560
- if (implementationFinalization.retryable) {
12561
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency)).catch(() => void 0);
12562
- return { status: "blocked", exitCode: 0, message: implementationFinalization.message };
12563
- }
12564
- throw new Error(implementationFinalization.message);
12565
- }
12566
- if (implementationFinalization.status === "deferred") {
12567
- const gateMessage = "Implementation test gate was queued and must pass before completion or PR handoff is finalized.";
12568
- await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12569
- status: "queued",
12570
- summary: gateMessage,
12571
- idempotencyKey: `runner_milestone_test_gate_required_${result.workItem.workItemId}_${result.workItem.attempt}`,
12572
- metadata: { tool: preview.toolName, durationMs, executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "", executionBranch: isolationTelemetry.executionBranch ?? "" }
12573
- });
12574
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12575
- console.log(gateMessage);
12576
- return { status: "blocked", exitCode: 0, message: gateMessage };
12577
- }
12578
- statusResult = { workItem: implementationFinalization.workItem };
12579
- } catch (error) {
12580
- if (error instanceof AmistioApiError && error.status === 409 && error.detail.includes("implementation_test_gate_required")) {
12581
- const gateMessage = "Implementation test gate was queued and must pass before completion or PR handoff is finalized.";
12582
- await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12583
- status: "queued",
12584
- summary: gateMessage,
12585
- idempotencyKey: `runner_milestone_test_gate_required_${result.workItem.workItemId}_${result.workItem.attempt}`,
12586
- metadata: { tool: preview.toolName, durationMs, executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "", executionBranch: isolationTelemetry.executionBranch ?? "" }
12587
- });
12588
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12589
- console.log(gateMessage);
12590
- return { status: "blocked", exitCode: 0 };
12591
- }
12592
- throw error;
12593
- }
12594
- await recordRunnerMilestone(apiClient, projectId, result.workItem, runnerId, repositoryLinkId, {
12595
- status: finalStatus,
12596
- summary: finalMessage,
12597
- idempotencyKey: `runner_milestone_finished_${result.workItem.workItemId}_${statusResult.workItem.idempotencyKey}`,
12598
- metadata: {
12599
- tool: preview.toolName,
12600
- durationMs,
12601
- exitCode: toolResult.exitCode,
12602
- verificationSummary: finalStatus === "completed" ? "Local execution reported completion." : "Local execution reported failure.",
12603
- executionWorktreeKey: isolationTelemetry.executionWorktreeKey ?? "",
12604
- executionBranch: isolationTelemetry.executionBranch ?? "",
12605
- ...implementationHandoff?.status ? { handoffStatus: implementationHandoff.status } : {},
12606
- ...implementationHandoff?.prUrl ? { prUrl: implementationHandoff.prUrl } : {},
12607
- ...implementationHandoff?.cleanupStatus ? { cleanupStatus: implementationHandoff.cleanupStatus } : {},
12608
- ...implementationHandoff?.artifacts ? artifactHandoffMetadata(implementationHandoff.artifacts) : {}
12609
- }
12862
+ status: "blocked",
12863
+ workItemId: workItem.workItemId,
12864
+ workTitle: workItem.title,
12865
+ ...workItem.workKind ? { workKind: workItem.workKind } : {},
12866
+ ...claimLaneId ? { claimLaneId } : {},
12867
+ message: "Runner skipped a locally conflicting active claim but could not release the server claim.",
12868
+ error: truncateLogExcerpt(errorDetail(error)),
12869
+ machineId: runnerMachineId()
12870
+ }).catch(() => void 0);
12610
12871
  });
12611
- await apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig, currentRunnerMode(), heartbeatConcurrency));
12612
- const durationSeconds = Math.round(durationMs / 1e3);
12613
- console.log(`Marked ${statusResult.workItem.workItemId} ${statusResult.workItem.status} after ${durationSeconds}s.`);
12614
- return { status: finalStatus, exitCode: finalStatus === "completed" ? toolResult.exitCode : 1 };
12872
+ await apiClient.recordRunnerLog(projectId, {
12873
+ runnerId,
12874
+ repositoryLinkId,
12875
+ status: "blocked",
12876
+ workItemId: workItem.workItemId,
12877
+ workTitle: workItem.title,
12878
+ ...workItem.workKind ? { workKind: workItem.workKind } : {},
12879
+ ...claimLaneId ? { claimLaneId } : {},
12880
+ message,
12881
+ machineId: runnerMachineId()
12882
+ }).catch(() => void 0);
12883
+ console.error(message);
12884
+ return { status: "idle", exitCode: 0, message };
12615
12885
  }
12616
12886
  function artifactHandoffMetadata(artifacts) {
12617
12887
  return {
@@ -12657,7 +12927,7 @@ async function prepareWorktreeForClaimedItem({ apiClient, heartbeatConcurrency,
12657
12927
  const telemetry = workItemIsolationTelemetry(workItem, { ...identity, baseRevision: workItem.baseRevision ?? "unknown", worktreePath: "" });
12658
12928
  const finalAttempt = workItem.attempt >= maxPreflightAttempts;
12659
12929
  const statusMessage = finalAttempt ? `Git worktree preflight failed after ${workItem.attempt}/${maxPreflightAttempts} attempts. ${message}` : `Git worktree preflight attempt ${workItem.attempt}/${maxPreflightAttempts} failed. Requeueing for retry. ${message}`;
12660
- const statusResult = await apiClient.updateWorkStatus(projectId, workItem.workItemId, finalAttempt ? "failed" : "approved", `worktree_${finalAttempt ? "failed" : "retry"}_${workItem.workItemId}_${workItem.attempt}_${randomUUID3()}`, runnerId, {
12930
+ const statusResult = await apiClient.updateWorkStatus(projectId, workItem.workItemId, finalAttempt ? "failed" : "approved", `worktree_${finalAttempt ? "failed" : "retry"}_${workItem.workItemId}_${workItem.attempt}_${randomUUID4()}`, runnerId, {
12661
12931
  ...telemetry,
12662
12932
  message: statusMessage,
12663
12933
  ...finalAttempt ? { blockerReason: message } : { releaseClaim: true },
@@ -12726,7 +12996,7 @@ async function recordFinalizationFailure({ apiClient, durationMs, error, isolati
12726
12996
  const settlements = await Promise.allSettled([
12727
12997
  apiClient.sendRunnerHeartbeat(projectId, runnerId, repositoryLinkId, "online", runnerHeartbeatMetadata(toolConfig)),
12728
12998
  markToolSessionBlocked(apiClient, projectId, sessionContext.toolSession, errorMessage7(error)),
12729
- apiClient.updateWorkStatus(projectId, workItem.workItemId, "failed", `finalize_failed_${workItem.workItemId}_${workItem.attempt}_${randomUUID3()}`, runnerId, {
12999
+ apiClient.updateWorkStatus(projectId, workItem.workItemId, "failed", `finalize_failed_${workItem.workItemId}_${workItem.attempt}_${randomUUID4()}`, runnerId, {
12730
13000
  ...isolationTelemetry,
12731
13001
  tool: toolName,
12732
13002
  durationMs,
@@ -12963,7 +13233,7 @@ async function updateRunnerCommandStatus(apiClient, context, command, status, me
12963
13233
  runnerId: context.runnerId,
12964
13234
  repositoryLinkId: context.repositoryLinkId,
12965
13235
  status,
12966
- idempotencyKey: `runner_command_${command.commandId}_${status}_${randomUUID3()}`,
13236
+ idempotencyKey: `runner_command_${command.commandId}_${status}_${randomUUID4()}`,
12967
13237
  message,
12968
13238
  ...error ? { error } : {},
12969
13239
  ...providerAuthStatus ? { providerAuthStatus } : {}
@@ -13055,7 +13325,7 @@ async function findRecoveryWorkItem(apiClient, projectId, workItemId) {
13055
13325
  return workItems.find((item) => item.workItemId === workItemId);
13056
13326
  }
13057
13327
  async function submitRecoveredHandoff(apiClient, context, workItem, handoff, action) {
13058
- await apiClient.updateWorkStatus(context.projectId, workItem.workItemId, recoveredHandoffWorkStatus(handoff), `handoff_recovery_${workItem.workItemId}_${action}_${randomUUID3()}`, context.runnerId, {
13328
+ await apiClient.updateWorkStatus(context.projectId, workItem.workItemId, recoveredHandoffWorkStatus(handoff), `handoff_recovery_${workItem.workItemId}_${action}_${randomUUID4()}`, context.runnerId, {
13059
13329
  implementationHandoff: handoff,
13060
13330
  ...handoff.message ? { message: handoff.message } : {},
13061
13331
  ...workItem.controllingAdrId ? { controllingAdrId: workItem.controllingAdrId } : {},
@@ -13243,7 +13513,8 @@ async function submitImplementationFinalizationEntry(apiClient, entry, options =
13243
13513
  ...entry.telemetry,
13244
13514
  message: message2,
13245
13515
  blockerReason: message2,
13246
- releaseClaim: true
13516
+ releaseClaim: true,
13517
+ releaseReason: "implementationTestGatePending"
13247
13518
  }).catch((releaseError) => {
13248
13519
  console.error(`Could not release implementation work ${entry.workItemId} while waiting for its test gate: ${truncateLogExcerpt(errorMessage7(releaseError))}`);
13249
13520
  });
@@ -13453,7 +13724,7 @@ ${toolResult.stderr}`);
13453
13724
  const resultMutation = {
13454
13725
  status: "completed",
13455
13726
  runnerId,
13456
- idempotencyKey: `generation_${workItem.workItemId}_${workItem.attempt}_${randomUUID3()}`,
13727
+ idempotencyKey: `generation_${workItem.workItemId}_${workItem.attempt}_${randomUUID4()}`,
13457
13728
  artifacts,
13458
13729
  tool: toolName,
13459
13730
  durationMs,
@@ -13528,7 +13799,7 @@ ${toolResult.stderr}`);
13528
13799
  const failedResult2 = await apiClient.submitBrainGenerationResult(projectId, workItem.workItemId, {
13529
13800
  status: "failed",
13530
13801
  runnerId,
13531
- idempotencyKey: `generation_${workItem.workItemId}_${randomUUID3()}`,
13802
+ idempotencyKey: `generation_${workItem.workItemId}_${randomUUID4()}`,
13532
13803
  tool: toolName,
13533
13804
  durationMs,
13534
13805
  ...failedSessionTelemetry,
@@ -13578,7 +13849,7 @@ ${toolResult.stderr}`);
13578
13849
  const resultMutation = {
13579
13850
  status: "completed",
13580
13851
  runnerId,
13581
- idempotencyKey: `assistant_${workItem.workItemId}_${randomUUID3()}`,
13852
+ idempotencyKey: `assistant_${workItem.workItemId}_${randomUUID4()}`,
13582
13853
  answer: answerResult.answer,
13583
13854
  sourceBoundary: answerResult.sourceBoundary,
13584
13855
  citations: answerResult.citations,
@@ -13614,7 +13885,7 @@ ${toolResult.stderr}`);
13614
13885
  const failedMutation = {
13615
13886
  status: "failed",
13616
13887
  runnerId,
13617
- idempotencyKey: `assistant_${workItem.workItemId}_${randomUUID3()}`,
13888
+ idempotencyKey: `assistant_${workItem.workItemId}_${randomUUID4()}`,
13618
13889
  tool: toolName,
13619
13890
  durationMs,
13620
13891
  ...sessionTelemetry,
@@ -13677,7 +13948,7 @@ ${toolResult.stderr}`);
13677
13948
  const resultMutation = {
13678
13949
  status: "completed",
13679
13950
  runnerId,
13680
- idempotencyKey: `impact_${workItem.workItemId}_${randomUUID3()}`,
13951
+ idempotencyKey: `impact_${workItem.workItemId}_${randomUUID4()}`,
13681
13952
  report: {
13682
13953
  ...report,
13683
13954
  analyzedRepoRevision: report.analyzedRepoRevision ?? metadata?.lastSyncedRevision
@@ -13714,7 +13985,7 @@ ${toolResult.stderr}`);
13714
13985
  const failedMutation = {
13715
13986
  status: "failed",
13716
13987
  runnerId,
13717
- idempotencyKey: `impact_${workItem.workItemId}_${randomUUID3()}`,
13988
+ idempotencyKey: `impact_${workItem.workItemId}_${randomUUID4()}`,
13718
13989
  tool: toolName,
13719
13990
  durationMs,
13720
13991
  ...sessionTelemetry,
@@ -13775,7 +14046,7 @@ ${toolResult.stderr}`);
13775
14046
  const resultMutation = {
13776
14047
  status: "completed",
13777
14048
  runnerId,
13778
- idempotencyKey: `issue_${workItem.workItemId}_${randomUUID3()}`,
14049
+ idempotencyKey: `issue_${workItem.workItemId}_${randomUUID4()}`,
13779
14050
  diagnosis,
13780
14051
  tool: toolName,
13781
14052
  durationMs,
@@ -13809,7 +14080,7 @@ ${toolResult.stderr}`);
13809
14080
  const failedMutation = {
13810
14081
  status: "failed",
13811
14082
  runnerId,
13812
- idempotencyKey: `issue_${workItem.workItemId}_${randomUUID3()}`,
14083
+ idempotencyKey: `issue_${workItem.workItemId}_${randomUUID4()}`,
13813
14084
  tool: toolName,
13814
14085
  durationMs,
13815
14086
  ...sessionTelemetry,
@@ -13870,7 +14141,7 @@ ${toolResult.stderr}`);
13870
14141
  const resultMutation = {
13871
14142
  status: "completed",
13872
14143
  runnerId,
13873
- idempotencyKey: `security_${workItem.workItemId}_${randomUUID3()}`,
14144
+ idempotencyKey: `security_${workItem.workItemId}_${randomUUID4()}`,
13874
14145
  result: scanResult,
13875
14146
  tool: toolName,
13876
14147
  durationMs,
@@ -13904,7 +14175,7 @@ ${toolResult.stderr}`);
13904
14175
  const failedMutation = {
13905
14176
  status: "failed",
13906
14177
  runnerId,
13907
- idempotencyKey: `security_${workItem.workItemId}_${randomUUID3()}`,
14178
+ idempotencyKey: `security_${workItem.workItemId}_${randomUUID4()}`,
13908
14179
  tool: toolName,
13909
14180
  durationMs,
13910
14181
  ...sessionTelemetry,
@@ -13965,7 +14236,7 @@ ${toolResult.stderr}`);
13965
14236
  const resultMutation = {
13966
14237
  status: "completed",
13967
14238
  runnerId,
13968
- idempotencyKey: `app_evaluation_${workItem.workItemId}_${randomUUID3()}`,
14239
+ idempotencyKey: `app_evaluation_${workItem.workItemId}_${randomUUID4()}`,
13969
14240
  result: scanResult,
13970
14241
  tool: toolName,
13971
14242
  durationMs,
@@ -13999,7 +14270,7 @@ ${toolResult.stderr}`);
13999
14270
  const failedMutation = {
14000
14271
  status: "failed",
14001
14272
  runnerId,
14002
- idempotencyKey: `app_evaluation_${workItem.workItemId}_${randomUUID3()}`,
14273
+ idempotencyKey: `app_evaluation_${workItem.workItemId}_${randomUUID4()}`,
14003
14274
  tool: toolName,
14004
14275
  durationMs,
14005
14276
  ...sessionTelemetry,
@@ -14060,7 +14331,7 @@ ${toolResult.stderr}`);
14060
14331
  const resultMutation = {
14061
14332
  status: "completed",
14062
14333
  runnerId,
14063
- idempotencyKey: `brain_consolidation_${workItem.workItemId}_${randomUUID3()}`,
14334
+ idempotencyKey: `brain_consolidation_${workItem.workItemId}_${randomUUID4()}`,
14064
14335
  result: scanResult,
14065
14336
  tool: toolName,
14066
14337
  durationMs,
@@ -14094,7 +14365,7 @@ ${toolResult.stderr}`);
14094
14365
  const failedMutation = {
14095
14366
  status: "failed",
14096
14367
  runnerId,
14097
- idempotencyKey: `brain_consolidation_${workItem.workItemId}_${randomUUID3()}`,
14368
+ idempotencyKey: `brain_consolidation_${workItem.workItemId}_${randomUUID4()}`,
14098
14369
  tool: toolName,
14099
14370
  durationMs,
14100
14371
  ...sessionTelemetry,
@@ -14156,7 +14427,7 @@ ${toolResult.stderr}`, { repositoryRoot: executionRoot });
14156
14427
  const resultMutation = {
14157
14428
  status: "completed",
14158
14429
  runnerId,
14159
- idempotencyKey: `project_context_${workItem.workItemId}_${randomUUID3()}`,
14430
+ idempotencyKey: `project_context_${workItem.workItemId}_${randomUUID4()}`,
14160
14431
  result: refreshResult,
14161
14432
  tool: toolName,
14162
14433
  durationMs,
@@ -14202,7 +14473,7 @@ ${toolResult.stderr}`, { repositoryRoot: executionRoot });
14202
14473
  const failedMutation = {
14203
14474
  status: "failed",
14204
14475
  runnerId,
14205
- idempotencyKey: `project_context_${workItem.workItemId}_${randomUUID3()}`,
14476
+ idempotencyKey: `project_context_${workItem.workItemId}_${randomUUID4()}`,
14206
14477
  tool: toolName,
14207
14478
  durationMs,
14208
14479
  ...sessionTelemetry,
@@ -14263,7 +14534,7 @@ ${toolResult.stderr}`);
14263
14534
  const resultMutation = {
14264
14535
  status: "completed",
14265
14536
  runnerId,
14266
- idempotencyKey: `implementation_verification_${workItem.workItemId}_${randomUUID3()}`,
14537
+ idempotencyKey: `implementation_verification_${workItem.workItemId}_${randomUUID4()}`,
14267
14538
  result: verificationResult,
14268
14539
  tool: toolName,
14269
14540
  durationMs,
@@ -14297,7 +14568,7 @@ ${toolResult.stderr}`);
14297
14568
  const failedMutation = {
14298
14569
  status: "failed",
14299
14570
  runnerId,
14300
- idempotencyKey: `implementation_verification_${workItem.workItemId}_${randomUUID3()}`,
14571
+ idempotencyKey: `implementation_verification_${workItem.workItemId}_${randomUUID4()}`,
14301
14572
  tool: toolName,
14302
14573
  durationMs,
14303
14574
  ...sessionTelemetry,
@@ -14358,7 +14629,7 @@ ${toolResult.stderr}`);
14358
14629
  const resultMutation = {
14359
14630
  status: "completed",
14360
14631
  runnerId,
14361
- idempotencyKey: `test_quality_${workItem.workItemId}_${randomUUID3()}`,
14632
+ idempotencyKey: `test_quality_${workItem.workItemId}_${randomUUID4()}`,
14362
14633
  result: scanResult,
14363
14634
  tool: toolName,
14364
14635
  durationMs,
@@ -14392,7 +14663,7 @@ ${toolResult.stderr}`);
14392
14663
  const failedMutation = {
14393
14664
  status: "failed",
14394
14665
  runnerId,
14395
- idempotencyKey: `test_quality_${workItem.workItemId}_${randomUUID3()}`,
14666
+ idempotencyKey: `test_quality_${workItem.workItemId}_${randomUUID4()}`,
14396
14667
  tool: toolName,
14397
14668
  durationMs,
14398
14669
  ...sessionTelemetry,
@@ -14453,7 +14724,7 @@ ${toolResult.stderr}`);
14453
14724
  const resultMutation = {
14454
14725
  status: "completed",
14455
14726
  runnerId,
14456
- idempotencyKey: `implementation_test_gate_${workItem.workItemId}_${randomUUID3()}`,
14727
+ idempotencyKey: `implementation_test_gate_${workItem.workItemId}_${randomUUID4()}`,
14457
14728
  result: gateResult,
14458
14729
  tool: toolName,
14459
14730
  durationMs,
@@ -14487,7 +14758,7 @@ ${toolResult.stderr}`);
14487
14758
  const failedMutation = {
14488
14759
  status: "failed",
14489
14760
  runnerId,
14490
- idempotencyKey: `implementation_test_gate_${workItem.workItemId}_${randomUUID3()}`,
14761
+ idempotencyKey: `implementation_test_gate_${workItem.workItemId}_${randomUUID4()}`,
14491
14762
  tool: toolName,
14492
14763
  durationMs,
14493
14764
  ...sessionTelemetry,
@@ -14724,7 +14995,7 @@ async function prepareToolSession({
14724
14995
  });
14725
14996
  return { ...selection, toolSession: toolSession2 };
14726
14997
  }
14727
- const toolSessionId = `tool_session_${randomUUID3()}`;
14998
+ const toolSessionId = `tool_session_${randomUUID4()}`;
14728
14999
  const { toolSession } = await apiClient.createToolSession(projectId, {
14729
15000
  toolSessionId,
14730
15001
  repositoryLinkId,
@@ -14883,7 +15154,7 @@ function runnerEnvironmentSetupCommands(setupPackageManagerInstall) {
14883
15154
  return setupPackageManagerInstall ? [{ id: "packageManager.install" }] : [];
14884
15155
  }
14885
15156
  function inferRepoName(root) {
14886
- return path19.basename(path19.resolve(root)) || "repository";
15157
+ return path20.basename(path20.resolve(root)) || "repository";
14887
15158
  }
14888
15159
  function createRepoFingerprint(accountId, projectId, repositoryLinkId) {
14889
15160
  return createHash9("sha256").update(`${accountId}:${projectId}:${repositoryLinkId}`).digest("hex");
@@ -15161,7 +15432,7 @@ function runnerHeartbeatMetadata(toolConfig, mode = currentRunnerMode(), concurr
15161
15432
  return {
15162
15433
  version: CLI_VERSION,
15163
15434
  mode,
15164
- hostname: os9.hostname(),
15435
+ hostname: os10.hostname(),
15165
15436
  ...runnerIsolationCapabilityMetadata(),
15166
15437
  maxConcurrentWork: concurrencyMetadata.maxConcurrentWork,
15167
15438
  activeClaimLaneIds: concurrencyMetadata.activeClaimLaneIds,
@@ -15186,9 +15457,9 @@ function runnerHeartbeatMetadata(toolConfig, mode = currentRunnerMode(), concurr
15186
15457
  };
15187
15458
  }
15188
15459
  function runnerMachineId() {
15189
- return createHash9("sha256").update(`${os9.hostname()}:${os9.platform()}:${os9.arch()}`).digest("hex").slice(0, 20);
15460
+ return createHash9("sha256").update(`${os10.hostname()}:${os10.platform()}:${os10.arch()}`).digest("hex").slice(0, 20);
15190
15461
  }
15191
- async function delay(milliseconds) {
15462
+ async function delay2(milliseconds) {
15192
15463
  await new Promise((resolve) => setTimeout(resolve, milliseconds));
15193
15464
  }
15194
15465
  program.parseAsync().catch((error) => {