@tablation/crew 0.47.1 → 0.47.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +106 -70
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { resolve as resolve4, dirname as dirname12, join as join23, basename as basename9 } from "path";
4
+ import { resolve as resolve4, dirname as dirname12, join as join24, basename as basename9 } from "path";
5
5
  import { fileURLToPath } from "url";
6
6
  import { hostname as hostname2, homedir as homedir8 } from "os";
7
7
  import { spawnSync as spawnSync5 } from "child_process";
@@ -4030,9 +4030,11 @@ import {
4030
4030
  statSync as statSync4,
4031
4031
  unlinkSync as unlinkSync2,
4032
4032
  readFileSync as readFileSync9,
4033
- writeFileSync as writeFileSync6
4033
+ writeFileSync as writeFileSync6,
4034
+ readdirSync as readdirSync3,
4035
+ rmSync as rmSync6
4034
4036
  } from "fs";
4035
- import { dirname as dirname5, basename as basename4 } from "path";
4037
+ import { dirname as dirname5, basename as basename4, join as join10 } from "path";
4036
4038
  var GitError = class extends Error {
4037
4039
  };
4038
4040
  function streamText(x) {
@@ -4367,12 +4369,36 @@ function recoverStrandedReleaseCheckouts(cwd) {
4367
4369
  if (line.startsWith("worktree ")) path = line.slice("worktree ".length);
4368
4370
  else if (line.startsWith("branch refs/heads/crew/release-") && path) {
4369
4371
  gitOk(cwd, ["worktree", "remove", "--force", path]);
4372
+ const root = dirname5(path);
4373
+ if (basename4(root).startsWith("crew-release-")) rmSync6(root, { recursive: true, force: true });
4370
4374
  }
4371
4375
  }
4372
4376
  const stranded = (gitOk(cwd, ["for-each-ref", "--format=%(refname:short)", "refs/heads/crew/release-*"]) ?? "").split("\n").filter(Boolean);
4373
4377
  for (const b of stranded) gitOk(cwd, ["branch", "-q", "-D", b]);
4374
4378
  return stranded;
4375
4379
  }
4380
+ function sweepStaleReleaseRoots(tmp, now = Date.now(), maxAgeMs = 60 * 60 * 1e3) {
4381
+ const removed = [];
4382
+ let names;
4383
+ try {
4384
+ names = readdirSync3(tmp);
4385
+ } catch {
4386
+ return removed;
4387
+ }
4388
+ for (const name of names) {
4389
+ if (!name.startsWith("crew-release-")) continue;
4390
+ const root = join10(tmp, name);
4391
+ try {
4392
+ const st = statSync4(root);
4393
+ if (!st.isDirectory() || now - st.mtimeMs < maxAgeMs) continue;
4394
+ if (existsSync9(join10(root, "checkout"))) continue;
4395
+ rmSync6(root, { recursive: true, force: true });
4396
+ removed.push(name);
4397
+ } catch {
4398
+ }
4399
+ }
4400
+ return removed;
4401
+ }
4376
4402
  function pushBranch(cwd, remote, branch, dst = branch) {
4377
4403
  git(cwd, ["push", remote, `${branch}:${dst}`]);
4378
4404
  }
@@ -6268,7 +6294,7 @@ function materializeBranchForTicket(dir, cfg, t, role) {
6268
6294
 
6269
6295
  // src/poll.ts
6270
6296
  import { writeFileSync as writeFileSync7 } from "fs";
6271
- import { join as join10 } from "path";
6297
+ import { join as join11 } from "path";
6272
6298
 
6273
6299
  // src/stalled.ts
6274
6300
  var STALLED_AFTER_CYCLES = 30;
@@ -6545,7 +6571,7 @@ async function decideCycle(o) {
6545
6571
  }
6546
6572
  return decision;
6547
6573
  }
6548
- var digestPath = (stateDir, route, role) => join10(stateDir, `digest-${route}-${role}.md`);
6574
+ var digestPath = (stateDir, route, role) => join11(stateDir, `digest-${route}-${role}.md`);
6549
6575
  function writeDigest(o, d, role, stateDir) {
6550
6576
  const me = o.route.resolved?.seats[role];
6551
6577
  if (!me) return false;
@@ -6993,7 +7019,7 @@ var alreadyReported = (ticket, g, events) => events.some((e) => e.record_id ===
6993
7019
  import { spawn as spawn2 } from "child_process";
6994
7020
  import { readFileSync as readFileSync12, existsSync as existsSync12, statSync as statSync5, mkdirSync as mkdirSync6, writeFileSync as writeFileSync8, createWriteStream } from "fs";
6995
7021
  import { finished } from "stream/promises";
6996
- import { join as join13, dirname as dirname6 } from "path";
7022
+ import { join as join14, dirname as dirname6 } from "path";
6997
7023
  import { createHash as createHash2 } from "crypto";
6998
7024
 
6999
7025
  // src/environment.ts
@@ -7408,14 +7434,14 @@ function expandSkillMarkers(text, lookup, opts = {}) {
7408
7434
  }
7409
7435
 
7410
7436
  // src/skills.ts
7411
- import { readFileSync as readFileSync11, readdirSync as readdirSync3, existsSync as existsSync11 } from "fs";
7412
- import { join as join12 } from "path";
7437
+ import { readFileSync as readFileSync11, readdirSync as readdirSync4, existsSync as existsSync11 } from "fs";
7438
+ import { join as join13 } from "path";
7413
7439
  import { parse as parseYaml } from "yaml";
7414
7440
  import { TablationClient as TablationClient3, StaleWriteError as StaleWriteError8, TablationApiError as TablationApiError2 } from "@tablation/client";
7415
7441
 
7416
7442
  // src/agents.ts
7417
7443
  import { readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
7418
- import { join as join11 } from "path";
7444
+ import { join as join12 } from "path";
7419
7445
  import { TablationClient as TablationClient2, StaleWriteError as StaleWriteError7, TablationApiError } from "@tablation/client";
7420
7446
  var PERSONA_NAME = {
7421
7447
  dev: "Developer",
@@ -7429,10 +7455,10 @@ var CREW_AGENT_COLUMN = "agent_id";
7429
7455
  var AgentsSyncError = class extends Error {
7430
7456
  };
7431
7457
  function personaDefaultPrompt(promptsDir, role) {
7432
- const briefPath = join11(promptsDir, "personas", `lane-${role}.md`);
7458
+ const briefPath = join12(promptsDir, "personas", `lane-${role}.md`);
7433
7459
  if (!existsSync10(briefPath)) throw new AgentsSyncError(`no brief at ${briefPath}`);
7434
7460
  if (SELF_CONTAINED_ROLES.has(role)) return readFileSync10(briefPath, "utf8");
7435
- const commonPath = join11(promptsDir, "personas", "common.md");
7461
+ const commonPath = join12(promptsDir, "personas", "common.md");
7436
7462
  if (!existsSync10(commonPath)) return readFileSync10(briefPath, "utf8");
7437
7463
  return `${readFileSync10(commonPath, "utf8")}${readFileSync10(briefPath, "utf8")}`;
7438
7464
  }
@@ -7812,9 +7838,9 @@ function parseSkillFile(path) {
7812
7838
  return { name: meta.name, description: meta.description, prompt: body, file: path };
7813
7839
  }
7814
7840
  function listLocalSkills(promptsDir) {
7815
- const dir = join12(promptsDir, "skills");
7841
+ const dir = join13(promptsDir, "skills");
7816
7842
  if (!existsSync11(dir)) return [];
7817
- return readdirSync3(dir).filter((f) => f.endsWith(".md")).map((f) => parseSkillFile(join12(dir, f)));
7843
+ return readdirSync4(dir).filter((f) => f.endsWith(".md")).map((f) => parseSkillFile(join13(dir, f)));
7818
7844
  }
7819
7845
  async function syncSkills(route, opts) {
7820
7846
  if (!route.resolved) {
@@ -8047,15 +8073,15 @@ var AgentError = class extends Error {
8047
8073
  var AgentSpawnError = class extends AgentError {
8048
8074
  };
8049
8075
  function planAgentRun(o) {
8050
- const briefPath = join13(o.route.promptsDir, "personas", `lane-${o.role}.md`);
8076
+ const briefPath = join14(o.route.promptsDir, "personas", `lane-${o.role}.md`);
8051
8077
  if (!existsSync12(briefPath)) {
8052
8078
  throw new AgentError(`no brief at ${briefPath} \u2014 refusing to run an unscoped session`);
8053
8079
  }
8054
- const commonPath = join13(o.route.promptsDir, "personas", "common.md");
8080
+ const commonPath = join14(o.route.promptsDir, "personas", "common.md");
8055
8081
  const usesCommon = !SELF_CONTAINED_ROLES.has(o.role) && existsSync12(commonPath);
8056
8082
  const now = o.now ?? (() => Date.now());
8057
8083
  const routeLabel = routeSlug(o.route.route);
8058
- const digestPath2 = join13(o.stateDir, `digest-${routeLabel}-${o.role}.md`);
8084
+ const digestPath2 = join14(o.stateDir, `digest-${routeLabel}-${o.role}.md`);
8059
8085
  let digest;
8060
8086
  let ageSeconds;
8061
8087
  if (existsSync12(digestPath2)) {
@@ -8085,7 +8111,7 @@ function planAgentRun(o) {
8085
8111
  digest
8086
8112
  });
8087
8113
  const promptSha = createHash2("sha256").update(expanded.text).digest("hex");
8088
- const streamsDir = join13(o.stateDir, "streams");
8114
+ const streamsDir = join14(o.stateDir, "streams");
8089
8115
  const base = `${routeLabel}-${o.role}-${o.cycle}`;
8090
8116
  const seat = resolveSeat(o.ship, o.route, o.role, o.agentPersona ?? (o.agentModel ? { model: o.agentModel } : {}), o.repo);
8091
8117
  const { toolchain, model } = seat;
@@ -8141,8 +8167,8 @@ function planAgentRun(o) {
8141
8167
  digestAttached: digest !== void 0,
8142
8168
  digestAgeSeconds: ageSeconds,
8143
8169
  model,
8144
- streamPath: join13(streamsDir, `${base}.jsonl`),
8145
- eventsPath: join13(streamsDir, `${base}.events.jsonl`),
8170
+ streamPath: join14(streamsDir, `${base}.jsonl`),
8171
+ eventsPath: join14(streamsDir, `${base}.events.jsonl`),
8146
8172
  ticket: o.ticket,
8147
8173
  agentLog,
8148
8174
  promptVersion: o.route.resolved?.agentPersonas?.[o.role]?.historyId,
@@ -8349,12 +8375,12 @@ function spawnAgent(plan, emit) {
8349
8375
 
8350
8376
  // src/run-worktree.ts
8351
8377
  import { existsSync as existsSync14 } from "fs";
8352
- import { dirname as dirname7, join as join15 } from "path";
8378
+ import { dirname as dirname7, join as join16 } from "path";
8353
8379
 
8354
8380
  // src/ports.ts
8355
8381
  import { execFileSync as execFileSync2 } from "child_process";
8356
8382
  import { existsSync as existsSync13 } from "fs";
8357
- import { join as join14 } from "path";
8383
+ import { join as join15 } from "path";
8358
8384
  var run = (cmd, args) => {
8359
8385
  try {
8360
8386
  return execFileSync2(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
@@ -8399,7 +8425,7 @@ function ticketForPort(port, s = DEFAULT_PORTS) {
8399
8425
  }
8400
8426
  function worktreeExists(parent, prefix, n) {
8401
8427
  for (const name of [`${prefix}${n}`, `${prefix}${String(n).padStart(3, "0")}`]) {
8402
- if (existsSync13(join14(parent, name, ".git"))) return true;
8428
+ if (existsSync13(join15(parent, name, ".git"))) return true;
8403
8429
  }
8404
8430
  return false;
8405
8431
  }
@@ -8487,7 +8513,7 @@ function planRunWorktree(dir, cfg, t, role) {
8487
8513
  if (countCommits(existing.path, `${baseRef}..HEAD`) > 0) return { action: "leave-unpushed", path: existing.path, branch };
8488
8514
  return { action: "recut", path: existing.path, branch, base: baseRef };
8489
8515
  }
8490
- const path = join15(dirname7(dir), worktreeForTicket(dir, cfg, t, role));
8516
+ const path = join16(dirname7(dir), worktreeForTicket(dir, cfg, t, role));
8491
8517
  if (located?.where === "remote" || located && hasRemote && remoteBranchExists(dir, remote, located.branch)) {
8492
8518
  return { action: "cut-remote", path, branch: located.branch };
8493
8519
  }
@@ -8695,7 +8721,7 @@ async function retireRunWorktree(tracker, dir, cfg, t, role, seatId, shipName2,
8695
8721
  }
8696
8722
 
8697
8723
  // src/connect-wizard.ts
8698
- import { delimiter, dirname as dirname8, join as join16 } from "path";
8724
+ import { delimiter, dirname as dirname8, join as join17 } from "path";
8699
8725
  import { accessSync as accessSync2, constants as constants2, existsSync as existsSync15, mkdirSync as mkdirSync7, writeFileSync as writeFileSync9 } from "fs";
8700
8726
  import { stringify } from "yaml";
8701
8727
  var HOST_PASSENGERS_DOCS_URL = "https://crew.tablation.dev/host-passengers";
@@ -8718,7 +8744,7 @@ function defaultIsExecutable(p) {
8718
8744
  function findOnPath2(name, pathEnv, isExecutable = defaultIsExecutable) {
8719
8745
  for (const dir of pathEnv.split(delimiter)) {
8720
8746
  if (!dir) continue;
8721
- const candidate = join16(dir, name);
8747
+ const candidate = join17(dir, name);
8722
8748
  if (isExecutable(candidate)) return candidate;
8723
8749
  }
8724
8750
  return void 0;
@@ -8813,8 +8839,8 @@ Wrote ${o.configPath}.
8813
8839
  }
8814
8840
 
8815
8841
  // src/release-run.ts
8816
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync16, copyFileSync, mkdirSync as mkdirSync8, mkdtempSync, rmSync as rmSync6 } from "fs";
8817
- import { dirname as dirname9, join as join17 } from "path";
8842
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync16, copyFileSync, mkdirSync as mkdirSync8, mkdtempSync, rmSync as rmSync7 } from "fs";
8843
+ import { dirname as dirname9, join as join18 } from "path";
8818
8844
  import { tmpdir as tmpdir2 } from "os";
8819
8845
 
8820
8846
  // src/release.ts
@@ -9472,7 +9498,7 @@ async function bump(o, size) {
9472
9498
  }
9473
9499
  return printed;
9474
9500
  }
9475
- const files = o.repo.release.versionFiles.map((f) => join17(o.cwd, f));
9501
+ const files = o.repo.release.versionFiles.map((f) => join18(o.cwd, f));
9476
9502
  const first = files[0];
9477
9503
  if (!existsSync16(first)) {
9478
9504
  o.emit.error(`no ${o.repo.release.versionFiles[0]} to read a version from`);
@@ -9504,7 +9530,7 @@ async function bump(o, size) {
9504
9530
  function writeChangelog(o, version, entries) {
9505
9531
  const file = o.repo.release.changelog;
9506
9532
  if (!file || entries.length === 0) return;
9507
- const path = join17(o.cwd, file);
9533
+ const path = join18(o.cwd, file);
9508
9534
  const section = renderChangelogSection(version, (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), entries);
9509
9535
  if (o.dryRun) {
9510
9536
  o.emit.emit(`would prepend ${entries.length} entr(ies) to ${file}`);
@@ -9589,17 +9615,25 @@ async function confirmLastRelease(o, decision) {
9589
9615
  if (!confirmed) o.emit.warn(`${decision.lastTag} is still not confirmed live \u2014 tickets stay verified`);
9590
9616
  return { confirmed, version };
9591
9617
  }
9618
+ function closeReleaseCheckout(cwd, root, dir, branch, run2 = gitOk) {
9619
+ try {
9620
+ run2(cwd, ["worktree", "remove", "--force", dir]);
9621
+ } finally {
9622
+ try {
9623
+ rmSync7(root, { recursive: true, force: true });
9624
+ } finally {
9625
+ run2(cwd, ["worktree", "prune"]);
9626
+ run2(cwd, ["branch", "-D", branch]);
9627
+ }
9628
+ }
9629
+ }
9592
9630
  function openReleaseCheckout(o) {
9593
9631
  const { remote, base } = o.repo.branch;
9594
9632
  const branch = `crew/release-${Date.now()}`;
9595
- const root = mkdtempSync(join17(tmpdir2(), "crew-release-"));
9596
- const dir = join17(root, "checkout");
9597
- const close = () => {
9598
- gitOk(o.cwd, ["worktree", "remove", "--force", dir]);
9599
- rmSync6(root, { recursive: true, force: true });
9600
- gitOk(o.cwd, ["worktree", "prune"]);
9601
- gitOk(o.cwd, ["branch", "-D", branch]);
9602
- };
9633
+ const root = mkdtempSync(join18(tmpdir2(), "crew-release-"));
9634
+ const dir = join18(root, "checkout");
9635
+ o.emit.emit(`release checkout: ${dir}`, { step: "release" });
9636
+ const close = () => closeReleaseCheckout(o.cwd, root, dir, branch);
9603
9637
  try {
9604
9638
  git(o.cwd, ["worktree", "add", "-q", "-b", branch, dir, `${remote}/${base}`]);
9605
9639
  } catch (e) {
@@ -9607,10 +9641,10 @@ function openReleaseCheckout(o) {
9607
9641
  throw e;
9608
9642
  }
9609
9643
  for (const f of o.repo.worktrees.copy) {
9610
- const src = join17(o.cwd, f);
9644
+ const src = join18(o.cwd, f);
9611
9645
  if (!existsSync16(src)) continue;
9612
- mkdirSync8(dirname9(join17(dir, f)), { recursive: true });
9613
- copyFileSync(src, join17(dir, f));
9646
+ mkdirSync8(dirname9(join18(dir, f)), { recursive: true });
9647
+ copyFileSync(src, join18(dir, f));
9614
9648
  }
9615
9649
  return { dir, branch, close };
9616
9650
  }
@@ -9689,6 +9723,8 @@ async function runRelease(o) {
9689
9723
  let checkout;
9690
9724
  const stranded = recoverStrandedReleaseCheckouts(o.cwd);
9691
9725
  if (stranded.length > 0) o.emit.warn(scoped(`dropped release checkout(s) stranded by a crash: ${stranded.join(", ")}`));
9726
+ const swept = sweepStaleReleaseRoots(tmpdir2());
9727
+ if (swept.length > 0) o.emit.emit(scoped(`removed ${swept.length} stale crew-release-* temp dir(s)`), { step: "release" });
9692
9728
  try {
9693
9729
  checkout = openReleaseCheckout(o);
9694
9730
  } catch (e) {
@@ -11451,14 +11487,14 @@ function applyRemoteBranchCleanup(cwd, remote, branches2, dryRun, log) {
11451
11487
  }
11452
11488
 
11453
11489
  // src/stream-sweep.ts
11454
- import { existsSync as existsSync19, readdirSync as readdirSync4, rmSync as rmSync7, statSync as statSync7 } from "fs";
11455
- import { join as join18 } from "path";
11490
+ import { existsSync as existsSync19, readdirSync as readdirSync5, rmSync as rmSync8, statSync as statSync7 } from "fs";
11491
+ import { join as join19 } from "path";
11456
11492
  var DAY_MS2 = 24 * 60 * 60 * 1e3;
11457
11493
  function planStreamSweep(stateDir, retentionDays, now = Date.now()) {
11458
- const dir = join18(stateDir, "streams");
11494
+ const dir = join19(stateDir, "streams");
11459
11495
  if (!existsSync19(dir)) return [];
11460
11496
  const cutoff = now - retentionDays * DAY_MS2;
11461
- return readdirSync4(dir).map((name) => join18(dir, name)).filter((path) => {
11497
+ return readdirSync5(dir).map((name) => join19(dir, name)).filter((path) => {
11462
11498
  try {
11463
11499
  return statSync7(path).mtimeMs < cutoff;
11464
11500
  } catch {
@@ -11474,7 +11510,7 @@ function applyStreamSweep(paths, dryRun, log) {
11474
11510
  continue;
11475
11511
  }
11476
11512
  try {
11477
- rmSync7(path, { force: true });
11513
+ rmSync8(path, { force: true });
11478
11514
  removed++;
11479
11515
  log.emit(`removed stream artifact ${path}`, { step: "worktree" });
11480
11516
  } catch (e) {
@@ -11486,7 +11522,7 @@ function applyStreamSweep(paths, dryRun, log) {
11486
11522
  function planEventsSweep(stateDir, retentionDays, now = Date.now()) {
11487
11523
  if (!existsSync19(stateDir)) return [];
11488
11524
  const cutoff = now - retentionDays * DAY_MS2;
11489
- return readdirSync4(stateDir).filter((name) => ROTATED_EVENTS_RE.test(name)).map((name) => join18(stateDir, name)).filter((path) => {
11525
+ return readdirSync5(stateDir).filter((name) => ROTATED_EVENTS_RE.test(name)).map((name) => join19(stateDir, name)).filter((path) => {
11490
11526
  try {
11491
11527
  return statSync7(path).mtimeMs < cutoff;
11492
11528
  } catch {
@@ -11503,11 +11539,11 @@ import { dirname as dirOf, resolve as resolvePath } from "path";
11503
11539
  // src/ssh-keys.ts
11504
11540
  import { execFileSync as execFileSync3 } from "child_process";
11505
11541
  import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync14, chmodSync } from "fs";
11506
- import { dirname as dirname11, join as join19 } from "path";
11542
+ import { dirname as dirname11, join as join20 } from "path";
11507
11543
  var SshKeyError = class extends Error {
11508
11544
  };
11509
11545
  function shipSshKeyPathFor(stateDir) {
11510
- return join19(stateDir, "ssh", "id_ed25519");
11546
+ return join20(stateDir, "ssh", "id_ed25519");
11511
11547
  }
11512
11548
  function ensureShipSshKeypair(stateDir) {
11513
11549
  const privateKeyPath = shipSshKeyPathFor(stateDir);
@@ -11752,9 +11788,9 @@ function syncAllPassengerCheckouts(cfg) {
11752
11788
 
11753
11789
  // src/tunnel.ts
11754
11790
  import { spawn as spawn3 } from "child_process";
11755
- import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync11, unlinkSync as unlinkSync3, readdirSync as readdirSync5 } from "fs";
11791
+ import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync11, unlinkSync as unlinkSync3, readdirSync as readdirSync6 } from "fs";
11756
11792
  import { randomInt } from "crypto";
11757
- import { join as join20 } from "path";
11793
+ import { join as join21 } from "path";
11758
11794
  var DEFAULT_SPAWN_OPTIONS = { stdio: "ignore", detached: true };
11759
11795
  var defaultSpawn = (cmd, args) => spawn3(cmd, args, DEFAULT_SPAWN_OPTIONS);
11760
11796
  var SLUG_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
@@ -11821,7 +11857,7 @@ function startTunnel(opts) {
11821
11857
  };
11822
11858
  }
11823
11859
  function tunnelStatePath(stateDir, workspaceId) {
11824
- return join20(stateDir, "passengers", `${workspaceId}.json`);
11860
+ return join21(stateDir, "passengers", `${workspaceId}.json`);
11825
11861
  }
11826
11862
  function readPersistedTunnel(stateDir, workspaceId) {
11827
11863
  const path = tunnelStatePath(stateDir, workspaceId);
@@ -11834,7 +11870,7 @@ function readPersistedTunnel(stateDir, workspaceId) {
11834
11870
  }
11835
11871
  function writePersistedTunnel(stateDir, state) {
11836
11872
  const path = tunnelStatePath(stateDir, state.workspaceId);
11837
- mkdirSync10(join20(stateDir, "passengers"), { recursive: true });
11873
+ mkdirSync10(join21(stateDir, "passengers"), { recursive: true });
11838
11874
  writeFileSync11(path, `${JSON.stringify(state, null, 2)}
11839
11875
  `);
11840
11876
  }
@@ -11932,9 +11968,9 @@ function syncPassengerTunnels(plans, relayHost, relayPort, privateKeyPath, state
11932
11968
  }
11933
11969
  }
11934
11970
  function readAllPersistedWorkspaceIds(stateDir) {
11935
- const dir = join20(stateDir, "passengers");
11971
+ const dir = join21(stateDir, "passengers");
11936
11972
  if (!existsSync21(dir)) return [];
11937
- return readdirSync5(dir).filter((f) => f.endsWith(".json") && !f.endsWith("-sync.json")).map((f) => f.slice(0, -".json".length));
11973
+ return readdirSync6(dir).filter((f) => f.endsWith(".json") && !f.endsWith("-sync.json")).map((f) => f.slice(0, -".json".length));
11938
11974
  }
11939
11975
 
11940
11976
  // src/mcp-endpoint-registry.ts
@@ -12054,8 +12090,8 @@ async function unregisterEndpoint(workspaceId, info, d) {
12054
12090
  import { createServer as createHttpServer } from "http";
12055
12091
  import { spawn as spawn4 } from "child_process";
12056
12092
  import { randomBytes } from "crypto";
12057
- import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, readdirSync as readdirSync6 } from "fs";
12058
- import { join as join21 } from "path";
12093
+ import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, readdirSync as readdirSync7 } from "fs";
12094
+ import { join as join22 } from "path";
12059
12095
 
12060
12096
  // src/secret-compare.ts
12061
12097
  import { timingSafeEqual } from "crypto";
@@ -12144,7 +12180,7 @@ var defaultSpawn2 = (cmd, args, env) => {
12144
12180
  return child;
12145
12181
  };
12146
12182
  function syncDaemonStatePath(stateDir, workspaceId) {
12147
- return join21(stateDir, "passengers", `${workspaceId}-sync.json`);
12183
+ return join22(stateDir, "passengers", `${workspaceId}-sync.json`);
12148
12184
  }
12149
12185
  function readPersistedSyncDaemon(stateDir, workspaceId) {
12150
12186
  const path = syncDaemonStatePath(stateDir, workspaceId);
@@ -12157,7 +12193,7 @@ function readPersistedSyncDaemon(stateDir, workspaceId) {
12157
12193
  }
12158
12194
  function writePersistedSyncDaemon(stateDir, state) {
12159
12195
  const path = syncDaemonStatePath(stateDir, state.workspaceId);
12160
- mkdirSync11(join21(stateDir, "passengers"), { recursive: true });
12196
+ mkdirSync11(join22(stateDir, "passengers"), { recursive: true });
12161
12197
  writeFileSync12(path, `${JSON.stringify(state, null, 2)}
12162
12198
  `);
12163
12199
  }
@@ -12178,10 +12214,10 @@ function waitForExit(pid, alive, timeoutMs = 5e3) {
12178
12214
  }
12179
12215
  }
12180
12216
  function readAllPersistedSyncWorkspaceIds(stateDir) {
12181
- const dir = join21(stateDir, "passengers");
12217
+ const dir = join22(stateDir, "passengers");
12182
12218
  if (!existsSync22(dir)) return [];
12183
12219
  const suffix = "-sync.json";
12184
- return readdirSync6(dir).filter((f) => f.endsWith(suffix)).map((f) => f.slice(0, -suffix.length));
12220
+ return readdirSync7(dir).filter((f) => f.endsWith(suffix)).map((f) => f.slice(0, -suffix.length));
12185
12221
  }
12186
12222
  function syncPassengerSyncDaemons(plans, cfg, stateDir, deps = {}) {
12187
12223
  const alive = deps.isPidAlive ?? isPidAlive;
@@ -12236,8 +12272,8 @@ function syncPassengerSyncDaemons(plans, cfg, stateDir, deps = {}) {
12236
12272
  }
12237
12273
 
12238
12274
  // src/daemon.ts
12239
- import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync17, readdirSync as readdirSync7, rmSync as rmSync8, statSync as statSync8, writeFileSync as writeFileSync13 } from "fs";
12240
- import { join as join22 } from "path";
12275
+ import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync17, readdirSync as readdirSync8, rmSync as rmSync9, statSync as statSync8, writeFileSync as writeFileSync13 } from "fs";
12276
+ import { join as join23 } from "path";
12241
12277
  var DEFAULT_FLOOR_MS = 5e3;
12242
12278
  var DEFAULT_CEILING_MS = INTERVAL_SECONDS * 1e3;
12243
12279
  var defaultSleep = (ms2) => new Promise((resolve5) => setTimeout(resolve5, ms2));
@@ -12275,8 +12311,8 @@ function latestMtime(path) {
12275
12311
  if (stat.isFile()) return stat.mtimeMs;
12276
12312
  if (!stat.isDirectory()) return 0;
12277
12313
  let latest = stat.mtimeMs;
12278
- for (const entry of readdirSync7(path, { withFileTypes: true })) {
12279
- latest = Math.max(latest, latestMtime(join22(path, entry.name)));
12314
+ for (const entry of readdirSync8(path, { withFileTypes: true })) {
12315
+ latest = Math.max(latest, latestMtime(join23(path, entry.name)));
12280
12316
  }
12281
12317
  return latest;
12282
12318
  }
@@ -12288,14 +12324,14 @@ function makeStaleChecker(paths, opts = {}) {
12288
12324
  return () => computeTreeSignature(paths) !== initial || opts.reloadSentinel !== void 0 && existsSync23(opts.reloadSentinel);
12289
12325
  }
12290
12326
  function reloadSentinelFor(stateDir) {
12291
- return join22(stateDir, "reload-requested");
12327
+ return join23(stateDir, "reload-requested");
12292
12328
  }
12293
12329
  function daemonStampFor(stateDir) {
12294
- return join22(stateDir, "daemon.started");
12330
+ return join23(stateDir, "daemon.started");
12295
12331
  }
12296
12332
  function noteDaemonStarted(stateDir, now = Date.now()) {
12297
12333
  mkdirSync12(stateDir, { recursive: true });
12298
- rmSync8(reloadSentinelFor(stateDir), { force: true });
12334
+ rmSync9(reloadSentinelFor(stateDir), { force: true });
12299
12335
  writeFileSync13(daemonStampFor(stateDir), `${JSON.stringify({ pid: process.pid, startedAt: now })}
12300
12336
  `);
12301
12337
  }
@@ -13115,7 +13151,7 @@ if (command === "passenger-sync-daemon") {
13115
13151
  }
13116
13152
  if (host === "linux" && hasSystemd) {
13117
13153
  const label = labelFor(CREW_HOME, "run");
13118
- const staleTimer = join23(homedir8(), ".config", "systemd", "user", `${label}.timer`);
13154
+ const staleTimer = join24(homedir8(), ".config", "systemd", "user", `${label}.timer`);
13119
13155
  if (existsSync24(staleTimer)) {
13120
13156
  process.stdout.write(
13121
13157
  `removing stale run timer from before the persistent-service cutover: ${staleTimer}${dryRun ? " (dry run)" : ""}
@@ -14123,7 +14159,7 @@ ${changed2.map((c) => ` - ${c}
14123
14159
  process.exit(1);
14124
14160
  }
14125
14161
  requireArmed("run the daemon loop");
14126
- const watchPaths = isCompiledBinary(import.meta.url) ? [process.execPath] : [join23(CREW_HOME, "src"), join23(CREW_HOME, "dist"), join23(CREW_HOME, "bin")];
14162
+ const watchPaths = isCompiledBinary(import.meta.url) ? [process.execPath] : [join24(CREW_HOME, "src"), join24(CREW_HOME, "dist"), join24(CREW_HOME, "bin")];
14127
14163
  const configPaths = daemonConfigPaths(cfg);
14128
14164
  watchPaths.push(...configPaths);
14129
14165
  noteDaemonStarted(cfg.ship.stateDir);
@@ -14803,7 +14839,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
14803
14839
  const keyPersisted = keychainBacked || apiKeyFile !== void 0;
14804
14840
  const wizard = firstRun;
14805
14841
  const writeFirstRun = wizard !== void 0 && !dryRun && keyPersisted;
14806
- const routeDir = value("dir") ?? (writeFirstRun ? join23(DEFAULT_REPOS_BASE_PATH, found.workspaceSlug) : void 0);
14842
+ const routeDir = value("dir") ?? (writeFirstRun ? join24(DEFAULT_REPOS_BASE_PATH, found.workspaceSlug) : void 0);
14807
14843
  const routeBlock = renderConnection(
14808
14844
  found,
14809
14845
  route2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tablation/crew",
3
- "version": "0.47.1",
3
+ "version": "0.47.2",
4
4
  "description": "A standing team of headless agents that picks work off a Tablation board, does it on a machine you control, and reports back.",
5
5
  "type": "module",
6
6
  "license": "MIT",