@aspectlylabs/mikka 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -49,10 +49,26 @@ index for inspection. The test daemon still performs its normal lifecycle
49
49
  cleanup inside the new dedicated fixture; previously retained resources are
50
50
  not part of that fixture.
51
51
 
52
- No global `tsx` or separate `@mikka/protocol` package is needed. The proposed
53
- release workflow uses npm trusted publishing from GitHub Actions, with npm
54
- provenance. It is manual and must be configured for the approved package before
55
- it can publish. Running tests or building a package does not publish it.
52
+ No global `tsx` or separate `@mikka/protocol` package is needed. Every push to
53
+ `main` publishes through `.github/workflows/publish-daemon.yml` after daemon
54
+ checks and the installed-package runtime test pass. The workflow uses npm
55
+ trusted publishing and provenance; its npm trust configuration must authorize
56
+ this exact repository and workflow filename.
57
+
58
+ CI stamps `0.0.<workflow run number + 1>` into the source manifest before the
59
+ build, so the npm package and runtime report the same version. Source commits
60
+ keep their development version. Re-running a workflow keeps its version and
61
+ skips publication if npm already records that version from the same commit.
62
+ CI writes the commit SHA into the published manifest as `gitHead`; an existing
63
+ version with absent or different commit metadata stops the release. After
64
+ publication, CI reads npm metadata back and checks the commit SHA. If npm
65
+ serves 404 while the published version becomes available, CI checks up to 31
66
+ times with 10-second waits. Exhausting that wait reports registry verification
67
+ as incomplete; it does not claim that npm rejected publication.
68
+ Releases queue without cancellation (up to GitHub's 100 pending-run limit).
69
+ An older run can publish under its own `build-<version>` tag, preserving the
70
+ newer `latest` version. Manual dispatch remains available on `main` and gets
71
+ a new run version. Running local tests or builds does not publish anything.
56
72
 
57
73
  `test:package` installs the actual tarball into a new directory with public
58
74
  registry dependencies, without workspace symlinks or install scripts. Plain
package/cli.js CHANGED
@@ -2216,7 +2216,7 @@ function closeLogger(logger) {
2216
2216
  // src/service.ts
2217
2217
  import { execFile } from "node:child_process";
2218
2218
  import { promisify } from "node:util";
2219
- import { mkdir, writeFile } from "node:fs/promises";
2219
+ import { mkdir, writeFile, rm } from "node:fs/promises";
2220
2220
  import { homedir } from "node:os";
2221
2221
  import { dirname as dirname2, join as join2, resolve } from "node:path";
2222
2222
  var exec = promisify(execFile);
@@ -2284,6 +2284,34 @@ async function restartService(update, beforeRestart, dependencies = {
2284
2284
  beforeRestart();
2285
2285
  dependencies.restart();
2286
2286
  }
2287
+ async function uninstallService(clearCredential, dependencies = {
2288
+ manager: process.env.MIKKA_SERVICE,
2289
+ home: homedir(),
2290
+ uid: process.getuid?.() ?? 0,
2291
+ run: async (program, args) => {
2292
+ await exec(program, args, { timeout: 1e4 });
2293
+ },
2294
+ exit: () => {
2295
+ process.exit(0);
2296
+ }
2297
+ }) {
2298
+ try {
2299
+ if (dependencies.manager === "systemd") {
2300
+ await dependencies.run("systemctl", ["--user", "disable", "mikka-daemon.service"]);
2301
+ await rm(join2(dependencies.home, ".config/systemd/user/mikka-daemon.service"), { force: true });
2302
+ await dependencies.run("systemctl", ["--user", "daemon-reload"]);
2303
+ } else if (dependencies.manager === "launchd") {
2304
+ await rm(join2(dependencies.home, "Library/LaunchAgents", `${label}.plist`), { force: true });
2305
+ }
2306
+ } finally {
2307
+ clearCredential();
2308
+ try {
2309
+ if (dependencies.manager === "launchd") await dependencies.run("launchctl", ["bootout", `gui/${dependencies.uid}/${label}`]);
2310
+ } finally {
2311
+ dependencies.exit();
2312
+ }
2313
+ }
2314
+ }
2287
2315
 
2288
2316
  // ../protocol/src/accounts.ts
2289
2317
  import { z } from "zod";
@@ -2971,13 +2999,18 @@ var runReport = z9.object({
2971
2999
  sha: z9.string().regex(/^[a-f0-9]{40}$/),
2972
3000
  readOnly: z9.literal(true)
2973
3001
  }).optional(),
3002
+ /** Preview branch created or used by the producing run; descriptive metadata only. */
3003
+ previewDatabaseBranch: z9.string().trim().min(1).max(500).optional(),
2974
3004
  /** Acceptance criteria the agent checked, with evidence. */
2975
3005
  criteria: z9.array(
2976
3006
  z9.object({
2977
3007
  criterionId: z9.uuid().optional(),
2978
3008
  text: z9.string().max(2e3).optional(),
2979
3009
  passed: z9.boolean(),
2980
- evidence: z9.string().max(1e4).optional()
3010
+ evidence: z9.string().max(1e4).optional(),
3011
+ /** Agent-reported criterion check; the daemon-owned verify remains authoritative. */
3012
+ command: z9.string().trim().min(1).max(2e3).optional(),
3013
+ exitCode: z9.number().int().nullable().optional()
2981
3014
  })
2982
3015
  ).max(200).optional(),
2983
3016
  /**
@@ -3321,7 +3354,7 @@ var heartbeatRunSchema = z13.object({
3321
3354
  /** Last tool call, turn boundary or file change (not raw output). */
3322
3355
  lastProgressAt: isoTime
3323
3356
  });
3324
- var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update"]) });
3357
+ var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update", "uninstall"]) });
3325
3358
  var deviceHeartbeatSchema = z13.object({
3326
3359
  completedDeviceCommands: z13.array(z13.uuid()).max(100).optional(),
3327
3360
  failedDeviceCommands: z13.array(z13.object({ id: z13.uuid(), error: z13.string().max(500) })).max(100).optional(),
@@ -4248,7 +4281,7 @@ import { join as join3 } from "node:path";
4248
4281
  // package.json
4249
4282
  var package_default = {
4250
4283
  name: "@mikka/daemon",
4251
- version: "0.0.1",
4284
+ version: "0.0.3",
4252
4285
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4253
4286
  type: "module",
4254
4287
  private: true,
@@ -4305,7 +4338,8 @@ var package_default = {
4305
4338
  },
4306
4339
  engines: {
4307
4340
  node: ">=24"
4308
- }
4341
+ },
4342
+ gitHead: "4d1f09bda63e1b86a6cf08c4c7f4dc159b2938a2"
4309
4343
  };
4310
4344
 
4311
4345
  // src/paths.ts
@@ -6193,6 +6227,7 @@ var RunContext = class {
6193
6227
  nextStep: file.nextStep ?? null,
6194
6228
  ...file.blockedOn ? { blockedOn: file.blockedOn } : {},
6195
6229
  ...plan ? { plan } : {},
6230
+ ...typeof file.previewDatabaseBranch === "string" ? { previewDatabaseBranch: file.previewDatabaseBranch } : {},
6196
6231
  ...Array.isArray(file.criteria) ? { criteria: file.criteria } : {},
6197
6232
  ...runQuestion.safeParse(file.question).success ? { question: runQuestion.parse(file.question) } : {}
6198
6233
  };
@@ -6635,6 +6670,7 @@ import {
6635
6670
  existsSync as existsSync6,
6636
6671
  mkdirSync as mkdirSync15,
6637
6672
  readFileSync as readFileSync11,
6673
+ rmSync as rmSync16,
6638
6674
  realpathSync as realpathSync11
6639
6675
  } from "node:fs";
6640
6676
  import { arch, hostname, platform as platform2 } from "node:os";
@@ -12605,18 +12641,21 @@ function pickAgentReport(agent) {
12605
12641
  const question = runQuestion.safeParse(agent.question);
12606
12642
  if (question.success) picked.question = question.data;
12607
12643
  if (agent.plan) picked.plan = agent.plan;
12644
+ if (typeof agent.previewDatabaseBranch === "string" && agent.previewDatabaseBranch.trim())
12645
+ picked.previewDatabaseBranch = agent.previewDatabaseBranch.trim().slice(0, 500);
12608
12646
  if (Array.isArray(agent.criteria)) {
12609
12647
  const criteria = [];
12610
12648
  for (const entry of agent.criteria) {
12611
12649
  if (criteria.length >= MAX_REPORTED_CRITERIA) break;
12612
12650
  if (!entry || typeof entry !== "object") continue;
12613
- const { criterionId, passed, evidence } = entry;
12651
+ const { criterionId, passed, evidence, command, exitCode } = entry;
12614
12652
  if (typeof criterionId !== "string" || !UUID_RE.test(criterionId))
12615
12653
  continue;
12616
12654
  if (typeof passed !== "boolean") continue;
12617
12655
  criteria.push({
12618
12656
  criterionId,
12619
12657
  passed,
12658
+ ...typeof command === "string" && command.trim() ? { command: command.trim().slice(0, 2e3), ...exitCode === null || typeof exitCode === "number" && Number.isSafeInteger(exitCode) ? { exitCode } : {} } : {},
12620
12659
  ...typeof evidence === "string" ? { evidence: evidence.slice(0, 1e4) } : {}
12621
12660
  });
12622
12661
  }
@@ -12789,7 +12828,7 @@ import { promisify as promisify4 } from "node:util";
12789
12828
 
12790
12829
  // src/agents/public-egress.ts
12791
12830
  import { lookup } from "node:dns/promises";
12792
- import { chmod, mkdtemp, rm } from "node:fs/promises";
12831
+ import { chmod, mkdtemp, rm as rm2 } from "node:fs/promises";
12793
12832
  import { createServer as createServer3, request as httpRequest } from "node:http";
12794
12833
  import { connect, isIP as isIP3 } from "node:net";
12795
12834
  import { tmpdir as tmpdir3 } from "node:os";
@@ -12971,7 +13010,7 @@ async function startPublicEgress(options) {
12971
13010
  for (const socket of sockets) socket.destroy();
12972
13011
  closing = new Promise((resolve10, reject) => server.close((error) => {
12973
13012
  options.signal.removeEventListener("abort", onAbort);
12974
- void rm(directory, { recursive: true, force: true }).then(() => error && error.code !== "ERR_SERVER_NOT_RUNNING" ? reject(error) : resolve10(), reject);
13013
+ void rm2(directory, { recursive: true, force: true }).then(() => error && error.code !== "ERR_SERVER_NOT_RUNNING" ? reject(error) : resolve10(), reject);
12975
13014
  }));
12976
13015
  return closing;
12977
13016
  };
@@ -14777,7 +14816,7 @@ var Daemon = class {
14777
14816
  }
14778
14817
  const deviceId = this.device.deviceId;
14779
14818
  const quotas = this.quota?.snapshot().quotas;
14780
- const { leases, revoked, cloudCredential, deviceCommands } = await link.heartbeat(deviceId, {
14819
+ const heartbeat = {
14781
14820
  completedDeviceCommands: this.device.completedDeviceCommands,
14782
14821
  failedDeviceCommands: this.device.failedDeviceCommands,
14783
14822
  harnesses: this.harnesses,
@@ -14785,7 +14824,8 @@ var Daemon = class {
14785
14824
  runs: this.supervisor.heartbeatRuns(),
14786
14825
  worktreeDiskBytes: await this.worktrees.diskUsage(),
14787
14826
  ...quotas ? { quotas } : {}
14788
- });
14827
+ };
14828
+ const { leases, revoked, cloudCredential, deviceCommands } = await link.heartbeat(deviceId, heartbeat);
14789
14829
  this.supervisor.renewLeases(leases);
14790
14830
  if (revoked) this.supervisor.revokeLeases(revoked);
14791
14831
  if (this.options.cloudComputer && cloudCredential && this.device.credential === credential) {
@@ -14794,6 +14834,26 @@ var Daemon = class {
14794
14834
  this.registered = false;
14795
14835
  }
14796
14836
  const command = deviceCommands?.[0];
14837
+ if (command?.kind === "uninstall") {
14838
+ this.draining = true;
14839
+ if (this.supervisor.heartbeatRuns().length === 0) {
14840
+ this.saveDevice({ completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14841
+ try {
14842
+ await link.heartbeat(deviceId, { ...heartbeat, runs: [], completedDeviceCommands: [command.id], failedDeviceCommands: [] });
14843
+ } catch {
14844
+ this.log.warn("Could not confirm uninstall receipt");
14845
+ }
14846
+ setImmediate(() => {
14847
+ void this.stop().then(() => uninstallService(() => {
14848
+ this.saveDevice({ credential: void 0 });
14849
+ rmSync16(this.paths.secret, { force: true });
14850
+ })).catch(() => {
14851
+ this.options.onDrained?.();
14852
+ });
14853
+ });
14854
+ }
14855
+ return;
14856
+ }
14797
14857
  if (command && !this.device.completedDeviceCommands?.includes(command.id) && !this.device.failedDeviceCommands?.some((failure) => failure.id === command.id)) {
14798
14858
  if (command.kind === "redetect" || this.supervisor.heartbeatRuns().length === 0) {
14799
14859
  try {
package/client.js CHANGED
@@ -2547,13 +2547,18 @@ var runReport = z9.object({
2547
2547
  sha: z9.string().regex(/^[a-f0-9]{40}$/),
2548
2548
  readOnly: z9.literal(true)
2549
2549
  }).optional(),
2550
+ /** Preview branch created or used by the producing run; descriptive metadata only. */
2551
+ previewDatabaseBranch: z9.string().trim().min(1).max(500).optional(),
2550
2552
  /** Acceptance criteria the agent checked, with evidence. */
2551
2553
  criteria: z9.array(
2552
2554
  z9.object({
2553
2555
  criterionId: z9.uuid().optional(),
2554
2556
  text: z9.string().max(2e3).optional(),
2555
2557
  passed: z9.boolean(),
2556
- evidence: z9.string().max(1e4).optional()
2558
+ evidence: z9.string().max(1e4).optional(),
2559
+ /** Agent-reported criterion check; the daemon-owned verify remains authoritative. */
2560
+ command: z9.string().trim().min(1).max(2e3).optional(),
2561
+ exitCode: z9.number().int().nullable().optional()
2557
2562
  })
2558
2563
  ).max(200).optional(),
2559
2564
  /**
@@ -2809,7 +2814,7 @@ var heartbeatRunSchema = z13.object({
2809
2814
  /** Last tool call, turn boundary or file change (not raw output). */
2810
2815
  lastProgressAt: isoTime
2811
2816
  });
2812
- var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update"]) });
2817
+ var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update", "uninstall"]) });
2813
2818
  var deviceHeartbeatSchema = z13.object({
2814
2819
  completedDeviceCommands: z13.array(z13.uuid()).max(100).optional(),
2815
2820
  failedDeviceCommands: z13.array(z13.object({ id: z13.uuid(), error: z13.string().max(500) })).max(100).optional(),
@@ -3616,7 +3621,7 @@ import { join } from "node:path";
3616
3621
  // package.json
3617
3622
  var package_default = {
3618
3623
  name: "@mikka/daemon",
3619
- version: "0.0.1",
3624
+ version: "0.0.3",
3620
3625
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3621
3626
  type: "module",
3622
3627
  private: true,
@@ -3673,7 +3678,8 @@ var package_default = {
3673
3678
  },
3674
3679
  engines: {
3675
3680
  node: ">=24"
3676
- }
3681
+ },
3682
+ gitHead: "4d1f09bda63e1b86a6cf08c4c7f4dc159b2938a2"
3677
3683
  };
3678
3684
 
3679
3685
  // src/paths.ts
package/http-link.js CHANGED
@@ -2993,13 +2993,18 @@ var runReport = z15.object({
2993
2993
  sha: z15.string().regex(/^[a-f0-9]{40}$/),
2994
2994
  readOnly: z15.literal(true)
2995
2995
  }).optional(),
2996
+ /** Preview branch created or used by the producing run; descriptive metadata only. */
2997
+ previewDatabaseBranch: z15.string().trim().min(1).max(500).optional(),
2996
2998
  /** Acceptance criteria the agent checked, with evidence. */
2997
2999
  criteria: z15.array(
2998
3000
  z15.object({
2999
3001
  criterionId: z15.uuid().optional(),
3000
3002
  text: z15.string().max(2e3).optional(),
3001
3003
  passed: z15.boolean(),
3002
- evidence: z15.string().max(1e4).optional()
3004
+ evidence: z15.string().max(1e4).optional(),
3005
+ /** Agent-reported criterion check; the daemon-owned verify remains authoritative. */
3006
+ command: z15.string().trim().min(1).max(2e3).optional(),
3007
+ exitCode: z15.number().int().nullable().optional()
3003
3008
  })
3004
3009
  ).max(200).optional(),
3005
3010
  /**
@@ -3217,7 +3222,7 @@ var heartbeatRunSchema = z17.object({
3217
3222
  /** Last tool call, turn boundary or file change (not raw output). */
3218
3223
  lastProgressAt: isoTime
3219
3224
  });
3220
- var deviceManagementCommand = z17.object({ id: z17.uuid(), kind: z17.enum(["redetect", "restart", "update"]) });
3225
+ var deviceManagementCommand = z17.object({ id: z17.uuid(), kind: z17.enum(["redetect", "restart", "update", "uninstall"]) });
3221
3226
  var deviceHeartbeatSchema = z17.object({
3222
3227
  completedDeviceCommands: z17.array(z17.uuid()).max(100).optional(),
3223
3228
  failedDeviceCommands: z17.array(z17.object({ id: z17.uuid(), error: z17.string().max(500) })).max(100).optional(),
@@ -3916,7 +3921,7 @@ var InvalidIdError = class extends DaemonError {
3916
3921
  // package.json
3917
3922
  var package_default = {
3918
3923
  name: "@mikka/daemon",
3919
- version: "0.0.1",
3924
+ version: "0.0.3",
3920
3925
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3921
3926
  type: "module",
3922
3927
  private: true,
@@ -3973,7 +3978,8 @@ var package_default = {
3973
3978
  },
3974
3979
  engines: {
3975
3980
  node: ">=24"
3976
- }
3981
+ },
3982
+ gitHead: "4d1f09bda63e1b86a6cf08c4c7f4dc159b2938a2"
3977
3983
  };
3978
3984
 
3979
3985
  // src/paths.ts
package/login.js CHANGED
@@ -2544,13 +2544,18 @@ var runReport = z9.object({
2544
2544
  sha: z9.string().regex(/^[a-f0-9]{40}$/),
2545
2545
  readOnly: z9.literal(true)
2546
2546
  }).optional(),
2547
+ /** Preview branch created or used by the producing run; descriptive metadata only. */
2548
+ previewDatabaseBranch: z9.string().trim().min(1).max(500).optional(),
2547
2549
  /** Acceptance criteria the agent checked, with evidence. */
2548
2550
  criteria: z9.array(
2549
2551
  z9.object({
2550
2552
  criterionId: z9.uuid().optional(),
2551
2553
  text: z9.string().max(2e3).optional(),
2552
2554
  passed: z9.boolean(),
2553
- evidence: z9.string().max(1e4).optional()
2555
+ evidence: z9.string().max(1e4).optional(),
2556
+ /** Agent-reported criterion check; the daemon-owned verify remains authoritative. */
2557
+ command: z9.string().trim().min(1).max(2e3).optional(),
2558
+ exitCode: z9.number().int().nullable().optional()
2554
2559
  })
2555
2560
  ).max(200).optional(),
2556
2561
  /**
@@ -2805,7 +2810,7 @@ var heartbeatRunSchema = z13.object({
2805
2810
  /** Last tool call, turn boundary or file change (not raw output). */
2806
2811
  lastProgressAt: isoTime
2807
2812
  });
2808
- var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update"]) });
2813
+ var deviceManagementCommand = z13.object({ id: z13.uuid(), kind: z13.enum(["redetect", "restart", "update", "uninstall"]) });
2809
2814
  var deviceHeartbeatSchema = z13.object({
2810
2815
  completedDeviceCommands: z13.array(z13.uuid()).max(100).optional(),
2811
2816
  failedDeviceCommands: z13.array(z13.object({ id: z13.uuid(), error: z13.string().max(500) })).max(100).optional(),
@@ -3623,7 +3628,7 @@ var ServerUnreachableError = class extends DaemonError {
3623
3628
  // package.json
3624
3629
  var package_default = {
3625
3630
  name: "@mikka/daemon",
3626
- version: "0.0.1",
3631
+ version: "0.0.3",
3627
3632
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3628
3633
  type: "module",
3629
3634
  private: true,
@@ -3680,7 +3685,8 @@ var package_default = {
3680
3685
  },
3681
3686
  engines: {
3682
3687
  node: ">=24"
3683
- }
3688
+ },
3689
+ gitHead: "4d1f09bda63e1b86a6cf08c4c7f4dc159b2938a2"
3684
3690
  };
3685
3691
 
3686
3692
  // src/paths.ts