@aspectlylabs/mikka 0.0.193 → 0.0.194

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/cli.js CHANGED
@@ -2433,7 +2433,8 @@ var CONFIGURABLE_PERMISSIONS = {
2433
2433
  // Everything outside the worktree is read-only in the sandbox (ADR 0009,
2434
2434
  // Stage 1 isolation), so writing there cannot be allowed wholesale.
2435
2435
  write_outside_repo: ["ask", "deny"],
2436
- git_push: ["allow", "ask", "deny"],
2436
+ // Push is what the GitHub App grants (decision 2026-11-01-1215): never asked.
2437
+ git_push: ["allow", "deny"],
2437
2438
  network: ["allow", "ask", "deny"],
2438
2439
  computer_use: ["allow", "ask", "deny"]
2439
2440
  };
@@ -2451,7 +2452,9 @@ var PERMISSION_DEFAULTS = {
2451
2452
  ...FIXED_PERMISSIONS,
2452
2453
  install_dependency: "allow",
2453
2454
  write_outside_repo: "ask",
2454
- git_push: "ask",
2455
+ // A run pushes only when the server sends allow for an admitted GitHub App
2456
+ // grant (decision 2026-11-01-1215); a policy that does not say so never pushes.
2457
+ git_push: "deny",
2455
2458
  // Agents reach the open internet unless a person restricts it in settings
2456
2459
  // (decision 2026-11-01-1230-network-open-by-default).
2457
2460
  network: "allow",
@@ -2479,7 +2482,8 @@ var networkAllowSchema = z2.array(networkDomainSchema).max(MAX_NETWORK_DOMAINS).
2479
2482
  var storedPermissionsSchema = z2.strictObject({
2480
2483
  install_dependency: z2.enum(CONFIGURABLE_PERMISSIONS.install_dependency),
2481
2484
  write_outside_repo: z2.enum(CONFIGURABLE_PERMISSIONS.write_outside_repo),
2482
- git_push: z2.enum(CONFIGURABLE_PERMISSIONS.git_push),
2485
+ // A stored ask predates decision 2026-11-01-1215 and reads as allow.
2486
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "allow" : value),
2483
2487
  network: z2.enum(CONFIGURABLE_PERMISSIONS.network),
2484
2488
  computer_use: z2.enum(CONFIGURABLE_PERMISSIONS.computer_use)
2485
2489
  }).partial();
@@ -2514,7 +2518,8 @@ var runPolicySchema = z2.strictObject({
2514
2518
  permissions: z2.strictObject({
2515
2519
  install_dependency: z2.enum(PERMISSION_DECISIONS),
2516
2520
  write_outside_repo: z2.enum(PERMISSION_DECISIONS),
2517
- git_push: z2.enum(PERMISSION_DECISIONS),
2521
+ // Push is allow (admitted) or deny; an older server's ask carries no push authority.
2522
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "deny" : value),
2518
2523
  network: z2.enum(PERMISSION_DECISIONS),
2519
2524
  // Older servers omit this field; the daemon treats that as ask, never allow.
2520
2525
  computer_use: z2.enum(PERMISSION_DECISIONS).optional()
@@ -4482,7 +4487,7 @@ import { join as join4 } from "node:path";
4482
4487
  // package.json
4483
4488
  var package_default = {
4484
4489
  name: "@mikka/daemon",
4485
- version: "0.0.193",
4490
+ version: "0.0.194",
4486
4491
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4487
4492
  type: "module",
4488
4493
  private: true,
@@ -4542,7 +4547,7 @@ var package_default = {
4542
4547
  engines: {
4543
4548
  node: ">=24"
4544
4549
  },
4545
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
4550
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
4546
4551
  };
4547
4552
 
4548
4553
  // src/paths.ts
@@ -4751,14 +4756,14 @@ function runDomains(policy, repoAllow = []) {
4751
4756
  const destinations = policy.permissions.network === "allow" ? ["*"] : [.../* @__PURE__ */ new Set([...policy.networkAllow, ...repoAllow, ...registries])];
4752
4757
  return policy.networkCeiling === void 0 ? destinations : intersectNetworkDomains(destinations, policy.networkCeiling);
4753
4758
  }
4754
- function pushDecision(policy, repoApproved) {
4759
+ function pushDecision(policy) {
4755
4760
  if (policy.readOnly)
4756
4761
  return { push: false, note: "A read-only check does not push" };
4757
4762
  const decision = policy.permissions.git_push;
4763
+ if (decision === "allow") return { push: true };
4758
4764
  if (decision === "deny")
4759
- return { push: false, note: "Push is turned off for this workspace" };
4760
- if (decision === "allow" || repoApproved) return { push: true };
4761
- return { push: false, note: "Push needs approval for this repo" };
4765
+ return { push: false, note: "Push is turned off for this run" };
4766
+ return { push: false, note: "Push needs the Mikka GitHub App's access on this repository" };
4762
4767
  }
4763
4768
  var INSTALL_COMMANDS = [
4764
4769
  ["npm", ["install", "i", "add", "ci"]],
@@ -6912,7 +6917,7 @@ async function publishRun(options) {
6912
6917
  pushed: false,
6913
6918
  remote: null,
6914
6919
  skipped: "not_approved",
6915
- note: options.push.note ?? "Push needs approval for this repo"
6920
+ note: options.push.note ?? "Push needs the Mikka GitHub App's access on this repository"
6916
6921
  };
6917
6922
  }
6918
6923
  return push(commit);
@@ -9864,6 +9869,9 @@ import { setTimeout as sleep2 } from "node:timers/promises";
9864
9869
  import { execa as execa5 } from "execa";
9865
9870
 
9866
9871
  // src/chunks.ts
9872
+ function runStageChunk(stage, ms, ok2) {
9873
+ return { type: "data-run-stage", data: { stage, ms: Math.max(0, Math.round(ms)), ok: ok2 } };
9874
+ }
9867
9875
  function runStateChunk(state, error, stopReason) {
9868
9876
  return {
9869
9877
  type: "data-run-state",
@@ -12732,6 +12740,23 @@ var RunSupervisor = class {
12732
12740
  this.deps.log.error({ run_id: runId, err }, "outbox compaction failed");
12733
12741
  });
12734
12742
  }
12743
+ /**
12744
+ * Runs one start-up stage and records it as a stored `data-run-stage`
12745
+ * chunk with its duration, ok or not, so a run that fails while starting
12746
+ * shows which stage it reached. The stage's own result or error passes
12747
+ * through unchanged.
12748
+ */
12749
+ async stage(runId, stage, work) {
12750
+ const started = performance.now();
12751
+ try {
12752
+ const value = await work();
12753
+ this.emit(runId, runStageChunk(stage, performance.now() - started, true));
12754
+ return value;
12755
+ } catch (error) {
12756
+ this.emit(runId, runStageChunk(stage, performance.now() - started, false));
12757
+ throw error;
12758
+ }
12759
+ }
12735
12760
  setState(runId, state, extra = {}) {
12736
12761
  const entry = this.deps.journal.update(runId, {
12737
12762
  state,
@@ -12866,7 +12891,7 @@ var RunSupervisor = class {
12866
12891
  }
12867
12892
  const branch = assignment.pushBranch;
12868
12893
  const base = await this.deps.baseRef(assignment);
12869
- if (!branch || !pushDecision(runPolicy(assignment.policy), repo.push?.approved === true).push) return base;
12894
+ if (!branch || !pushDecision(runPolicy(assignment.policy)).push) return base;
12870
12895
  try {
12871
12896
  return await withRunGitCredentials(
12872
12897
  assignment,
@@ -12978,7 +13003,7 @@ var RunSupervisor = class {
12978
13003
  this.setState(runId, "preparing");
12979
13004
  entry = this.deps.journal.get(runId);
12980
13005
  }
12981
- await this.deps.prepareRepository(assignment, AbortSignal.any([this.stopController.signal, run3.abort.signal]));
13006
+ await this.stage(runId, "repository", () => this.deps.prepareRepository(assignment, AbortSignal.any([this.stopController.signal, run3.abort.signal])));
12982
13007
  if (this.stopping || run3.cancelRequested) {
12983
13008
  if (!this.stopping) this.finish(runId, run3.forcedStop ?? "cancelled");
12984
13009
  return;
@@ -12997,11 +13022,11 @@ var RunSupervisor = class {
12997
13022
  );
12998
13023
  if (assignment.requireWorktreeContinuation && !entry.worktree && !continued)
12999
13024
  throw new CheckpointRecoveryError("Original worktree is unavailable and there is no usable recovery snapshot.");
13000
- const worktree = entry.worktree ?? continued ?? await this.deps.worktrees.create(
13025
+ const worktree = entry.worktree ?? continued ?? await this.stage(runId, "worktree", async () => this.deps.worktrees.create(
13001
13026
  runId,
13002
13027
  repo.path,
13003
13028
  await this.startPoint(runId, repo, assignment)
13004
- );
13029
+ ));
13005
13030
  if (!entry.worktree) {
13006
13031
  const baseCommit = (continued && assignment.continuesRunId ? this.deps.journal.get(assignment.continuesRunId)?.baseCommit : void 0) ?? await headCommit(repo.path, worktree);
13007
13032
  if (!continued && assignment.resumeFrom) {
@@ -13125,7 +13150,7 @@ var RunSupervisor = class {
13125
13150
  let session;
13126
13151
  if (assignment.subscriptionBinding && assignment.modelCredential) throw new Error("A run has one model credential");
13127
13152
  try {
13128
- session = assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
13153
+ session = await this.stage(runId, "agent_start", async () => assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
13129
13154
  throw new Error("subscription_hosted_runtime_unavailable");
13130
13155
  })() : resuming ? await adapter.resume(entry.sessionId, options) : await (async () => {
13131
13156
  if (assignment.requireSessionResume)
@@ -13138,7 +13163,7 @@ var RunSupervisor = class {
13138
13163
  continueSession,
13139
13164
  requireSessionResume: assignment.requireSessionResume
13140
13165
  });
13141
- })();
13166
+ })());
13142
13167
  } catch (error) {
13143
13168
  if (assignment.skillReceipt) this.deps.journal.update(runId, { skillMount: void 0, execution: void 0, runtime: void 0 });
13144
13169
  throw error;
@@ -13275,7 +13300,7 @@ var RunSupervisor = class {
13275
13300
  const policy = runPolicy(assignment.policy);
13276
13301
  if (stopReason === "submitted" && report.verify.status !== "failed" && tree && // The draft-PR exception requires an explicit repository push
13277
13302
  // approval. It must not even create a local commit without it.
13278
- (report.verify.status === "passed" || pushDecision(policy, repo.push?.approved === true).push) && // A read-only check (ADR 0046) never commits or pushes: it reports
13303
+ (report.verify.status === "passed" || pushDecision(policy).push) && // A read-only check (ADR 0046) never commits or pushes: it reports
13279
13304
  // on the commit the implementation run already pushed.
13280
13305
  policy.readOnly !== true) {
13281
13306
  const publish = await this.publish(
@@ -13672,9 +13697,15 @@ var bootstrap = fileURLToPath3(
13672
13697
  );
13673
13698
  var placeholder = "mikka-native-broker-placeholder";
13674
13699
  var unavailable3 = (cause) => new Error("subscription_hosted_runtime_unavailable", cause === void 0 ? void 0 : { cause });
13675
- var dockerFailure = (error) => {
13700
+ var DOCKER_CREATE_TIMEOUT_MS = 18e4;
13701
+ var dockerFailure = (error, startedAt) => {
13676
13702
  const value = error;
13677
- return new Error(String(value.stderr || value.message || error).trim().slice(-500));
13703
+ const took = startedAt === void 0 ? "" : ` after ${Math.round((performance.now() - startedAt) / 1e3)}s`;
13704
+ const stderr = String(value.stderr ?? "").trim();
13705
+ if (stderr) return new Error(`${stderr.slice(-500)}${took}`);
13706
+ if (value.killed) return new Error(`docker timed out${took}`);
13707
+ if (error instanceof Error && error.message === "subscription_hosted_runtime_unavailable") return new Error(`run fenced${took}`);
13708
+ return new Error(`docker failed (exit ${String(value.code ?? value.signal ?? "unknown")})${took}`);
13678
13709
  };
13679
13710
  var blockedSandbox = {
13680
13711
  kind: "none",
@@ -13871,7 +13902,7 @@ async function createHostedBotRunner(host) {
13871
13902
  "-c",
13872
13903
  script
13873
13904
  ],
13874
- { env: bareEnv, timeout: 3e4, signal, maxBuffer: 1024 * 1024 }
13905
+ { env: bareEnv, timeout: DOCKER_CREATE_TIMEOUT_MS, signal, maxBuffer: 1024 * 1024 }
13875
13906
  );
13876
13907
  resource.id = created.stdout.trim();
13877
13908
  if (!/^[a-f0-9]{64}$/.test(resource.id)) throw unavailable3();
@@ -14191,10 +14222,11 @@ async function createHostedBotRunner(host) {
14191
14222
  ];
14192
14223
  await live();
14193
14224
  writeJsonAtomic(resourceFile, resource);
14225
+ const createStarted = performance.now();
14194
14226
  try {
14195
14227
  creating = exec3("docker", containerArgs2, {
14196
14228
  env: bareEnv,
14197
- timeout: 3e4
14229
+ timeout: DOCKER_CREATE_TIMEOUT_MS
14198
14230
  }).then((created) => {
14199
14231
  resource.id = created.stdout.trim();
14200
14232
  if (!/^[a-f0-9]{64}$/.test(resource.id)) throw unavailable3();
@@ -14202,9 +14234,10 @@ async function createHostedBotRunner(host) {
14202
14234
  writeJsonAtomic(resourceFile, resource);
14203
14235
  });
14204
14236
  await creating;
14237
+ console.info(`run ${assignment.runId}: hosted container created in ${Math.round((performance.now() - createStarted) / 1e3)}s`);
14205
14238
  await live();
14206
14239
  } catch (error) {
14207
- const reason = dockerFailure(error);
14240
+ const reason = dockerFailure(error, createStarted);
14208
14241
  try {
14209
14242
  await close();
14210
14243
  } catch (cleanup) {
@@ -15190,10 +15223,7 @@ var Daemon = class {
15190
15223
  pushBranch: assignment.pushBranch,
15191
15224
  baseBranch: assignment.remoteUrl ? await this.repositories.baseRef(assignment.remoteUrl, assignment.baseBranch) : assignment.baseBranch,
15192
15225
  push: (() => {
15193
- const decision = pushDecision(
15194
- runPolicy(assignment.policy),
15195
- repo.push?.approved === true
15196
- );
15226
+ const decision = pushDecision(runPolicy(assignment.policy));
15197
15227
  return {
15198
15228
  approved: decision.push,
15199
15229
  remote: repo.push?.remote ?? "origin",
package/client.js CHANGED
@@ -2054,7 +2054,8 @@ var CONFIGURABLE_PERMISSIONS = {
2054
2054
  // Everything outside the worktree is read-only in the sandbox (ADR 0009,
2055
2055
  // Stage 1 isolation), so writing there cannot be allowed wholesale.
2056
2056
  write_outside_repo: ["ask", "deny"],
2057
- git_push: ["allow", "ask", "deny"],
2057
+ // Push is what the GitHub App grants (decision 2026-11-01-1215): never asked.
2058
+ git_push: ["allow", "deny"],
2058
2059
  network: ["allow", "ask", "deny"],
2059
2060
  computer_use: ["allow", "ask", "deny"]
2060
2061
  };
@@ -2072,7 +2073,9 @@ var PERMISSION_DEFAULTS = {
2072
2073
  ...FIXED_PERMISSIONS,
2073
2074
  install_dependency: "allow",
2074
2075
  write_outside_repo: "ask",
2075
- git_push: "ask",
2076
+ // A run pushes only when the server sends allow for an admitted GitHub App
2077
+ // grant (decision 2026-11-01-1215); a policy that does not say so never pushes.
2078
+ git_push: "deny",
2076
2079
  // Agents reach the open internet unless a person restricts it in settings
2077
2080
  // (decision 2026-11-01-1230-network-open-by-default).
2078
2081
  network: "allow",
@@ -2092,7 +2095,8 @@ var networkAllowSchema = z2.array(networkDomainSchema).max(MAX_NETWORK_DOMAINS).
2092
2095
  var storedPermissionsSchema = z2.strictObject({
2093
2096
  install_dependency: z2.enum(CONFIGURABLE_PERMISSIONS.install_dependency),
2094
2097
  write_outside_repo: z2.enum(CONFIGURABLE_PERMISSIONS.write_outside_repo),
2095
- git_push: z2.enum(CONFIGURABLE_PERMISSIONS.git_push),
2098
+ // A stored ask predates decision 2026-11-01-1215 and reads as allow.
2099
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "allow" : value),
2096
2100
  network: z2.enum(CONFIGURABLE_PERMISSIONS.network),
2097
2101
  computer_use: z2.enum(CONFIGURABLE_PERMISSIONS.computer_use)
2098
2102
  }).partial();
@@ -2101,7 +2105,8 @@ var runPolicySchema = z2.strictObject({
2101
2105
  permissions: z2.strictObject({
2102
2106
  install_dependency: z2.enum(PERMISSION_DECISIONS),
2103
2107
  write_outside_repo: z2.enum(PERMISSION_DECISIONS),
2104
- git_push: z2.enum(PERMISSION_DECISIONS),
2108
+ // Push is allow (admitted) or deny; an older server's ask carries no push authority.
2109
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "deny" : value),
2105
2110
  network: z2.enum(PERMISSION_DECISIONS),
2106
2111
  // Older servers omit this field; the daemon treats that as ask, never allow.
2107
2112
  computer_use: z2.enum(PERMISSION_DECISIONS).optional()
@@ -3743,7 +3748,7 @@ import { join } from "node:path";
3743
3748
  // package.json
3744
3749
  var package_default = {
3745
3750
  name: "@mikka/daemon",
3746
- version: "0.0.193",
3751
+ version: "0.0.194",
3747
3752
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3748
3753
  type: "module",
3749
3754
  private: true,
@@ -3803,7 +3808,7 @@ var package_default = {
3803
3808
  engines: {
3804
3809
  node: ">=24"
3805
3810
  },
3806
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
3811
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
3807
3812
  };
3808
3813
 
3809
3814
  // src/paths.ts
package/http-link.js CHANGED
@@ -2181,7 +2181,8 @@ var CONFIGURABLE_PERMISSIONS = {
2181
2181
  // Everything outside the worktree is read-only in the sandbox (ADR 0009,
2182
2182
  // Stage 1 isolation), so writing there cannot be allowed wholesale.
2183
2183
  write_outside_repo: ["ask", "deny"],
2184
- git_push: ["allow", "ask", "deny"],
2184
+ // Push is what the GitHub App grants (decision 2026-11-01-1215): never asked.
2185
+ git_push: ["allow", "deny"],
2185
2186
  network: ["allow", "ask", "deny"],
2186
2187
  computer_use: ["allow", "ask", "deny"]
2187
2188
  };
@@ -2199,7 +2200,9 @@ var PERMISSION_DEFAULTS = {
2199
2200
  ...FIXED_PERMISSIONS,
2200
2201
  install_dependency: "allow",
2201
2202
  write_outside_repo: "ask",
2202
- git_push: "ask",
2203
+ // A run pushes only when the server sends allow for an admitted GitHub App
2204
+ // grant (decision 2026-11-01-1215); a policy that does not say so never pushes.
2205
+ git_push: "deny",
2203
2206
  // Agents reach the open internet unless a person restricts it in settings
2204
2207
  // (decision 2026-11-01-1230-network-open-by-default).
2205
2208
  network: "allow",
@@ -2224,7 +2227,8 @@ var networkAllowSchema = z2.array(networkDomainSchema).max(MAX_NETWORK_DOMAINS).
2224
2227
  var storedPermissionsSchema = z2.strictObject({
2225
2228
  install_dependency: z2.enum(CONFIGURABLE_PERMISSIONS.install_dependency),
2226
2229
  write_outside_repo: z2.enum(CONFIGURABLE_PERMISSIONS.write_outside_repo),
2227
- git_push: z2.enum(CONFIGURABLE_PERMISSIONS.git_push),
2230
+ // A stored ask predates decision 2026-11-01-1215 and reads as allow.
2231
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "allow" : value),
2228
2232
  network: z2.enum(CONFIGURABLE_PERMISSIONS.network),
2229
2233
  computer_use: z2.enum(CONFIGURABLE_PERMISSIONS.computer_use)
2230
2234
  }).partial();
@@ -2238,7 +2242,8 @@ var runPolicySchema = z2.strictObject({
2238
2242
  permissions: z2.strictObject({
2239
2243
  install_dependency: z2.enum(PERMISSION_DECISIONS),
2240
2244
  write_outside_repo: z2.enum(PERMISSION_DECISIONS),
2241
- git_push: z2.enum(PERMISSION_DECISIONS),
2245
+ // Push is allow (admitted) or deny; an older server's ask carries no push authority.
2246
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "deny" : value),
2242
2247
  network: z2.enum(PERMISSION_DECISIONS),
2243
2248
  // Older servers omit this field; the daemon treats that as ask, never allow.
2244
2249
  computer_use: z2.enum(PERMISSION_DECISIONS).optional()
@@ -4177,7 +4182,7 @@ var InvalidIdError = class extends DaemonError {
4177
4182
  // package.json
4178
4183
  var package_default = {
4179
4184
  name: "@mikka/daemon",
4180
- version: "0.0.193",
4185
+ version: "0.0.194",
4181
4186
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4182
4187
  type: "module",
4183
4188
  private: true,
@@ -4237,7 +4242,7 @@ var package_default = {
4237
4242
  engines: {
4238
4243
  node: ">=24"
4239
4244
  },
4240
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
4245
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
4241
4246
  };
4242
4247
 
4243
4248
  // src/paths.ts
package/login.js CHANGED
@@ -2050,7 +2050,8 @@ var CONFIGURABLE_PERMISSIONS = {
2050
2050
  // Everything outside the worktree is read-only in the sandbox (ADR 0009,
2051
2051
  // Stage 1 isolation), so writing there cannot be allowed wholesale.
2052
2052
  write_outside_repo: ["ask", "deny"],
2053
- git_push: ["allow", "ask", "deny"],
2053
+ // Push is what the GitHub App grants (decision 2026-11-01-1215): never asked.
2054
+ git_push: ["allow", "deny"],
2054
2055
  network: ["allow", "ask", "deny"],
2055
2056
  computer_use: ["allow", "ask", "deny"]
2056
2057
  };
@@ -2068,7 +2069,9 @@ var PERMISSION_DEFAULTS = {
2068
2069
  ...FIXED_PERMISSIONS,
2069
2070
  install_dependency: "allow",
2070
2071
  write_outside_repo: "ask",
2071
- git_push: "ask",
2072
+ // A run pushes only when the server sends allow for an admitted GitHub App
2073
+ // grant (decision 2026-11-01-1215); a policy that does not say so never pushes.
2074
+ git_push: "deny",
2072
2075
  // Agents reach the open internet unless a person restricts it in settings
2073
2076
  // (decision 2026-11-01-1230-network-open-by-default).
2074
2077
  network: "allow",
@@ -2088,7 +2091,8 @@ var networkAllowSchema = z2.array(networkDomainSchema).max(MAX_NETWORK_DOMAINS).
2088
2091
  var storedPermissionsSchema = z2.strictObject({
2089
2092
  install_dependency: z2.enum(CONFIGURABLE_PERMISSIONS.install_dependency),
2090
2093
  write_outside_repo: z2.enum(CONFIGURABLE_PERMISSIONS.write_outside_repo),
2091
- git_push: z2.enum(CONFIGURABLE_PERMISSIONS.git_push),
2094
+ // A stored ask predates decision 2026-11-01-1215 and reads as allow.
2095
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "allow" : value),
2092
2096
  network: z2.enum(CONFIGURABLE_PERMISSIONS.network),
2093
2097
  computer_use: z2.enum(CONFIGURABLE_PERMISSIONS.computer_use)
2094
2098
  }).partial();
@@ -2097,7 +2101,8 @@ var runPolicySchema = z2.strictObject({
2097
2101
  permissions: z2.strictObject({
2098
2102
  install_dependency: z2.enum(PERMISSION_DECISIONS),
2099
2103
  write_outside_repo: z2.enum(PERMISSION_DECISIONS),
2100
- git_push: z2.enum(PERMISSION_DECISIONS),
2104
+ // Push is allow (admitted) or deny; an older server's ask carries no push authority.
2105
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "deny" : value),
2101
2106
  network: z2.enum(PERMISSION_DECISIONS),
2102
2107
  // Older servers omit this field; the daemon treats that as ask, never allow.
2103
2108
  computer_use: z2.enum(PERMISSION_DECISIONS).optional()
@@ -3750,7 +3755,7 @@ var ServerUnreachableError = class extends DaemonError {
3750
3755
  // package.json
3751
3756
  var package_default = {
3752
3757
  name: "@mikka/daemon",
3753
- version: "0.0.193",
3758
+ version: "0.0.194",
3754
3759
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3755
3760
  type: "module",
3756
3761
  private: true,
@@ -3810,7 +3815,7 @@ var package_default = {
3810
3815
  engines: {
3811
3816
  node: ">=24"
3812
3817
  },
3813
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
3818
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
3814
3819
  };
3815
3820
 
3816
3821
  // src/paths.ts
package/main.js CHANGED
@@ -2456,7 +2456,8 @@ var CONFIGURABLE_PERMISSIONS = {
2456
2456
  // Everything outside the worktree is read-only in the sandbox (ADR 0009,
2457
2457
  // Stage 1 isolation), so writing there cannot be allowed wholesale.
2458
2458
  write_outside_repo: ["ask", "deny"],
2459
- git_push: ["allow", "ask", "deny"],
2459
+ // Push is what the GitHub App grants (decision 2026-11-01-1215): never asked.
2460
+ git_push: ["allow", "deny"],
2460
2461
  network: ["allow", "ask", "deny"],
2461
2462
  computer_use: ["allow", "ask", "deny"]
2462
2463
  };
@@ -2474,7 +2475,9 @@ var PERMISSION_DEFAULTS = {
2474
2475
  ...FIXED_PERMISSIONS,
2475
2476
  install_dependency: "allow",
2476
2477
  write_outside_repo: "ask",
2477
- git_push: "ask",
2478
+ // A run pushes only when the server sends allow for an admitted GitHub App
2479
+ // grant (decision 2026-11-01-1215); a policy that does not say so never pushes.
2480
+ git_push: "deny",
2478
2481
  // Agents reach the open internet unless a person restricts it in settings
2479
2482
  // (decision 2026-11-01-1230-network-open-by-default).
2480
2483
  network: "allow",
@@ -2502,7 +2505,8 @@ var networkAllowSchema = z.array(networkDomainSchema).max(MAX_NETWORK_DOMAINS).t
2502
2505
  var storedPermissionsSchema = z.strictObject({
2503
2506
  install_dependency: z.enum(CONFIGURABLE_PERMISSIONS.install_dependency),
2504
2507
  write_outside_repo: z.enum(CONFIGURABLE_PERMISSIONS.write_outside_repo),
2505
- git_push: z.enum(CONFIGURABLE_PERMISSIONS.git_push),
2508
+ // A stored ask predates decision 2026-11-01-1215 and reads as allow.
2509
+ git_push: z.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "allow" : value),
2506
2510
  network: z.enum(CONFIGURABLE_PERMISSIONS.network),
2507
2511
  computer_use: z.enum(CONFIGURABLE_PERMISSIONS.computer_use)
2508
2512
  }).partial();
@@ -2537,7 +2541,8 @@ var runPolicySchema = z.strictObject({
2537
2541
  permissions: z.strictObject({
2538
2542
  install_dependency: z.enum(PERMISSION_DECISIONS),
2539
2543
  write_outside_repo: z.enum(PERMISSION_DECISIONS),
2540
- git_push: z.enum(PERMISSION_DECISIONS),
2544
+ // Push is allow (admitted) or deny; an older server's ask carries no push authority.
2545
+ git_push: z.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "deny" : value),
2541
2546
  network: z.enum(PERMISSION_DECISIONS),
2542
2547
  // Older servers omit this field; the daemon treats that as ask, never allow.
2543
2548
  computer_use: z.enum(PERMISSION_DECISIONS).optional()
@@ -3216,7 +3221,7 @@ async function publishRun(options) {
3216
3221
  pushed: false,
3217
3222
  remote: null,
3218
3223
  skipped: "not_approved",
3219
- note: options.push.note ?? "Push needs approval for this repo"
3224
+ note: options.push.note ?? "Push needs the Mikka GitHub App's access on this repository"
3220
3225
  };
3221
3226
  }
3222
3227
  return push(commit);
@@ -3803,7 +3808,7 @@ import { join as join5 } from "node:path";
3803
3808
  // package.json
3804
3809
  var package_default = {
3805
3810
  name: "@mikka/daemon",
3806
- version: "0.0.193",
3811
+ version: "0.0.194",
3807
3812
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3808
3813
  type: "module",
3809
3814
  private: true,
@@ -3863,7 +3868,7 @@ var package_default = {
3863
3868
  engines: {
3864
3869
  node: ">=24"
3865
3870
  },
3866
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
3871
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
3867
3872
  };
3868
3873
 
3869
3874
  // src/paths.ts
@@ -3937,14 +3942,14 @@ function runDomains(policy, repoAllow = []) {
3937
3942
  const destinations = policy.permissions.network === "allow" ? ["*"] : [.../* @__PURE__ */ new Set([...policy.networkAllow, ...repoAllow, ...registries])];
3938
3943
  return policy.networkCeiling === void 0 ? destinations : intersectNetworkDomains(destinations, policy.networkCeiling);
3939
3944
  }
3940
- function pushDecision(policy, repoApproved) {
3945
+ function pushDecision(policy) {
3941
3946
  if (policy.readOnly)
3942
3947
  return { push: false, note: "A read-only check does not push" };
3943
3948
  const decision = policy.permissions.git_push;
3949
+ if (decision === "allow") return { push: true };
3944
3950
  if (decision === "deny")
3945
- return { push: false, note: "Push is turned off for this workspace" };
3946
- if (decision === "allow" || repoApproved) return { push: true };
3947
- return { push: false, note: "Push needs approval for this repo" };
3951
+ return { push: false, note: "Push is turned off for this run" };
3952
+ return { push: false, note: "Push needs the Mikka GitHub App's access on this repository" };
3948
3953
  }
3949
3954
  var INSTALL_COMMANDS = [
3950
3955
  ["npm", ["install", "i", "add", "ci"]],
@@ -8677,6 +8682,9 @@ import { setTimeout as sleep } from "node:timers/promises";
8677
8682
  import { execa as execa5 } from "execa";
8678
8683
 
8679
8684
  // src/chunks.ts
8685
+ function runStageChunk(stage, ms, ok2) {
8686
+ return { type: "data-run-stage", data: { stage, ms: Math.max(0, Math.round(ms)), ok: ok2 } };
8687
+ }
8680
8688
  function runStateChunk(state, error, stopReason) {
8681
8689
  return {
8682
8690
  type: "data-run-state",
@@ -11786,6 +11794,23 @@ var RunSupervisor = class {
11786
11794
  this.deps.log.error({ run_id: runId, err }, "outbox compaction failed");
11787
11795
  });
11788
11796
  }
11797
+ /**
11798
+ * Runs one start-up stage and records it as a stored `data-run-stage`
11799
+ * chunk with its duration, ok or not, so a run that fails while starting
11800
+ * shows which stage it reached. The stage's own result or error passes
11801
+ * through unchanged.
11802
+ */
11803
+ async stage(runId, stage, work) {
11804
+ const started = performance.now();
11805
+ try {
11806
+ const value = await work();
11807
+ this.emit(runId, runStageChunk(stage, performance.now() - started, true));
11808
+ return value;
11809
+ } catch (error) {
11810
+ this.emit(runId, runStageChunk(stage, performance.now() - started, false));
11811
+ throw error;
11812
+ }
11813
+ }
11789
11814
  setState(runId, state, extra = {}) {
11790
11815
  const entry = this.deps.journal.update(runId, {
11791
11816
  state,
@@ -11920,7 +11945,7 @@ var RunSupervisor = class {
11920
11945
  }
11921
11946
  const branch = assignment.pushBranch;
11922
11947
  const base = await this.deps.baseRef(assignment);
11923
- if (!branch || !pushDecision(runPolicy(assignment.policy), repo.push?.approved === true).push) return base;
11948
+ if (!branch || !pushDecision(runPolicy(assignment.policy)).push) return base;
11924
11949
  try {
11925
11950
  return await withRunGitCredentials(
11926
11951
  assignment,
@@ -12032,7 +12057,7 @@ var RunSupervisor = class {
12032
12057
  this.setState(runId, "preparing");
12033
12058
  entry = this.deps.journal.get(runId);
12034
12059
  }
12035
- await this.deps.prepareRepository(assignment, AbortSignal.any([this.stopController.signal, run3.abort.signal]));
12060
+ await this.stage(runId, "repository", () => this.deps.prepareRepository(assignment, AbortSignal.any([this.stopController.signal, run3.abort.signal])));
12036
12061
  if (this.stopping || run3.cancelRequested) {
12037
12062
  if (!this.stopping) this.finish(runId, run3.forcedStop ?? "cancelled");
12038
12063
  return;
@@ -12051,11 +12076,11 @@ var RunSupervisor = class {
12051
12076
  );
12052
12077
  if (assignment.requireWorktreeContinuation && !entry.worktree && !continued)
12053
12078
  throw new CheckpointRecoveryError("Original worktree is unavailable and there is no usable recovery snapshot.");
12054
- const worktree = entry.worktree ?? continued ?? await this.deps.worktrees.create(
12079
+ const worktree = entry.worktree ?? continued ?? await this.stage(runId, "worktree", async () => this.deps.worktrees.create(
12055
12080
  runId,
12056
12081
  repo.path,
12057
12082
  await this.startPoint(runId, repo, assignment)
12058
- );
12083
+ ));
12059
12084
  if (!entry.worktree) {
12060
12085
  const baseCommit = (continued && assignment.continuesRunId ? this.deps.journal.get(assignment.continuesRunId)?.baseCommit : void 0) ?? await headCommit(repo.path, worktree);
12061
12086
  if (!continued && assignment.resumeFrom) {
@@ -12179,7 +12204,7 @@ var RunSupervisor = class {
12179
12204
  let session;
12180
12205
  if (assignment.subscriptionBinding && assignment.modelCredential) throw new Error("A run has one model credential");
12181
12206
  try {
12182
- session = assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
12207
+ session = await this.stage(runId, "agent_start", async () => assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
12183
12208
  throw new Error("subscription_hosted_runtime_unavailable");
12184
12209
  })() : resuming ? await adapter.resume(entry.sessionId, options) : await (async () => {
12185
12210
  if (assignment.requireSessionResume)
@@ -12192,7 +12217,7 @@ var RunSupervisor = class {
12192
12217
  continueSession,
12193
12218
  requireSessionResume: assignment.requireSessionResume
12194
12219
  });
12195
- })();
12220
+ })());
12196
12221
  } catch (error) {
12197
12222
  if (assignment.skillReceipt) this.deps.journal.update(runId, { skillMount: void 0, execution: void 0, runtime: void 0 });
12198
12223
  throw error;
@@ -12329,7 +12354,7 @@ var RunSupervisor = class {
12329
12354
  const policy = runPolicy(assignment.policy);
12330
12355
  if (stopReason === "submitted" && report.verify.status !== "failed" && tree && // The draft-PR exception requires an explicit repository push
12331
12356
  // approval. It must not even create a local commit without it.
12332
- (report.verify.status === "passed" || pushDecision(policy, repo.push?.approved === true).push) && // A read-only check (ADR 0046) never commits or pushes: it reports
12357
+ (report.verify.status === "passed" || pushDecision(policy).push) && // A read-only check (ADR 0046) never commits or pushes: it reports
12333
12358
  // on the commit the implementation run already pushed.
12334
12359
  policy.readOnly !== true) {
12335
12360
  const publish = await this.publish(
@@ -12738,9 +12763,15 @@ var bootstrap = fileURLToPath3(
12738
12763
  );
12739
12764
  var placeholder = "mikka-native-broker-placeholder";
12740
12765
  var unavailable3 = (cause) => new Error("subscription_hosted_runtime_unavailable", cause === void 0 ? void 0 : { cause });
12741
- var dockerFailure = (error) => {
12766
+ var DOCKER_CREATE_TIMEOUT_MS = 18e4;
12767
+ var dockerFailure = (error, startedAt) => {
12742
12768
  const value = error;
12743
- return new Error(String(value.stderr || value.message || error).trim().slice(-500));
12769
+ const took = startedAt === void 0 ? "" : ` after ${Math.round((performance.now() - startedAt) / 1e3)}s`;
12770
+ const stderr = String(value.stderr ?? "").trim();
12771
+ if (stderr) return new Error(`${stderr.slice(-500)}${took}`);
12772
+ if (value.killed) return new Error(`docker timed out${took}`);
12773
+ if (error instanceof Error && error.message === "subscription_hosted_runtime_unavailable") return new Error(`run fenced${took}`);
12774
+ return new Error(`docker failed (exit ${String(value.code ?? value.signal ?? "unknown")})${took}`);
12744
12775
  };
12745
12776
  var blockedSandbox = {
12746
12777
  kind: "none",
@@ -12937,7 +12968,7 @@ async function createHostedBotRunner(host) {
12937
12968
  "-c",
12938
12969
  script
12939
12970
  ],
12940
- { env: bareEnv, timeout: 3e4, signal, maxBuffer: 1024 * 1024 }
12971
+ { env: bareEnv, timeout: DOCKER_CREATE_TIMEOUT_MS, signal, maxBuffer: 1024 * 1024 }
12941
12972
  );
12942
12973
  resource.id = created.stdout.trim();
12943
12974
  if (!/^[a-f0-9]{64}$/.test(resource.id)) throw unavailable3();
@@ -13257,10 +13288,11 @@ async function createHostedBotRunner(host) {
13257
13288
  ];
13258
13289
  await live();
13259
13290
  writeJsonAtomic(resourceFile, resource);
13291
+ const createStarted = performance.now();
13260
13292
  try {
13261
13293
  creating = exec3("docker", containerArgs2, {
13262
13294
  env: bareEnv,
13263
- timeout: 3e4
13295
+ timeout: DOCKER_CREATE_TIMEOUT_MS
13264
13296
  }).then((created) => {
13265
13297
  resource.id = created.stdout.trim();
13266
13298
  if (!/^[a-f0-9]{64}$/.test(resource.id)) throw unavailable3();
@@ -13268,9 +13300,10 @@ async function createHostedBotRunner(host) {
13268
13300
  writeJsonAtomic(resourceFile, resource);
13269
13301
  });
13270
13302
  await creating;
13303
+ console.info(`run ${assignment.runId}: hosted container created in ${Math.round((performance.now() - createStarted) / 1e3)}s`);
13271
13304
  await live();
13272
13305
  } catch (error) {
13273
- const reason = dockerFailure(error);
13306
+ const reason = dockerFailure(error, createStarted);
13274
13307
  try {
13275
13308
  await close();
13276
13309
  } catch (cleanup) {
@@ -14256,10 +14289,7 @@ var Daemon = class {
14256
14289
  pushBranch: assignment.pushBranch,
14257
14290
  baseBranch: assignment.remoteUrl ? await this.repositories.baseRef(assignment.remoteUrl, assignment.baseBranch) : assignment.baseBranch,
14258
14291
  push: (() => {
14259
- const decision = pushDecision(
14260
- runPolicy(assignment.policy),
14261
- repo.push?.approved === true
14262
- );
14292
+ const decision = pushDecision(runPolicy(assignment.policy));
14263
14293
  return {
14264
14294
  approved: decision.push,
14265
14295
  remote: repo.push?.remote ?? "origin",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "version": 1,
3
- "sourceSha": "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b",
3
+ "sourceSha": "c28c48908fb4b35a1cb5f57c391d27cc68aae252",
4
4
  "repository": "alexj11324/Mikka",
5
- "buildRunId": "41312499534",
5
+ "buildRunId": "41316302270",
6
6
  "buildKind": "github-actions-main",
7
7
  "sourceLockSha256": "c99f1e4f641d8e004cfe807653478e10f91e53fcf47102add5f4c154cdc1cb57",
8
- "createdAt": "2026-11-01T14:44:20.643Z",
8
+ "createdAt": "2026-11-01T14:49:22.004Z",
9
9
  "sbom": "sbom.cdx.json",
10
10
  "files": [
11
11
  {
@@ -40,13 +40,13 @@
40
40
  },
41
41
  {
42
42
  "path": "cli.js",
43
- "size": 652780,
44
- "sha256": "fdccebf7a555446dff920a0fb4588504c6a836eab03e1891c985203ba54badb2"
43
+ "size": 654772,
44
+ "sha256": "12286d810a77bb3af96496faffa3fe69d8605c1d59e02c0f0084d603cfc74638"
45
45
  },
46
46
  {
47
47
  "path": "client.js",
48
- "size": 141342,
49
- "sha256": "54b5ec5cce1903535b4a02c7b0a232f882e416c210ae4c24026d71a2d1a1392d"
48
+ "size": 141838,
49
+ "sha256": "538f6f65ed041a1a80b0297e3ca0307abc538829e639f34f771a09e8d33849a0"
50
50
  },
51
51
  {
52
52
  "path": "computer/driver.mjs",
@@ -175,8 +175,8 @@
175
175
  },
176
176
  {
177
177
  "path": "http-link.js",
178
- "size": 184275,
179
- "sha256": "314b00afc84636988e9f119fa16865c9ebac4aa8510ef89e95d2159470968e40"
178
+ "size": 184771,
179
+ "sha256": "904f3ee238a7189fec153dbe0841246c386d0a2ab4049465ebe2388c8ae1d61c"
180
180
  },
181
181
  {
182
182
  "path": "log.js",
@@ -185,13 +185,13 @@
185
185
  },
186
186
  {
187
187
  "path": "login.js",
188
- "size": 146220,
189
- "sha256": "6c12846b1e72f0ed2157831ede757d4384d47da0592b413d810ea81ba15e8b13"
188
+ "size": 146716,
189
+ "sha256": "fea6b4b25199dcb5b6a0c327d320560caca96b9767f8cd85509f3cd68f7066d7"
190
190
  },
191
191
  {
192
192
  "path": "main.js",
193
- "size": 597997,
194
- "sha256": "cf67e7024fd5c766fc28b2b83ecb1df3fb5893649de4cb0f2a0152b6db9142c4"
193
+ "size": 599989,
194
+ "sha256": "2f3f8ae8033053cd35d605901661ada617f7b48e469e991bdf53f7a1db7d7499"
195
195
  },
196
196
  {
197
197
  "path": "mikka-mcp.mjs",
@@ -200,23 +200,23 @@
200
200
  },
201
201
  {
202
202
  "path": "mikka.js",
203
- "size": 652796,
204
- "sha256": "d7b9824bcf7732358feeeecebe26836763d931a4e093008b2823c0e662c99593"
203
+ "size": 654788,
204
+ "sha256": "d5d50e32789fb9c2a41836b744896d52152fa35f64d568a1e40e8ae08d1acb30"
205
205
  },
206
206
  {
207
207
  "path": "npm-shrinkwrap.json",
208
208
  "size": 78117,
209
- "sha256": "dde9cf97a2ef3c980117f436eab19add4589b368b6303313a5adafe21419f260"
209
+ "sha256": "8413ae7a61c4ccbcb8d4057e386bc464fc45475b08914b27a0d60f633263e3f1"
210
210
  },
211
211
  {
212
212
  "path": "package.json",
213
213
  "size": 1247,
214
- "sha256": "61030ffae3f847591ee9c5fa6d277bac6e30254e55e0e63780d09df25c4a0a2a"
214
+ "sha256": "cf50bd8cc85decabee2e373153b0c8291236337ef3fe005bc5a84d92ad3f60c3"
215
215
  },
216
216
  {
217
217
  "path": "paths.js",
218
218
  "size": 4138,
219
- "sha256": "34334c3022e05698adc7554cacea9a5dbaea36c55b109774203be834c44de197"
219
+ "sha256": "2d8980e4b4edb9f70609503c56a7e3c281b7af138ec8efc11f1b4b006344e481"
220
220
  },
221
221
  {
222
222
  "path": "run-sandbox-worker.mjs",
@@ -231,7 +231,7 @@
231
231
  {
232
232
  "path": "sbom.cdx.json",
233
233
  "size": 144314,
234
- "sha256": "80f48439a26ba0542aabc94684d9615c32db1d029c10aa3e2f581204e5d38427"
234
+ "sha256": "74f7c4498bffbc5f9808459363773cfbe29f9ecf496eac262c6506626bd3fd68"
235
235
  }
236
236
  ]
237
237
  }
package/mikka.js CHANGED
@@ -2434,7 +2434,8 @@ var CONFIGURABLE_PERMISSIONS = {
2434
2434
  // Everything outside the worktree is read-only in the sandbox (ADR 0009,
2435
2435
  // Stage 1 isolation), so writing there cannot be allowed wholesale.
2436
2436
  write_outside_repo: ["ask", "deny"],
2437
- git_push: ["allow", "ask", "deny"],
2437
+ // Push is what the GitHub App grants (decision 2026-11-01-1215): never asked.
2438
+ git_push: ["allow", "deny"],
2438
2439
  network: ["allow", "ask", "deny"],
2439
2440
  computer_use: ["allow", "ask", "deny"]
2440
2441
  };
@@ -2452,7 +2453,9 @@ var PERMISSION_DEFAULTS = {
2452
2453
  ...FIXED_PERMISSIONS,
2453
2454
  install_dependency: "allow",
2454
2455
  write_outside_repo: "ask",
2455
- git_push: "ask",
2456
+ // A run pushes only when the server sends allow for an admitted GitHub App
2457
+ // grant (decision 2026-11-01-1215); a policy that does not say so never pushes.
2458
+ git_push: "deny",
2456
2459
  // Agents reach the open internet unless a person restricts it in settings
2457
2460
  // (decision 2026-11-01-1230-network-open-by-default).
2458
2461
  network: "allow",
@@ -2480,7 +2483,8 @@ var networkAllowSchema = z2.array(networkDomainSchema).max(MAX_NETWORK_DOMAINS).
2480
2483
  var storedPermissionsSchema = z2.strictObject({
2481
2484
  install_dependency: z2.enum(CONFIGURABLE_PERMISSIONS.install_dependency),
2482
2485
  write_outside_repo: z2.enum(CONFIGURABLE_PERMISSIONS.write_outside_repo),
2483
- git_push: z2.enum(CONFIGURABLE_PERMISSIONS.git_push),
2486
+ // A stored ask predates decision 2026-11-01-1215 and reads as allow.
2487
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "allow" : value),
2484
2488
  network: z2.enum(CONFIGURABLE_PERMISSIONS.network),
2485
2489
  computer_use: z2.enum(CONFIGURABLE_PERMISSIONS.computer_use)
2486
2490
  }).partial();
@@ -2515,7 +2519,8 @@ var runPolicySchema = z2.strictObject({
2515
2519
  permissions: z2.strictObject({
2516
2520
  install_dependency: z2.enum(PERMISSION_DECISIONS),
2517
2521
  write_outside_repo: z2.enum(PERMISSION_DECISIONS),
2518
- git_push: z2.enum(PERMISSION_DECISIONS),
2522
+ // Push is allow (admitted) or deny; an older server's ask carries no push authority.
2523
+ git_push: z2.enum(PERMISSION_DECISIONS).transform((value) => value === "ask" ? "deny" : value),
2519
2524
  network: z2.enum(PERMISSION_DECISIONS),
2520
2525
  // Older servers omit this field; the daemon treats that as ask, never allow.
2521
2526
  computer_use: z2.enum(PERMISSION_DECISIONS).optional()
@@ -4483,7 +4488,7 @@ import { join as join4 } from "node:path";
4483
4488
  // package.json
4484
4489
  var package_default = {
4485
4490
  name: "@mikka/daemon",
4486
- version: "0.0.193",
4491
+ version: "0.0.194",
4487
4492
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4488
4493
  type: "module",
4489
4494
  private: true,
@@ -4543,7 +4548,7 @@ var package_default = {
4543
4548
  engines: {
4544
4549
  node: ">=24"
4545
4550
  },
4546
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
4551
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
4547
4552
  };
4548
4553
 
4549
4554
  // src/paths.ts
@@ -4752,14 +4757,14 @@ function runDomains(policy, repoAllow = []) {
4752
4757
  const destinations = policy.permissions.network === "allow" ? ["*"] : [.../* @__PURE__ */ new Set([...policy.networkAllow, ...repoAllow, ...registries])];
4753
4758
  return policy.networkCeiling === void 0 ? destinations : intersectNetworkDomains(destinations, policy.networkCeiling);
4754
4759
  }
4755
- function pushDecision(policy, repoApproved) {
4760
+ function pushDecision(policy) {
4756
4761
  if (policy.readOnly)
4757
4762
  return { push: false, note: "A read-only check does not push" };
4758
4763
  const decision = policy.permissions.git_push;
4764
+ if (decision === "allow") return { push: true };
4759
4765
  if (decision === "deny")
4760
- return { push: false, note: "Push is turned off for this workspace" };
4761
- if (decision === "allow" || repoApproved) return { push: true };
4762
- return { push: false, note: "Push needs approval for this repo" };
4766
+ return { push: false, note: "Push is turned off for this run" };
4767
+ return { push: false, note: "Push needs the Mikka GitHub App's access on this repository" };
4763
4768
  }
4764
4769
  var INSTALL_COMMANDS = [
4765
4770
  ["npm", ["install", "i", "add", "ci"]],
@@ -6913,7 +6918,7 @@ async function publishRun(options) {
6913
6918
  pushed: false,
6914
6919
  remote: null,
6915
6920
  skipped: "not_approved",
6916
- note: options.push.note ?? "Push needs approval for this repo"
6921
+ note: options.push.note ?? "Push needs the Mikka GitHub App's access on this repository"
6917
6922
  };
6918
6923
  }
6919
6924
  return push(commit);
@@ -9865,6 +9870,9 @@ import { setTimeout as sleep2 } from "node:timers/promises";
9865
9870
  import { execa as execa5 } from "execa";
9866
9871
 
9867
9872
  // src/chunks.ts
9873
+ function runStageChunk(stage, ms, ok2) {
9874
+ return { type: "data-run-stage", data: { stage, ms: Math.max(0, Math.round(ms)), ok: ok2 } };
9875
+ }
9868
9876
  function runStateChunk(state, error, stopReason) {
9869
9877
  return {
9870
9878
  type: "data-run-state",
@@ -12733,6 +12741,23 @@ var RunSupervisor = class {
12733
12741
  this.deps.log.error({ run_id: runId, err }, "outbox compaction failed");
12734
12742
  });
12735
12743
  }
12744
+ /**
12745
+ * Runs one start-up stage and records it as a stored `data-run-stage`
12746
+ * chunk with its duration, ok or not, so a run that fails while starting
12747
+ * shows which stage it reached. The stage's own result or error passes
12748
+ * through unchanged.
12749
+ */
12750
+ async stage(runId, stage, work) {
12751
+ const started = performance.now();
12752
+ try {
12753
+ const value = await work();
12754
+ this.emit(runId, runStageChunk(stage, performance.now() - started, true));
12755
+ return value;
12756
+ } catch (error) {
12757
+ this.emit(runId, runStageChunk(stage, performance.now() - started, false));
12758
+ throw error;
12759
+ }
12760
+ }
12736
12761
  setState(runId, state, extra = {}) {
12737
12762
  const entry = this.deps.journal.update(runId, {
12738
12763
  state,
@@ -12867,7 +12892,7 @@ var RunSupervisor = class {
12867
12892
  }
12868
12893
  const branch = assignment.pushBranch;
12869
12894
  const base = await this.deps.baseRef(assignment);
12870
- if (!branch || !pushDecision(runPolicy(assignment.policy), repo.push?.approved === true).push) return base;
12895
+ if (!branch || !pushDecision(runPolicy(assignment.policy)).push) return base;
12871
12896
  try {
12872
12897
  return await withRunGitCredentials(
12873
12898
  assignment,
@@ -12979,7 +13004,7 @@ var RunSupervisor = class {
12979
13004
  this.setState(runId, "preparing");
12980
13005
  entry = this.deps.journal.get(runId);
12981
13006
  }
12982
- await this.deps.prepareRepository(assignment, AbortSignal.any([this.stopController.signal, run3.abort.signal]));
13007
+ await this.stage(runId, "repository", () => this.deps.prepareRepository(assignment, AbortSignal.any([this.stopController.signal, run3.abort.signal])));
12983
13008
  if (this.stopping || run3.cancelRequested) {
12984
13009
  if (!this.stopping) this.finish(runId, run3.forcedStop ?? "cancelled");
12985
13010
  return;
@@ -12998,11 +13023,11 @@ var RunSupervisor = class {
12998
13023
  );
12999
13024
  if (assignment.requireWorktreeContinuation && !entry.worktree && !continued)
13000
13025
  throw new CheckpointRecoveryError("Original worktree is unavailable and there is no usable recovery snapshot.");
13001
- const worktree = entry.worktree ?? continued ?? await this.deps.worktrees.create(
13026
+ const worktree = entry.worktree ?? continued ?? await this.stage(runId, "worktree", async () => this.deps.worktrees.create(
13002
13027
  runId,
13003
13028
  repo.path,
13004
13029
  await this.startPoint(runId, repo, assignment)
13005
- );
13030
+ ));
13006
13031
  if (!entry.worktree) {
13007
13032
  const baseCommit = (continued && assignment.continuesRunId ? this.deps.journal.get(assignment.continuesRunId)?.baseCommit : void 0) ?? await headCommit(repo.path, worktree);
13008
13033
  if (!continued && assignment.resumeFrom) {
@@ -13126,7 +13151,7 @@ var RunSupervisor = class {
13126
13151
  let session;
13127
13152
  if (assignment.subscriptionBinding && assignment.modelCredential) throw new Error("A run has one model credential");
13128
13153
  try {
13129
- session = assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
13154
+ session = await this.stage(runId, "agent_start", async () => assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
13130
13155
  throw new Error("subscription_hosted_runtime_unavailable");
13131
13156
  })() : resuming ? await adapter.resume(entry.sessionId, options) : await (async () => {
13132
13157
  if (assignment.requireSessionResume)
@@ -13139,7 +13164,7 @@ var RunSupervisor = class {
13139
13164
  continueSession,
13140
13165
  requireSessionResume: assignment.requireSessionResume
13141
13166
  });
13142
- })();
13167
+ })());
13143
13168
  } catch (error) {
13144
13169
  if (assignment.skillReceipt) this.deps.journal.update(runId, { skillMount: void 0, execution: void 0, runtime: void 0 });
13145
13170
  throw error;
@@ -13276,7 +13301,7 @@ var RunSupervisor = class {
13276
13301
  const policy = runPolicy(assignment.policy);
13277
13302
  if (stopReason === "submitted" && report.verify.status !== "failed" && tree && // The draft-PR exception requires an explicit repository push
13278
13303
  // approval. It must not even create a local commit without it.
13279
- (report.verify.status === "passed" || pushDecision(policy, repo.push?.approved === true).push) && // A read-only check (ADR 0046) never commits or pushes: it reports
13304
+ (report.verify.status === "passed" || pushDecision(policy).push) && // A read-only check (ADR 0046) never commits or pushes: it reports
13280
13305
  // on the commit the implementation run already pushed.
13281
13306
  policy.readOnly !== true) {
13282
13307
  const publish = await this.publish(
@@ -13673,9 +13698,15 @@ var bootstrap = fileURLToPath3(
13673
13698
  );
13674
13699
  var placeholder = "mikka-native-broker-placeholder";
13675
13700
  var unavailable3 = (cause) => new Error("subscription_hosted_runtime_unavailable", cause === void 0 ? void 0 : { cause });
13676
- var dockerFailure = (error) => {
13701
+ var DOCKER_CREATE_TIMEOUT_MS = 18e4;
13702
+ var dockerFailure = (error, startedAt) => {
13677
13703
  const value = error;
13678
- return new Error(String(value.stderr || value.message || error).trim().slice(-500));
13704
+ const took = startedAt === void 0 ? "" : ` after ${Math.round((performance.now() - startedAt) / 1e3)}s`;
13705
+ const stderr = String(value.stderr ?? "").trim();
13706
+ if (stderr) return new Error(`${stderr.slice(-500)}${took}`);
13707
+ if (value.killed) return new Error(`docker timed out${took}`);
13708
+ if (error instanceof Error && error.message === "subscription_hosted_runtime_unavailable") return new Error(`run fenced${took}`);
13709
+ return new Error(`docker failed (exit ${String(value.code ?? value.signal ?? "unknown")})${took}`);
13679
13710
  };
13680
13711
  var blockedSandbox = {
13681
13712
  kind: "none",
@@ -13872,7 +13903,7 @@ async function createHostedBotRunner(host) {
13872
13903
  "-c",
13873
13904
  script
13874
13905
  ],
13875
- { env: bareEnv, timeout: 3e4, signal, maxBuffer: 1024 * 1024 }
13906
+ { env: bareEnv, timeout: DOCKER_CREATE_TIMEOUT_MS, signal, maxBuffer: 1024 * 1024 }
13876
13907
  );
13877
13908
  resource.id = created.stdout.trim();
13878
13909
  if (!/^[a-f0-9]{64}$/.test(resource.id)) throw unavailable3();
@@ -14192,10 +14223,11 @@ async function createHostedBotRunner(host) {
14192
14223
  ];
14193
14224
  await live();
14194
14225
  writeJsonAtomic(resourceFile, resource);
14226
+ const createStarted = performance.now();
14195
14227
  try {
14196
14228
  creating = exec3("docker", containerArgs2, {
14197
14229
  env: bareEnv,
14198
- timeout: 3e4
14230
+ timeout: DOCKER_CREATE_TIMEOUT_MS
14199
14231
  }).then((created) => {
14200
14232
  resource.id = created.stdout.trim();
14201
14233
  if (!/^[a-f0-9]{64}$/.test(resource.id)) throw unavailable3();
@@ -14203,9 +14235,10 @@ async function createHostedBotRunner(host) {
14203
14235
  writeJsonAtomic(resourceFile, resource);
14204
14236
  });
14205
14237
  await creating;
14238
+ console.info(`run ${assignment.runId}: hosted container created in ${Math.round((performance.now() - createStarted) / 1e3)}s`);
14206
14239
  await live();
14207
14240
  } catch (error) {
14208
- const reason = dockerFailure(error);
14241
+ const reason = dockerFailure(error, createStarted);
14209
14242
  try {
14210
14243
  await close();
14211
14244
  } catch (cleanup) {
@@ -15191,10 +15224,7 @@ var Daemon = class {
15191
15224
  pushBranch: assignment.pushBranch,
15192
15225
  baseBranch: assignment.remoteUrl ? await this.repositories.baseRef(assignment.remoteUrl, assignment.baseBranch) : assignment.baseBranch,
15193
15226
  push: (() => {
15194
- const decision = pushDecision(
15195
- runPolicy(assignment.policy),
15196
- repo.push?.approved === true
15197
- );
15227
+ const decision = pushDecision(runPolicy(assignment.policy));
15198
15228
  return {
15199
15229
  approved: decision.push,
15200
15230
  remote: repo.push?.remote ?? "origin",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@aspectlylabs/mikka",
3
- "version": "0.0.193",
3
+ "version": "0.0.194",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@aspectlylabs/mikka",
9
- "version": "0.0.193",
9
+ "version": "0.0.194",
10
10
  "license": "AGPL-3.0-only",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "1.9.0",
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@aspectlylabs/mikka",
3
- "version": "0.0.193",
3
+ "version": "0.0.194",
4
4
  "description": "Local Mikka daemon: runs agents through the user's own CLIs",
5
- "gitHead": "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b",
5
+ "gitHead": "c28c48908fb4b35a1cb5f57c391d27cc68aae252",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "license": "AGPL-3.0-only",
package/paths.js CHANGED
@@ -6,7 +6,7 @@ import { join } from "node:path";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@mikka/daemon",
9
- version: "0.0.193",
9
+ version: "0.0.194",
10
10
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
11
11
  type: "module",
12
12
  private: true,
@@ -66,7 +66,7 @@ var package_default = {
66
66
  engines: {
67
67
  node: ">=24"
68
68
  },
69
- gitHead: "f7cc3fffbc2cce990feb9c2c4eb65f59140b305b"
69
+ gitHead: "c28c48908fb4b35a1cb5f57c391d27cc68aae252"
70
70
  };
71
71
 
72
72
  // src/paths.ts
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:a26f957c-a2dc-4cb0-bec9-884207cd15cd",
5
+ "serialNumber": "urn:uuid:69e426b6-72e9-483e-a52c-15a9d233512a",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-11-01T14:44:19.699Z",
8
+ "timestamp": "2026-11-01T14:49:21.369Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "pre-build"
@@ -19,13 +19,13 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@aspectlylabs/mikka@0.0.193",
22
+ "bom-ref": "@aspectlylabs/mikka@0.0.194",
23
23
  "type": "library",
24
- "name": ".retained-build-iOfsYo",
25
- "version": "0.0.193",
24
+ "name": ".retained-build-iDX1L4",
25
+ "version": "0.0.194",
26
26
  "scope": "required",
27
27
  "description": "Local Mikka daemon: runs agents through the user's own CLIs",
28
- "purl": "pkg:npm/%40aspectlylabs/mikka@0.0.193",
28
+ "purl": "pkg:npm/%40aspectlylabs/mikka@0.0.194",
29
29
  "properties": [],
30
30
  "externalReferences": [
31
31
  {
@@ -4627,7 +4627,7 @@
4627
4627
  ],
4628
4628
  "dependencies": [
4629
4629
  {
4630
- "ref": "@aspectlylabs/mikka@0.0.193",
4630
+ "ref": "@aspectlylabs/mikka@0.0.194",
4631
4631
  "dependsOn": [
4632
4632
  "@agentclientprotocol/sdk@1.9.0",
4633
4633
  "@anthropic-ai/claude-agent-sdk@0.3.305",