@aspectlylabs/mikka 0.0.63 → 0.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/mikka.js CHANGED
@@ -265,14 +265,14 @@ var require_semver = __commonJS({
265
265
  if (!m[4]) {
266
266
  this.prerelease = [];
267
267
  } else {
268
- this.prerelease = m[4].split(".").map((id3) => {
269
- if (/^[0-9]+$/.test(id3)) {
270
- const num = +id3;
268
+ this.prerelease = m[4].split(".").map((id4) => {
269
+ if (/^[0-9]+$/.test(id4)) {
270
+ const num = +id4;
271
271
  if (num >= 0 && num < MAX_SAFE_INTEGER) {
272
272
  return num;
273
273
  }
274
274
  }
275
- return id3;
275
+ return id4;
276
276
  });
277
277
  }
278
278
  this.build = m[5] ? m[5].split(".") : [];
@@ -1141,23 +1141,23 @@ var require_range = __commonJS({
1141
1141
  debug("stars", comp);
1142
1142
  return comp;
1143
1143
  };
1144
- var isX = (id3) => !id3 || id3.toLowerCase() === "x" || id3 === "*";
1144
+ var isX = (id4) => !id4 || id4.toLowerCase() === "x" || id4 === "*";
1145
1145
  var invalidXRangeOrder = (M, m, p) => isX(M) && !isX(m) || isX(m) && p && !isX(p);
1146
1146
  var replaceTildes = (comp, options) => {
1147
1147
  return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" ");
1148
1148
  };
1149
1149
  var replaceTilde = (comp, options) => {
1150
1150
  const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE];
1151
- const z31 = options.includePrerelease ? "-0" : "";
1151
+ const z32 = options.includePrerelease ? "-0" : "";
1152
1152
  return comp.replace(r, (_, M, m, p, pr) => {
1153
1153
  debug("tilde", comp, _, M, m, p, pr);
1154
1154
  let ret;
1155
1155
  if (isX(M)) {
1156
1156
  ret = "";
1157
1157
  } else if (isX(m)) {
1158
- ret = `>=${M}.0.0${z31} <${+M + 1}.0.0-0`;
1158
+ ret = `>=${M}.0.0${z32} <${+M + 1}.0.0-0`;
1159
1159
  } else if (isX(p)) {
1160
- ret = `>=${M}.${m}.0${z31} <${M}.${+m + 1}.0-0`;
1160
+ ret = `>=${M}.${m}.0${z32} <${M}.${+m + 1}.0-0`;
1161
1161
  } else if (pr) {
1162
1162
  debug("replaceTilde pr", pr);
1163
1163
  ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
@@ -1174,19 +1174,19 @@ var require_range = __commonJS({
1174
1174
  var replaceCaret = (comp, options) => {
1175
1175
  debug("caret", comp, options);
1176
1176
  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
1177
- const z31 = options.includePrerelease ? "-0" : "";
1177
+ const z32 = options.includePrerelease ? "-0" : "";
1178
1178
  return comp.replace(r, (_, M, m, p, pr) => {
1179
1179
  debug("caret", comp, _, M, m, p, pr);
1180
1180
  let ret;
1181
1181
  if (isX(M)) {
1182
1182
  ret = "";
1183
1183
  } else if (isX(m)) {
1184
- ret = `>=${M}.0.0${z31} <${+M + 1}.0.0-0`;
1184
+ ret = `>=${M}.0.0${z32} <${+M + 1}.0.0-0`;
1185
1185
  } else if (isX(p)) {
1186
1186
  if (M === "0") {
1187
- ret = `>=${M}.${m}.0${z31} <${M}.${+m + 1}.0-0`;
1187
+ ret = `>=${M}.${m}.0${z32} <${M}.${+m + 1}.0-0`;
1188
1188
  } else {
1189
- ret = `>=${M}.${m}.0${z31} <${+M + 1}.0.0-0`;
1189
+ ret = `>=${M}.${m}.0${z32} <${+M + 1}.0.0-0`;
1190
1190
  }
1191
1191
  } else if (pr) {
1192
1192
  debug("replaceCaret pr", pr);
@@ -3211,37 +3211,91 @@ var daemonRpc = {
3211
3211
  };
3212
3212
 
3213
3213
  // ../protocol/src/device.ts
3214
- import { z as z13 } from "zod";
3214
+ import { z as z14 } from "zod";
3215
+
3216
+ // ../protocol/src/policy-snapshot.ts
3217
+ import { z as z11 } from "zod";
3218
+ var POLICY_SNAPSHOT_HEADER = "x-mikka-policy-snapshot";
3219
+ var POLICY_SNAPSHOT_VERSION = "1";
3220
+ var POLICY_SNAPSHOT_TTL_MS = 5 * 6e4;
3221
+ var POLICY_SNAPSHOT_REFRESH_MS = 3e4;
3222
+ var id = z11.string().min(1).max(128);
3223
+ var digest = z11.string().regex(/^[a-f0-9]{64}$/);
3224
+ var policyScopeSchema = z11.strictObject({
3225
+ workspaceIds: z11.array(id).max(2),
3226
+ hierarchy: z11.strictObject({ workspaceId: z11.uuid(), teamId: z11.uuid(), projectId: z11.uuid().nullable() }).nullable()
3227
+ });
3228
+ var policySnapshotPayloadSchema = z11.strictObject({
3229
+ version: z11.literal(1),
3230
+ issuer: z11.url().max(1e3),
3231
+ ownerId: id,
3232
+ deviceId: id,
3233
+ runId: id,
3234
+ revision: digest,
3235
+ policyHash: digest,
3236
+ scope: policyScopeSchema,
3237
+ policy: runPolicySchema,
3238
+ issuedAt: z11.number().int().nonnegative(),
3239
+ expiresAt: z11.number().int().nonnegative()
3240
+ });
3241
+ var signedPolicySnapshotSchema = z11.strictObject({
3242
+ algorithm: z11.literal("Ed25519"),
3243
+ keyId: digest,
3244
+ payload: policySnapshotPayloadSchema,
3245
+ signature: z11.string().regex(/^[A-Za-z0-9_-]{86}$/)
3246
+ });
3247
+ var policyDistributionContextSchema = z11.strictObject({
3248
+ version: z11.literal(1),
3249
+ algorithm: z11.literal("Ed25519"),
3250
+ keyId: digest,
3251
+ publicKey: z11.string().regex(/^[A-Za-z0-9_-]{59}$/),
3252
+ issuer: z11.url().max(1e3),
3253
+ ownerId: id,
3254
+ deviceId: id,
3255
+ runId: id,
3256
+ revision: digest,
3257
+ scope: policyScopeSchema,
3258
+ required: z11.boolean()
3259
+ });
3260
+ function policyIssuer(base) {
3261
+ const url = new URL(base);
3262
+ const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
3263
+ if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) throw Error("policyIssuerInvalid");
3264
+ return `${url.origin}${url.pathname.replace(/\/+$/, "")}`;
3265
+ }
3266
+ function policySnapshotMessage(payload) {
3267
+ return new TextEncoder().encode(JSON.stringify(policySnapshotPayloadSchema.parse(payload)));
3268
+ }
3215
3269
 
3216
3270
  // ../protocol/src/skill.ts
3217
- import { z as z12 } from "zod";
3271
+ import { z as z13 } from "zod";
3218
3272
 
3219
3273
  // ../protocol/src/skill-artifact.ts
3220
- import { z as z11 } from "zod";
3274
+ import { z as z12 } from "zod";
3221
3275
  var SKILL_ARTIFACT_HEADER = "x-mikka-skill-artifacts";
3222
3276
  var TEAM_SKILL_HEADER = "x-mikka-team-skills";
3223
- var skillArtifactRefSchema = z11.object({
3224
- schemaVersion: z11.literal(1),
3225
- registryId: z11.enum(["mikka-builtin", "mikka-team"]),
3226
- skillId: z11.uuid(),
3227
- versionId: z11.uuid(),
3228
- format: z11.literal("single-skill-md-v1"),
3229
- sha256: z11.string().regex(/^[a-f0-9]{64}$/)
3277
+ var skillArtifactRefSchema = z12.object({
3278
+ schemaVersion: z12.literal(1),
3279
+ registryId: z12.enum(["mikka-builtin", "mikka-team"]),
3280
+ skillId: z12.uuid(),
3281
+ versionId: z12.uuid(),
3282
+ format: z12.literal("single-skill-md-v1"),
3283
+ sha256: z12.string().regex(/^[a-f0-9]{64}$/)
3230
3284
  }).strict();
3231
- var skillAssignmentReceiptSchema = z11.object({
3232
- id: z11.uuid(),
3233
- runId: z11.uuid(),
3234
- issueId: z11.uuid(),
3235
- agentId: z11.uuid(),
3236
- repoId: z11.uuid(),
3237
- deviceId: z11.uuid(),
3238
- leaseExpiresAt: z11.iso.datetime(),
3239
- assignedAt: z11.iso.datetime(),
3285
+ var skillAssignmentReceiptSchema = z12.object({
3286
+ id: z12.uuid(),
3287
+ runId: z12.uuid(),
3288
+ issueId: z12.uuid(),
3289
+ agentId: z12.uuid(),
3290
+ repoId: z12.uuid(),
3291
+ deviceId: z12.uuid(),
3292
+ leaseExpiresAt: z12.iso.datetime(),
3293
+ assignedAt: z12.iso.datetime(),
3240
3294
  artifact: skillArtifactRefSchema
3241
3295
  }).strict();
3242
- var skillReceiptRevalidationSchema = z11.object({
3296
+ var skillReceiptRevalidationSchema = z12.object({
3243
3297
  skillReceipt: skillAssignmentReceiptSchema,
3244
- leaseExpiresAt: z11.iso.datetime()
3298
+ leaseExpiresAt: z12.iso.datetime()
3245
3299
  }).strict();
3246
3300
 
3247
3301
  // ../protocol/src/skill.ts
@@ -3253,27 +3307,27 @@ var MAX_SKILL_FILES = 20;
3253
3307
  var MAX_SKILL_FILE_PATH_LENGTH = 200;
3254
3308
  var MAX_SKILL_FILE_CONTENT_LENGTH = 1e5;
3255
3309
  var SKILLS_HEADING = "Skills from your workspace (apply them on this task):";
3256
- var skillFilePathSchema = z12.string().min(1).max(MAX_SKILL_FILE_PATH_LENGTH).refine(
3310
+ var skillFilePathSchema = z13.string().min(1).max(MAX_SKILL_FILE_PATH_LENGTH).refine(
3257
3311
  (path) => !path.startsWith("/") && !path.includes("\\") && !path.split("/").some((segment) => segment === ".." || segment === ""),
3258
3312
  { message: "A skill file path must be relative and stay inside the skill." }
3259
3313
  );
3260
- var skillFileSchema = z12.object({
3314
+ var skillFileSchema = z13.object({
3261
3315
  path: skillFilePathSchema,
3262
- content: z12.string().max(MAX_SKILL_FILE_CONTENT_LENGTH)
3316
+ content: z13.string().max(MAX_SKILL_FILE_CONTENT_LENGTH)
3263
3317
  });
3264
- var skillFilesSchema = z12.array(skillFileSchema).max(MAX_SKILL_FILES);
3265
- var skillNameSchema = z12.string().trim().min(1).max(MAX_SKILL_NAME_LENGTH);
3266
- var skillDescriptionSchema = z12.string().trim().max(MAX_SKILL_DESCRIPTION_LENGTH);
3267
- var skillInstructionsSchema = z12.string().trim().min(1).max(MAX_SKILL_INSTRUCTIONS_LENGTH);
3268
- var runSkillSchema = z12.object({
3269
- id: z12.uuid(),
3318
+ var skillFilesSchema = z13.array(skillFileSchema).max(MAX_SKILL_FILES);
3319
+ var skillNameSchema = z13.string().trim().min(1).max(MAX_SKILL_NAME_LENGTH);
3320
+ var skillDescriptionSchema = z13.string().trim().max(MAX_SKILL_DESCRIPTION_LENGTH);
3321
+ var skillInstructionsSchema = z13.string().trim().min(1).max(MAX_SKILL_INSTRUCTIONS_LENGTH);
3322
+ var runSkillSchema = z13.object({
3323
+ id: z13.uuid(),
3270
3324
  name: skillNameSchema,
3271
- description: z12.string().nullable(),
3325
+ description: z13.string().nullable(),
3272
3326
  instructions: skillInstructionsSchema,
3273
3327
  files: skillFilesSchema
3274
3328
  });
3275
- var runSkillRefSchema = z12.object({
3276
- id: z12.uuid(),
3329
+ var runSkillRefSchema = z13.object({
3330
+ id: z13.uuid(),
3277
3331
  name: skillNameSchema
3278
3332
  });
3279
3333
  function skillSlug(name) {
@@ -3312,8 +3366,8 @@ function skillsPromptSection(skills, directory) {
3312
3366
  }
3313
3367
 
3314
3368
  // ../protocol/src/device.ts
3315
- var id = z13.string().min(1).max(64);
3316
- var isoTime = z13.iso.datetime({ offset: true });
3369
+ var id2 = z14.string().min(1).max(64);
3370
+ var isoTime = z14.iso.datetime({ offset: true });
3317
3371
  var RUN_LEASE_MS = 9e4;
3318
3372
  var seg = encodeURIComponent;
3319
3373
  var DEVICE_ROUTES = {
@@ -3340,16 +3394,16 @@ var devicePaths = {
3340
3394
  runPatch: (runId) => `/v1/runs/${seg(runId)}`,
3341
3395
  runCheckpoint: (runId) => `/v1/runs/${seg(runId)}/checkpoint`
3342
3396
  };
3343
- var deviceComputerCapability = z13.object({ installed: z13.boolean(), version: z13.string().max(100).nullable() }).strict();
3344
- var deviceRegistration = z13.object({
3345
- deviceType: z13.enum(["laptop", "server"]).optional(),
3346
- name: z13.string().trim().min(1).max(200),
3347
- hostname: z13.string().max(255).nullable().optional(),
3348
- platform: z13.string().max(50),
3349
- arch: z13.string().max(50),
3350
- daemonVersion: z13.string().max(50),
3351
- protocolVersion: z13.number().int(),
3352
- harnesses: z13.array(harnessInfoSchema).max(20),
3397
+ var deviceComputerCapability = z14.object({ installed: z14.boolean(), version: z14.string().max(100).nullable() }).strict();
3398
+ var deviceRegistration = z14.object({
3399
+ deviceType: z14.enum(["laptop", "server"]).optional(),
3400
+ name: z14.string().trim().min(1).max(200),
3401
+ hostname: z14.string().max(255).nullable().optional(),
3402
+ platform: z14.string().max(50),
3403
+ arch: z14.string().max(50),
3404
+ daemonVersion: z14.string().max(50),
3405
+ protocolVersion: z14.number().int(),
3406
+ harnesses: z14.array(harnessInfoSchema).max(20),
3353
3407
  computerUse: deviceComputerCapability.optional(),
3354
3408
  /**
3355
3409
  * This machine's one device id, the same in every workspace (ADR ORV-284).
@@ -3357,106 +3411,106 @@ var deviceRegistration = z13.object({
3357
3411
  * An id the server does not know yet becomes the new device's id; another
3358
3412
  * person's id registers a new device.
3359
3413
  */
3360
- deviceId: id.optional(),
3414
+ deviceId: id2.optional(),
3361
3415
  /** Needed only when the user belongs to more than one workspace. */
3362
- workspaceId: z13.uuid().optional()
3416
+ workspaceId: z14.uuid().optional()
3363
3417
  });
3364
- var deviceRegistered = z13.object({
3365
- deviceId: id,
3366
- workspaceId: z13.uuid()
3418
+ var deviceRegistered = z14.object({
3419
+ deviceId: id2,
3420
+ workspaceId: z14.uuid()
3367
3421
  });
3368
- var heartbeatRunSchema = z13.object({
3369
- runId: id,
3422
+ var heartbeatRunSchema = z14.object({
3423
+ runId: id2,
3370
3424
  /** Last tool call, turn boundary or file change (not raw output). */
3371
3425
  lastProgressAt: isoTime
3372
3426
  });
3373
- var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update", "uninstall"]) });
3374
- var deviceHeartbeatSchema = z13.object({
3375
- completedDeviceCommands: z13.array(z13.uuid()).max(100).optional(),
3376
- failedDeviceCommands: z13.array(z13.object({ id: z13.uuid(), error: z13.string().max(500) })).max(100).optional(),
3377
- harnesses: z13.array(harnessInfoSchema).max(20),
3427
+ var deviceManagementCommand = z14.object({ id: z14.uuid(), kind: z14.enum(["redetect", "restart", "update", "uninstall"]) });
3428
+ var deviceHeartbeatSchema = z14.object({
3429
+ completedDeviceCommands: z14.array(z14.uuid()).max(100).optional(),
3430
+ failedDeviceCommands: z14.array(z14.object({ id: z14.uuid(), error: z14.string().max(500) })).max(100).optional(),
3431
+ harnesses: z14.array(harnessInfoSchema).max(20),
3378
3432
  computerUse: deviceComputerCapability.optional(),
3379
- deviceType: z13.enum(["laptop", "server"]).optional(),
3380
- runs: z13.array(heartbeatRunSchema).max(500),
3381
- worktreeDiskBytes: z13.number().int().nonnegative(),
3433
+ deviceType: z14.enum(["laptop", "server"]).optional(),
3434
+ runs: z14.array(heartbeatRunSchema).max(500),
3435
+ worktreeDiskBytes: z14.number().int().nonnegative(),
3382
3436
  /**
3383
3437
  * Subscription windows read on this device. Absent when the daemon is not
3384
3438
  * polling. Numbers only, never a vendor credential (ADR 0027).
3385
3439
  */
3386
- quotas: z13.array(quotaSnapshotSchema).max(6).optional()
3440
+ quotas: z14.array(quotaSnapshotSchema).max(6).optional()
3387
3441
  });
3388
- var heartbeatResultSchema = z13.object({
3389
- deviceCommands: z13.array(deviceManagementCommand).max(1).optional(),
3442
+ var heartbeatResultSchema = z14.object({
3443
+ deviceCommands: z14.array(deviceManagementCommand).max(1).optional(),
3390
3444
  /** Renewed lease expiry per run id; a run missing here is not renewed. */
3391
- leases: z13.record(z13.string(), isoTime),
3445
+ leases: z14.record(z14.string(), isoTime),
3392
3446
  /**
3393
3447
  * Runs the device reported that it no longer holds: they ended on the
3394
3448
  * server, or went to another attempt after the lease ran out. The daemon
3395
3449
  * stops them now instead of when their lease runs out.
3396
3450
  */
3397
- revoked: z13.array(id).max(500).optional(),
3451
+ revoked: z14.array(id2).max(500).optional(),
3398
3452
  /** Short-lived cloud device token, returned only over its authenticated link. */
3399
- cloudCredential: z13.string().regex(/^orv_[A-Za-z0-9_-]{43}$/).optional()
3453
+ cloudCredential: z14.string().regex(/^orv_[A-Za-z0-9_-]{43}$/).optional()
3400
3454
  });
3401
3455
  var RUN_CHECKPOINT_MAX_BYTES = 8 * 1024 * 1024;
3402
3456
  var RECOVERY_WORKTREE_HEADER = "x-mikka-recovery-worktree";
3403
3457
  var RUN_CHECKPOINT_RECOVERY_MAX_AGE_MS = 30 * 6e4;
3404
- var runCheckpointSchema = z13.object({
3458
+ var runCheckpointSchema = z14.object({
3405
3459
  /** The commit the run's worktree started from. */
3406
- baseCommit: z13.string().regex(/^[0-9a-f]{40,64}$/),
3460
+ baseCommit: z14.string().regex(/^[0-9a-f]{40,64}$/),
3407
3461
  /**
3408
3462
  * `git diff --binary` from `baseCommit` to the whole worktree (tracked
3409
3463
  * and untracked files, ignored ones left out, the agent's own commits
3410
3464
  * included), gzipped, base64.
3411
3465
  */
3412
- patch: z13.string().max(Math.ceil(RUN_CHECKPOINT_MAX_BYTES * 4 / 3) + 4),
3466
+ patch: z14.string().max(Math.ceil(RUN_CHECKPOINT_MAX_BYTES * 4 / 3) + 4),
3413
3467
  /** Files the patch touches. */
3414
- files: z13.number().int().nonnegative(),
3468
+ files: z14.number().int().nonnegative(),
3415
3469
  takenAt: isoTime,
3416
3470
  /** The latest tree could not be checkpointed; it supersedes older patches. */
3417
- unavailableReason: z13.literal("too_large").optional()
3471
+ unavailableReason: z14.literal("too_large").optional()
3418
3472
  });
3419
- var setupRecipeSchema = z13.object({
3473
+ var setupRecipeSchema = z14.object({
3420
3474
  /** Paths relative to the main checkout copied into each new worktree. */
3421
- copyFiles: z13.array(z13.string().max(1e3)).max(200),
3475
+ copyFiles: z14.array(z14.string().max(1e3)).max(200),
3422
3476
  /** Shell command run in the worktree, e.g. `bun install`. */
3423
- command: z13.string().max(2e3).optional(),
3477
+ command: z14.string().max(2e3).optional(),
3424
3478
  /** Approved once per repo by the user; unapproved recipes never run. */
3425
- approved: z13.boolean()
3479
+ approved: z14.boolean()
3426
3480
  });
3427
3481
  var REPO_ORIGIN_HEADER = "x-mikka-repo-origin-check";
3428
- var deviceRepoSchema = z13.object({
3429
- repoId: id,
3430
- name: z13.string().max(500),
3482
+ var deviceRepoSchema = z14.object({
3483
+ repoId: id2,
3484
+ name: z14.string().max(500),
3431
3485
  /** Logical repository key; only trusted cloud runtimes use an absolute path. */
3432
- path: z13.string().min(1).max(4e3),
3433
- remoteUrl: z13.string().max(2e3).nullable().optional(),
3486
+ path: z14.string().min(1).max(4e3),
3487
+ remoteUrl: z14.string().max(2e3).nullable().optional(),
3434
3488
  setup: setupRecipeSchema.optional(),
3435
3489
  /** Domains agents may reach in this repo, on top of the harness's own. */
3436
- networkAllow: z13.array(z13.string().min(1).max(253)).max(200).optional(),
3490
+ networkAllow: z14.array(z14.string().min(1).max(253)).max(200).optional(),
3437
3491
  /** Push run branches after a verified hand-in ("always for this repo"). */
3438
- push: z13.object({
3439
- approved: z13.boolean(),
3440
- remote: z13.string().min(1).max(200).optional()
3492
+ push: z14.object({
3493
+ approved: z14.boolean(),
3494
+ remote: z14.string().min(1).max(200).optional()
3441
3495
  }).optional()
3442
3496
  });
3443
- var deviceReposResponse = z13.object({
3444
- repos: z13.array(deviceRepoSchema)
3497
+ var deviceReposResponse = z14.object({
3498
+ repos: z14.array(deviceRepoSchema)
3445
3499
  });
3446
- var pendingRunsResponse = z13.object({ runIds: z13.array(id) });
3500
+ var pendingRunsResponse = z14.object({ runIds: z14.array(id2) });
3447
3501
  var RUN_KINDS = ["implement", "acceptance", "fix", "plan"];
3448
- var runAssignmentSchema = z13.object({
3449
- runId: id,
3450
- issueId: id,
3451
- deviceId: id,
3452
- repoId: id,
3502
+ var runAssignmentSchema = z14.object({
3503
+ runId: id2,
3504
+ issueId: id2,
3505
+ deviceId: id2,
3506
+ repoId: id2,
3453
3507
  /** Clone URL for local runs; hosted computer assignments keep their isolated workspace. */
3454
- remoteUrl: z13.string().min(1).max(4e3).optional(),
3508
+ remoteUrl: z14.string().min(1).max(4e3).optional(),
3455
3509
  /** Absent means origin/HEAD after fetch. */
3456
- baseBranch: z13.string().min(1).max(500).optional(),
3457
- expectedRepoRemote: z13.string().max(2e3).optional(),
3510
+ baseBranch: z14.string().min(1).max(500).optional(),
3511
+ expectedRepoRemote: z14.string().max(2e3).optional(),
3458
3512
  harness: harnessSchema,
3459
- prompt: z13.string().max(1e5),
3513
+ prompt: z14.string().max(1e5),
3460
3514
  /**
3461
3515
  * The model the harness's CLI is asked to run, from the per-harness
3462
3516
  * preference of the person this run works for (ADR 0060). Absent: the
@@ -3465,42 +3519,42 @@ var runAssignmentSchema = z13.object({
3465
3519
  */
3466
3520
  model: modelNameSchema.optional(),
3467
3521
  /** Owner-bound selection only; no subscription credential enters the assignment. */
3468
- subscriptionBinding: z13.object({
3469
- bindingId: z13.uuid(),
3470
- ownerId: z13.string().min(1).max(128),
3471
- workspaceId: z13.uuid(),
3472
- consumerId: z13.uuid(),
3473
- route: z13.enum(["codex_cli", "claude_code_cli"])
3522
+ subscriptionBinding: z14.object({
3523
+ bindingId: z14.uuid(),
3524
+ ownerId: z14.string().min(1).max(128),
3525
+ workspaceId: z14.uuid(),
3526
+ consumerId: z14.uuid(),
3527
+ route: z14.enum(["codex_cli", "claude_code_cli"])
3474
3528
  }).strict().optional(),
3475
3529
  /** Local host authority comes only from the server's owner-bound Bot run. */
3476
- localComputer: z13.object({
3477
- botId: z13.uuid(),
3478
- ownerId: z13.string().min(1).max(128),
3479
- workspaceId: z13.uuid(),
3480
- policyVersion: z13.number().int().nonnegative().max(2147483647),
3481
- permission: z13.enum(["allow", "ask"])
3530
+ localComputer: z14.object({
3531
+ botId: z14.uuid(),
3532
+ ownerId: z14.string().min(1).max(128),
3533
+ workspaceId: z14.uuid(),
3534
+ policyVersion: z14.number().int().nonnegative().max(2147483647),
3535
+ permission: z14.enum(["allow", "ask"])
3482
3536
  }).strict().optional(),
3483
3537
  /** Trusted server assignment; the model cannot choose a Bot or display. */
3484
- computer: z13.object({
3485
- botId: z13.uuid(),
3486
- ownerId: z13.string().min(1).max(128),
3487
- display: z13.string().regex(/^:[1-9][0-9]{0,2}$/),
3488
- policyVersion: z13.number().int().nonnegative().max(2147483647)
3538
+ computer: z14.object({
3539
+ botId: z14.uuid(),
3540
+ ownerId: z14.string().min(1).max(128),
3541
+ display: z14.string().regex(/^:[1-9][0-9]{0,2}$/),
3542
+ policyVersion: z14.number().int().nonnegative().max(2147483647)
3489
3543
  }).strict().optional(),
3490
3544
  /**
3491
3545
  * 4e3: the task's explicit user variables (workspace + matching repository secrets/env, NAME -> value).
3492
3546
  * Cloud workers only. Passed into the task container through its own channel, never into the worker's
3493
3547
  * env, and never written to the run journal.
3494
3548
  */
3495
- taskEnv: z13.record(z13.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/), z13.string().max(65536)).optional(),
3549
+ taskEnv: z14.record(z14.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/), z14.string().max(65536)).optional(),
3496
3550
  /**
3497
3551
  * Names in `taskEnv` that are secrets (kind 'secret'; env vars are not listed). The daemon masks
3498
3552
  * their values (raw + standard base64) in run output before anything is uploaded; the server
3499
3553
  * masks again. Older daemons strip this field and rely on server-side masking only.
3500
3554
  */
3501
- taskSecretNames: z13.array(z13.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/)).max(500).optional(),
3555
+ taskSecretNames: z14.array(z14.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/)).max(500).optional(),
3502
3556
  /** Mock harness only: fixture name under `packages/daemon/fixtures`. */
3503
- fixture: z13.string().max(200).optional(),
3557
+ fixture: z14.string().max(200).optional(),
3504
3558
  /**
3505
3559
  * The issue's branch (`mikka/<team>-<number>`, ADR 0024): every run of
3506
3560
  * the issue pushes its verified commit here, so one pull request follows
@@ -3508,9 +3562,9 @@ var runAssignmentSchema = z13.object({
3508
3562
  * this branch from the remote when it exists. Without it the daemon
3509
3563
  * pushes the run's own branch.
3510
3564
  */
3511
- pushBranch: z13.string().min(1).max(250).optional(),
3565
+ pushBranch: z14.string().min(1).max(250).optional(),
3512
3566
  /** Run by the daemon in the worktree after the agent submits. */
3513
- verifyCommand: z13.string().max(2e3).optional(),
3567
+ verifyCommand: z14.string().max(2e3).optional(),
3514
3568
  /** Run lease; renewed through the device heartbeat. */
3515
3569
  leaseExpiresAt: isoTime.optional(),
3516
3570
  /**
@@ -3519,27 +3573,27 @@ var runAssignmentSchema = z13.object({
3519
3573
  * it stops working when the run ends. Absent: the server could not issue
3520
3574
  * one, and the run goes ahead without it.
3521
3575
  */
3522
- mcp: z13.object({ url: z13.url(), token: z13.string().min(1).max(200), mailbox: z13.literal(true).optional() }).optional(),
3576
+ mcp: z14.object({ url: z14.url(), token: z14.string().min(1).max(200), mailbox: z14.literal(true).optional() }).optional(),
3523
3577
  /** Agent-owned GitHub delivery; the same run token exchanges short-lived credentials. */
3524
- github: z13.object({
3525
- endpoint: z13.url(),
3526
- repository: z13.string().regex(/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/),
3527
- branch: z13.string().regex(/^mikka\/[a-z0-9-]+-[1-9][0-9]*$/)
3578
+ github: z14.object({
3579
+ endpoint: z14.url(),
3580
+ repository: z14.string().regex(/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/),
3581
+ branch: z14.string().regex(/^mikka\/[a-z0-9-]+-[1-9][0-9]*$/)
3528
3582
  }).strict().optional(),
3529
3583
  /** Question continuation must not silently open a different session. */
3530
3584
  /**
3531
3585
  * What the orchestrator dispatched this run for (ADR 0023). `plan` writes a
3532
3586
  * spec and proposes a split instead of changing code (ADR ORV-205).
3533
3587
  */
3534
- kind: z13.enum(RUN_KINDS).optional(),
3588
+ kind: z14.enum(RUN_KINDS).optional(),
3535
3589
  /**
3536
3590
  * The earlier run this one continues (continue, fix, answer, a person's
3537
3591
  * message): the daemon works on in that run's worktree, on this run's
3538
3592
  * branch, so nothing the earlier run left uncommitted is lost.
3539
3593
  */
3540
- continuesRunId: id.optional(),
3594
+ continuesRunId: id2.optional(),
3541
3595
  /** A same-device retry with no usable snapshot must reuse its real worktree. */
3542
- requireWorktreeContinuation: z13.literal(true).optional(),
3596
+ requireWorktreeContinuation: z14.literal(true).optional(),
3543
3597
  /**
3544
3598
  * The latest checkpoint of the attempt this run takes over after its
3545
3599
  * machine went offline. Used only for a new worktree (another machine, or
@@ -3552,37 +3606,40 @@ var runAssignmentSchema = z13.object({
3552
3606
  * The harness session to continue. A daemon that cannot resume starts a
3553
3607
  * new session with `prompt`, which always carries the full brief.
3554
3608
  */
3555
- resumeSessionId: z13.string().max(500).optional(),
3556
- requireSessionResume: z13.boolean().optional(),
3557
- preserveQuestionWorktree: z13.boolean().optional(),
3558
- questionId: z13.uuid().optional(),
3609
+ resumeSessionId: z14.string().max(500).optional(),
3610
+ requireSessionResume: z14.boolean().optional(),
3611
+ preserveQuestionWorktree: z14.boolean().optional(),
3612
+ questionId: z14.uuid().optional(),
3559
3613
  /**
3560
3614
  * What this run adds on top of the brief (a person's message, an answer,
3561
3615
  * a fix request). A resumed session gets only this as its next message;
3562
3616
  * a new session gets `prompt`, which already includes it.
3563
3617
  */
3564
- followUp: z13.string().max(1e5).optional(),
3618
+ followUp: z14.string().max(1e5).optional(),
3565
3619
  /**
3566
3620
  * The workspace's agent permissions and network allow-list (ADR 0028).
3567
3621
  * Absent from an older server: the daemon applies the ADR 0009 defaults.
3568
3622
  */
3569
3623
  policy: runPolicySchema.optional(),
3570
3624
  /** Trusted server revision for the exact run policy; older servers omit it. */
3571
- policyRevision: z13.string().regex(/^[a-f0-9]{64}$/).optional(),
3625
+ policyRevision: z14.string().regex(/^[a-f0-9]{64}$/).optional(),
3626
+ /** Only a trusted server context can make a snapshot required. */
3627
+ policySnapshotRequired: z14.boolean().optional(),
3628
+ policySnapshot: signedPolicySnapshotSchema.optional(),
3572
3629
  /**
3573
3630
  * The skills mounted on this run's agent and still enabled, resolved at
3574
3631
  * claim time the way `policy` is. The daemon inlines them into the agent's
3575
3632
  * brief and writes them under the run's directory. Absent from an older
3576
3633
  * server: the run simply has none.
3577
3634
  */
3578
- skills: z13.array(runSkillSchema).max(MAX_SKILLS_PER_RUN).optional(),
3635
+ skills: z14.array(runSkillSchema).max(MAX_SKILLS_PER_RUN).optional(),
3579
3636
  /** Server-minted assignment provenance; does not grant any policy permission. */
3580
3637
  skillReceipt: skillAssignmentReceiptSchema.optional(),
3581
3638
  /** Frozen by the server benchmark ledger; never extracted from model output. */
3582
3639
  benchmark: runBenchmarkContext.optional()
3583
3640
  });
3584
- var runPatchSchema = z13.object({
3585
- state: z13.enum([
3641
+ var runPatchSchema = z14.object({
3642
+ state: z14.enum([
3586
3643
  "queued",
3587
3644
  "preparing",
3588
3645
  "running",
@@ -3593,73 +3650,73 @@ var runPatchSchema = z13.object({
3593
3650
  "failed",
3594
3651
  "cancelled"
3595
3652
  ]),
3596
- sessionId: z13.string().max(500).nullable().optional(),
3597
- worktree: z13.string().max(4e3).nullable().optional(),
3598
- error: z13.string().max(1e4).nullable().optional(),
3653
+ sessionId: z14.string().max(500).nullable().optional(),
3654
+ worktree: z14.string().max(4e3).nullable().optional(),
3655
+ error: z14.string().max(1e4).nullable().optional(),
3599
3656
  /** Set on every terminal state. */
3600
3657
  stopReason: runStopReason.optional()
3601
3658
  });
3602
- var runEventBatchSchema = z13.object({
3603
- fromSeq: z13.number().int().min(1),
3604
- chunks: z13.array(z13.looseObject({ type: z13.string() })).min(1).max(1e3)
3659
+ var runEventBatchSchema = z14.object({
3660
+ fromSeq: z14.number().int().min(1),
3661
+ chunks: z14.array(z14.looseObject({ type: z14.string() })).min(1).max(1e3)
3605
3662
  });
3606
- var runEventsAccepted = z13.object({
3663
+ var runEventsAccepted = z14.object({
3607
3664
  /** Producer seq of the last chunk the server holds for this run. */
3608
- offset: z13.string()
3665
+ offset: z14.string()
3609
3666
  });
3610
3667
  var COMMANDS_MAX_WAIT_SECONDS = 25;
3611
3668
  var COMMANDS_SKIP_PARAM = "skip";
3612
3669
  var COMMANDS_MAX_SKIP = 100;
3613
- var runCommandSchema = z13.discriminatedUnion("kind", [
3614
- z13.object({
3615
- kind: z13.literal("input"),
3616
- runId: id,
3617
- messageId: z13.uuid(),
3618
- text: z13.string().min(1).max(1e5)
3670
+ var runCommandSchema = z14.discriminatedUnion("kind", [
3671
+ z14.object({
3672
+ kind: z14.literal("input"),
3673
+ runId: id2,
3674
+ messageId: z14.uuid(),
3675
+ text: z14.string().min(1).max(1e5)
3619
3676
  }),
3620
- z13.object({ kind: z13.literal("stop"), runId: id })
3677
+ z14.object({ kind: z14.literal("stop"), runId: id2 })
3621
3678
  ]);
3622
- var runCommandsResponse = z13.object({
3623
- commands: z13.array(runCommandSchema).max(500)
3679
+ var runCommandsResponse = z14.object({
3680
+ commands: z14.array(runCommandSchema).max(500)
3624
3681
  });
3625
- var runCommandsAck = z13.object({
3626
- delivered: z13.array(z13.uuid()).max(500)
3682
+ var runCommandsAck = z14.object({
3683
+ delivered: z14.array(z14.uuid()).max(500)
3627
3684
  });
3628
3685
  var FS_REQUESTS_MAX_WAIT_SECONDS = 25;
3629
3686
  var FS_MAX_ENTRIES = 500;
3630
- var fsBrowseRequest = z13.object({
3687
+ var fsBrowseRequest = z14.object({
3631
3688
  /** Absolute path on the device; omitted: the device's home folder. */
3632
- path: z13.string().trim().min(1).max(4e3).optional(),
3633
- showHidden: z13.boolean().optional()
3689
+ path: z14.string().trim().min(1).max(4e3).optional(),
3690
+ showHidden: z14.boolean().optional()
3634
3691
  });
3635
- var fsPendingRequest = fsBrowseRequest.extend({ id: z13.uuid() });
3636
- var fsRequestsResponse = z13.object({
3637
- requests: z13.array(fsPendingRequest).max(50)
3692
+ var fsPendingRequest = fsBrowseRequest.extend({ id: z14.uuid() });
3693
+ var fsRequestsResponse = z14.object({
3694
+ requests: z14.array(fsPendingRequest).max(50)
3638
3695
  });
3639
- var fsEntry = z13.object({
3640
- name: z13.string().max(1e3),
3641
- path: z13.string().max(4e3),
3696
+ var fsEntry = z14.object({
3697
+ name: z14.string().max(1e3),
3698
+ path: z14.string().max(4e3),
3642
3699
  /** The folder is the top level of a git repo (it has a `.git`). */
3643
- isRepo: z13.boolean()
3700
+ isRepo: z14.boolean()
3644
3701
  });
3645
- var fsListing = z13.object({
3646
- ok: z13.literal(true),
3647
- path: z13.string().max(4e3),
3702
+ var fsListing = z14.object({
3703
+ ok: z14.literal(true),
3704
+ path: z14.string().max(4e3),
3648
3705
  /** Null at the filesystem root. */
3649
- parent: z13.string().max(4e3).nullable(),
3650
- home: z13.string().max(4e3),
3706
+ parent: z14.string().max(4e3).nullable(),
3707
+ home: z14.string().max(4e3),
3651
3708
  /** `darwin`, `linux`, `win32`: for path separators and wording. */
3652
- platform: z13.string().max(50),
3653
- entries: z13.array(fsEntry).max(FS_MAX_ENTRIES),
3709
+ platform: z14.string().max(50),
3710
+ entries: z14.array(fsEntry).max(FS_MAX_ENTRIES),
3654
3711
  /** More folders existed than `FS_MAX_ENTRIES`. */
3655
- truncated: z13.boolean(),
3712
+ truncated: z14.boolean(),
3656
3713
  /**
3657
3714
  * The git repo `path` is in, if any: its top level and `origin` (or the
3658
3715
  * first remote). This is what `device.addRepo` should be given.
3659
3716
  */
3660
- repo: z13.object({
3661
- path: z13.string().max(4e3),
3662
- remoteUrl: z13.string().max(2e3).nullable()
3717
+ repo: z14.object({
3718
+ path: z14.string().max(4e3),
3719
+ remoteUrl: z14.string().max(2e3).nullable()
3663
3720
  }).nullable()
3664
3721
  });
3665
3722
  var FS_ERROR_CODES = [
@@ -3668,12 +3725,12 @@ var FS_ERROR_CODES = [
3668
3725
  "denied",
3669
3726
  "failed"
3670
3727
  ];
3671
- var fsFailure = z13.object({
3672
- ok: z13.literal(false),
3673
- code: z13.enum(FS_ERROR_CODES),
3674
- message: z13.string().max(1e3)
3728
+ var fsFailure = z14.object({
3729
+ ok: z14.literal(false),
3730
+ code: z14.enum(FS_ERROR_CODES),
3731
+ message: z14.string().max(1e3)
3675
3732
  });
3676
- var fsResult = z13.discriminatedUnion("ok", [fsListing, fsFailure]);
3733
+ var fsResult = z14.discriminatedUnion("ok", [fsListing, fsFailure]);
3677
3734
  var fsPaths = {
3678
3735
  browse: (deviceId) => `/v1/devices/${seg(deviceId)}/fs/browse`,
3679
3736
  requests: (deviceId, waitSeconds) => `/v1/devices/${seg(deviceId)}/fs/requests?wait=${waitSeconds}`,
@@ -3681,38 +3738,38 @@ var fsPaths = {
3681
3738
  };
3682
3739
 
3683
3740
  // ../protocol/src/orchestrator.ts
3684
- import { z as z14 } from "zod";
3741
+ import { z as z15 } from "zod";
3685
3742
  var minutes = (n) => n * 6e4;
3686
- var orchestratorSettingsSchema = z14.object({
3743
+ var orchestratorSettingsSchema = z15.object({
3687
3744
  /** "Continue" prompts after a turn ended without a submit. */
3688
- maxContinuations: z14.number().int().min(0).max(20).default(3),
3745
+ maxContinuations: z15.number().int().min(0).max(20).default(3),
3689
3746
  /** Resumes after the CLI crashed, before one fresh session. */
3690
- maxCrashRetries: z14.number().int().min(0).max(20).default(3),
3747
+ maxCrashRetries: z15.number().int().min(0).max(20).default(3),
3691
3748
  /** Fix rounds after the daemon's verify failed. */
3692
- maxFixAttempts: z14.number().int().min(0).max(20).default(3),
3749
+ maxFixAttempts: z15.number().int().min(0).max(20).default(3),
3693
3750
  /** "You seem stuck" prompts after a run stalled. */
3694
- maxStallRecoveries: z14.number().int().min(0).max(20).default(2),
3751
+ maxStallRecoveries: z15.number().int().min(0).max(20).default(2),
3695
3752
  /** No progress for this long while the lease is fresh = stalled. */
3696
- stalledAfterMs: z14.number().int().min(minutes(1)).default(minutes(10)),
3753
+ stalledAfterMs: z15.number().int().min(minutes(1)).default(minutes(10)),
3697
3754
  /** A device offline this long is handed to a person (no auto switch). */
3698
- deviceOfflineEscalateMs: z14.number().int().min(0).default(minutes(30)),
3755
+ deviceOfflineEscalateMs: z15.number().int().min(0).default(minutes(30)),
3699
3756
  /** An unanswered question frees its concurrency slot after this. */
3700
- questionSlotReleaseMs: z14.number().int().min(0).default(minutes(24 * 60)),
3757
+ questionSlotReleaseMs: z15.number().int().min(0).default(minutes(24 * 60)),
3701
3758
  /** Automatic dispatches per issue per hour before a person looks. */
3702
- maxDispatchesPerHour: z14.number().int().min(1).max(100).default(6),
3759
+ maxDispatchesPerHour: z15.number().int().min(1).max(100).default(6),
3703
3760
  /** Wait before resuming a run that hit its quota (no reset time known). */
3704
- quotaBackoffMs: z14.number().int().min(0).default(minutes(15)),
3761
+ quotaBackoffMs: z15.number().int().min(0).default(minutes(15)),
3705
3762
  /**
3706
3763
  * How often an issue waiting on its pull request or CI asks GitHub again
3707
3764
  * when no webhook arrived (ADR 0024).
3708
3765
  */
3709
- ciRecheckMs: z14.number().int().min(3e4).default(minutes(2)),
3766
+ ciRecheckMs: z15.number().int().min(3e4).default(minutes(2)),
3710
3767
  /** A pushed commit with no checks after this long has no CI: it passes. */
3711
- ciNoChecksMs: z14.number().int().min(0).default(minutes(5)),
3768
+ ciNoChecksMs: z15.number().int().min(0).default(minutes(5)),
3712
3769
  /** CI still running after this long goes to a person. */
3713
- ciTimeoutMs: z14.number().int().min(minutes(5)).default(minutes(120)),
3770
+ ciTimeoutMs: z15.number().int().min(minutes(5)).default(minutes(120)),
3714
3771
  /** Remote URL of the repo this project's issues run in. */
3715
- repoUrl: z14.string().max(2e3).optional()
3772
+ repoUrl: z15.string().max(2e3).optional()
3716
3773
  });
3717
3774
  var CRASH_BACKOFF_MS = [1e4, 6e4, minutes(5)];
3718
3775
  var UPSTREAM_RECHECK_MS = minutes(5);
@@ -3756,30 +3813,30 @@ var WAIT_DETAIL_CODES = [
3756
3813
  ...PERSON_WAIT_DETAIL_CODES,
3757
3814
  ...EXTERNAL_WAIT_DETAIL_CODES
3758
3815
  ];
3759
- var waitDetailSchema = z14.object({
3760
- code: z14.enum(WAIT_DETAIL_CODES),
3761
- params: z14.record(
3762
- z14.string(),
3763
- z14.union([
3764
- z14.string(),
3765
- z14.number(),
3766
- z14.array(z14.string()),
3816
+ var waitDetailSchema = z15.object({
3817
+ code: z15.enum(WAIT_DETAIL_CODES),
3818
+ params: z15.record(
3819
+ z15.string(),
3820
+ z15.union([
3821
+ z15.string(),
3822
+ z15.number(),
3823
+ z15.array(z15.string()),
3767
3824
  // `repo_ambiguous`: the repos a person can pick from.
3768
- z14.array(z14.record(z14.string(), z14.string()))
3825
+ z15.array(z15.record(z15.string(), z15.string()))
3769
3826
  ])
3770
3827
  ).optional()
3771
3828
  });
3772
- var prChecksSchema = z14.object({
3773
- state: z14.enum(["pending", "success", "failure", "none"]),
3829
+ var prChecksSchema = z15.object({
3830
+ state: z15.enum(["pending", "success", "failure", "none"]),
3774
3831
  /** Failed checks, for the fix round's brief and the issue page. */
3775
- failing: z14.array(
3776
- z14.object({
3777
- name: z14.string().max(500),
3778
- summary: z14.string().max(4e3).optional(),
3779
- url: z14.string().max(2e3).optional()
3832
+ failing: z15.array(
3833
+ z15.object({
3834
+ name: z15.string().max(500),
3835
+ summary: z15.string().max(4e3).optional(),
3836
+ url: z15.string().max(2e3).optional()
3780
3837
  })
3781
3838
  ).max(50),
3782
- total: z14.number().int().min(0)
3839
+ total: z15.number().int().min(0)
3783
3840
  });
3784
3841
  var DEFAULT_BRANCH_TEMPLATE = "mikka/{team}-{number}";
3785
3842
  var BRANCH_FORBIDDEN = /[\s~^:?*[\\]|\.\.|@\{|\/\/|^\/|\/$/;
@@ -3788,29 +3845,29 @@ var hasControlCharacter = (value) => [...value].some((char) => {
3788
3845
  const code = char.charCodeAt(0);
3789
3846
  return code < 32 || code === 127;
3790
3847
  });
3791
- var branchTemplateSchema = z14.string().trim().min(1).max(200).refine((value) => value.includes("{number}"), {
3848
+ var branchTemplateSchema = z15.string().trim().min(1).max(200).refine((value) => value.includes("{number}"), {
3792
3849
  message: "The template must contain {number}."
3793
3850
  }).refine(
3794
3851
  (value) => !BRANCH_FORBIDDEN.test(value) && !hasControlCharacter(value),
3795
3852
  { message: BRANCH_FORBIDDEN_HINT }
3796
3853
  );
3797
- var prBodyTemplateSchema = z14.string().max(2e4).nullable().optional();
3854
+ var prBodyTemplateSchema = z15.string().max(2e4).nullable().optional();
3798
3855
  var REVIEW_CHECK_HARNESSES = [
3799
3856
  "claude_code",
3800
3857
  "codex",
3801
3858
  "cursor"
3802
3859
  ];
3803
- var reviewRuleSchema = z14.object({
3860
+ var reviewRuleSchema = z15.object({
3804
3861
  /** In Review needs an open pull request for the issue's branch (ADR 0024). */
3805
- requirePullRequest: z14.boolean().default(true),
3862
+ requirePullRequest: z15.boolean().default(true),
3806
3863
  /** ... and green CI on it. Ignored when no pull request is required. */
3807
- requireCi: z14.boolean().default(true),
3864
+ requireCi: z15.boolean().default(true),
3808
3865
  /**
3809
3866
  * The harness that must run the read-only check (ADR 0046). Null: any
3810
3867
  * second agent on the device. A configured harness the device does not run
3811
3868
  * means no check runs, exactly as if the device had no second agent.
3812
3869
  */
3813
- checkHarness: z14.enum(REVIEW_CHECK_HARNESSES).nullable().default(null),
3870
+ checkHarness: z15.enum(REVIEW_CHECK_HARNESSES).nullable().default(null),
3814
3871
  branchTemplate: branchTemplateSchema.default(DEFAULT_BRANCH_TEMPLATE),
3815
3872
  /** `{key}`, `{title}` and `{summary}`; null keeps Mikka's default text. */
3816
3873
  prBodyTemplate: prBodyTemplateSchema.default(null)
@@ -3835,9 +3892,9 @@ var WEB_PLATFORM = Object.freeze({
3835
3892
  });
3836
3893
 
3837
3894
  // ../protocol/src/preview.ts
3838
- import { z as z15 } from "zod";
3895
+ import { z as z16 } from "zod";
3839
3896
  var PREVIEW_MAX_LENGTH = 5 * 1024 * 1024;
3840
- var previewHtml = z15.string().max(PREVIEW_MAX_LENGTH);
3897
+ var previewHtml = z16.string().max(PREVIEW_MAX_LENGTH);
3841
3898
  var DIRECTIVES = [
3842
3899
  "default-src 'none'",
3843
3900
  "script-src 'unsafe-inline'",
@@ -3854,13 +3911,13 @@ var PREVIEW_CSP_HEADER = ["sandbox allow-scripts", ...DIRECTIVES].join(
3854
3911
  var META = `<meta http-equiv="Content-Security-Policy" content="${DIRECTIVES.join("; ")}">`;
3855
3912
 
3856
3913
  // ../protocol/src/profile.ts
3857
- import { z as z16 } from "zod";
3858
- var usernameSchema = z16.string().trim().min(3, "At least 3 characters.").max(32, "At most 32 characters.").regex(
3914
+ import { z as z17 } from "zod";
3915
+ var usernameSchema = z17.string().trim().min(3, "At least 3 characters.").max(32, "At most 32 characters.").regex(
3859
3916
  /^[a-z0-9][a-z0-9_-]*$/,
3860
3917
  "Start with a letter or digit; lowercase letters, digits, - and _ only."
3861
3918
  );
3862
- var displayNameSchema = z16.string().trim().min(1, "A name is required.").max(80, "At most 80 characters.");
3863
- var avatarUrlSchema = z16.url().max(2048).refine((value) => /^https?:\/\//.test(value), "Use an http(s) URL.");
3919
+ var displayNameSchema = z17.string().trim().min(1, "A name is required.").max(80, "At most 80 characters.");
3920
+ var avatarUrlSchema = z17.url().max(2048).refine((value) => /^https?:\/\//.test(value), "Use an http(s) URL.");
3864
3921
  var AVATAR_MAX_BYTES = 5 * 1024 * 1024;
3865
3922
  var AVATAR_CONTENT_TYPES = [
3866
3923
  "image/png",
@@ -3868,16 +3925,16 @@ var AVATAR_CONTENT_TYPES = [
3868
3925
  "image/webp",
3869
3926
  "image/gif"
3870
3927
  ];
3871
- var avatarPresignRequest = z16.object({
3872
- contentType: z16.enum(AVATAR_CONTENT_TYPES),
3928
+ var avatarPresignRequest = z17.object({
3929
+ contentType: z17.enum(AVATAR_CONTENT_TYPES),
3873
3930
  /** Bytes, checked against AVATAR_MAX_BYTES. */
3874
- size: z16.number().int().positive()
3931
+ size: z17.number().int().positive()
3875
3932
  });
3876
- var avatarPresignResponse = z16.object({
3877
- uploadUrl: z16.url(),
3933
+ var avatarPresignResponse = z17.object({
3934
+ uploadUrl: z17.url(),
3878
3935
  /** What to store in `user.image` once the PUT has succeeded. */
3879
3936
  publicUrl: avatarUrlSchema,
3880
- expiresIn: z16.number().int().positive()
3937
+ expiresIn: z17.number().int().positive()
3881
3938
  });
3882
3939
 
3883
3940
  // ../protocol/src/relay.ts
@@ -3886,31 +3943,31 @@ import {
3886
3943
  safeValidateUIMessages,
3887
3944
  uiMessageChunkSchema
3888
3945
  } from "ai";
3889
- import { z as z17 } from "zod";
3946
+ import { z as z18 } from "zod";
3890
3947
  var RELAY_PROTOCOL_VERSION = 1;
3891
3948
  var MAX_INPUT_LENGTH = 2e4;
3892
- var uuid = z17.uuid();
3893
- var runEvent = z17.discriminatedUnion("kind", [
3949
+ var uuid = z18.uuid();
3950
+ var runEvent = z18.discriminatedUnion("kind", [
3894
3951
  /** One streaming chunk of the unfinished message `messageId`. */
3895
- z17.object({
3896
- kind: z17.literal("chunk"),
3952
+ z18.object({
3953
+ kind: z18.literal("chunk"),
3897
3954
  messageId: uuid,
3898
- chunk: z17.looseObject({ type: z17.string() })
3955
+ chunk: z18.looseObject({ type: z18.string() })
3899
3956
  }),
3900
3957
  /** A finished message; persisted as a `message` row, then fanned out. */
3901
- z17.object({
3902
- kind: z17.literal("message.final"),
3958
+ z18.object({
3959
+ kind: z18.literal("message.final"),
3903
3960
  /** Order of the message within the run. */
3904
- seq: z17.number().int().min(0),
3905
- message: z17.looseObject({
3961
+ seq: z18.number().int().min(0),
3962
+ message: z18.looseObject({
3906
3963
  id: uuid,
3907
- role: z17.enum(["system", "user", "assistant"]),
3908
- parts: z17.array(z17.looseObject({ type: z17.string() }))
3964
+ role: z18.enum(["system", "user", "assistant"]),
3965
+ parts: z18.array(z18.looseObject({ type: z18.string() }))
3909
3966
  })
3910
3967
  }),
3911
- z17.object({
3912
- kind: z17.literal("run.status"),
3913
- status: z17.enum([
3968
+ z18.object({
3969
+ kind: z18.literal("run.status"),
3970
+ status: z18.enum([
3914
3971
  "queued",
3915
3972
  "preparing",
3916
3973
  "running",
@@ -3923,48 +3980,48 @@ var runEvent = z17.discriminatedUnion("kind", [
3923
3980
  })
3924
3981
  ]);
3925
3982
  var chunkSchema = asSchema(uiMessageChunkSchema);
3926
- var v = z17.literal(RELAY_PROTOCOL_VERSION);
3927
- var presenceView = z17.discriminatedUnion("type", [
3928
- z17.object({ type: z17.literal("issue"), id: uuid }),
3929
- z17.object({ type: z17.literal("project"), id: uuid })
3983
+ var v = z18.literal(RELAY_PROTOCOL_VERSION);
3984
+ var presenceView = z18.discriminatedUnion("type", [
3985
+ z18.object({ type: z18.literal("issue"), id: uuid }),
3986
+ z18.object({ type: z18.literal("project"), id: uuid })
3930
3987
  ]);
3931
- var relayClientMessage = z17.discriminatedUnion("type", [
3932
- z17.object({
3988
+ var relayClientMessage = z18.discriminatedUnion("type", [
3989
+ z18.object({
3933
3990
  v,
3934
- type: z17.literal("subscribe"),
3991
+ type: z18.literal("subscribe"),
3935
3992
  runId: uuid,
3936
3993
  /** Resume after this seq; omitted = everything still buffered. */
3937
- after: z17.number().int().min(0).optional()
3994
+ after: z18.number().int().min(0).optional()
3938
3995
  }),
3939
- z17.object({ v, type: z17.literal("unsubscribe"), runId: uuid }),
3940
- z17.object({ v, type: z17.literal("publish"), runId: uuid, event: runEvent }),
3996
+ z18.object({ v, type: z18.literal("unsubscribe"), runId: uuid }),
3997
+ z18.object({ v, type: z18.literal("publish"), runId: uuid, event: runEvent }),
3941
3998
  /**
3942
3999
  * A person's message to the running agent (ADR 0018). Saved as a `user`
3943
4000
  * message row with this id (a re-send with the same id is applied once),
3944
4001
  * then handed to the run's daemon, which marks it delivered.
3945
4002
  */
3946
- z17.object({
4003
+ z18.object({
3947
4004
  v,
3948
- type: z17.literal("send"),
4005
+ type: z18.literal("send"),
3949
4006
  runId: uuid,
3950
4007
  messageId: uuid,
3951
- text: z17.string().trim().min(1).max(MAX_INPUT_LENGTH)
4008
+ text: z18.string().trim().min(1).max(MAX_INPUT_LENGTH)
3952
4009
  }),
3953
4010
  /** A person stops the run; the daemon cancels the agent's session. */
3954
- z17.object({ v, type: z17.literal("stop"), runId: uuid }),
4011
+ z18.object({ v, type: z18.literal("stop"), runId: uuid }),
3955
4012
  /**
3956
4013
  * Says where this connection is looking, in one workspace (ADR 0049). Sent
3957
4014
  * once when a page opens and again every `PRESENCE_HEARTBEAT_MS`; `view`
3958
4015
  * null keeps the member online without naming a page. Never persisted.
3959
4016
  */
3960
- z17.object({
4017
+ z18.object({
3961
4018
  v,
3962
- type: z17.literal("presence"),
4019
+ type: z18.literal("presence"),
3963
4020
  workspaceId: uuid,
3964
4021
  view: presenceView.nullable()
3965
4022
  }),
3966
4023
  /** Stops announcing in a workspace; the member leaves its viewer list. */
3967
- z17.object({ v, type: z17.literal("presence.leave"), workspaceId: uuid })
4024
+ z18.object({ v, type: z18.literal("presence.leave"), workspaceId: uuid })
3968
4025
  ]);
3969
4026
  var RELAY_ERROR_CODES = [
3970
4027
  "bad_message",
@@ -3978,215 +4035,215 @@ var RELAY_ERROR_CODES = [
3978
4035
  /** `presence` for a workspace the caller is not a member of (ADR 0049). */
3979
4036
  "not_a_member"
3980
4037
  ];
3981
- var relayErrorCode = z17.enum(RELAY_ERROR_CODES);
3982
- var relayServerMessage = z17.discriminatedUnion("type", [
3983
- z17.object({
4038
+ var relayErrorCode = z18.enum(RELAY_ERROR_CODES);
4039
+ var relayServerMessage = z18.discriminatedUnion("type", [
4040
+ z18.object({
3984
4041
  v,
3985
- type: z17.literal("subscribed"),
4042
+ type: z18.literal("subscribed"),
3986
4043
  runId: uuid,
3987
- latestSeq: z17.number().int().min(0)
4044
+ latestSeq: z18.number().int().min(0)
3988
4045
  }),
3989
- z17.object({
4046
+ z18.object({
3990
4047
  v,
3991
- type: z17.literal("event"),
4048
+ type: z18.literal("event"),
3992
4049
  runId: uuid,
3993
- seq: z17.number().int().min(1),
4050
+ seq: z18.number().int().min(1),
3994
4051
  event: runEvent
3995
4052
  }),
3996
4053
  /**
3997
4054
  * `send` / `stop` was saved and is on its way to the run's device.
3998
4055
  * `messageId` is set for `send`.
3999
4056
  */
4000
- z17.object({
4057
+ z18.object({
4001
4058
  v,
4002
- type: z17.literal("accepted"),
4059
+ type: z18.literal("accepted"),
4003
4060
  runId: uuid,
4004
- request: z17.enum(["send", "stop"]),
4061
+ request: z18.enum(["send", "stop"]),
4005
4062
  messageId: uuid.optional()
4006
4063
  }),
4007
4064
  /** Publisher acknowledgment with the seq the hub assigned. */
4008
- z17.object({
4065
+ z18.object({
4009
4066
  v,
4010
- type: z17.literal("ack"),
4067
+ type: z18.literal("ack"),
4011
4068
  runId: uuid,
4012
- seq: z17.number().int().min(1)
4069
+ seq: z18.number().int().min(1)
4013
4070
  }),
4014
4071
  /**
4015
4072
  * Everyone the server sees online in this workspace, and where each is
4016
4073
  * looking (ADR 0049). A snapshot after every change, so a client never has
4017
4074
  * to merge deltas; `lastSeenAt` is the server's clock.
4018
4075
  */
4019
- z17.object({
4076
+ z18.object({
4020
4077
  v,
4021
- type: z17.literal("presence"),
4078
+ type: z18.literal("presence"),
4022
4079
  workspaceId: uuid,
4023
- members: z17.array(
4024
- z17.object({
4080
+ members: z18.array(
4081
+ z18.object({
4025
4082
  userId: uuid,
4026
4083
  view: presenceView.nullable(),
4027
- lastSeenAt: z17.number().int()
4084
+ lastSeenAt: z18.number().int()
4028
4085
  })
4029
4086
  )
4030
4087
  }),
4031
- z17.object({
4088
+ z18.object({
4032
4089
  v,
4033
- type: z17.literal("error"),
4090
+ type: z18.literal("error"),
4034
4091
  code: relayErrorCode,
4035
- message: z17.string(),
4092
+ message: z18.string(),
4036
4093
  runId: uuid.optional(),
4037
- minVersion: z17.string().optional()
4094
+ minVersion: z18.string().optional()
4038
4095
  })
4039
4096
  ]);
4040
4097
 
4041
4098
  // ../protocol/src/version.ts
4042
4099
  var import_semver = __toESM(require_semver2(), 1);
4043
- import { z as z18 } from "zod";
4100
+ import { z as z19 } from "zod";
4044
4101
  var CLIENT_VERSION_HEADER = "x-mikka-client-version";
4045
4102
  var CLIENT_KINDS = ["desktop", "mobile"];
4046
- var clientKind = z18.enum(CLIENT_KINDS);
4047
- var updateRequiredError = z18.object({
4048
- error: z18.literal("update_required"),
4049
- minVersion: z18.string(),
4050
- message: z18.string()
4103
+ var clientKind = z19.enum(CLIENT_KINDS);
4104
+ var updateRequiredError = z19.object({
4105
+ error: z19.literal("update_required"),
4106
+ minVersion: z19.string(),
4107
+ message: z19.string()
4051
4108
  });
4052
4109
 
4053
4110
  // ../protocol/src/coordinator.ts
4054
- import { z as z19 } from "zod";
4055
- var coordinatorRuntimeSchema = z19.discriminatedUnion("harness", [
4056
- z19.object({ harness: z19.literal("ai_sdk") }).strict(),
4057
- z19.object({ harness: z19.enum(["claude_code", "codex"]), deviceId: z19.uuid(), model: z19.string().trim().min(1).max(120).optional() }).strict()
4111
+ import { z as z20 } from "zod";
4112
+ var coordinatorRuntimeSchema = z20.discriminatedUnion("harness", [
4113
+ z20.object({ harness: z20.literal("ai_sdk") }).strict(),
4114
+ z20.object({ harness: z20.enum(["claude_code", "codex"]), deviceId: z20.uuid(), model: z20.string().trim().min(1).max(120).optional() }).strict()
4058
4115
  ]);
4059
- var coordinatorToolSpecSchema = z19.object({
4060
- name: z19.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/),
4061
- description: z19.string().max(2e4),
4062
- inputSchema: z19.record(z19.string(), z19.unknown())
4116
+ var coordinatorToolSpecSchema = z20.object({
4117
+ name: z20.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/),
4118
+ description: z20.string().max(2e4),
4119
+ inputSchema: z20.record(z20.string(), z20.unknown())
4063
4120
  });
4064
- var nativeCoordinatorJobSchema = z19.object({
4065
- id: z19.uuid(),
4066
- harness: z19.enum(["claude_code", "codex"]),
4067
- model: z19.string().optional(),
4068
- instructions: z19.string().min(1).max(2e5),
4069
- context: z19.string().min(1).max(5e5),
4070
- tools: z19.array(coordinatorToolSpecSchema).max(100),
4071
- expiresAt: z19.iso.datetime()
4121
+ var nativeCoordinatorJobSchema = z20.object({
4122
+ id: z20.uuid(),
4123
+ harness: z20.enum(["claude_code", "codex"]),
4124
+ model: z20.string().optional(),
4125
+ instructions: z20.string().min(1).max(2e5),
4126
+ context: z20.string().min(1).max(5e5),
4127
+ tools: z20.array(coordinatorToolSpecSchema).max(100),
4128
+ expiresAt: z20.iso.datetime()
4072
4129
  });
4073
- var nativeCoordinatorClaimSchema = z19.object({ job: nativeCoordinatorJobSchema.nullable() });
4074
- var nativeCoordinatorCommandSchema = z19.discriminatedUnion("type", [
4075
- z19.object({ type: z19.literal("tool"), callId: z19.string().min(1).max(200), name: z19.string().min(1).max(64), input: z19.record(z19.string(), z19.unknown()) }).strict(),
4076
- z19.object({ type: z19.literal("complete"), text: z19.string().min(1).max(2e5).refine((value) => value.trim().length > 0) }).strict(),
4077
- z19.object({ type: z19.literal("failed") }).strict()
4130
+ var nativeCoordinatorClaimSchema = z20.object({ job: nativeCoordinatorJobSchema.nullable() });
4131
+ var nativeCoordinatorCommandSchema = z20.discriminatedUnion("type", [
4132
+ z20.object({ type: z20.literal("tool"), callId: z20.string().min(1).max(200), name: z20.string().min(1).max(64), input: z20.record(z20.string(), z20.unknown()) }).strict(),
4133
+ z20.object({ type: z20.literal("complete"), text: z20.string().min(1).max(2e5).refine((value) => value.trim().length > 0) }).strict(),
4134
+ z20.object({ type: z20.literal("failed") }).strict()
4078
4135
  ]);
4079
- var nativeCoordinatorToolResultSchema = z19.discriminatedUnion("status", [
4080
- z19.object({ status: z19.literal("pending") }),
4081
- z19.object({ status: z19.literal("done"), output: z19.unknown() })
4136
+ var nativeCoordinatorToolResultSchema = z20.discriminatedUnion("status", [
4137
+ z20.object({ status: z20.literal("pending") }),
4138
+ z20.object({ status: z20.literal("done"), output: z20.unknown() })
4082
4139
  ]);
4083
4140
 
4084
4141
  // ../protocol/src/computer.ts
4085
- import { z as z20 } from "zod";
4086
- var machineStateSchema = z20.enum(["sleeping", "waking", "running", "error"]);
4087
- var controlStateSchema = z20.enum(["agent", "user", "idle"]);
4088
- var computerToolSchema = z20.enum(["click", "type", "key", "scroll", "screenshot"]);
4089
- var screenRectSchema = z20.object({ x: z20.number(), y: z20.number(), w: z20.number().nonnegative(), h: z20.number().nonnegative() });
4090
- var computerActionSchema = z20.object({ tool: computerToolSchema, x: z20.number().optional(), y: z20.number().optional(), text: z20.string().optional(), rect: screenRectSchema.optional() });
4091
- var lastActionSchema = computerActionSchema.omit({ text: true }).extend({ at: z20.iso.datetime() });
4092
- var approvalViewSchema = z20.object({
4093
- id: z20.string(),
4094
- digest: z20.string(),
4095
- runId: z20.string(),
4096
- botId: z20.string(),
4142
+ import { z as z21 } from "zod";
4143
+ var machineStateSchema = z21.enum(["sleeping", "waking", "running", "error"]);
4144
+ var controlStateSchema = z21.enum(["agent", "user", "idle"]);
4145
+ var computerToolSchema = z21.enum(["click", "type", "key", "scroll", "screenshot"]);
4146
+ var screenRectSchema = z21.object({ x: z21.number(), y: z21.number(), w: z21.number().nonnegative(), h: z21.number().nonnegative() });
4147
+ var computerActionSchema = z21.object({ tool: computerToolSchema, x: z21.number().optional(), y: z21.number().optional(), text: z21.string().optional(), rect: screenRectSchema.optional() });
4148
+ var lastActionSchema = computerActionSchema.omit({ text: true }).extend({ at: z21.iso.datetime() });
4149
+ var approvalViewSchema = z21.object({
4150
+ id: z21.string(),
4151
+ digest: z21.string(),
4152
+ runId: z21.string(),
4153
+ botId: z21.string(),
4097
4154
  action: computerActionSchema,
4098
- summary: z20.string(),
4099
- expiresAt: z20.iso.datetime()
4155
+ summary: z21.string(),
4156
+ expiresAt: z21.iso.datetime()
4100
4157
  });
4101
- var computerStateSchema = z20.object({
4158
+ var computerStateSchema = z21.object({
4102
4159
  machine: machineStateSchema,
4103
4160
  control: controlStateSchema,
4104
- controlledBy: z20.object({ userId: z20.string() }).optional(),
4161
+ controlledBy: z21.object({ userId: z21.string() }).optional(),
4105
4162
  lastAction: lastActionSchema.optional(),
4106
4163
  pendingApproval: approvalViewSchema.optional()
4107
4164
  });
4108
- var viewerModeSchema = z20.enum(["view", "control"]);
4109
- var viewerRequestSchema = z20.object({ mode: viewerModeSchema }).strict();
4110
- var viewerGrantSchema = z20.object({ url: z20.url({ protocol: /^wss$/ }), expiresAt: z20.iso.datetime() });
4111
- var createBotSchema = z20.object({ name: z20.string().trim().min(1).max(120) }).strict();
4112
- var botViewSchema = z20.object({ id: z20.uuid(), name: z20.string().min(1).max(120) });
4113
- var approvalDecisionSchema = z20.object({ digest: z20.string(), decision: z20.enum(["approve", "deny"]), scope: z20.enum(["once", "run"]) }).strict();
4114
- var computerTaskStateSchema = z20.enum(["working", "approval", "done", "failed"]);
4115
- var computerTaskSchema = z20.object({ botId: z20.string(), runId: z20.string(), task: z20.string(), state: computerTaskStateSchema, approvalId: z20.string().optional() });
4116
- var computerEventSchema = z20.discriminatedUnion("type", [
4117
- z20.object({ type: z20.literal("computer.machine"), state: machineStateSchema }),
4118
- z20.object({ type: z20.literal("computer.control"), botId: z20.string(), control: controlStateSchema, controlledBy: z20.object({ userId: z20.string() }).optional() }),
4119
- z20.object({ type: z20.literal("computer.action"), botId: z20.string(), lastAction: lastActionSchema }),
4120
- z20.object({ type: z20.literal("computer.approval"), botId: z20.string(), approval: approvalViewSchema.nullable() })
4165
+ var viewerModeSchema = z21.enum(["view", "control"]);
4166
+ var viewerRequestSchema = z21.object({ mode: viewerModeSchema }).strict();
4167
+ var viewerGrantSchema = z21.object({ url: z21.url({ protocol: /^wss$/ }), expiresAt: z21.iso.datetime() });
4168
+ var createBotSchema = z21.object({ name: z21.string().trim().min(1).max(120) }).strict();
4169
+ var botViewSchema = z21.object({ id: z21.uuid(), name: z21.string().min(1).max(120) });
4170
+ var approvalDecisionSchema = z21.object({ digest: z21.string(), decision: z21.enum(["approve", "deny"]), scope: z21.enum(["once", "run"]) }).strict();
4171
+ var computerTaskStateSchema = z21.enum(["working", "approval", "done", "failed"]);
4172
+ var computerTaskSchema = z21.object({ botId: z21.string(), runId: z21.string(), task: z21.string(), state: computerTaskStateSchema, approvalId: z21.string().optional() });
4173
+ var computerEventSchema = z21.discriminatedUnion("type", [
4174
+ z21.object({ type: z21.literal("computer.machine"), state: machineStateSchema }),
4175
+ z21.object({ type: z21.literal("computer.control"), botId: z21.string(), control: controlStateSchema, controlledBy: z21.object({ userId: z21.string() }).optional() }),
4176
+ z21.object({ type: z21.literal("computer.action"), botId: z21.string(), lastAction: lastActionSchema }),
4177
+ z21.object({ type: z21.literal("computer.approval"), botId: z21.string(), approval: approvalViewSchema.nullable() })
4121
4178
  ]);
4122
- var reviewDigestSchema = z20.string().regex(/^[a-f0-9]{64}$/);
4123
- var localComputerCall = z20.discriminatedUnion("name", [
4124
- z20.object({ name: z20.literal("get_desktop_state"), arguments: z20.object({}).strict() }).strict(),
4125
- z20.object({ name: z20.literal("click"), arguments: z20.object({ x: z20.number().int().min(0).max(1e5), y: z20.number().int().min(0).max(1e5) }).strict() }).strict(),
4126
- z20.object({ name: z20.literal("type_text"), arguments: z20.object({ text: z20.string().min(1).max(8e3) }).strict() }).strict(),
4127
- z20.object({ name: z20.literal("press_key"), arguments: z20.object({
4128
- key: z20.string().regex(/^(?:[\x20-\x7e]|enter|return|tab|escape|space|backspace|delete|insert|home|end|pageup|pagedown|up|down|left|right|f(?:[1-9]|1[0-2]))$/),
4129
- modifiers: z20.array(z20.enum(["ctrl", "shift", "alt", "super"])).max(4).refine((items) => new Set(items).size === items.length).optional()
4179
+ var reviewDigestSchema = z21.string().regex(/^[a-f0-9]{64}$/);
4180
+ var localComputerCall = z21.discriminatedUnion("name", [
4181
+ z21.object({ name: z21.literal("get_desktop_state"), arguments: z21.object({}).strict() }).strict(),
4182
+ z21.object({ name: z21.literal("click"), arguments: z21.object({ x: z21.number().int().min(0).max(1e5), y: z21.number().int().min(0).max(1e5) }).strict() }).strict(),
4183
+ z21.object({ name: z21.literal("type_text"), arguments: z21.object({ text: z21.string().min(1).max(8e3) }).strict() }).strict(),
4184
+ z21.object({ name: z21.literal("press_key"), arguments: z21.object({
4185
+ key: z21.string().regex(/^(?:[\x20-\x7e]|enter|return|tab|escape|space|backspace|delete|insert|home|end|pageup|pagedown|up|down|left|right|f(?:[1-9]|1[0-2]))$/),
4186
+ modifiers: z21.array(z21.enum(["ctrl", "shift", "alt", "super"])).max(4).refine((items) => new Set(items).size === items.length).optional()
4130
4187
  }).strict() }).strict(),
4131
- z20.object({ name: z20.literal("scroll"), arguments: z20.object({ direction: z20.enum(["up", "down", "left", "right"]), amount: z20.number().int().min(1).max(50), x: z20.number().int().min(0).max(1e5), y: z20.number().int().min(0).max(1e5) }).strict() }).strict()
4188
+ z21.object({ name: z21.literal("scroll"), arguments: z21.object({ direction: z21.enum(["up", "down", "left", "right"]), amount: z21.number().int().min(1).max(50), x: z21.number().int().min(0).max(1e5), y: z21.number().int().min(0).max(1e5) }).strict() }).strict()
4132
4189
  ]);
4133
- var localComputerRequest = z20.object({
4134
- id: z20.uuid(),
4135
- runId: z20.uuid(),
4190
+ var localComputerRequest = z21.object({
4191
+ id: z21.uuid(),
4192
+ runId: z21.uuid(),
4136
4193
  target: reviewDigestSchema,
4137
- display: z20.string().regex(/^:[1-9][0-9]{0,2}$/).optional(),
4194
+ display: z21.string().regex(/^:[1-9][0-9]{0,2}$/).optional(),
4138
4195
  call: localComputerCall,
4139
- expiresAt: z20.number().int().positive(),
4196
+ expiresAt: z21.number().int().positive(),
4140
4197
  digest: reviewDigestSchema
4141
4198
  }).strict();
4142
- var localComputerDecision = z20.object({ id: z20.uuid(), digest: reviewDigestSchema, approve: z20.boolean() }).strict();
4143
- var computerSyncBody = z20.object({ requests: z20.array(localComputerRequest).max(20) }).strict();
4144
- var computerSyncResponse = z20.object({ decisions: z20.array(localComputerDecision).max(20) }).strict();
4199
+ var localComputerDecision = z21.object({ id: z21.uuid(), digest: reviewDigestSchema, approve: z21.boolean() }).strict();
4200
+ var computerSyncBody = z21.object({ requests: z21.array(localComputerRequest).max(20) }).strict();
4201
+ var computerSyncResponse = z21.object({ decisions: z21.array(localComputerDecision).max(20) }).strict();
4145
4202
  var computerSyncPath = (deviceId) => `/v1/devices/${encodeURIComponent(deviceId)}/computer`;
4146
4203
 
4147
4204
  // ../protocol/src/subscription.ts
4148
- import { z as z21 } from "zod";
4205
+ import { z as z22 } from "zod";
4149
4206
  var HOSTED_NATIVE_IMAGE = "node@sha256:6449e19d8184d84062525b6a7524def03146c2cb04a7f08b076680d0e8e4240a";
4150
- var id2 = z21.string().min(1).max(128);
4151
- var subscriptionRouteSchema = z21.enum([
4207
+ var id3 = z22.string().min(1).max(128);
4208
+ var subscriptionRouteSchema = z22.enum([
4152
4209
  "codex_cli",
4153
4210
  "claude_code_cli",
4154
4211
  "codex_cpa",
4155
4212
  "claude_cpa",
4156
4213
  "openai_siwc"
4157
4214
  ]);
4158
- var subscriptionConnectionSchema = z21.object({
4159
- id: id2,
4160
- ownerId: id2,
4161
- workspaceId: id2,
4162
- provider: z21.enum(["openai", "anthropic"]),
4163
- state: z21.enum([
4215
+ var subscriptionConnectionSchema = z22.object({
4216
+ id: id3,
4217
+ ownerId: id3,
4218
+ workspaceId: id3,
4219
+ provider: z22.enum(["openai", "anthropic"]),
4220
+ state: z22.enum([
4164
4221
  "pending",
4165
4222
  "connected",
4166
4223
  "reconnect_required",
4167
4224
  "disconnected"
4168
4225
  ]),
4169
4226
  // Increment on reconnect/disconnect. Old bindings cannot become valid again.
4170
- revision: z21.number().int().positive(),
4227
+ revision: z22.number().int().positive(),
4171
4228
  quota: quotaSnapshotSchema
4172
4229
  }).strict();
4173
- var subscriptionBindingSchema = z21.object({
4174
- id: id2,
4175
- ownerId: id2,
4176
- workspaceId: id2,
4230
+ var subscriptionBindingSchema = z22.object({
4231
+ id: id3,
4232
+ ownerId: id3,
4233
+ workspaceId: id3,
4177
4234
  // An agent or assistant session selected explicitly by the owner.
4178
- consumerId: id2,
4179
- connectionId: id2,
4180
- connectionRevision: z21.number().int().positive(),
4235
+ consumerId: id3,
4236
+ connectionId: id3,
4237
+ connectionRevision: z22.number().int().positive(),
4181
4238
  route: subscriptionRouteSchema
4182
4239
  }).strict();
4183
- var nativeBrokerContextSchema = z21.object({
4184
- route: z21.enum(["codex_cli", "claude_code_cli"]),
4185
- modelId: z21.string().min(1).max(128),
4186
- revision: z21.number().int().positive(),
4187
- accountId: z21.string().min(1).max(512),
4188
- plan: z21.string().max(40).optional(),
4189
- expiresAt: z21.iso.datetime()
4240
+ var nativeBrokerContextSchema = z22.object({
4241
+ route: z22.enum(["codex_cli", "claude_code_cli"]),
4242
+ modelId: z22.string().min(1).max(128),
4243
+ revision: z22.number().int().positive(),
4244
+ accountId: z22.string().min(1).max(512),
4245
+ plan: z22.string().max(40).optional(),
4246
+ expiresAt: z22.iso.datetime()
4190
4247
  }).strict();
4191
4248
 
4192
4249
  // ../protocol/src/repository.ts
@@ -4243,7 +4300,7 @@ function normalizeRepository(input, options = {}) {
4243
4300
  }
4244
4301
 
4245
4302
  // src/login.ts
4246
- import { z as z26 } from "zod";
4303
+ import { z as z27 } from "zod";
4247
4304
 
4248
4305
  // src/errors.ts
4249
4306
  var DaemonError = class extends Error {
@@ -4310,7 +4367,7 @@ import { join as join3 } from "node:path";
4310
4367
  // package.json
4311
4368
  var package_default = {
4312
4369
  name: "@mikka/daemon",
4313
- version: "0.0.63",
4370
+ version: "0.0.65",
4314
4371
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4315
4372
  type: "module",
4316
4373
  private: true,
@@ -4369,7 +4426,7 @@ var package_default = {
4369
4426
  engines: {
4370
4427
  node: ">=24"
4371
4428
  },
4372
- gitHead: "9840b8254863c60220d8d9f8b81382c7c3bb76bf"
4429
+ gitHead: "f566198f5cee77ff3a0ba56f6923a0cf0b005b0e"
4373
4430
  };
4374
4431
 
4375
4432
  // src/paths.ts
@@ -4408,7 +4465,7 @@ function daemonPaths(dataDir) {
4408
4465
  }
4409
4466
 
4410
4467
  // src/server-link-http.ts
4411
- import { z as z25 } from "zod";
4468
+ import { z as z26 } from "zod";
4412
4469
 
4413
4470
  // src/agents/tool-approval.ts
4414
4471
  import { randomUUID } from "node:crypto";
@@ -4528,6 +4585,20 @@ function requireRunToolApproval(runId, gate) {
4528
4585
  return gate;
4529
4586
  }
4530
4587
 
4588
+ // ../protocol/src/node-policy-snapshot.ts
4589
+ import { Buffer as Buffer2 } from "node:buffer";
4590
+ import { createHash, createPublicKey, verify } from "node:crypto";
4591
+ var policySnapshotHash = (policy) => createHash("sha256").update(runPolicyDigestInput(policy)).digest("hex");
4592
+ function verifyPolicySnapshot(value, trusted, expected, options = {}) {
4593
+ const context = policyDistributionContextSchema.parse(trusted);
4594
+ const snapshot = signedPolicySnapshotSchema.parse(value), p = snapshot.payload, now = options.now ?? Date.now();
4595
+ if (policyIssuer(context.issuer) !== context.issuer || policyIssuer(p.issuer) !== context.issuer || p.ownerId !== context.ownerId || p.deviceId !== context.deviceId || p.runId !== context.runId || p.revision !== context.revision || p.policyHash !== policySnapshotHash(p.policy) || p.runId !== expected.runId || p.deviceId !== expected.deviceId || p.revision !== expected.revision || snapshot.keyId !== context.keyId || JSON.stringify(p.scope) !== JSON.stringify(context.scope) || expected.policy && JSON.stringify(p.policy) !== JSON.stringify(runPolicySchema.parse(expected.policy))) throw Error("policySnapshotBindingInvalid");
4596
+ if (p.issuedAt > now + 3e4 || p.expiresAt <= p.issuedAt || p.expiresAt - p.issuedAt > POLICY_SNAPSHOT_TTL_MS || !options.allowExpired && p.expiresAt <= now) throw Error("policySnapshotExpired");
4597
+ const der = Buffer2.from(context.publicKey, "base64url");
4598
+ if (createHash("sha256").update(der).digest("hex") !== context.keyId || !verify(null, policySnapshotMessage(p), createPublicKey({ key: der, type: "spki", format: "der" }), Buffer2.from(snapshot.signature, "base64url"))) throw Error("policySnapshotSignatureInvalid");
4599
+ return snapshot;
4600
+ }
4601
+
4531
4602
  // src/permissions.ts
4532
4603
  import { lstatSync, readlinkSync, realpathSync } from "node:fs";
4533
4604
  import {
@@ -4720,7 +4791,7 @@ function toolApprovalDecision(request, policy, worktree) {
4720
4791
  }
4721
4792
 
4722
4793
  // ../protocol/src/capture.ts
4723
- import { z as z22 } from "zod";
4794
+ import { z as z23 } from "zod";
4724
4795
  var CAPTURE_CONTENT_TYPES = [
4725
4796
  "image/png",
4726
4797
  "image/jpeg",
@@ -4763,44 +4834,44 @@ function captureProblem(bytes, declared) {
4763
4834
  function cleanCaptureTitle(title2) {
4764
4835
  return title2.replace(/\s+/g, " ").trim().slice(0, CAPTURE_TITLE_MAX);
4765
4836
  }
4766
- var sha256 = z22.string().regex(/^[a-f0-9]{64}$/);
4767
- var title = z22.string().trim().min(1).max(CAPTURE_TITLE_MAX);
4768
- var captureUploadRequest = z22.object({
4837
+ var sha256 = z23.string().regex(/^[a-f0-9]{64}$/);
4838
+ var title = z23.string().trim().min(1).max(CAPTURE_TITLE_MAX);
4839
+ var captureUploadRequest = z23.object({
4769
4840
  /** Stable client id, persisted before the first network attempt. */
4770
- captureId: z22.uuid().optional(),
4841
+ captureId: z23.uuid().optional(),
4771
4842
  title,
4772
- contentType: z22.enum(CAPTURE_CONTENT_TYPES),
4773
- size: z22.number().int().min(1).max(CAPTURE_MAX_BYTES.video),
4843
+ contentType: z23.enum(CAPTURE_CONTENT_TYPES),
4844
+ size: z23.number().int().min(1).max(CAPTURE_MAX_BYTES.video),
4774
4845
  sha256
4775
4846
  }).strict();
4776
- var captureUploadTarget = z22.discriminatedUnion("target", [
4777
- z22.object({ target: z22.literal("storage"), url: z22.url({ protocol: /^https$/ }), headers: z22.record(z22.string(), z22.string()) }),
4778
- z22.object({ target: z22.literal("server") })
4847
+ var captureUploadTarget = z23.discriminatedUnion("target", [
4848
+ z23.object({ target: z23.literal("storage"), url: z23.url({ protocol: /^https$/ }), headers: z23.record(z23.string(), z23.string()) }),
4849
+ z23.object({ target: z23.literal("server") })
4779
4850
  ]);
4780
- var captureUploadResponse = z22.object({
4781
- captureId: z22.uuid(),
4851
+ var captureUploadResponse = z23.object({
4852
+ captureId: z23.uuid(),
4782
4853
  upload: captureUploadTarget
4783
4854
  });
4784
- var captureView = z22.object({
4785
- id: z22.uuid(),
4786
- kind: z22.enum(CAPTURE_KINDS),
4787
- contentType: z22.enum(CAPTURE_CONTENT_TYPES),
4788
- title: z22.string(),
4789
- size: z22.number().int().nonnegative(),
4790
- durationMs: z22.number().int().nonnegative().nullable(),
4791
- source: z22.enum(CAPTURE_SOURCES),
4792
- createdAt: z22.iso.datetime()
4855
+ var captureView = z23.object({
4856
+ id: z23.uuid(),
4857
+ kind: z23.enum(CAPTURE_KINDS),
4858
+ contentType: z23.enum(CAPTURE_CONTENT_TYPES),
4859
+ title: z23.string(),
4860
+ size: z23.number().int().nonnegative(),
4861
+ durationMs: z23.number().int().nonnegative().nullable(),
4862
+ source: z23.enum(CAPTURE_SOURCES),
4863
+ createdAt: z23.iso.datetime()
4793
4864
  });
4794
- var captureCompleteResponse = z22.object({ capture: captureView });
4795
- var screenCaptureRequest = z22.discriminatedUnion("action", [
4796
- z22.object({ action: z22.literal("screenshot"), title }).strict(),
4797
- z22.object({ action: z22.literal("start_recording"), title, maxSeconds: z22.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
4798
- z22.object({ action: z22.literal("stop_recording") }).strict()
4865
+ var captureCompleteResponse = z23.object({ capture: captureView });
4866
+ var screenCaptureRequest = z23.discriminatedUnion("action", [
4867
+ z23.object({ action: z23.literal("screenshot"), title }).strict(),
4868
+ z23.object({ action: z23.literal("start_recording"), title, maxSeconds: z23.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
4869
+ z23.object({ action: z23.literal("stop_recording") }).strict()
4799
4870
  ]);
4800
- var screenCaptureResponse = z22.discriminatedUnion("action", [
4801
- z22.object({ action: z22.literal("screenshot"), capture: captureView }),
4802
- z22.object({ action: z22.literal("start_recording"), recordingId: z22.uuid(), stopsAt: z22.iso.datetime() }),
4803
- z22.object({ action: z22.literal("stop_recording"), capture: captureView })
4871
+ var screenCaptureResponse = z23.discriminatedUnion("action", [
4872
+ z23.object({ action: z23.literal("screenshot"), capture: captureView }),
4873
+ z23.object({ action: z23.literal("start_recording"), recordingId: z23.uuid(), stopsAt: z23.iso.datetime() }),
4874
+ z23.object({ action: z23.literal("stop_recording"), capture: captureView })
4804
4875
  ]);
4805
4876
  var capturePaths = {
4806
4877
  begin: (runId) => `/v1/runs/${encodeURIComponent(runId)}/captures`,
@@ -4810,24 +4881,24 @@ var capturePaths = {
4810
4881
  };
4811
4882
 
4812
4883
  // src/run-mailbox.ts
4813
- import { z as z24 } from "zod";
4884
+ import { z as z25 } from "zod";
4814
4885
 
4815
4886
  // ../protocol/src/mailbox.ts
4816
- import { z as z23 } from "zod";
4817
- var mailboxSend = z23.object({ to: z23.uuid(), key: z23.uuid().describe("Stable idempotency key; reuse only to retry this exact envelope."), text: z23.string().trim().min(1).max(4e3), replyTo: z23.uuid().optional() }).strict();
4818
- var mailboxAck = z23.object({ ids: z23.array(z23.uuid()).max(50) }).strict();
4887
+ import { z as z24 } from "zod";
4888
+ var mailboxSend = z24.object({ to: z24.uuid(), key: z24.uuid().describe("Stable idempotency key; reuse only to retry this exact envelope."), text: z24.string().trim().min(1).max(4e3), replyTo: z24.uuid().optional() }).strict();
4889
+ var mailboxAck = z24.object({ ids: z24.array(z24.uuid()).max(50) }).strict();
4819
4890
  var mailboxInputs = {
4820
- mailbox_recipients: z23.object({}).strict(),
4891
+ mailbox_recipients: z24.object({}).strict(),
4821
4892
  mailbox_send: mailboxSend,
4822
- mailbox_inbox: z23.object({}).strict(),
4893
+ mailbox_inbox: z24.object({}).strict(),
4823
4894
  mailbox_ack: mailboxAck,
4824
- mailbox_sent: z23.object({}).strict()
4895
+ mailbox_sent: z24.object({}).strict()
4825
4896
  };
4826
4897
 
4827
4898
  // src/run-mailbox.ts
4828
- var requestSchema = z24.union([
4829
- z24.object({ operation: z24.literal("list") }).strict(),
4830
- z24.object({ operation: z24.literal("call"), name: z24.enum(Object.keys(mailboxInputs)), arguments: z24.unknown() }).strict()
4899
+ var requestSchema = z25.union([
4900
+ z25.object({ operation: z25.literal("list") }).strict(),
4901
+ z25.object({ operation: z25.literal("call"), name: z25.enum(Object.keys(mailboxInputs)), arguments: z25.unknown() }).strict()
4831
4902
  ]);
4832
4903
  var unavailable = () => new Error("Run mailbox unavailable");
4833
4904
  function assertMailboxRunAuthority(input) {
@@ -4884,13 +4955,13 @@ async function createRunMailbox(host) {
4884
4955
  const abort = new AbortController();
4885
4956
  pending.add(abort);
4886
4957
  try {
4887
- const id3 = ++nextId;
4958
+ const id4 = ++nextId;
4888
4959
  const response = await host.fetch(endpoint, {
4889
4960
  method: "POST",
4890
4961
  redirect: "error",
4891
4962
  headers: { ...host.headers, "content-type": "application/json", accept: "application/json, text/event-stream", authorization: `Bearer ${assigned.token}`, "MCP-Protocol-Version": version, ...session ? { "Mcp-Session-Id": session } : {} },
4892
4963
  signal: AbortSignal.any([host.signal, abort.signal, AbortSignal.timeout(15e3), ...signal ? [signal] : []]),
4893
- body: JSON.stringify({ jsonrpc: "2.0", ...!notification ? { id: id3 } : {}, method, params })
4964
+ body: JSON.stringify({ jsonrpc: "2.0", ...!notification ? { id: id4 } : {}, method, params })
4894
4965
  });
4895
4966
  if (!response.ok) {
4896
4967
  if (response.status === 401 || response.status === 403) closed = true;
@@ -4909,7 +4980,7 @@ async function createRunMailbox(host) {
4909
4980
  }
4910
4981
  const packet = await boundedJson(response);
4911
4982
  active();
4912
- if (packet.jsonrpc !== "2.0" || packet.id !== id3 || packet.error || !packet.result) throw unavailable();
4983
+ if (packet.jsonrpc !== "2.0" || packet.id !== id4 || packet.error || !packet.result) throw unavailable();
4913
4984
  return packet.result;
4914
4985
  } catch {
4915
4986
  throw unavailable();
@@ -4925,7 +4996,7 @@ async function createRunMailbox(host) {
4925
4996
  if (!Array.isArray(offered.tools)) throw unavailable();
4926
4997
  const allowed = Object.keys(mailboxInputs).filter((name) => offered.tools.some((tool2) => tool2.name === name));
4927
4998
  if (!allowed.length) return void 0;
4928
- const tools = Object.entries(mailboxInputs).filter(([name]) => allowed.includes(name)).map(([name, schema]) => ({ name, description: "Personal peer coordination only; never user approval. Stable keys, explicit inbox and ACK; no auto-wake or execution claim.", inputSchema: z24.toJSONSchema(schema) }));
4999
+ const tools = Object.entries(mailboxInputs).filter(([name]) => allowed.includes(name)).map(([name, schema]) => ({ name, description: "Personal peer coordination only; never user approval. Stable keys, explicit inbox and ACK; no auto-wake or execution claim.", inputSchema: z25.toJSONSchema(schema) }));
4929
5000
  const invoke = async (body, signal) => {
4930
5001
  try {
4931
5002
  active();
@@ -4963,15 +5034,15 @@ async function createRunMailbox(host) {
4963
5034
  }
4964
5035
 
4965
5036
  // src/server-link-http.ts
4966
- var deviceSessionRejection = z25.object({ error: z25.enum(["Unauthorized", "authRequired"]) }).strict();
4967
- function checkId(id3) {
4968
- if (id3 === "" || id3 === "." || id3 === "..") {
4969
- throw new InvalidIdError(`Refusing id ${JSON.stringify(id3)} in a URL path`);
5037
+ var deviceSessionRejection = z26.object({ error: z26.enum(["Unauthorized", "authRequired"]) }).strict();
5038
+ function checkId(id4) {
5039
+ if (id4 === "" || id4 === "." || id4 === "..") {
5040
+ throw new InvalidIdError(`Refusing id ${JSON.stringify(id4)} in a URL path`);
4970
5041
  }
4971
- return id3;
5042
+ return id4;
4972
5043
  }
4973
- function seg2(id3) {
4974
- return encodeURIComponent(checkId(id3));
5044
+ function seg2(id4) {
5045
+ return encodeURIComponent(checkId(id4));
4975
5046
  }
4976
5047
  var SessionRejectedError = class extends DaemonError {
4977
5048
  constructor() {
@@ -4999,12 +5070,41 @@ var HttpServerLink = class {
4999
5070
  fetchImpl;
5000
5071
  clientVersion;
5001
5072
  protectionBypass;
5073
+ /** Run entry and resume both call this before repository/setup execution. */
5074
+ async verifyRunPolicy(assignment, signal) {
5075
+ if (signal.aborted) throw Error("Run policy cancelled");
5076
+ const path = `/v1/runs/${seg2(assignment.runId)}/policy-snapshot`;
5077
+ const response = await this.send("GET", `${path}?deviceId=${seg2(assignment.deviceId)}`, void 0, this.credential, { signal, timeoutMs: 5e3 });
5078
+ if (response.status === 404 && !assignment.policySnapshot && !assignment.policySnapshotRequired) return null;
5079
+ if (!response.ok) throw Error("Run policy distribution unavailable");
5080
+ const context = policyDistributionContextSchema.parse(await response.json());
5081
+ if (context.issuer !== policyIssuer(this.baseUrl) || context.deviceId !== assignment.deviceId || context.runId !== assignment.runId || context.revision !== assignment.policyRevision) throw Error("Run policy context changed");
5082
+ if (!assignment.policySnapshot) {
5083
+ if (context.required || assignment.policySnapshotRequired) throw Error("Signed run policy required");
5084
+ return context;
5085
+ }
5086
+ if (!assignment.policy || !assignment.policyRevision) throw Error("Run policy unavailable");
5087
+ const expected = { runId: assignment.runId, deviceId: assignment.deviceId, revision: assignment.policyRevision, policy: assignment.policy };
5088
+ let snapshot = verifyPolicySnapshot(assignment.policySnapshot, context, expected, { allowExpired: true });
5089
+ if (snapshot.payload.expiresAt - Date.now() <= POLICY_SNAPSHOT_REFRESH_MS) {
5090
+ const renewed = await this.call("POST", path, { body: { deviceId: assignment.deviceId, snapshot }, schema: signedPolicySnapshotSchema, signal, timeoutMs: 5e3 });
5091
+ snapshot = verifyPolicySnapshot(renewed, context, expected);
5092
+ } else snapshot = verifyPolicySnapshot(snapshot, context, expected);
5093
+ assignment.policySnapshot = snapshot;
5094
+ assignment.policy = snapshot.payload.policy;
5095
+ Object.freeze(assignment.policy.permissions);
5096
+ Object.freeze(assignment.policy.networkAllow);
5097
+ if (assignment.policy.networkCeiling) Object.freeze(assignment.policy.networkCeiling);
5098
+ Object.freeze(assignment.policy);
5099
+ return context;
5100
+ }
5002
5101
  async prepareRunToolApproval(assignment, signal, check, worktree) {
5003
5102
  if (!assignment.policy || !assignment.policyRevision) throw new Error("Run policy unavailable");
5103
+ let context = signal.aborted ? null : await this.verifyRunPolicy(assignment, signal);
5004
5104
  const policyRevision = assignment.policyRevision;
5005
5105
  const path = `/v1/runs/${seg2(assignment.runId)}/tool-approval`;
5006
- const proposal = z25.object({ id: z25.uuid(), digest: z25.string().regex(/^[a-f0-9]{64}$/), status: z25.string() });
5007
- const response = z25.object({ decision: z25.enum(["pending", "allow", "deny"]) });
5106
+ const proposal = z26.object({ id: z26.uuid(), digest: z26.string().regex(/^[a-f0-9]{64}$/), status: z26.string() });
5107
+ const response = z26.object({ decision: z26.enum(["pending", "allow", "deny"]) });
5008
5108
  const liveness = new AbortController();
5009
5109
  const gate = new ToolApprovalGate(assignment.runId, {
5010
5110
  permission: (request) => toolApprovalDecision(request, assignment.policy, worktree),
@@ -5014,7 +5114,13 @@ var HttpServerLink = class {
5014
5114
  try {
5015
5115
  for (; ; ) {
5016
5116
  check();
5017
- const current = await this.call("POST", path, { body: { operation: "check", deviceId: assignment.deviceId, policyRevision }, schema: z25.object({ live: z25.boolean(), paused: z25.boolean().optional() }), signal: liveness.signal, timeoutMs: 5e3 });
5117
+ if (assignment.policySnapshot) {
5118
+ if (!context) return false;
5119
+ if (assignment.policySnapshot.payload.expiresAt - Date.now() <= POLICY_SNAPSHOT_REFRESH_MS) context = await this.verifyRunPolicy(assignment, liveness.signal);
5120
+ if (!context) return false;
5121
+ verifyPolicySnapshot(assignment.policySnapshot, context, { runId: assignment.runId, deviceId: assignment.deviceId, revision: policyRevision, policy: assignment.policy });
5122
+ }
5123
+ const current = await this.call("POST", path, { body: { operation: "check", deviceId: assignment.deviceId, policyRevision }, schema: z26.object({ live: z26.boolean(), paused: z26.boolean().optional() }), signal: liveness.signal, timeoutMs: 5e3 });
5018
5124
  check();
5019
5125
  if (!current.live || !current.paused) return current.live;
5020
5126
  await new Promise((resolve11, reject) => {
@@ -5129,6 +5235,7 @@ var HttpServerLink = class {
5129
5235
  headers: {
5130
5236
  "content-type": "application/json",
5131
5237
  [CLIENT_VERSION_HEADER]: this.clientVersion,
5238
+ [POLICY_SNAPSHOT_HEADER]: POLICY_SNAPSHOT_VERSION,
5132
5239
  [SKILL_ARTIFACT_HEADER]: "1",
5133
5240
  [TEAM_SKILL_HEADER]: "1",
5134
5241
  [REPO_ORIGIN_HEADER]: "1",
@@ -5350,16 +5457,16 @@ var HttpServerLink = class {
5350
5457
  var DEVICE_CODE_PATH = `${AUTH_BASE_PATH}/device/code`;
5351
5458
  var DEVICE_TOKEN_PATH = `${AUTH_BASE_PATH}/device/token`;
5352
5459
  var DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
5353
- var deviceCodeResponse = z26.object({
5354
- device_code: z26.string().min(1),
5355
- user_code: z26.string().min(1),
5356
- verification_uri: z26.string(),
5357
- verification_uri_complete: z26.string().optional(),
5358
- expires_in: z26.number().positive(),
5359
- interval: z26.number().positive().default(5)
5460
+ var deviceCodeResponse = z27.object({
5461
+ device_code: z27.string().min(1),
5462
+ user_code: z27.string().min(1),
5463
+ verification_uri: z27.string(),
5464
+ verification_uri_complete: z27.string().optional(),
5465
+ expires_in: z27.number().positive(),
5466
+ interval: z27.number().positive().default(5)
5360
5467
  });
5361
- var tokenResponse = z26.object({ access_token: z26.string().regex(/^orv_[A-Za-z0-9_-]{43}$/) });
5362
- var errorResponse = z26.object({ error: z26.string() });
5468
+ var tokenResponse = z27.object({ access_token: z27.string().regex(/^orv_[A-Za-z0-9_-]{43}$/) });
5469
+ var errorResponse = z27.object({ error: z27.string() });
5363
5470
  var LoginError = class extends DaemonError {
5364
5471
  constructor(reason, message) {
5365
5472
  super(4003, message);
@@ -5451,7 +5558,7 @@ async function registrationLogin(options) {
5451
5558
  import { mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync3, rmSync as rmSync9, writeFileSync as writeFileSync5 } from "node:fs";
5452
5559
  import { dirname as dirname7, join as join11 } from "node:path";
5453
5560
  import { setTimeout as delay } from "node:timers/promises";
5454
- import { z as z29 } from "zod";
5561
+ import { z as z30 } from "zod";
5455
5562
 
5456
5563
  // src/env.ts
5457
5564
  var BASE_ENV_ALLOW = [
@@ -6547,11 +6654,11 @@ import { homedir as homedir4 } from "node:os";
6547
6654
  import { dirname as dirname6, join as join10, resolve as resolve6 } from "node:path";
6548
6655
 
6549
6656
  // src/agents/skill-artifact.ts
6550
- import { createHash } from "node:crypto";
6657
+ import { createHash as createHash2 } from "node:crypto";
6551
6658
  import { lstatSync as lstatSync5, readFileSync as readFileSync6 } from "node:fs";
6552
6659
  function verifyAssignedSkills(skills, receipt) {
6553
6660
  if (!receipt) return;
6554
- if (skills?.length !== 1 || skills[0].id !== receipt.artifact.skillId || skills[0].files.length !== 0 || createHash("sha256").update(skillMarkdown(skills[0]), "utf8").digest("hex") !== receipt.artifact.sha256)
6661
+ if (skills?.length !== 1 || skills[0].id !== receipt.artifact.skillId || skills[0].files.length !== 0 || createHash2("sha256").update(skillMarkdown(skills[0]), "utf8").digest("hex") !== receipt.artifact.sha256)
6555
6662
  throw new Error("Assigned Skill artifact digest mismatch");
6556
6663
  }
6557
6664
  function verifySkillAssignment(assignment) {
@@ -6562,7 +6669,7 @@ function verifySkillAssignment(assignment) {
6562
6669
  verifyAssignedSkills(assignment.skills, receipt);
6563
6670
  }
6564
6671
  function verifyMountedSkill(file, receipt) {
6565
- if (!lstatSync5(file).isFile() || lstatSync5(file).isSymbolicLink() || lstatSync5(file).nlink !== 1 || createHash("sha256").update(readFileSync6(file)).digest("hex") !== receipt.artifact.sha256)
6672
+ if (!lstatSync5(file).isFile() || lstatSync5(file).isSymbolicLink() || lstatSync5(file).nlink !== 1 || createHash2("sha256").update(readFileSync6(file)).digest("hex") !== receipt.artifact.sha256)
6566
6673
  throw new Error("Mounted Skill artifact digest mismatch");
6567
6674
  }
6568
6675
  function verifySkillResume(assignment, current) {
@@ -6572,7 +6679,7 @@ function verifySkillResume(assignment, current) {
6572
6679
  }
6573
6680
 
6574
6681
  // src/captures.ts
6575
- import { createHash as createHash2 } from "node:crypto";
6682
+ import { createHash as createHash3 } from "node:crypto";
6576
6683
  import { closeSync as closeSync2, constants, fstatSync, lstatSync as lstatSync6, mkdirSync as mkdirSync7, openSync as openSync2, readFileSync as readFileSync7, readdirSync as readdirSync3, rmSync as rmSync7 } from "node:fs";
6577
6684
  import { join as join9 } from "node:path";
6578
6685
  var CAPTURES_DIR = "captures";
@@ -6593,34 +6700,34 @@ function readPlain(path, max) {
6593
6700
  closeSync2(fd);
6594
6701
  }
6595
6702
  }
6596
- var drop = (dir, id3) => {
6597
- for (const name of [`${id3}.json`, ...EXTENSIONS.map((ext) => `${id3}.${ext}`)]) rmSync7(join9(dir, name), { force: true });
6703
+ var drop = (dir, id4) => {
6704
+ for (const name of [`${id4}.json`, ...EXTENSIONS.map((ext) => `${id4}.${ext}`)]) rmSync7(join9(dir, name), { force: true });
6598
6705
  };
6599
6706
  async function uploadCaptures(dir, runId, link, log, pendingDir, existingOnly = false) {
6600
6707
  if (!link.beginCapture || !link.sendCapture || !link.completeCapture) return 0;
6601
6708
  if (!lstatSync6(dir, { throwIfNoEntry: false })?.isDirectory()) return 0;
6602
6709
  let sent = 0;
6603
6710
  for (const name of readdirSync3(dir).sort()) {
6604
- const id3 = name.endsWith(".json") ? name.slice(0, -5) : "";
6605
- if (!ID.test(id3)) continue;
6711
+ const id4 = name.endsWith(".json") ? name.slice(0, -5) : "";
6712
+ if (!ID.test(id4)) continue;
6606
6713
  const meta = readPlain(join9(dir, name), 4096);
6607
6714
  let title2 = "";
6608
6715
  try {
6609
6716
  title2 = cleanCaptureTitle(String(JSON.parse(new TextDecoder().decode(meta ?? new Uint8Array())).title ?? ""));
6610
6717
  } catch {
6611
6718
  }
6612
- const file = EXTENSIONS.map((ext) => join9(dir, `${id3}.${ext}`)).find((path) => lstatSync6(path, { throwIfNoEntry: false }));
6719
+ const file = EXTENSIONS.map((ext) => join9(dir, `${id4}.${ext}`)).find((path) => lstatSync6(path, { throwIfNoEntry: false }));
6613
6720
  const bytes = file ? readPlain(file, CAPTURE_MAX_BYTES.video) : null;
6614
6721
  const problem = !title2 ? "no title" : !bytes ? "no regular file" : captureProblem(bytes);
6615
6722
  const contentType = bytes && sniffCaptureType(bytes);
6616
6723
  if (problem || !bytes || !contentType) {
6617
- log.warn({ run_id: runId, capture: id3, problem }, "capture dropped");
6618
- drop(dir, id3);
6724
+ log.warn({ run_id: runId, capture: id4, problem }, "capture dropped");
6725
+ drop(dir, id4);
6619
6726
  continue;
6620
6727
  }
6621
6728
  try {
6622
- const sha2562 = createHash2("sha256").update(bytes).digest("hex");
6623
- const pendingPath = pendingDir ? join9(pendingDir, `${id3}.json`) : null;
6729
+ const sha2562 = createHash3("sha256").update(bytes).digest("hex");
6730
+ const pendingPath = pendingDir ? join9(pendingDir, `${id4}.json`) : null;
6624
6731
  let pending;
6625
6732
  if (pendingPath) {
6626
6733
  try {
@@ -6634,7 +6741,7 @@ async function uploadCaptures(dir, runId, link, log, pendingDir, existingOnly =
6634
6741
  if (pending) {
6635
6742
  try {
6636
6743
  await link.completeCapture(runId, pending.captureId);
6637
- drop(dir, id3);
6744
+ drop(dir, id4);
6638
6745
  if (pendingPath) rmSync7(pendingPath, { force: true });
6639
6746
  sent += 1;
6640
6747
  continue;
@@ -6651,33 +6758,33 @@ async function uploadCaptures(dir, runId, link, log, pendingDir, existingOnly =
6651
6758
  } else {
6652
6759
  if (pendingPath) {
6653
6760
  mkdirSync7(pendingDir, { recursive: true, mode: 448 });
6654
- writeJsonAtomic(pendingPath, { captureId: id3, sha256: sha2562 });
6761
+ writeJsonAtomic(pendingPath, { captureId: id4, sha256: sha2562 });
6655
6762
  }
6656
- target = await link.beginCapture(runId, { ...pendingPath ? { captureId: id3 } : {}, title: title2, contentType, size: bytes.length, sha256: sha2562 });
6657
- if (pendingPath && target.captureId !== id3) throw new Error("Capture reservation id changed");
6763
+ target = await link.beginCapture(runId, { ...pendingPath ? { captureId: id4 } : {}, title: title2, contentType, size: bytes.length, sha256: sha2562 });
6764
+ if (pendingPath && target.captureId !== id4) throw new Error("Capture reservation id changed");
6658
6765
  }
6659
6766
  const { captureId, upload } = target;
6660
6767
  await link.sendCapture(runId, captureId, upload, bytes, contentType);
6661
6768
  await link.completeCapture(runId, captureId);
6662
- drop(dir, id3);
6769
+ drop(dir, id4);
6663
6770
  if (pendingPath) rmSync7(pendingPath, { force: true });
6664
6771
  sent += 1;
6665
6772
  } catch (error) {
6666
6773
  if (error instanceof ServerUnreachableError) {
6667
- log.warn({ run_id: runId, capture: id3 }, "capture upload deferred");
6774
+ log.warn({ run_id: runId, capture: id4 }, "capture upload deferred");
6668
6775
  return sent;
6669
6776
  }
6670
6777
  if (error instanceof DaemonError && (error.code === 401 || error.code === 403 || error.code === 404 || error.code === 409 || error.code === DAEMON_RPC_ERRORS.unauthorized)) {
6671
- log.warn({ run_id: runId, capture: id3, status: error.code }, "capture reservation unavailable; retry stopped");
6778
+ log.warn({ run_id: runId, capture: id4, status: error.code }, "capture reservation unavailable; retry stopped");
6672
6779
  if (pendingDir) {
6673
6780
  mkdirSync7(pendingDir, { recursive: true, mode: 448 });
6674
6781
  writeJsonAtomic(join9(pendingDir, "blocked.json"), { status: error.code });
6675
6782
  }
6676
6783
  return sent;
6677
6784
  }
6678
- log.warn({ run_id: runId, capture: id3, status: error instanceof DaemonError ? error.code : void 0 }, "capture refused");
6679
- drop(dir, id3);
6680
- if (pendingDir) rmSync7(join9(pendingDir, `${id3}.json`), { force: true });
6785
+ log.warn({ run_id: runId, capture: id4, status: error instanceof DaemonError ? error.code : void 0 }, "capture refused");
6786
+ drop(dir, id4);
6787
+ if (pendingDir) rmSync7(join9(pendingDir, `${id4}.json`), { force: true });
6681
6788
  }
6682
6789
  }
6683
6790
  return sent;
@@ -6763,19 +6870,20 @@ function daemonSecrets(dataDir) {
6763
6870
  ];
6764
6871
  }
6765
6872
  function runPaths(stateDir, runId) {
6766
- const id3 = assertSafeId("run id", runId);
6873
+ const id4 = assertSafeId("run id", runId);
6767
6874
  return {
6768
6875
  /** The daemon's data dir (`stateDir` is `<dataDir>/adapters`). */
6769
6876
  privateDir: resolve6(stateDir, ".."),
6770
6877
  /** Writable from the sandbox. */
6771
- runDir: join10(stateDir, "runs", id3),
6878
+ runDir: join10(stateDir, "runs", id4),
6772
6879
  /** Daemon only. */
6773
- pidFile: join10(stateDir, "pids", `${id3}.pgid`)
6880
+ pidFile: join10(stateDir, "pids", `${id4}.pgid`)
6774
6881
  };
6775
6882
  }
6776
6883
  var RunContext = class {
6777
6884
  constructor(options) {
6778
6885
  this.options = options;
6886
+ if (options.policyHash && (!options.policy || policySnapshotHash(options.policy) !== options.policyHash)) throw new Error("Run child policy hash mismatch");
6779
6887
  this.worktree = realpathSync7(options.worktree);
6780
6888
  this.gitDir = realpathSync7(
6781
6889
  execFileSync("git", ["rev-parse", "--absolute-git-dir"], {
@@ -6929,7 +7037,7 @@ var RunContext = class {
6929
7037
  * and zsh writes here-docs to `$TMPPREFIX` (default `/tmp/zsh`).
6930
7038
  */
6931
7039
  tempEnv() {
6932
- return { TMPDIR: this.tmpDir, TMPPREFIX: join10(this.tmpDir, "zsh"), ...this.githubEnv };
7040
+ return { TMPDIR: this.tmpDir, TMPPREFIX: join10(this.tmpDir, "zsh"), ...this.githubEnv, ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
6933
7041
  }
6934
7042
  /** A hand-in from an earlier session would end this one at once. */
6935
7043
  clearHandoff() {
@@ -7053,7 +7161,7 @@ import { randomUUID as randomUUID2 } from "node:crypto";
7053
7161
  import { createSdkMcpServer, query, tool } from "@anthropic-ai/claude-agent-sdk";
7054
7162
 
7055
7163
  // src/coordinator/contract.ts
7056
- import { z as z27 } from "zod";
7164
+ import { z as z28 } from "zod";
7057
7165
  var COORDINATOR_DEFAULT_TIMEOUT_MS = 12e4;
7058
7166
  var COORDINATOR_DEFAULT_TOOL_LIMIT = 40;
7059
7167
  var MAX_REPLY_CHARS = 2e5;
@@ -7106,7 +7214,7 @@ var CoordinatorToolHost = class {
7106
7214
  if (!callId || callId.length > 200) return Promise.reject(new Error("coordinatorCallIdInvalid"));
7107
7215
  const tool2 = this.tools.get(name);
7108
7216
  if (!tool2) return Promise.reject(new Error("coordinatorToolUnavailable"));
7109
- const parsed = z27.object(tool2.inputSchema).strict().safeParse(input);
7217
+ const parsed = z28.object(tool2.inputSchema).strict().safeParse(input);
7110
7218
  if (!parsed.success) return Promise.reject(new Error("coordinatorToolInputInvalid"));
7111
7219
  const key2 = JSON.stringify([name, parsed.data]);
7112
7220
  const prior = this.calls.get(callId);
@@ -7194,7 +7302,7 @@ async function runClaudeCoordinator(input, host) {
7194
7302
  }
7195
7303
 
7196
7304
  // src/coordinator/codex.ts
7197
- import { z as z28 } from "zod";
7305
+ import { z as z29 } from "zod";
7198
7306
  var CODEX_COORDINATOR_APPROVAL_POLICY = "on-request";
7199
7307
  function codexCoordinatorThread(input, host, tools) {
7200
7308
  return {
@@ -7208,12 +7316,12 @@ function codexCoordinatorThread(input, host, tools) {
7208
7316
  dynamicTools: [...tools.tools.values()].map((definition) => ({
7209
7317
  name: definition.name,
7210
7318
  description: definition.description,
7211
- inputSchema: z28.toJSONSchema(z28.object(definition.inputSchema).strict(), { target: "draft-7" })
7319
+ inputSchema: z29.toJSONSchema(z29.object(definition.inputSchema).strict(), { target: "draft-7" })
7212
7320
  })),
7213
7321
  ...input.model ? { model: input.model } : {}
7214
7322
  };
7215
7323
  }
7216
- var toolRequest = z28.object({ threadId: z28.string(), turnId: z28.string(), callId: z28.string(), tool: z28.string(), arguments: z28.unknown() });
7324
+ var toolRequest = z29.object({ threadId: z29.string(), turnId: z29.string(), callId: z29.string(), tool: z29.string(), arguments: z29.unknown() });
7217
7325
  async function runCodexCoordinator(input, host) {
7218
7326
  const deadline = coordinatorDeadline(input);
7219
7327
  const signal = deadline.controller.signal;
@@ -7267,7 +7375,7 @@ async function runCodexCoordinator(input, host) {
7267
7375
  rpc.onRequest("item/tool/requestUserInput", () => ({ answers: {} }));
7268
7376
  rpc.onRequest("mcpServer/elicitation/request", () => ({ action: "decline", content: null }));
7269
7377
  rpc.onNotification("item/completed", (raw) => {
7270
- const parsed = z28.object({ threadId: z28.string(), turnId: z28.string(), item: z28.object({ id: z28.string(), type: z28.string(), text: z28.string().optional(), phase: z28.string().nullable().optional() }) }).safeParse(raw);
7378
+ const parsed = z29.object({ threadId: z29.string(), turnId: z29.string(), item: z29.object({ id: z29.string(), type: z29.string(), text: z29.string().optional(), phase: z29.string().nullable().optional() }) }).safeParse(raw);
7271
7379
  if (!parsed.success || parsed.data.threadId !== threadId || turnId && parsed.data.turnId !== turnId) return;
7272
7380
  turnId ??= parsed.data.turnId;
7273
7381
  const item = parsed.data.item;
@@ -7280,7 +7388,7 @@ async function runCodexCoordinator(input, host) {
7280
7388
  }
7281
7389
  });
7282
7390
  rpc.onNotification("turn/completed", (raw) => {
7283
- const parsed = z28.object({ threadId: z28.string(), turn: z28.object({ id: z28.string(), status: z28.string() }) }).safeParse(raw);
7391
+ const parsed = z29.object({ threadId: z29.string(), turn: z29.object({ id: z29.string(), status: z29.string() }) }).safeParse(raw);
7284
7392
  if (!parsed.success || parsed.data.threadId !== threadId || turnId && parsed.data.turn.id !== turnId) return;
7285
7393
  turnId ??= parsed.data.turn.id;
7286
7394
  acceptingTools = false;
@@ -7292,11 +7400,11 @@ async function runCodexCoordinator(input, host) {
7292
7400
  await request("initialize", { clientInfo: { name: "mikka_coordinator", version: "1.0.0" }, capabilities: { experimentalApi: true } });
7293
7401
  await rpc.sendNotification("initialized");
7294
7402
  const thread = await request("thread/start", codexCoordinatorThread(input, host, tools));
7295
- threadId = z28.string().min(1).parse(thread.thread.id);
7403
+ threadId = z29.string().min(1).parse(thread.thread.id);
7296
7404
  acceptingTools = true;
7297
7405
  const turn = await request("turn/start", { threadId, input: [{ type: "text", text: input.context, text_elements: [] }] });
7298
7406
  if (turnId && turnId !== turn.turn.id) throw new Error("coordinatorCodexTurnMismatch");
7299
- turnId = z28.string().min(1).parse(turn.turn.id);
7407
+ turnId = z29.string().min(1).parse(turn.turn.id);
7300
7408
  await Promise.race([ended, cancellation]);
7301
7409
  signal.throwIfAborted();
7302
7410
  const items = [...messages.values()];
@@ -7335,8 +7443,8 @@ async function runNativeCoordinatorJob(job, options) {
7335
7443
  mkdirSync9(cwd, { mode: 448 });
7336
7444
  try {
7337
7445
  const tools = job.tools.map((spec) => {
7338
- const schema = z29.fromJSONSchema(spec.inputSchema);
7339
- if (!(schema instanceof z29.ZodObject)) throw new Error("coordinatorToolSchemaUnsupported");
7446
+ const schema = z30.fromJSONSchema(spec.inputSchema);
7447
+ if (!(schema instanceof z30.ZodObject)) throw new Error("coordinatorToolSchemaUnsupported");
7340
7448
  return {
7341
7449
  name: spec.name,
7342
7450
  description: spec.description,
@@ -7573,33 +7681,33 @@ run sandbox group termination failed: ${String(error)}`;
7573
7681
  return;
7574
7682
  }
7575
7683
  if (value.type !== "network" || !Number.isSafeInteger(value.id) || value.id < 1 || pending.has(value.id)) return;
7576
- const id3 = value.id;
7684
+ const id4 = value.id;
7577
7685
  const request = {
7578
7686
  host: typeof value.host === "string" ? value.host : "",
7579
7687
  port: typeof value.port === "number" ? value.port : 0
7580
7688
  };
7581
7689
  if (typeof value.port !== "number" || stopped || lifetime.signal.aborted || pending.size >= MAX_PENDING_NETWORK || !matchesRunSandboxDomain(request, maximum)) {
7582
- send({ type: "decision", id: id3, allow: false });
7690
+ send({ type: "decision", id: id4, allow: false });
7583
7691
  return;
7584
7692
  }
7585
7693
  const controller = new AbortController();
7586
7694
  const timer = setTimeout(() => {
7587
- if (!pending.delete(id3)) return;
7695
+ if (!pending.delete(id4)) return;
7588
7696
  controller.abort();
7589
- send({ type: "decision", id: id3, allow: false });
7697
+ send({ type: "decision", id: id4, allow: false });
7590
7698
  }, NETWORK_DECISION_MS);
7591
- pending.set(id3, { controller, timer });
7699
+ pending.set(id4, { controller, timer });
7592
7700
  void Promise.resolve().then(() => {
7593
7701
  if (stopped || lifetime.signal.aborted) return false;
7594
7702
  return onNetwork(request, controller.signal);
7595
7703
  }).then((allow) => {
7596
- if (!pending.delete(id3)) return;
7704
+ if (!pending.delete(id4)) return;
7597
7705
  clearTimeout(timer);
7598
- send({ type: "decision", id: id3, allow: allow === true && !stopped && !lifetime.signal.aborted && !controller.signal.aborted });
7706
+ send({ type: "decision", id: id4, allow: allow === true && !stopped && !lifetime.signal.aborted && !controller.signal.aborted });
7599
7707
  }, () => {
7600
- if (pending.delete(id3)) {
7708
+ if (pending.delete(id4)) {
7601
7709
  clearTimeout(timer);
7602
- send({ type: "decision", id: id3, allow: false });
7710
+ send({ type: "decision", id: id4, allow: false });
7603
7711
  }
7604
7712
  });
7605
7713
  });
@@ -7844,18 +7952,18 @@ function claudeChunks(message) {
7844
7952
  const chunks = [];
7845
7953
  if (message.type === "assistant") {
7846
7954
  message.message.content.forEach((block, index) => {
7847
- const id3 = `${message.message.id ?? randomUUID3()}-${index}`;
7955
+ const id4 = `${message.message.id ?? randomUUID3()}-${index}`;
7848
7956
  if (block.type === "text" && block.text) {
7849
7957
  chunks.push(
7850
- { type: "text-start", id: id3 },
7851
- { type: "text-delta", id: id3, delta: block.text },
7852
- { type: "text-end", id: id3 }
7958
+ { type: "text-start", id: id4 },
7959
+ { type: "text-delta", id: id4, delta: block.text },
7960
+ { type: "text-end", id: id4 }
7853
7961
  );
7854
7962
  } else if (block.type === "thinking" && block.thinking) {
7855
7963
  chunks.push(
7856
- { type: "reasoning-start", id: id3 },
7857
- { type: "reasoning-delta", id: id3, delta: block.thinking },
7858
- { type: "reasoning-end", id: id3 }
7964
+ { type: "reasoning-start", id: id4 },
7965
+ { type: "reasoning-delta", id: id4, delta: block.thinking },
7966
+ { type: "reasoning-end", id: id4 }
7859
7967
  );
7860
7968
  } else if (block.type === "tool_use") {
7861
7969
  chunks.push({
@@ -8068,6 +8176,7 @@ var ClaudeAdapter = class {
8068
8176
  gitWritePaths: options.gitWritePaths,
8069
8177
  networkAllow: options.networkAllow,
8070
8178
  policy: options.policy,
8179
+ policyHash: options.policyHash,
8071
8180
  skills: options.skills,
8072
8181
  skillReceipt: options.skillReceipt,
8073
8182
  runDir,
@@ -8509,6 +8618,7 @@ var CodexAdapter = class {
8509
8618
  gitWritePaths: options.gitWritePaths,
8510
8619
  networkAllow: options.networkAllow,
8511
8620
  policy: options.policy,
8621
+ policyHash: options.policyHash,
8512
8622
  skills: options.skills,
8513
8623
  skillReceipt: options.skillReceipt,
8514
8624
  runDir,
@@ -8740,7 +8850,7 @@ var CodexAdapter = class {
8740
8850
  });
8741
8851
  rpc.listen();
8742
8852
  const turnCompleted = async (turn) => {
8743
- for (const [id3, item] of pendingMcp) if (item.turnId === turn.id) pendingMcp.delete(id3);
8853
+ for (const [id4, item] of pendingMcp) if (item.turnId === turn.id) pendingMcp.delete(id4);
8744
8854
  queue.chunk({
8745
8855
  type: "data-usage",
8746
8856
  data: {
@@ -8975,24 +9085,24 @@ var AcpChunker = class {
8975
9085
  /** Closes an open text or reasoning part. */
8976
9086
  close() {
8977
9087
  if (!this.open) return [];
8978
- const { kind, id: id3 } = this.open;
9088
+ const { kind, id: id4 } = this.open;
8979
9089
  this.open = null;
8980
- return [{ type: kind === "text" ? "text-end" : "reasoning-end", id: id3 }];
9090
+ return [{ type: kind === "text" ? "text-end" : "reasoning-end", id: id4 }];
8981
9091
  }
8982
9092
  part(kind, delta) {
8983
9093
  const chunks = [];
8984
9094
  if (this.open?.kind !== kind) {
8985
9095
  chunks.push(...this.close());
8986
- const id4 = `${this.prefix}-${++this.count}`;
8987
- this.open = { kind, id: id4 };
9096
+ const id5 = `${this.prefix}-${++this.count}`;
9097
+ this.open = { kind, id: id5 };
8988
9098
  chunks.push({
8989
9099
  type: kind === "text" ? "text-start" : "reasoning-start",
8990
- id: id4
9100
+ id: id5
8991
9101
  });
8992
9102
  }
8993
- const id3 = this.open?.id;
9103
+ const id4 = this.open?.id;
8994
9104
  chunks.push(
8995
- kind === "text" ? { type: "text-delta", id: id3, delta } : { type: "reasoning-delta", id: id3, delta }
9105
+ kind === "text" ? { type: "text-delta", id: id4, delta } : { type: "reasoning-delta", id: id4, delta }
8996
9106
  );
8997
9107
  return chunks;
8998
9108
  }
@@ -9095,6 +9205,7 @@ var CursorAdapter = class {
9095
9205
  gitWritePaths: options.gitWritePaths,
9096
9206
  networkAllow: options.networkAllow,
9097
9207
  policy: options.policy,
9208
+ policyHash: options.policyHash,
9098
9209
  skills: options.skills,
9099
9210
  skillReceipt: options.skillReceipt,
9100
9211
  runDir,
@@ -9444,13 +9555,13 @@ var MockAdapter = class {
9444
9555
  }
9445
9556
  while (inbox.length > 0) {
9446
9557
  const text3 = inbox.shift();
9447
- const id3 = `ack-${randomUUID4()}`;
9448
- yield { type: "chunk", chunk: { type: "text-start", id: id3 } };
9558
+ const id4 = `ack-${randomUUID4()}`;
9559
+ yield { type: "chunk", chunk: { type: "text-start", id: id4 } };
9449
9560
  yield {
9450
9561
  type: "chunk",
9451
- chunk: { type: "text-delta", id: id3, delta: `Noted: ${text3}` }
9562
+ chunk: { type: "text-delta", id: id4, delta: `Noted: ${text3}` }
9452
9563
  };
9453
- yield { type: "chunk", chunk: { type: "text-end", id: id3 } };
9564
+ yield { type: "chunk", chunk: { type: "text-end", id: id4 } };
9454
9565
  }
9455
9566
  if (line.hang) {
9456
9567
  if (!abort.signal.aborted) {
@@ -10166,7 +10277,7 @@ var Outbox = class {
10166
10277
  }
10167
10278
  }
10168
10279
  async flushAll() {
10169
- await Promise.all(this.runIds().map((id3) => this.flush(id3)));
10280
+ await Promise.all(this.runIds().map((id4) => this.flush(id4)));
10170
10281
  }
10171
10282
  /** Serialized per run so items always leave in append order. */
10172
10283
  flush(runId) {
@@ -11247,7 +11358,7 @@ function withoutTaskEnv(assignment) {
11247
11358
 
11248
11359
  // src/runs/journal.ts
11249
11360
  function persisted(entries) {
11250
- return Object.fromEntries(Object.entries(entries).map(([id3, entry]) => [id3, { ...entry, assignment: withoutTaskEnv(entry.assignment) }]));
11361
+ return Object.fromEntries(Object.entries(entries).map(([id4, entry]) => [id4, { ...entry, assignment: withoutTaskEnv(entry.assignment) }]));
11251
11362
  }
11252
11363
  var RunJournal = class {
11253
11364
  constructor(file) {
@@ -11387,9 +11498,9 @@ function createRunMasker(secrets) {
11387
11498
  pending.delete(key2);
11388
11499
  if (!held) return null;
11389
11500
  const sep = key2.indexOf(":");
11390
- const prefix = key2.slice(0, sep), id3 = key2.slice(sep + 1);
11501
+ const prefix = key2.slice(0, sep), id4 = key2.slice(sep + 1);
11391
11502
  const masked = text3(held);
11392
- return prefix === "tool" ? { type: "tool-input-delta", toolCallId: id3, inputTextDelta: masked } : { type: DELTA_FOR_PREFIX[prefix], id: id3, delta: masked };
11503
+ return prefix === "tool" ? { type: "tool-input-delta", toolCallId: id4, inputTextDelta: masked } : { type: DELTA_FOR_PREFIX[prefix], id: id4, delta: masked };
11393
11504
  };
11394
11505
  const flush = () => {
11395
11506
  const out = [];
@@ -11442,7 +11553,7 @@ function createRunMasker(secrets) {
11442
11553
  }
11443
11554
 
11444
11555
  // src/runs/supervisor.ts
11445
- import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
11556
+ import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
11446
11557
  import { join as join23, resolve as resolve9 } from "node:path";
11447
11558
  import { execa as execa12 } from "execa";
11448
11559
 
@@ -11663,7 +11774,7 @@ var MemoryServer = class {
11663
11774
  registerDevice: async (credential, info, knownDeviceId) => {
11664
11775
  this.check();
11665
11776
  const existing = [...this.devices].find(
11666
- ([id3, d]) => d.credential === credential && (!knownDeviceId || id3 === knownDeviceId)
11777
+ ([id4, d]) => d.credential === credential && (!knownDeviceId || id4 === knownDeviceId)
11667
11778
  );
11668
11779
  const deviceId = existing?.[0] ?? this.fixedDeviceId ?? randomUUID5();
11669
11780
  this.devices.set(deviceId, { credential, info });
@@ -11693,7 +11804,7 @@ var MemoryServer = class {
11693
11804
  },
11694
11805
  pendingRuns: async (deviceId) => {
11695
11806
  this.check();
11696
- return [...this.runs].filter(([, r]) => r.deviceId === deviceId && r.state === "queued").map(([id3]) => id3);
11807
+ return [...this.runs].filter(([, r]) => r.deviceId === deviceId && r.state === "queued").map(([id4]) => id4);
11697
11808
  },
11698
11809
  claimRun: async (deviceId, runId) => {
11699
11810
  this.check();
@@ -11760,8 +11871,8 @@ var MemoryServer = class {
11760
11871
  },
11761
11872
  ackCommands: async (_deviceId, delivered) => {
11762
11873
  this.check();
11763
- for (const id3 of delivered) {
11764
- const input = this.inputs.get(id3);
11874
+ for (const id4 of delivered) {
11875
+ const input = this.inputs.get(id4);
11765
11876
  if (input && !input.deliveredAt) input.deliveredAt = Date.now();
11766
11877
  }
11767
11878
  }
@@ -12544,6 +12655,8 @@ var RunSupervisor = class {
12544
12655
  const log = this.deps.log.child({ run_id: runId });
12545
12656
  let entry = this.deps.journal.get(runId);
12546
12657
  const { assignment } = entry;
12658
+ if ((assignment.policySnapshotRequired || assignment.policySnapshot) && !this.deps.verifyRunPolicy) throw new Error("Run policy verification unavailable");
12659
+ await this.deps.verifyRunPolicy?.(assignment, AbortSignal.any([this.stopController.signal, run2.abort.signal]));
12547
12660
  verifySkillAssignment(assignment);
12548
12661
  if (assignment.skillReceipt && (this.leases.get(runId) ?? 0) <= Date.now())
12549
12662
  throw new Error("Receipted Skill assignment requires a current server lease");
@@ -12668,6 +12781,7 @@ var RunSupervisor = class {
12668
12781
  networkAllow: repo.networkAllow,
12669
12782
  gitWritePaths: await worktreeGitWritePaths(repo.path, worktree, runId),
12670
12783
  policy: assignment.policy,
12784
+ policyHash: assignment.policySnapshot?.payload.policyHash,
12671
12785
  skills: assignment.skills,
12672
12786
  skillReceipt: assignment.skillReceipt,
12673
12787
  onRuntimeModel: assignment.skillReceipt ? (sessionId, observedModel) => {
@@ -12693,13 +12807,13 @@ var RunSupervisor = class {
12693
12807
  if (assignment.requireSessionResume && (assignment.subscriptionBinding || !assignment.resumeSessionId || !assignment.continuesRunId || !adapter.capabilities.supportsResume || !resuming && !continueSession || resuming && entry.sessionId !== assignment.resumeSessionId))
12694
12808
  throw new Error("factory_question_session_resume_required");
12695
12809
  const benchmark = assignment.benchmark;
12696
- const policyDigest = assignment.skillReceipt ? createHash3("sha256").update(runPolicyDigestInput(assignment.policy)).digest("hex") : void 0;
12810
+ const policyDigest = assignment.skillReceipt ? createHash4("sha256").update(runPolicyDigestInput(assignment.policy)).digest("hex") : void 0;
12697
12811
  if (benchmark && (!assignment.skillReceipt || assignment.harness === "mock" || !assignment.verifyCommand || benchmark.sourceCommit !== this.deps.journal.get(runId)?.baseCommit || policyDigest !== benchmark.policyDigest)) throw new Error("Frozen benchmark execution configuration mismatch");
12698
12812
  let fixtureDigest;
12699
12813
  if (benchmark) {
12700
12814
  if (runPolicy(assignment.policy).readOnly !== true) throw new Error("Benchmark fixture must be read-only");
12701
12815
  const fixed = await fixedCheckSnapshot(repo.path, worktree, benchmark.sourceCommit);
12702
- fixtureDigest = createHash3("sha256").update(fixed.sha).digest("hex");
12816
+ fixtureDigest = createHash4("sha256").update(fixed.sha).digest("hex");
12703
12817
  if (fixtureDigest !== benchmark.fixtureDigest) throw new Error("Frozen benchmark fixture digest mismatch");
12704
12818
  }
12705
12819
  const previousMount = entry.skillMount;
@@ -12839,7 +12953,7 @@ var RunSupervisor = class {
12839
12953
  const error = event.error ?? (stopReason === "turn_ended" ? "Session ended without a submission" : stopReason === "timeout" ? "No progress before the watchdog limit" : stopReason === "device_lost" ? "Run lease expired; the server could not be reached" : void 0);
12840
12954
  if (assignment.benchmark) {
12841
12955
  const fixed = await fixedCheckSnapshot(repo.path, worktree, assignment.benchmark.sourceCommit);
12842
- if (createHash3("sha256").update(fixed.sha).digest("hex") !== assignment.benchmark.fixtureDigest)
12956
+ if (createHash4("sha256").update(fixed.sha).digest("hex") !== assignment.benchmark.fixtureDigest)
12843
12957
  throw new Error("Benchmark fixture changed during model execution");
12844
12958
  }
12845
12959
  const outcome = await this.report(
@@ -12994,7 +13108,7 @@ function fixedCandidateCheck(assignment) {
12994
13108
  }
12995
13109
 
12996
13110
  // src/repositories.ts
12997
- import { createHash as createHash4, randomUUID as randomUUID7 } from "node:crypto";
13111
+ import { createHash as createHash5, randomUUID as randomUUID7 } from "node:crypto";
12998
13112
  import { existsSync as existsSync5, lstatSync as lstatSync8, mkdirSync as mkdirSync14, readdirSync as readdirSync5, realpathSync as realpathSync10, renameSync as renameSync2, rmSync as rmSync15 } from "node:fs";
12999
13113
  import { dirname as dirname10, join as join24, resolve as resolve10 } from "node:path";
13000
13114
  import { setTimeout as delay2 } from "node:timers/promises";
@@ -13011,7 +13125,7 @@ var RepositoryCache = class {
13011
13125
  retainResources;
13012
13126
  pathFor(remoteUrl) {
13013
13127
  const { key: key2 } = normalizeRepository(remoteUrl, { allowFile: this.allowFile });
13014
- const path = resolve10(this.root, "v2", createHash4("sha256").update(key2).digest("hex"));
13128
+ const path = resolve10(this.root, "v2", createHash5("sha256").update(key2).digest("hex"));
13015
13129
  if (!isInside(resolve10(this.root), path) || path === resolve10(this.root)) throw new Error("Invalid repository cache path");
13016
13130
  return path;
13017
13131
  }
@@ -13131,8 +13245,8 @@ import { join as join25 } from "node:path";
13131
13245
  import { BlockList, isIP as isIP2 } from "node:net";
13132
13246
 
13133
13247
  // ../../lib/search/url-schema.ts
13134
- import { z as z30 } from "zod";
13135
- var webUrlSchema = z30.string().max(2048).url().refine((value) => {
13248
+ import { z as z31 } from "zod";
13249
+ var webUrlSchema = z31.string().max(2048).url().refine((value) => {
13136
13250
  const url = new URL(value);
13137
13251
  return url.protocol === "https:" && !url.username && !url.password && !url.port && !url.hostname.includes(":") && !/^\d+\.\d+\.\d+\.\d+$/.test(url.hostname) && url.hostname.includes(".") && !/(?:^|\.)(?:localhost|local|internal|test|invalid|example|onion)\.?$/i.test(url.hostname);
13138
13252
  }, "\u53EA\u5141\u8BB8\u8BFB\u53D6\u516C\u5F00 HTTPS \u7F51\u9875\uFF0C\u4E0D\u652F\u6301\u51ED\u636E\u3001IP \u5730\u5740\u6216\u81EA\u5B9A\u4E49\u7AEF\u53E3\u3002");
@@ -13381,10 +13495,10 @@ async function createHostedBotRunner(host) {
13381
13495
  }
13382
13496
  throw new Error("native_runtime_cleanup_unconfirmed");
13383
13497
  }
13384
- const [id3, labels] = described.stdout.trim().split("|").map((part) => JSON.parse(part));
13385
- if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id3)
13498
+ const [id4, labels] = described.stdout.trim().split("|").map((part) => JSON.parse(part));
13499
+ if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
13386
13500
  throw unavailable2();
13387
- await exec2("docker", ["rm", "-f", id3], { env: bareEnv, timeout: 3e4 });
13501
+ await exec2("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
13388
13502
  if (record.assets?.startsWith(join26(host.stateDir, "native-verify-git-")))
13389
13503
  rmSync16(record.assets, { recursive: true, force: true });
13390
13504
  rmSync16(file, { force: true });
@@ -13997,7 +14111,7 @@ async function createHostedBotRunner(host) {
13997
14111
  import {
13998
14112
  randomBytes as randomBytes2,
13999
14113
  randomUUID as randomUUID9,
14000
- createHash as createHash6,
14114
+ createHash as createHash7,
14001
14115
  timingSafeEqual as timingSafeEqual2
14002
14116
  } from "node:crypto";
14003
14117
  import { chmodSync as chmodSync3 } from "node:fs";
@@ -14007,7 +14121,7 @@ import { createServer as createServer4 } from "node:net";
14007
14121
  import { spawn as spawn5 } from "node:child_process";
14008
14122
  import { execFile as execFile5 } from "node:child_process";
14009
14123
  import { promisify as promisify5 } from "node:util";
14010
- import { createHash as createHash5 } from "node:crypto";
14124
+ import { createHash as createHash6 } from "node:crypto";
14011
14125
  import { readFile as readFile2, realpath as realpath2 } from "node:fs/promises";
14012
14126
  import { createInterface } from "node:readline";
14013
14127
  var exec3 = promisify5(execFile5);
@@ -14024,7 +14138,7 @@ async function detectComputerDriver(binary = "cua-driver") {
14024
14138
  installed: true,
14025
14139
  version,
14026
14140
  path,
14027
- fingerprint: createHash5("sha256").update(await readFile2(path)).digest("hex")
14141
+ fingerprint: createHash6("sha256").update(await readFile2(path)).digest("hex")
14028
14142
  };
14029
14143
  } catch {
14030
14144
  return null;
@@ -14079,7 +14193,7 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
14079
14193
  if (display !== void 0 && !/^:[1-9][0-9]{0,3}$/.test(display))
14080
14194
  throw new Error("Invalid desktop display");
14081
14195
  const call = normalizeCall(input);
14082
- const fingerprint = createHash5("sha256").update(await readFile2(driver.path)).digest("hex");
14196
+ const fingerprint = createHash6("sha256").update(await readFile2(driver.path)).digest("hex");
14083
14197
  if (fingerprint !== driver.fingerprint)
14084
14198
  throw new Error("Driver changed; restart and approve a new request");
14085
14199
  const args = driverArguments(call);
@@ -14106,7 +14220,7 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
14106
14220
  env: { ...env, ...display === void 0 ? {} : { DISPLAY: display } },
14107
14221
  stdio: ["pipe", "pipe", "pipe"]
14108
14222
  });
14109
- let id3 = 0, bytes = 0;
14223
+ let id4 = 0, bytes = 0;
14110
14224
  const pending = /* @__PURE__ */ new Map();
14111
14225
  const fail = (error) => {
14112
14226
  for (const p of pending.values()) p.reject(error);
@@ -14142,7 +14256,7 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
14142
14256
  )
14143
14257
  );
14144
14258
  const request = (method, params) => new Promise((resolve11, reject) => {
14145
- const n = ++id3;
14259
+ const n = ++id4;
14146
14260
  pending.set(n, { resolve: resolve11, reject });
14147
14261
  child.stdin.write(
14148
14262
  JSON.stringify({ jsonrpc: "2.0", id: n, method, params }) + "\n"
@@ -14277,7 +14391,7 @@ var ComputerBroker = class {
14277
14391
  call,
14278
14392
  expiresAt: this.now() + this.ttl
14279
14393
  };
14280
- const digest = createHash6("sha256").update(JSON.stringify(request)).digest("hex");
14394
+ const digest2 = createHash7("sha256").update(JSON.stringify(request)).digest("hex");
14281
14395
  return new Promise((resolve11, reject) => {
14282
14396
  const timer = setTimeout(() => {
14283
14397
  this.pending.delete(request.id);
@@ -14294,7 +14408,7 @@ var ComputerBroker = class {
14294
14408
  token,
14295
14409
  assertLive,
14296
14410
  cleanup: () => signal?.removeEventListener("abort", cancel),
14297
- request: { ...request, digest },
14411
+ request: { ...request, digest: digest2 },
14298
14412
  resolve: resolve11,
14299
14413
  reject,
14300
14414
  timer
@@ -14322,21 +14436,21 @@ var ComputerBroker = class {
14322
14436
  }
14323
14437
  revoke(token) {
14324
14438
  this.grants.delete(token);
14325
- for (const [id3, row] of this.pending) {
14439
+ for (const [id4, row] of this.pending) {
14326
14440
  if (row.token !== token) continue;
14327
- this.pending.delete(id3);
14441
+ this.pending.delete(id4);
14328
14442
  clearTimeout(row.timer);
14329
14443
  row.cleanup();
14330
14444
  row.reject(new Error("Run ended; approval discarded"));
14331
14445
  }
14332
14446
  }
14333
- async decide(id3, digest, approve) {
14334
- const row = this.pending.get(id3);
14447
+ async decide(id4, digest2, approve) {
14448
+ const row = this.pending.get(id4);
14335
14449
  if (!row) throw new Error("Request expired or already consumed");
14336
- const left = Buffer.from(row.request.digest), right = Buffer.from(digest);
14450
+ const left = Buffer.from(row.request.digest), right = Buffer.from(digest2);
14337
14451
  if (left.length !== right.length || !timingSafeEqual2(left, right))
14338
14452
  throw new Error("Review changed");
14339
- this.pending.delete(id3);
14453
+ this.pending.delete(id4);
14340
14454
  row.cleanup();
14341
14455
  clearTimeout(row.timer);
14342
14456
  const { runId, call, expiresAt, target, display } = row.request;
@@ -14351,7 +14465,7 @@ var ComputerBroker = class {
14351
14465
  throw new Error("Not permitted");
14352
14466
  };
14353
14467
  assertLive();
14354
- row.resolve(await this.execute(this.driver, call, display, runId, { actionId: id3, assertLive }));
14468
+ row.resolve(await this.execute(this.driver, call, display, runId, { actionId: id4, assertLive }));
14355
14469
  } catch (error) {
14356
14470
  row.reject(error);
14357
14471
  }
@@ -14377,16 +14491,16 @@ var ComputerBroker = class {
14377
14491
  };
14378
14492
 
14379
14493
  // src/computer/credential-executor.ts
14380
- import { createHash as createHash7 } from "node:crypto";
14494
+ import { createHash as createHash8 } from "node:crypto";
14381
14495
  function credentialAwareExecutor(deps) {
14382
14496
  return async (driver, call, display, runId, context) => {
14383
- const digest = createHash7("sha256").update(JSON.stringify(call)).digest("hex");
14384
- const resolved = await deps.consumeMatchingIntent(runId, context.actionId, digest);
14497
+ const digest2 = createHash8("sha256").update(JSON.stringify(call)).digest("hex");
14498
+ const resolved = await deps.consumeMatchingIntent(runId, context.actionId, digest2);
14385
14499
  context.assertLive();
14386
14500
  if (resolved.kind === "ordinary") return deps.executeOrdinary(driver, call, display, runId, context.assertLive);
14387
14501
  if (resolved.kind !== "credential") throw new Error("Credential action already consumed");
14388
14502
  const { intent } = resolved;
14389
- if (![intent.actionId, intent.runId, intent.userId, intent.workspaceId, intent.botId, intent.subagentId, intent.targetId, intent.loaderId].every((value) => typeof value === "string" && value.length > 0) || intent.actionId !== context.actionId || !Number.isSafeInteger(intent.epoch) || intent.epoch < 0 || !Number.isSafeInteger(intent.policyVersion) || intent.policyVersion < 0 || intent.runId !== runId || intent.callDigest !== digest || intent.driverFingerprint !== driver.fingerprint || intent.display !== display || !Number.isSafeInteger(intent.backendNodeId) || intent.backendNodeId < 1 || !["username", "password"].includes(intent.role) || !Number.isSafeInteger(intent.expiresAt) || intent.expiresAt <= (deps.now ?? Date.now)()) throw new Error("Credential action unavailable");
14503
+ if (![intent.actionId, intent.runId, intent.userId, intent.workspaceId, intent.botId, intent.subagentId, intent.targetId, intent.loaderId].every((value) => typeof value === "string" && value.length > 0) || intent.actionId !== context.actionId || !Number.isSafeInteger(intent.epoch) || intent.epoch < 0 || !Number.isSafeInteger(intent.policyVersion) || intent.policyVersion < 0 || intent.runId !== runId || intent.callDigest !== digest2 || intent.driverFingerprint !== driver.fingerprint || intent.display !== display || !Number.isSafeInteger(intent.backendNodeId) || intent.backendNodeId < 1 || !["username", "password"].includes(intent.role) || !Number.isSafeInteger(intent.expiresAt) || intent.expiresAt <= (deps.now ?? Date.now)()) throw new Error("Credential action unavailable");
14390
14504
  const url = new URL(intent.origin);
14391
14505
  if (url.protocol !== "https:" || url.username || url.password || url.origin !== intent.origin) throw new Error("Credential action unavailable");
14392
14506
  return deps.withCurrentLease(intent, async (live) => {
@@ -14468,7 +14582,7 @@ function loadDeviceFile(raw) {
14468
14582
  const { deviceIds, ...file } = raw;
14469
14583
  if (!file.deviceId && deviceIds && typeof deviceIds === "object") {
14470
14584
  const first = Object.values(deviceIds).find(
14471
- (id3) => typeof id3 === "string"
14585
+ (id4) => typeof id4 === "string"
14472
14586
  );
14473
14587
  if (first) file.deviceId = first;
14474
14588
  }
@@ -14679,6 +14793,11 @@ var Daemon = class {
14679
14793
  startSubscription: hosted?.start,
14680
14794
  prepareRunMailbox: this.options.link.prepareRunMailbox?.bind(this.options.link),
14681
14795
  prepareRunToolApproval: this.options.link.prepareRunToolApproval?.bind(this.options.link),
14796
+ verifyRunPolicy: this.options.link.verifyRunPolicy ? async (assignment, signal) => {
14797
+ if (!this.device.credential) throw new Error("Current policy device credential unavailable");
14798
+ if (!this.registered || !this.device.deviceId) await this.register(this.device.credential);
14799
+ return this.options.link.verifyRunPolicy(assignment, signal);
14800
+ } : void 0,
14682
14801
  bootstrap: hosted ? async (worktree, repo) => {
14683
14802
  if (repo.setup?.copyFiles.some(
14684
14803
  (path) => /(^|\/)(\.git|\.codex\/auth\.json|\.claude\/\.credentials\.json)(\/|$)/.test(
@@ -14825,7 +14944,7 @@ var Daemon = class {
14825
14944
  if (this.unacked.size > 0) {
14826
14945
  const ids = [...this.unacked];
14827
14946
  await link.ackCommands(deviceId, ids);
14828
- for (const id3 of ids) this.unacked.delete(id3);
14947
+ for (const id4 of ids) this.unacked.delete(id4);
14829
14948
  }
14830
14949
  const skipRuns = [...this.stopping, ...this.ended].slice(
14831
14950
  0,
@@ -14887,13 +15006,13 @@ var Daemon = class {
14887
15006
  if (remaining > 0) await this.pauseCommands(remaining, signal);
14888
15007
  }
14889
15008
  await Promise.all(
14890
- requests.map(async ({ id: id3, ...request }) => {
15009
+ requests.map(async ({ id: id4, ...request }) => {
14891
15010
  const result = await browseFolder(request).catch(() => ({
14892
15011
  ok: false,
14893
15012
  code: "failed",
14894
15013
  message: "Could not read that folder."
14895
15014
  }));
14896
- await link.answerFsRequest(deviceId, id3, result);
15015
+ await link.answerFsRequest(deviceId, id4, result);
14897
15016
  })
14898
15017
  );
14899
15018
  } catch (error) {