@aspectlylabs/mikka 0.0.154 → 0.0.156

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
@@ -4480,7 +4480,7 @@ import { join as join4 } from "node:path";
4480
4480
  // package.json
4481
4481
  var package_default = {
4482
4482
  name: "@mikka/daemon",
4483
- version: "0.0.154",
4483
+ version: "0.0.156",
4484
4484
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4485
4485
  type: "module",
4486
4486
  private: true,
@@ -4540,7 +4540,7 @@ var package_default = {
4540
4540
  engines: {
4541
4541
  node: ">=24"
4542
4542
  },
4543
- gitHead: "d0202e732423480928c02e91adce73bfcaa58f90"
4543
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
4544
4544
  };
4545
4545
 
4546
4546
  // src/paths.ts
@@ -4815,7 +4815,7 @@ function classifySegment(segment, depth) {
4815
4815
  if (entry && verb && entry[1].includes(verb)) return "install_dependency";
4816
4816
  return null;
4817
4817
  }
4818
- function claudePermissionRules(policy) {
4818
+ function claudePermissionRules(policy, agentDelivers = false) {
4819
4819
  const install2 = INSTALL_COMMANDS.flatMap(
4820
4820
  ([tool2, verbs]) => verbs.map((verb) => `Bash(${tool2} ${verb}:*)`)
4821
4821
  );
@@ -4825,7 +4825,7 @@ function claudePermissionRules(policy) {
4825
4825
  ask: decision === "ask" ? install2 : [],
4826
4826
  deny: [
4827
4827
  ...!rawCliShellAvailable(policy) ? ["Bash", "PowerShell", "Monitor"] : [],
4828
- "Bash(git push:*)",
4828
+ ...agentDelivers && !policy.readOnly ? [] : ["Bash(git push:*)"],
4829
4829
  ...policy.readOnly ? READ_ONLY_TOOLS : [],
4830
4830
  ...decision === "deny" ? install2 : []
4831
4831
  ]
@@ -6115,7 +6115,7 @@ import {
6115
6115
  rmSync as rmSync5
6116
6116
  } from "node:fs";
6117
6117
  import { tmpdir } from "node:os";
6118
- import { dirname as dirname7, join as join8, resolve as resolve5 } from "node:path";
6118
+ import { basename as basename2, dirname as dirname7, join as join8, resolve as resolve5 } from "node:path";
6119
6119
 
6120
6120
  // src/ids.ts
6121
6121
  var SAFE_ID = /^[A-Za-z0-9_-]{1,64}$/;
@@ -6532,12 +6532,10 @@ async function worktreeGitDir(repoPath, worktree) {
6532
6532
  throw new Error(`${worktree} is not a worktree of ${repoPath}`);
6533
6533
  }
6534
6534
  async function worktreeGitWritePaths(repoPath, worktree, runId) {
6535
- const gitDir = await worktreeGitDir(repoPath, worktree);
6536
- const common = resolve5(gitDir, "..", "..");
6537
- const branch = `mikka/run-${assertSafeId("run id", runId)}`;
6538
- const ref = join8(common, "refs", "heads", branch);
6539
- const logsRef = join8(common, "logs", "refs", "heads", branch);
6540
- return [gitDir, join8(common, "objects"), dirname7(ref), ref, `${ref}.lock`, dirname7(logsRef), logsRef];
6535
+ assertSafeId("run id", runId);
6536
+ const common = resolve5(await worktreeGitDir(repoPath, worktree), "..", "..");
6537
+ if (basename2(common) !== ".git") throw new Error(`${repoPath} is not a standard clone`);
6538
+ return [dirname7(common)];
6541
6539
  }
6542
6540
  function safeRealpath(path) {
6543
6541
  try {
@@ -7014,6 +7012,16 @@ var HARNESS_DOMAINS = {
7014
7012
  var MCP_SERVER_SCRIPT = resolve7(import.meta.dirname, "mikka-mcp.mjs");
7015
7013
  var MCP_SERVER_NAME = "mikka";
7016
7014
  var COMPUTER_MCP_SERVER_NAME = "mikka_computer";
7015
+ var RUN_GIT_CONFIG = [["maintenance.auto", "false"], ["gc.auto", "0"]];
7016
+ function withGitConfig(env, entries) {
7017
+ const start = Number(env.GIT_CONFIG_COUNT ?? 0);
7018
+ const out = { ...env, GIT_CONFIG_COUNT: String(start + entries.length) };
7019
+ entries.forEach(([key2, value], i) => {
7020
+ out[`GIT_CONFIG_KEY_${start + i}`] = key2;
7021
+ out[`GIT_CONFIG_VALUE_${start + i}`] = value;
7022
+ });
7023
+ return out;
7024
+ }
7017
7025
  function credentialDenyRead(harness, home = homedir4()) {
7018
7026
  return [
7019
7027
  ".ssh",
@@ -7155,6 +7163,10 @@ var RunContext = class {
7155
7163
  join11(this.gitDir, "commondir"),
7156
7164
  join11(this.gitDir, "gitdir"),
7157
7165
  join11(this.gitDir, "config.worktree"),
7166
+ // sandbox-runtime's own protection of a repository's config and hooks
7167
+ // covers repositories under the process's working directory only;
7168
+ // the shared clone lies outside it, so it is declared here the same way.
7169
+ ...this.options.gitWritePaths?.length ? [join11(this.gitDir, "..", "..", "config"), join11(this.gitDir, "..", "..", "hooks")] : [],
7158
7170
  ...readOnly ? [this.worktree, ...this.options.gitWritePaths ?? []] : []
7159
7171
  ],
7160
7172
  denyRead: [
@@ -7216,7 +7228,15 @@ var RunContext = class {
7216
7228
  * and zsh writes here-docs to `$TMPPREFIX` (default `/tmp/zsh`).
7217
7229
  */
7218
7230
  tempEnv() {
7219
- return { TMPDIR: this.tmpDir, TMPPREFIX: join11(this.tmpDir, "zsh"), ...this.githubEnv, ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
7231
+ return { TMPDIR: this.tmpDir, TMPPREFIX: join11(this.tmpDir, "zsh"), ...withGitConfig(this.githubEnv, RUN_GIT_CONFIG), ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
7232
+ }
7233
+ /**
7234
+ * The agent delivers this run itself: it commits, pushes to the issue
7235
+ * branch and opens the pull request with run-scoped GitHub credentials. The
7236
+ * server sends GitHub delivery only for a run whose push is allowed.
7237
+ */
7238
+ get agentDelivers() {
7239
+ return Object.keys(this.githubEnv).length > 0;
7220
7240
  }
7221
7241
  /** A hand-in from an earlier session would end this one at once. */
7222
7242
  clearHandoff() {
@@ -8240,10 +8260,10 @@ function claudeSandboxSettings(policy) {
8240
8260
  }
8241
8261
  };
8242
8262
  }
8243
- function claudeSettings(policy, workspace) {
8263
+ function claudeSettings(policy, workspace, agentDelivers = false) {
8244
8264
  return {
8245
8265
  sandbox: claudeSandboxSettings(policy),
8246
- permissions: claudePermissionRules(runPolicy(workspace))
8266
+ permissions: claudePermissionRules(runPolicy(workspace), agentDelivers)
8247
8267
  };
8248
8268
  }
8249
8269
  function claudeChunks(message) {
@@ -8583,7 +8603,7 @@ var ClaudeAdapter = class {
8583
8603
  },
8584
8604
  settingSources: [],
8585
8605
  settings: {
8586
- ...claudeSettings(ctx.policy(), options.policy),
8606
+ ...claudeSettings(ctx.policy(), options.policy, ctx.agentDelivers),
8587
8607
  // The official runtime launcher encloses the entire CLI. Nesting
8588
8608
  // the CLI's Bash-only sandbox is unsupported on macOS.
8589
8609
  ...outerLocal ? { sandbox: { enabled: false, allowUnsandboxedCommands: true, autoAllowBashIfSandboxed: false } } : {},
@@ -9438,7 +9458,7 @@ var CodexAdapter = class {
9438
9458
  import { Readable, Writable } from "node:stream";
9439
9459
  import * as acp from "@agentclientprotocol/sdk";
9440
9460
  import { join as join16 } from "node:path";
9441
- function acpPermissionResponse(params, policy) {
9461
+ function acpPermissionResponse(params, policy, agentDelivers = false) {
9442
9462
  const pick = (kinds) => {
9443
9463
  for (const kind of kinds) {
9444
9464
  const option = params.options.find((o) => o.kind === kind);
@@ -9450,7 +9470,7 @@ function acpPermissionResponse(params, policy) {
9450
9470
  const raw = params.toolCall.rawInput;
9451
9471
  const command = Array.isArray(raw?.command) ? raw.command.join(" ") : typeof raw?.command === "string" ? raw.command : params.toolCall.title ?? "";
9452
9472
  const action = classifyCommand(command);
9453
- const refused = action === "git_push" || action !== null && decide(action, { policy: runPolicy(policy) }) !== "allow";
9473
+ const refused = action === "git_push" && !agentDelivers || action !== null && decide(action, { policy: runPolicy(policy) }) !== "allow";
9454
9474
  if (refused)
9455
9475
  return { response: pick(["reject_once", "reject_always"]), refused };
9456
9476
  const allowed = pick(["allow_always", "allow_once"]);
@@ -9633,7 +9653,8 @@ var CursorAdapter = class {
9633
9653
  async requestPermission(params) {
9634
9654
  const { response, refused } = acpPermissionResponse(
9635
9655
  params,
9636
- options.policy
9656
+ options.policy,
9657
+ ctx.agentDelivers
9637
9658
  );
9638
9659
  if (refused)
9639
9660
  log.info(
@@ -10226,7 +10247,7 @@ import { SandboxManager as SandboxManager2 } from "@anthropic-ai/sandbox-runtime
10226
10247
  import { execFile as execFile3 } from "node:child_process";
10227
10248
  import { readdir as readdir2, realpath, stat } from "node:fs/promises";
10228
10249
  import { homedir as homedir5, platform } from "node:os";
10229
- import { basename as basename2, dirname as dirname11, isAbsolute as isAbsolute5, join as join19, resolve as resolve9 } from "node:path";
10250
+ import { basename as basename3, dirname as dirname11, isAbsolute as isAbsolute5, join as join19, resolve as resolve9 } from "node:path";
10230
10251
  import { promisify as promisify3 } from "node:util";
10231
10252
  var run = promisify3(execFile3);
10232
10253
  async function git(cwd, args) {
@@ -10312,7 +10333,7 @@ async function browseFolder(request) {
10312
10333
  return {
10313
10334
  ok: true,
10314
10335
  path,
10315
- parent: parent === path || basename2(path) === "" ? null : parent,
10336
+ parent: parent === path || basename3(path) === "" ? null : parent,
10316
10337
  home,
10317
10338
  platform: platform(),
10318
10339
  entries: folders,
package/client.js CHANGED
@@ -3741,7 +3741,7 @@ import { join } from "node:path";
3741
3741
  // package.json
3742
3742
  var package_default = {
3743
3743
  name: "@mikka/daemon",
3744
- version: "0.0.154",
3744
+ version: "0.0.156",
3745
3745
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3746
3746
  type: "module",
3747
3747
  private: true,
@@ -3801,7 +3801,7 @@ var package_default = {
3801
3801
  engines: {
3802
3802
  node: ">=24"
3803
3803
  },
3804
- gitHead: "d0202e732423480928c02e91adce73bfcaa58f90"
3804
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
3805
3805
  };
3806
3806
 
3807
3807
  // src/paths.ts
package/http-link.js CHANGED
@@ -4144,7 +4144,7 @@ var InvalidIdError = class extends DaemonError {
4144
4144
  // package.json
4145
4145
  var package_default = {
4146
4146
  name: "@mikka/daemon",
4147
- version: "0.0.154",
4147
+ version: "0.0.156",
4148
4148
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4149
4149
  type: "module",
4150
4150
  private: true,
@@ -4204,7 +4204,7 @@ var package_default = {
4204
4204
  engines: {
4205
4205
  node: ">=24"
4206
4206
  },
4207
- gitHead: "d0202e732423480928c02e91adce73bfcaa58f90"
4207
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
4208
4208
  };
4209
4209
 
4210
4210
  // src/paths.ts
package/login.js CHANGED
@@ -3748,7 +3748,7 @@ var ServerUnreachableError = class extends DaemonError {
3748
3748
  // package.json
3749
3749
  var package_default = {
3750
3750
  name: "@mikka/daemon",
3751
- version: "0.0.154",
3751
+ version: "0.0.156",
3752
3752
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3753
3753
  type: "module",
3754
3754
  private: true,
@@ -3808,7 +3808,7 @@ var package_default = {
3808
3808
  engines: {
3809
3809
  node: ">=24"
3810
3810
  },
3811
- gitHead: "d0202e732423480928c02e91adce73bfcaa58f90"
3811
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
3812
3812
  };
3813
3813
 
3814
3814
  // src/paths.ts
package/main.js CHANGED
@@ -2665,7 +2665,7 @@ import {
2665
2665
  rmSync as rmSync4
2666
2666
  } from "node:fs";
2667
2667
  import { tmpdir } from "node:os";
2668
- import { dirname as dirname3, join as join3, resolve as resolve2 } from "node:path";
2668
+ import { basename, dirname as dirname3, join as join3, resolve as resolve2 } from "node:path";
2669
2669
 
2670
2670
  // src/ids.ts
2671
2671
  var SAFE_ID = /^[A-Za-z0-9_-]{1,64}$/;
@@ -3082,12 +3082,10 @@ async function worktreeGitDir(repoPath, worktree) {
3082
3082
  throw new Error(`${worktree} is not a worktree of ${repoPath}`);
3083
3083
  }
3084
3084
  async function worktreeGitWritePaths(repoPath, worktree, runId) {
3085
- const gitDir = await worktreeGitDir(repoPath, worktree);
3086
- const common = resolve2(gitDir, "..", "..");
3087
- const branch = `mikka/run-${assertSafeId("run id", runId)}`;
3088
- const ref = join3(common, "refs", "heads", branch);
3089
- const logsRef = join3(common, "logs", "refs", "heads", branch);
3090
- return [gitDir, join3(common, "objects"), dirname3(ref), ref, `${ref}.lock`, dirname3(logsRef), logsRef];
3085
+ assertSafeId("run id", runId);
3086
+ const common = resolve2(await worktreeGitDir(repoPath, worktree), "..", "..");
3087
+ if (basename(common) !== ".git") throw new Error(`${repoPath} is not a standard clone`);
3088
+ return [dirname3(common)];
3091
3089
  }
3092
3090
  function safeRealpath(path) {
3093
3091
  try {
@@ -3787,7 +3785,7 @@ import { join as join5 } from "node:path";
3787
3785
  // package.json
3788
3786
  var package_default = {
3789
3787
  name: "@mikka/daemon",
3790
- version: "0.0.154",
3788
+ version: "0.0.156",
3791
3789
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3792
3790
  type: "module",
3793
3791
  private: true,
@@ -3847,7 +3845,7 @@ var package_default = {
3847
3845
  engines: {
3848
3846
  node: ">=24"
3849
3847
  },
3850
- gitHead: "d0202e732423480928c02e91adce73bfcaa58f90"
3848
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
3851
3849
  };
3852
3850
 
3853
3851
  // src/paths.ts
@@ -3890,7 +3888,7 @@ function daemonPaths(dataDir) {
3890
3888
  // src/permissions.ts
3891
3889
  import { lstatSync as lstatSync5, readlinkSync, realpathSync as realpathSync5 } from "node:fs";
3892
3890
  import {
3893
- basename,
3891
+ basename as basename2,
3894
3892
  dirname as dirname4,
3895
3893
  isAbsolute as isAbsolute2,
3896
3894
  join as join6,
@@ -3961,7 +3959,7 @@ function classifySegment(segment, depth) {
3961
3959
  words.shift();
3962
3960
  continue;
3963
3961
  }
3964
- if (WRAPPERS.has(basename(words[0]))) {
3962
+ if (WRAPPERS.has(basename2(words[0]))) {
3965
3963
  words.shift();
3966
3964
  while (words.length && words[0].startsWith("-")) {
3967
3965
  const option = words.shift();
@@ -3973,7 +3971,7 @@ function classifySegment(segment, depth) {
3973
3971
  }
3974
3972
  const [tool2, verb] = words;
3975
3973
  if (!tool2) return null;
3976
- const name = basename(tool2);
3974
+ const name = basename2(tool2);
3977
3975
  if (SHELLS.has(name) && depth < 3) {
3978
3976
  const index = words.findIndex((word) => word === "--command" || /^-[A-Za-z]*c[A-Za-z]*$/.test(word));
3979
3977
  if (index !== -1) {
@@ -3987,7 +3985,7 @@ function classifySegment(segment, depth) {
3987
3985
  if (entry && verb && entry[1].includes(verb)) return "install_dependency";
3988
3986
  return null;
3989
3987
  }
3990
- function claudePermissionRules(policy) {
3988
+ function claudePermissionRules(policy, agentDelivers = false) {
3991
3989
  const install2 = INSTALL_COMMANDS.flatMap(
3992
3990
  ([tool2, verbs]) => verbs.map((verb) => `Bash(${tool2} ${verb}:*)`)
3993
3991
  );
@@ -3997,7 +3995,7 @@ function claudePermissionRules(policy) {
3997
3995
  ask: decision === "ask" ? install2 : [],
3998
3996
  deny: [
3999
3997
  ...!rawCliShellAvailable(policy) ? ["Bash", "PowerShell", "Monitor"] : [],
4000
- "Bash(git push:*)",
3998
+ ...agentDelivers && !policy.readOnly ? [] : ["Bash(git push:*)"],
4001
3999
  ...policy.readOnly ? READ_ONLY_TOOLS : [],
4002
4000
  ...decision === "deny" ? install2 : []
4003
4001
  ]
@@ -4037,7 +4035,7 @@ function realTarget(path) {
4037
4035
  }
4038
4036
  const parent = dirname4(current);
4039
4037
  if (parent === current) return path;
4040
- missing.push(basename(current));
4038
+ missing.push(basename2(current));
4041
4039
  current = parent;
4042
4040
  }
4043
4041
  }
@@ -5799,6 +5797,16 @@ var HARNESS_DOMAINS = {
5799
5797
  var MCP_SERVER_SCRIPT = resolve5(import.meta.dirname, "mikka-mcp.mjs");
5800
5798
  var MCP_SERVER_NAME = "mikka";
5801
5799
  var COMPUTER_MCP_SERVER_NAME = "mikka_computer";
5800
+ var RUN_GIT_CONFIG = [["maintenance.auto", "false"], ["gc.auto", "0"]];
5801
+ function withGitConfig(env, entries) {
5802
+ const start = Number(env.GIT_CONFIG_COUNT ?? 0);
5803
+ const out = { ...env, GIT_CONFIG_COUNT: String(start + entries.length) };
5804
+ entries.forEach(([key2, value], i) => {
5805
+ out[`GIT_CONFIG_KEY_${start + i}`] = key2;
5806
+ out[`GIT_CONFIG_VALUE_${start + i}`] = value;
5807
+ });
5808
+ return out;
5809
+ }
5802
5810
  function credentialDenyRead(harness, home = homedir2()) {
5803
5811
  return [
5804
5812
  ".ssh",
@@ -5940,6 +5948,10 @@ var RunContext = class {
5940
5948
  join8(this.gitDir, "commondir"),
5941
5949
  join8(this.gitDir, "gitdir"),
5942
5950
  join8(this.gitDir, "config.worktree"),
5951
+ // sandbox-runtime's own protection of a repository's config and hooks
5952
+ // covers repositories under the process's working directory only;
5953
+ // the shared clone lies outside it, so it is declared here the same way.
5954
+ ...this.options.gitWritePaths?.length ? [join8(this.gitDir, "..", "..", "config"), join8(this.gitDir, "..", "..", "hooks")] : [],
5943
5955
  ...readOnly ? [this.worktree, ...this.options.gitWritePaths ?? []] : []
5944
5956
  ],
5945
5957
  denyRead: [
@@ -6001,7 +6013,15 @@ var RunContext = class {
6001
6013
  * and zsh writes here-docs to `$TMPPREFIX` (default `/tmp/zsh`).
6002
6014
  */
6003
6015
  tempEnv() {
6004
- return { TMPDIR: this.tmpDir, TMPPREFIX: join8(this.tmpDir, "zsh"), ...this.githubEnv, ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
6016
+ return { TMPDIR: this.tmpDir, TMPPREFIX: join8(this.tmpDir, "zsh"), ...withGitConfig(this.githubEnv, RUN_GIT_CONFIG), ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
6017
+ }
6018
+ /**
6019
+ * The agent delivers this run itself: it commits, pushes to the issue
6020
+ * branch and opens the pull request with run-scoped GitHub credentials. The
6021
+ * server sends GitHub delivery only for a run whose push is allowed.
6022
+ */
6023
+ get agentDelivers() {
6024
+ return Object.keys(this.githubEnv).length > 0;
6005
6025
  }
6006
6026
  /** A hand-in from an earlier session would end this one at once. */
6007
6027
  clearHandoff() {
@@ -7060,10 +7080,10 @@ function claudeSandboxSettings(policy) {
7060
7080
  }
7061
7081
  };
7062
7082
  }
7063
- function claudeSettings(policy, workspace) {
7083
+ function claudeSettings(policy, workspace, agentDelivers = false) {
7064
7084
  return {
7065
7085
  sandbox: claudeSandboxSettings(policy),
7066
- permissions: claudePermissionRules(runPolicy(workspace))
7086
+ permissions: claudePermissionRules(runPolicy(workspace), agentDelivers)
7067
7087
  };
7068
7088
  }
7069
7089
  function claudeChunks(message) {
@@ -7403,7 +7423,7 @@ var ClaudeAdapter = class {
7403
7423
  },
7404
7424
  settingSources: [],
7405
7425
  settings: {
7406
- ...claudeSettings(ctx.policy(), options.policy),
7426
+ ...claudeSettings(ctx.policy(), options.policy, ctx.agentDelivers),
7407
7427
  // The official runtime launcher encloses the entire CLI. Nesting
7408
7428
  // the CLI's Bash-only sandbox is unsupported on macOS.
7409
7429
  ...outerLocal ? { sandbox: { enabled: false, allowUnsandboxedCommands: true, autoAllowBashIfSandboxed: false } } : {},
@@ -8258,7 +8278,7 @@ var CodexAdapter = class {
8258
8278
  import { Readable, Writable } from "node:stream";
8259
8279
  import * as acp from "@agentclientprotocol/sdk";
8260
8280
  import { join as join13 } from "node:path";
8261
- function acpPermissionResponse(params, policy) {
8281
+ function acpPermissionResponse(params, policy, agentDelivers = false) {
8262
8282
  const pick = (kinds) => {
8263
8283
  for (const kind of kinds) {
8264
8284
  const option = params.options.find((o) => o.kind === kind);
@@ -8270,7 +8290,7 @@ function acpPermissionResponse(params, policy) {
8270
8290
  const raw = params.toolCall.rawInput;
8271
8291
  const command = Array.isArray(raw?.command) ? raw.command.join(" ") : typeof raw?.command === "string" ? raw.command : params.toolCall.title ?? "";
8272
8292
  const action = classifyCommand(command);
8273
- const refused = action === "git_push" || action !== null && decide(action, { policy: runPolicy(policy) }) !== "allow";
8293
+ const refused = action === "git_push" && !agentDelivers || action !== null && decide(action, { policy: runPolicy(policy) }) !== "allow";
8274
8294
  if (refused)
8275
8295
  return { response: pick(["reject_once", "reject_always"]), refused };
8276
8296
  const allowed = pick(["allow_always", "allow_once"]);
@@ -8453,7 +8473,8 @@ var CursorAdapter = class {
8453
8473
  async requestPermission(params) {
8454
8474
  const { response, refused } = acpPermissionResponse(
8455
8475
  params,
8456
- options.policy
8476
+ options.policy,
8477
+ ctx.agentDelivers
8457
8478
  );
8458
8479
  if (refused)
8459
8480
  log.info(
@@ -9046,7 +9067,7 @@ import { SandboxManager as SandboxManager2 } from "@anthropic-ai/sandbox-runtime
9046
9067
  import { execFile } from "node:child_process";
9047
9068
  import { readdir as readdir2, realpath, stat } from "node:fs/promises";
9048
9069
  import { homedir as homedir3, platform } from "node:os";
9049
- import { basename as basename2, dirname as dirname9, isAbsolute as isAbsolute5, join as join16, resolve as resolve7 } from "node:path";
9070
+ import { basename as basename3, dirname as dirname9, isAbsolute as isAbsolute5, join as join16, resolve as resolve7 } from "node:path";
9050
9071
  import { promisify } from "node:util";
9051
9072
  var run = promisify(execFile);
9052
9073
  async function git(cwd, args) {
@@ -9132,7 +9153,7 @@ async function browseFolder(request) {
9132
9153
  return {
9133
9154
  ok: true,
9134
9155
  path,
9135
- parent: parent === path || basename2(path) === "" ? null : parent,
9156
+ parent: parent === path || basename3(path) === "" ? null : parent,
9136
9157
  home,
9137
9158
  platform: platform(),
9138
9159
  entries: folders,
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "version": 1,
3
- "sourceSha": "d0202e732423480928c02e91adce73bfcaa58f90",
3
+ "sourceSha": "3fe02256b52ef29ce2581173987f01d3b2054448",
4
4
  "repository": "alexj11324/Mikka",
5
- "buildRunId": "41301616580",
5
+ "buildRunId": "41301873626",
6
6
  "buildKind": "github-actions-main",
7
7
  "sourceLockSha256": "c99f1e4f641d8e004cfe807653478e10f91e53fcf47102add5f4c154cdc1cb57",
8
- "createdAt": "2026-11-01T11:24:42.088Z",
8
+ "createdAt": "2026-11-01T11:34:59.039Z",
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": 648726,
44
- "sha256": "1dd251f6c3cb66b7bfe24639b9304069051f5236fd6c6080fc2fd882c962534c"
43
+ "size": 649906,
44
+ "sha256": "ea0a5d8f7d1729d9a7febf4a1474182ea867594b08bba034046ce9e1660ea88a"
45
45
  },
46
46
  {
47
47
  "path": "client.js",
48
48
  "size": 141206,
49
- "sha256": "377c2d2b7b07e582c4ae6dc40e0544f8067c10de99852208cd300c89c583c198"
49
+ "sha256": "186de19be0c69837ec16496844d3fce1054404df99236b0c632751ae004a6d9f"
50
50
  },
51
51
  {
52
52
  "path": "computer/driver.mjs",
@@ -176,7 +176,7 @@
176
176
  {
177
177
  "path": "http-link.js",
178
178
  "size": 182550,
179
- "sha256": "5a0dfc5997254175ab653f60394b3691d394c369a01790085804d05c5fb76d4c"
179
+ "sha256": "b16fcb4cc7efaeb1d01b7737d7d398736c080e99b77510f42539c00cde8865a7"
180
180
  },
181
181
  {
182
182
  "path": "log.js",
@@ -186,12 +186,12 @@
186
186
  {
187
187
  "path": "login.js",
188
188
  "size": 145941,
189
- "sha256": "ecfae2e89a895ff8d04b3b3db95ac6358ccce9ec0878f8c8c28173f2c04fa5db"
189
+ "sha256": "fc3edd9d7e5c7d59028e288c6f18c1f53380da713b49a63476d0742e2aabf1d0"
190
190
  },
191
191
  {
192
192
  "path": "main.js",
193
- "size": 594252,
194
- "sha256": "67911e1330b8a82be97ebc9c0442ba7ac1ee3ee5a4f611f19d50b5607a41b2bb"
193
+ "size": 595432,
194
+ "sha256": "056bb0f88e08eacfdc643f775a2d101593e0f722d076006515358c05f99f8b90"
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": 648742,
204
- "sha256": "f64d7ea79daf514ceaab7a8a148e5f56527651de15118d7c7e22ccd0488b3911"
203
+ "size": 649922,
204
+ "sha256": "8e03efbabb2d9a8ff443ebfbab63fd859e4b05fff4340f8543d3003eb0731053"
205
205
  },
206
206
  {
207
207
  "path": "npm-shrinkwrap.json",
208
208
  "size": 78117,
209
- "sha256": "5766de72f85da7c99eae90ec4d1d224ad1e8bbb9478a9931b56583f302bf0f39"
209
+ "sha256": "7a9077f4872f82c1b74dab4c0d5abe22862bcc4cf0b349560439bd51df7f1c11"
210
210
  },
211
211
  {
212
212
  "path": "package.json",
213
213
  "size": 1247,
214
- "sha256": "634c2e055b5adbace810c43d3d9db0debc848629ffb517a24a0594d8334dab36"
214
+ "sha256": "10cd534abaa4aedba3968f2000a3dfe0738ef5af654a76567b15edfbdb9a1db4"
215
215
  },
216
216
  {
217
217
  "path": "paths.js",
218
218
  "size": 4138,
219
- "sha256": "0822e291361365bc8db2e9faf78efb4d9b55e1da4e717c836515826dde609e8d"
219
+ "sha256": "3f687c02d1b5442dd6243b682e8d2db4902bdf4354e4fe9b9507ff3966b9e27d"
220
220
  },
221
221
  {
222
222
  "path": "sandbox.js",
@@ -226,7 +226,7 @@
226
226
  {
227
227
  "path": "sbom.cdx.json",
228
228
  "size": 144314,
229
- "sha256": "14fc7dc44acb9e8479fd6afdb345f05a008c36cab586c00f65b0d78146a197ea"
229
+ "sha256": "93003336a8e6c7f2520b064b5250af5188aad04e25550daee8d6fdf89164ff17"
230
230
  }
231
231
  ]
232
232
  }
package/mikka.js CHANGED
@@ -4481,7 +4481,7 @@ import { join as join4 } from "node:path";
4481
4481
  // package.json
4482
4482
  var package_default = {
4483
4483
  name: "@mikka/daemon",
4484
- version: "0.0.154",
4484
+ version: "0.0.156",
4485
4485
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4486
4486
  type: "module",
4487
4487
  private: true,
@@ -4541,7 +4541,7 @@ var package_default = {
4541
4541
  engines: {
4542
4542
  node: ">=24"
4543
4543
  },
4544
- gitHead: "d0202e732423480928c02e91adce73bfcaa58f90"
4544
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
4545
4545
  };
4546
4546
 
4547
4547
  // src/paths.ts
@@ -4816,7 +4816,7 @@ function classifySegment(segment, depth) {
4816
4816
  if (entry && verb && entry[1].includes(verb)) return "install_dependency";
4817
4817
  return null;
4818
4818
  }
4819
- function claudePermissionRules(policy) {
4819
+ function claudePermissionRules(policy, agentDelivers = false) {
4820
4820
  const install2 = INSTALL_COMMANDS.flatMap(
4821
4821
  ([tool2, verbs]) => verbs.map((verb) => `Bash(${tool2} ${verb}:*)`)
4822
4822
  );
@@ -4826,7 +4826,7 @@ function claudePermissionRules(policy) {
4826
4826
  ask: decision === "ask" ? install2 : [],
4827
4827
  deny: [
4828
4828
  ...!rawCliShellAvailable(policy) ? ["Bash", "PowerShell", "Monitor"] : [],
4829
- "Bash(git push:*)",
4829
+ ...agentDelivers && !policy.readOnly ? [] : ["Bash(git push:*)"],
4830
4830
  ...policy.readOnly ? READ_ONLY_TOOLS : [],
4831
4831
  ...decision === "deny" ? install2 : []
4832
4832
  ]
@@ -6116,7 +6116,7 @@ import {
6116
6116
  rmSync as rmSync5
6117
6117
  } from "node:fs";
6118
6118
  import { tmpdir } from "node:os";
6119
- import { dirname as dirname7, join as join8, resolve as resolve5 } from "node:path";
6119
+ import { basename as basename2, dirname as dirname7, join as join8, resolve as resolve5 } from "node:path";
6120
6120
 
6121
6121
  // src/ids.ts
6122
6122
  var SAFE_ID = /^[A-Za-z0-9_-]{1,64}$/;
@@ -6533,12 +6533,10 @@ async function worktreeGitDir(repoPath, worktree) {
6533
6533
  throw new Error(`${worktree} is not a worktree of ${repoPath}`);
6534
6534
  }
6535
6535
  async function worktreeGitWritePaths(repoPath, worktree, runId) {
6536
- const gitDir = await worktreeGitDir(repoPath, worktree);
6537
- const common = resolve5(gitDir, "..", "..");
6538
- const branch = `mikka/run-${assertSafeId("run id", runId)}`;
6539
- const ref = join8(common, "refs", "heads", branch);
6540
- const logsRef = join8(common, "logs", "refs", "heads", branch);
6541
- return [gitDir, join8(common, "objects"), dirname7(ref), ref, `${ref}.lock`, dirname7(logsRef), logsRef];
6536
+ assertSafeId("run id", runId);
6537
+ const common = resolve5(await worktreeGitDir(repoPath, worktree), "..", "..");
6538
+ if (basename2(common) !== ".git") throw new Error(`${repoPath} is not a standard clone`);
6539
+ return [dirname7(common)];
6542
6540
  }
6543
6541
  function safeRealpath(path) {
6544
6542
  try {
@@ -7015,6 +7013,16 @@ var HARNESS_DOMAINS = {
7015
7013
  var MCP_SERVER_SCRIPT = resolve7(import.meta.dirname, "mikka-mcp.mjs");
7016
7014
  var MCP_SERVER_NAME = "mikka";
7017
7015
  var COMPUTER_MCP_SERVER_NAME = "mikka_computer";
7016
+ var RUN_GIT_CONFIG = [["maintenance.auto", "false"], ["gc.auto", "0"]];
7017
+ function withGitConfig(env, entries) {
7018
+ const start = Number(env.GIT_CONFIG_COUNT ?? 0);
7019
+ const out = { ...env, GIT_CONFIG_COUNT: String(start + entries.length) };
7020
+ entries.forEach(([key2, value], i) => {
7021
+ out[`GIT_CONFIG_KEY_${start + i}`] = key2;
7022
+ out[`GIT_CONFIG_VALUE_${start + i}`] = value;
7023
+ });
7024
+ return out;
7025
+ }
7018
7026
  function credentialDenyRead(harness, home = homedir4()) {
7019
7027
  return [
7020
7028
  ".ssh",
@@ -7156,6 +7164,10 @@ var RunContext = class {
7156
7164
  join11(this.gitDir, "commondir"),
7157
7165
  join11(this.gitDir, "gitdir"),
7158
7166
  join11(this.gitDir, "config.worktree"),
7167
+ // sandbox-runtime's own protection of a repository's config and hooks
7168
+ // covers repositories under the process's working directory only;
7169
+ // the shared clone lies outside it, so it is declared here the same way.
7170
+ ...this.options.gitWritePaths?.length ? [join11(this.gitDir, "..", "..", "config"), join11(this.gitDir, "..", "..", "hooks")] : [],
7159
7171
  ...readOnly ? [this.worktree, ...this.options.gitWritePaths ?? []] : []
7160
7172
  ],
7161
7173
  denyRead: [
@@ -7217,7 +7229,15 @@ var RunContext = class {
7217
7229
  * and zsh writes here-docs to `$TMPPREFIX` (default `/tmp/zsh`).
7218
7230
  */
7219
7231
  tempEnv() {
7220
- return { TMPDIR: this.tmpDir, TMPPREFIX: join11(this.tmpDir, "zsh"), ...this.githubEnv, ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
7232
+ return { TMPDIR: this.tmpDir, TMPPREFIX: join11(this.tmpDir, "zsh"), ...withGitConfig(this.githubEnv, RUN_GIT_CONFIG), ...this.options.policyHash ? { MIKKA_POLICY_HASH: this.options.policyHash } : {} };
7233
+ }
7234
+ /**
7235
+ * The agent delivers this run itself: it commits, pushes to the issue
7236
+ * branch and opens the pull request with run-scoped GitHub credentials. The
7237
+ * server sends GitHub delivery only for a run whose push is allowed.
7238
+ */
7239
+ get agentDelivers() {
7240
+ return Object.keys(this.githubEnv).length > 0;
7221
7241
  }
7222
7242
  /** A hand-in from an earlier session would end this one at once. */
7223
7243
  clearHandoff() {
@@ -8241,10 +8261,10 @@ function claudeSandboxSettings(policy) {
8241
8261
  }
8242
8262
  };
8243
8263
  }
8244
- function claudeSettings(policy, workspace) {
8264
+ function claudeSettings(policy, workspace, agentDelivers = false) {
8245
8265
  return {
8246
8266
  sandbox: claudeSandboxSettings(policy),
8247
- permissions: claudePermissionRules(runPolicy(workspace))
8267
+ permissions: claudePermissionRules(runPolicy(workspace), agentDelivers)
8248
8268
  };
8249
8269
  }
8250
8270
  function claudeChunks(message) {
@@ -8584,7 +8604,7 @@ var ClaudeAdapter = class {
8584
8604
  },
8585
8605
  settingSources: [],
8586
8606
  settings: {
8587
- ...claudeSettings(ctx.policy(), options.policy),
8607
+ ...claudeSettings(ctx.policy(), options.policy, ctx.agentDelivers),
8588
8608
  // The official runtime launcher encloses the entire CLI. Nesting
8589
8609
  // the CLI's Bash-only sandbox is unsupported on macOS.
8590
8610
  ...outerLocal ? { sandbox: { enabled: false, allowUnsandboxedCommands: true, autoAllowBashIfSandboxed: false } } : {},
@@ -9439,7 +9459,7 @@ var CodexAdapter = class {
9439
9459
  import { Readable, Writable } from "node:stream";
9440
9460
  import * as acp from "@agentclientprotocol/sdk";
9441
9461
  import { join as join16 } from "node:path";
9442
- function acpPermissionResponse(params, policy) {
9462
+ function acpPermissionResponse(params, policy, agentDelivers = false) {
9443
9463
  const pick = (kinds) => {
9444
9464
  for (const kind of kinds) {
9445
9465
  const option = params.options.find((o) => o.kind === kind);
@@ -9451,7 +9471,7 @@ function acpPermissionResponse(params, policy) {
9451
9471
  const raw = params.toolCall.rawInput;
9452
9472
  const command = Array.isArray(raw?.command) ? raw.command.join(" ") : typeof raw?.command === "string" ? raw.command : params.toolCall.title ?? "";
9453
9473
  const action = classifyCommand(command);
9454
- const refused = action === "git_push" || action !== null && decide(action, { policy: runPolicy(policy) }) !== "allow";
9474
+ const refused = action === "git_push" && !agentDelivers || action !== null && decide(action, { policy: runPolicy(policy) }) !== "allow";
9455
9475
  if (refused)
9456
9476
  return { response: pick(["reject_once", "reject_always"]), refused };
9457
9477
  const allowed = pick(["allow_always", "allow_once"]);
@@ -9634,7 +9654,8 @@ var CursorAdapter = class {
9634
9654
  async requestPermission(params) {
9635
9655
  const { response, refused } = acpPermissionResponse(
9636
9656
  params,
9637
- options.policy
9657
+ options.policy,
9658
+ ctx.agentDelivers
9638
9659
  );
9639
9660
  if (refused)
9640
9661
  log.info(
@@ -10227,7 +10248,7 @@ import { SandboxManager as SandboxManager2 } from "@anthropic-ai/sandbox-runtime
10227
10248
  import { execFile as execFile3 } from "node:child_process";
10228
10249
  import { readdir as readdir2, realpath, stat } from "node:fs/promises";
10229
10250
  import { homedir as homedir5, platform } from "node:os";
10230
- import { basename as basename2, dirname as dirname11, isAbsolute as isAbsolute5, join as join19, resolve as resolve9 } from "node:path";
10251
+ import { basename as basename3, dirname as dirname11, isAbsolute as isAbsolute5, join as join19, resolve as resolve9 } from "node:path";
10231
10252
  import { promisify as promisify3 } from "node:util";
10232
10253
  var run = promisify3(execFile3);
10233
10254
  async function git(cwd, args) {
@@ -10313,7 +10334,7 @@ async function browseFolder(request) {
10313
10334
  return {
10314
10335
  ok: true,
10315
10336
  path,
10316
- parent: parent === path || basename2(path) === "" ? null : parent,
10337
+ parent: parent === path || basename3(path) === "" ? null : parent,
10317
10338
  home,
10318
10339
  platform: platform(),
10319
10340
  entries: folders,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@aspectlylabs/mikka",
3
- "version": "0.0.154",
3
+ "version": "0.0.156",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@aspectlylabs/mikka",
9
- "version": "0.0.154",
9
+ "version": "0.0.156",
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.154",
3
+ "version": "0.0.156",
4
4
  "description": "Local Mikka daemon: runs agents through the user's own CLIs",
5
- "gitHead": "d0202e732423480928c02e91adce73bfcaa58f90",
5
+ "gitHead": "3fe02256b52ef29ce2581173987f01d3b2054448",
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.154",
9
+ version: "0.0.156",
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: "d0202e732423480928c02e91adce73bfcaa58f90"
69
+ gitHead: "3fe02256b52ef29ce2581173987f01d3b2054448"
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:eb1697db-3201-4fa1-b522-b4e2b2fa3ab0",
5
+ "serialNumber": "urn:uuid:8d063e4c-21da-49c9-a7fa-c1346a8fad06",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-11-01T11:24:41.150Z",
8
+ "timestamp": "2026-11-01T11:34:58.062Z",
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.154",
22
+ "bom-ref": "@aspectlylabs/mikka@0.0.156",
23
23
  "type": "library",
24
- "name": ".retained-build-WI5HWa",
25
- "version": "0.0.154",
24
+ "name": ".retained-build-SsBNoF",
25
+ "version": "0.0.156",
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.154",
28
+ "purl": "pkg:npm/%40aspectlylabs/mikka@0.0.156",
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.154",
4630
+ "ref": "@aspectlylabs/mikka@0.0.156",
4631
4631
  "dependsOn": [
4632
4632
  "@agentclientprotocol/sdk@1.9.0",
4633
4633
  "@anthropic-ai/claude-agent-sdk@0.3.305",