dahrk-node 0.1.24 → 0.1.25

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/main.js +232 -162
  2. package/package.json +4 -4
package/dist/main.js CHANGED
@@ -2,11 +2,11 @@
2
2
  import "./chunk-FYS2JH42.js";
3
3
 
4
4
  // src/main.ts
5
- import { execFileSync as execFileSync9 } from "child_process";
6
- import { existsSync as existsSync14, readFileSync as readFileSync11, realpathSync as realpathSync5 } from "fs";
5
+ import { execFileSync as execFileSync10 } from "child_process";
6
+ import { existsSync as existsSync15, readFileSync as readFileSync12, realpathSync as realpathSync5 } from "fs";
7
7
  import { randomUUID as randomUUID3 } from "crypto";
8
8
  import { homedir as homedir7, platform as osPlatform4 } from "os";
9
- import { basename as basename2, join as join19 } from "path";
9
+ import { basename as basename2, join as join20 } from "path";
10
10
  import { pathToFileURL } from "url";
11
11
 
12
12
  // ../../packages/edge/src/ws-client.ts
@@ -245,12 +245,12 @@ function documentsBlock(ctx) {
245
245
  const truncated = body.length > cap;
246
246
  const excerpt = truncated ? body.slice(0, cap) : body;
247
247
  budget -= excerpt.length;
248
- const tail = truncated ? `
248
+ const tail2 = truncated ? `
249
249
  ...(truncated; full text at ${path})` : "";
250
250
  const title = doc.title.replace(/[<>"]/g, "'");
251
251
  parts.push(
252
252
  `<document title="${title}" file="${path}">
253
- ${neutraliseDelimiters(excerpt)}${tail}
253
+ ${neutraliseDelimiters(excerpt)}${tail2}
254
254
  </document>`
255
255
  );
256
256
  if (budget <= 0) break;
@@ -2564,6 +2564,59 @@ async function overlayComponents(opts) {
2564
2564
  return result;
2565
2565
  }
2566
2566
 
2567
+ // ../../packages/executor-worktree/src/repo-setup.ts
2568
+ import { execFileSync as execFileSync3 } from "child_process";
2569
+ import { createHash as createHash3 } from "crypto";
2570
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
2571
+ import { dirname as dirname4, join as join10 } from "path";
2572
+ var noopLogger2 = { info: () => {
2573
+ }, warn: () => {
2574
+ } };
2575
+ var SCRATCH_DIR2 = join10(".dahrk", "scratch");
2576
+ var MARKER_NAME = ".setup-done";
2577
+ var DEFAULT_TIMEOUT_MS = 6e5;
2578
+ var OUTPUT_CAP = 16384;
2579
+ function digest(command) {
2580
+ return createHash3("sha256").update(command).digest("hex").slice(0, 16);
2581
+ }
2582
+ function tail(output) {
2583
+ return output.length > OUTPUT_CAP ? output.slice(output.length - OUTPUT_CAP) : output;
2584
+ }
2585
+ function runRepoSetup(opts) {
2586
+ const { worktreePath, command } = opts;
2587
+ const log = opts.log ?? noopLogger2;
2588
+ const markerPath = join10(worktreePath, SCRATCH_DIR2, MARKER_NAME);
2589
+ const want = digest(command);
2590
+ if (existsSync5(markerPath)) {
2591
+ try {
2592
+ if (readFileSync4(markerPath, "utf8").trim() === want) {
2593
+ log.info(`repo setup: cached (marker matches), skipping`);
2594
+ return { status: "cached" };
2595
+ }
2596
+ } catch {
2597
+ }
2598
+ }
2599
+ log.info(`repo setup: running \`${command}\``);
2600
+ try {
2601
+ const stdout = execFileSync3("sh", ["-c", command], {
2602
+ cwd: worktreePath,
2603
+ env: opts.env ?? process.env,
2604
+ timeout: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
2605
+ encoding: "utf8",
2606
+ // Fold stderr into stdout so the captured trace shows what the installer said, in order.
2607
+ stdio: ["ignore", "pipe", "pipe"]
2608
+ });
2609
+ mkdirSync5(dirname4(markerPath), { recursive: true });
2610
+ writeFileSync6(markerPath, want);
2611
+ return { status: "ran", output: tail(stdout ?? "") };
2612
+ } catch (e) {
2613
+ const err = e;
2614
+ const combined = `${err.stdout?.toString() ?? ""}${err.stderr?.toString() ?? ""}` || e.message;
2615
+ log.warn(`repo setup failed (exit ${err.status ?? "null"})`);
2616
+ return { status: "failed", exitCode: err.status ?? null, output: tail(combined) };
2617
+ }
2618
+ }
2619
+
2567
2620
  // ../../packages/executor-worktree/src/index.ts
2568
2621
  function makeRunner(runtime) {
2569
2622
  if ((process.env.DAHRK_RUNNER ?? process.env.SKAKEL_RUNNER ?? "real") === "mock") return createMockRunner(runtime);
@@ -2630,8 +2683,8 @@ function collectHealth(inputs) {
2630
2683
  }
2631
2684
 
2632
2685
  // ../../packages/edge/src/job-ledger.ts
2633
- import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync4, renameSync, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
2634
- import { dirname as dirname4, join as join10 } from "path";
2686
+ import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync5, renameSync, unlinkSync, writeFileSync as writeFileSync7 } from "fs";
2687
+ import { dirname as dirname5, join as join11 } from "path";
2635
2688
  var FILE_MODE = 384;
2636
2689
  var DIR_MODE = 448;
2637
2690
  function nullJobLedger() {
@@ -2647,9 +2700,9 @@ var isEntry = (v) => {
2647
2700
  };
2648
2701
  function fileJobLedger(file, warn = console.warn) {
2649
2702
  const read = () => {
2650
- if (!existsSync5(file)) return [];
2703
+ if (!existsSync6(file)) return [];
2651
2704
  try {
2652
- const parsed = JSON.parse(readFileSync4(file, "utf8"));
2705
+ const parsed = JSON.parse(readFileSync5(file, "utf8"));
2653
2706
  if (!Array.isArray(parsed)) return [];
2654
2707
  return parsed.filter(isEntry);
2655
2708
  } catch {
@@ -2659,15 +2712,15 @@ function fileJobLedger(file, warn = console.warn) {
2659
2712
  const write = (entries) => {
2660
2713
  const tmp = `${file}.${process.pid}.tmp`;
2661
2714
  try {
2662
- mkdirSync5(dirname4(file), { recursive: true, mode: DIR_MODE });
2663
- writeFileSync6(tmp, `${JSON.stringify(entries, null, 2)}
2715
+ mkdirSync6(dirname5(file), { recursive: true, mode: DIR_MODE });
2716
+ writeFileSync7(tmp, `${JSON.stringify(entries, null, 2)}
2664
2717
  `, { mode: FILE_MODE });
2665
2718
  chmodSync(tmp, FILE_MODE);
2666
2719
  renameSync(tmp, file);
2667
2720
  } catch (e) {
2668
2721
  warn(`could not persist the job ledger to ${file}: ${e.message}`);
2669
2722
  try {
2670
- if (existsSync5(tmp)) unlinkSync(tmp);
2723
+ if (existsSync6(tmp)) unlinkSync(tmp);
2671
2724
  } catch {
2672
2725
  }
2673
2726
  }
@@ -2695,7 +2748,7 @@ function announceableJobs(entries) {
2695
2748
  return out2;
2696
2749
  }
2697
2750
  function jobLedgerFile(stateDir2) {
2698
- return join10(stateDir2, "jobs.json");
2751
+ return join11(stateDir2, "jobs.json");
2699
2752
  }
2700
2753
 
2701
2754
  // ../../packages/edge/src/log-shipper.ts
@@ -2798,8 +2851,8 @@ function ceilingFromEnv(env) {
2798
2851
  }
2799
2852
 
2800
2853
  // ../../packages/edge/src/logger.ts
2801
- import { closeSync, existsSync as existsSync6, mkdirSync as mkdirSync6, openSync, renameSync as renameSync2, rmSync as rmSync5, statSync as statSync2, writeSync } from "fs";
2802
- import { join as join11 } from "path";
2854
+ import { closeSync, existsSync as existsSync7, mkdirSync as mkdirSync7, openSync, renameSync as renameSync2, rmSync as rmSync5, statSync as statSync2, writeSync } from "fs";
2855
+ import { join as join12 } from "path";
2803
2856
  import pino from "pino";
2804
2857
 
2805
2858
  // ../../packages/edge/src/redact.ts
@@ -2895,7 +2948,7 @@ var RotatingFile = class {
2895
2948
  open() {
2896
2949
  try {
2897
2950
  this.fd = openSync(this.path, "a");
2898
- this.size = existsSync6(this.path) ? statSync2(this.path).size : 0;
2951
+ this.size = existsSync7(this.path) ? statSync2(this.path).size : 0;
2899
2952
  } catch (e) {
2900
2953
  this.disable(e);
2901
2954
  }
@@ -2923,12 +2976,12 @@ var RotatingFile = class {
2923
2976
  closeSync(this.fd);
2924
2977
  this.fd = void 0;
2925
2978
  const oldest = `${this.path}.${this.maxFiles}`;
2926
- if (existsSync6(oldest)) rmSync5(oldest, { force: true });
2979
+ if (existsSync7(oldest)) rmSync5(oldest, { force: true });
2927
2980
  for (let i = this.maxFiles - 1; i >= 1; i--) {
2928
2981
  const from = `${this.path}.${i}`;
2929
- if (existsSync6(from)) renameSync2(from, `${this.path}.${i + 1}`);
2982
+ if (existsSync7(from)) renameSync2(from, `${this.path}.${i + 1}`);
2930
2983
  }
2931
- if (existsSync6(this.path)) renameSync2(this.path, `${this.path}.1`);
2984
+ if (existsSync7(this.path)) renameSync2(this.path, `${this.path}.1`);
2932
2985
  this.open();
2933
2986
  } catch (e) {
2934
2987
  this.disable(e);
@@ -2988,8 +3041,8 @@ function createNodeLogger(opts = {}) {
2988
3041
  if (level !== "silent") streams.push({ level, stream: humanSink });
2989
3042
  if (opts.dir && fileLevel !== "silent") {
2990
3043
  try {
2991
- mkdirSync6(opts.dir, { recursive: true, mode: 448 });
2992
- const file = new RotatingFile(join11(opts.dir, "node.jsonl"), opts.maxBytes ?? 10 * 1024 * 1024, opts.maxFiles ?? 5);
3044
+ mkdirSync7(opts.dir, { recursive: true, mode: 448 });
3045
+ const file = new RotatingFile(join12(opts.dir, "node.jsonl"), opts.maxBytes ?? 10 * 1024 * 1024, opts.maxFiles ?? 5);
2993
3046
  streams.push({ level: fileLevel, stream: file });
2994
3047
  } catch (e) {
2995
3048
  process.stderr.write(`dahrk: file logging disabled (${e.message})
@@ -3045,21 +3098,21 @@ function denyToolRule(tool3) {
3045
3098
  }
3046
3099
 
3047
3100
  // ../../packages/edge/src/stage-runner.ts
3048
- import { execFileSync as execFileSync5 } from "child_process";
3049
- import { createHash as createHash3 } from "crypto";
3050
- import { mkdirSync as mkdirSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
3101
+ import { execFileSync as execFileSync6 } from "child_process";
3102
+ import { createHash as createHash4 } from "crypto";
3103
+ import { mkdirSync as mkdirSync8, readdirSync as readdirSync3, readFileSync as readFileSync6, rmSync as rmSync6, writeFileSync as writeFileSync8 } from "fs";
3051
3104
  import { tmpdir as tmpdir5 } from "os";
3052
- import { isAbsolute as isAbsolute3, join as join13, relative as relative3, resolve as resolve2, sep as sep3 } from "path";
3105
+ import { isAbsolute as isAbsolute3, join as join14, relative as relative3, resolve as resolve2, sep as sep3 } from "path";
3053
3106
  import { attachedDocBasename as attachedDocBasename2 } from "@dahrk/contracts";
3054
3107
 
3055
3108
  // ../../packages/edge/src/builtins.ts
3056
- import { execFileSync as execFileSync4 } from "child_process";
3109
+ import { execFileSync as execFileSync5 } from "child_process";
3057
3110
 
3058
3111
  // ../../packages/edge/src/fs-roots.ts
3059
- import { execFileSync as execFileSync3 } from "child_process";
3060
- import { existsSync as existsSync7, realpathSync as realpathSync2 } from "fs";
3112
+ import { execFileSync as execFileSync4 } from "child_process";
3113
+ import { existsSync as existsSync8, realpathSync as realpathSync2 } from "fs";
3061
3114
  import { homedir as homedir3, tmpdir as tmpdir4 } from "os";
3062
- import { dirname as dirname5, isAbsolute as isAbsolute2, join as join12, relative as relative2, resolve, sep as sep2 } from "path";
3115
+ import { dirname as dirname6, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve, sep as sep2 } from "path";
3063
3116
  function isUnder(root, target) {
3064
3117
  const rel = relative2(resolve(root), resolve(target));
3065
3118
  return rel === "" || !rel.startsWith(`..${sep2}`) && rel !== ".." && !isAbsolute2(rel);
@@ -3071,17 +3124,17 @@ function expandPath(raw, cwd) {
3071
3124
  }
3072
3125
  function realish(p) {
3073
3126
  let head = p;
3074
- const tail = [];
3075
- while (head !== dirname5(head)) {
3076
- if (existsSync7(head)) {
3127
+ const tail2 = [];
3128
+ while (head !== dirname6(head)) {
3129
+ if (existsSync8(head)) {
3077
3130
  try {
3078
- return join12(realpathSync2.native(head), ...tail.reverse());
3131
+ return join13(realpathSync2.native(head), ...tail2.reverse());
3079
3132
  } catch {
3080
3133
  return p;
3081
3134
  }
3082
3135
  }
3083
- tail.push(head.slice(dirname5(head).length + 1));
3084
- head = dirname5(head);
3136
+ tail2.push(head.slice(dirname6(head).length + 1));
3137
+ head = dirname6(head);
3085
3138
  }
3086
3139
  return p;
3087
3140
  }
@@ -3095,7 +3148,7 @@ function withinRoots(raw, roots, need) {
3095
3148
  }
3096
3149
  function gitCommonDir(worktreePath) {
3097
3150
  try {
3098
- const out2 = execFileSync3("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
3151
+ const out2 = execFileSync4("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
3099
3152
  cwd: worktreePath,
3100
3153
  stdio: ["ignore", "pipe", "ignore"]
3101
3154
  }).toString().trim();
@@ -3108,7 +3161,7 @@ var pnpmStoreCache;
3108
3161
  function pnpmStore() {
3109
3162
  if (pnpmStoreCache) return pnpmStoreCache.path;
3110
3163
  try {
3111
- const out2 = execFileSync3("pnpm", ["store", "path"], { stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 }).toString().trim();
3164
+ const out2 = execFileSync4("pnpm", ["store", "path"], { stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 }).toString().trim();
3112
3165
  pnpmStoreCache = { path: out2 || void 0 };
3113
3166
  } catch {
3114
3167
  pnpmStoreCache = { path: void 0 };
@@ -3144,26 +3197,26 @@ function computeFsRoots(opts) {
3144
3197
  "/System",
3145
3198
  "/proc",
3146
3199
  "/sys",
3147
- join12(home, ".gitconfig"),
3148
- join12(home, ".config"),
3149
- join12(home, ".npmrc"),
3150
- join12(home, ".cache"),
3151
- join12(home, "Library", "Caches"),
3152
- join12(home, "Library", "pnpm"),
3153
- join12(home, ".local", "share"),
3154
- join12(home, ".nvm"),
3155
- join12(home, ".volta"),
3156
- join12(home, ".asdf"),
3157
- join12(home, ".cargo"),
3158
- join12(home, ".rustup"),
3200
+ join13(home, ".gitconfig"),
3201
+ join13(home, ".config"),
3202
+ join13(home, ".npmrc"),
3203
+ join13(home, ".cache"),
3204
+ join13(home, "Library", "Caches"),
3205
+ join13(home, "Library", "pnpm"),
3206
+ join13(home, ".local", "share"),
3207
+ join13(home, ".nvm"),
3208
+ join13(home, ".volta"),
3209
+ join13(home, ".asdf"),
3210
+ join13(home, ".cargo"),
3211
+ join13(home, ".rustup"),
3159
3212
  ...splitRoots(process.env.DAHRK_FS_EXTRA_READ_ROOTS).map((p) => realish(resolve(p)))
3160
3213
  ].map(realish);
3161
3214
  const deny = [
3162
- join12(home, ".ssh"),
3163
- join12(home, ".aws"),
3164
- join12(home, ".gnupg"),
3165
- join12(home, ".config", "gcloud"),
3166
- join12(home, "Library", "Keychains"),
3215
+ join13(home, ".ssh"),
3216
+ join13(home, ".aws"),
3217
+ join13(home, ".gnupg"),
3218
+ join13(home, ".config", "gcloud"),
3219
+ join13(home, "Library", "Keychains"),
3167
3220
  "/Volumes",
3168
3221
  "/etc/shadow",
3169
3222
  "/etc/sudoers"
@@ -3515,7 +3568,7 @@ function isDangerousRm(cmd) {
3515
3568
  }
3516
3569
  function currentBranch(worktreePath) {
3517
3570
  try {
3518
- return execFileSync4("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: worktreePath }).toString().trim();
3571
+ return execFileSync5("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: worktreePath }).toString().trim();
3519
3572
  } catch {
3520
3573
  return "";
3521
3574
  }
@@ -3817,34 +3870,34 @@ var attemptOf = (jobId) => {
3817
3870
  const m = /-(\d+)$/.exec(jobId);
3818
3871
  return m ? Number(m[1]) : 1;
3819
3872
  };
3820
- var digest = (value) => `sha256:${createHash3("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16)}`;
3873
+ var digest2 = (value) => `sha256:${createHash4("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16)}`;
3821
3874
  function writeScratchState(ref, job, attempt, status) {
3822
- const statePath = join13(ref.scratchPath, "state.json");
3875
+ const statePath = join14(ref.scratchPath, "state.json");
3823
3876
  let state;
3824
3877
  try {
3825
- state = JSON.parse(readFileSync5(statePath, "utf8"));
3878
+ state = JSON.parse(readFileSync6(statePath, "utf8"));
3826
3879
  } catch {
3827
3880
  state = { runId: job.runId, tenantId: job.tenantId, stages: {} };
3828
3881
  }
3829
3882
  state.stages[job.stageId] = { currentAttempt: attempt, status };
3830
- mkdirSync7(ref.scratchPath, { recursive: true });
3831
- writeFileSync7(statePath, JSON.stringify(state, null, 2));
3883
+ mkdirSync8(ref.scratchPath, { recursive: true });
3884
+ writeFileSync8(statePath, JSON.stringify(state, null, 2));
3832
3885
  }
3833
3886
  function writeIssueContext(ref, issueContext) {
3834
3887
  if (issueContext === void 0) return;
3835
3888
  try {
3836
- mkdirSync7(ref.scratchPath, { recursive: true });
3837
- writeFileSync7(join13(ref.scratchPath, "issue.md"), issueContext);
3889
+ mkdirSync8(ref.scratchPath, { recursive: true });
3890
+ writeFileSync8(join14(ref.scratchPath, "issue.md"), issueContext);
3838
3891
  } catch {
3839
3892
  }
3840
3893
  }
3841
3894
  function writeAttachedDocuments(ref, docs) {
3842
3895
  if (!docs || docs.length === 0) return;
3843
3896
  try {
3844
- const dir = join13(ref.scratchPath, "docs");
3845
- mkdirSync7(dir, { recursive: true });
3897
+ const dir = join14(ref.scratchPath, "docs");
3898
+ mkdirSync8(dir, { recursive: true });
3846
3899
  for (const doc of docs) {
3847
- writeFileSync7(join13(dir, `${attachedDocBasename2(doc)}.md`), doc.content);
3900
+ writeFileSync8(join14(dir, `${attachedDocBasename2(doc)}.md`), doc.content);
3848
3901
  }
3849
3902
  } catch {
3850
3903
  }
@@ -3862,8 +3915,8 @@ ${lines.join("\n")}
3862
3915
  function writeGuidance(ref, guidance) {
3863
3916
  if (!guidance || guidance.length === 0) return;
3864
3917
  try {
3865
- mkdirSync7(ref.scratchPath, { recursive: true });
3866
- writeFileSync7(join13(ref.scratchPath, "guidance.md"), renderGuidanceMarkdown(guidance));
3918
+ mkdirSync8(ref.scratchPath, { recursive: true });
3919
+ writeFileSync8(join14(ref.scratchPath, "guidance.md"), renderGuidanceMarkdown(guidance));
3867
3920
  } catch {
3868
3921
  }
3869
3922
  }
@@ -3889,7 +3942,7 @@ function readEmittedArtifact(ref, relPath) {
3889
3942
  const path = resolveWorktreeRelativePath(ref, relPath);
3890
3943
  if (!path) return void 0;
3891
3944
  try {
3892
- const raw = readFileSync5(path, "utf8");
3945
+ const raw = readFileSync6(path, "utf8");
3893
3946
  return { path: relPath, content: capContent(raw) };
3894
3947
  } catch {
3895
3948
  return void 0;
@@ -3898,12 +3951,12 @@ function readEmittedArtifact(ref, relPath) {
3898
3951
  function scanScratchOutput(ref, preferRel) {
3899
3952
  const preferBase = preferRel?.split("/").pop();
3900
3953
  try {
3901
- const names = readdirSync3(join13(ref.worktreePath, SCRATCH_OUTPUT_DIR)).filter(
3954
+ const names = readdirSync3(join14(ref.worktreePath, SCRATCH_OUTPUT_DIR)).filter(
3902
3955
  (n) => n.toLowerCase().endsWith(".md")
3903
3956
  );
3904
3957
  if (names.length === 0) return void 0;
3905
3958
  const pick = preferBase && names.includes(preferBase) ? preferBase : names[0];
3906
- const raw = readFileSync5(join13(ref.worktreePath, SCRATCH_OUTPUT_DIR, pick), "utf8");
3959
+ const raw = readFileSync6(join14(ref.worktreePath, SCRATCH_OUTPUT_DIR, pick), "utf8");
3907
3960
  if (raw.trim().length === 0) return void 0;
3908
3961
  return { path: `${SCRATCH_OUTPUT_DIR}/${pick}`, content: capContent(raw) };
3909
3962
  } catch {
@@ -3913,7 +3966,7 @@ function scanScratchOutput(ref, preferRel) {
3913
3966
  function scanChangedMarkdown(ref) {
3914
3967
  const git = (args) => {
3915
3968
  try {
3916
- return execFileSync5("git", ["-C", ref.worktreePath, ...args], { encoding: "utf8" }).split("\n").map((s) => s.trim()).filter(Boolean);
3969
+ return execFileSync6("git", ["-C", ref.worktreePath, ...args], { encoding: "utf8" }).split("\n").map((s) => s.trim()).filter(Boolean);
3917
3970
  } catch {
3918
3971
  return [];
3919
3972
  }
@@ -3923,7 +3976,7 @@ function scanChangedMarkdown(ref) {
3923
3976
  );
3924
3977
  for (const rel of rels) {
3925
3978
  try {
3926
- const raw = readFileSync5(join13(ref.worktreePath, rel), "utf8");
3979
+ const raw = readFileSync6(join14(ref.worktreePath, rel), "utf8");
3927
3980
  if (raw.trim().length > 0) return { path: rel, content: capContent(raw) };
3928
3981
  } catch {
3929
3982
  }
@@ -4049,10 +4102,10 @@ function createStageRunner(deps) {
4049
4102
  ...job.workspaceRef.credentialToken ? { credentialToken: job.workspaceRef.credentialToken } : {}
4050
4103
  });
4051
4104
  } else {
4052
- const base = deps.scratchRoot ?? join13(tmpdir5(), "dahrk", "scratch");
4053
- const worktreePath = join13(base, runId);
4054
- const scratchPath = join13(worktreePath, ".dahrk", "scratch");
4055
- mkdirSync7(scratchPath, { recursive: true });
4105
+ const base = deps.scratchRoot ?? join14(tmpdir5(), "dahrk", "scratch");
4106
+ const worktreePath = join14(base, runId);
4107
+ const scratchPath = join14(worktreePath, ".dahrk", "scratch");
4108
+ mkdirSync8(scratchPath, { recursive: true });
4056
4109
  ref = { repoId: "", gitUrl: "", repo: "", baseBranch: "", worktreePath, scratchPath };
4057
4110
  scratchOnly.add(runId);
4058
4111
  }
@@ -4067,7 +4120,7 @@ function createStageRunner(deps) {
4067
4120
  const slash = job.agentConfig.emitArtifact.lastIndexOf("/");
4068
4121
  if (artifactDir && slash > 0) {
4069
4122
  try {
4070
- mkdirSync7(join13(ref.worktreePath, job.agentConfig.emitArtifact.slice(0, slash)), { recursive: true });
4123
+ mkdirSync8(join14(ref.worktreePath, job.agentConfig.emitArtifact.slice(0, slash)), { recursive: true });
4071
4124
  } catch {
4072
4125
  }
4073
4126
  }
@@ -4082,7 +4135,7 @@ function createStageRunner(deps) {
4082
4135
  runtime: agentConfig.runtime,
4083
4136
  model: agentConfig.model,
4084
4137
  sessionId: job.sessionId,
4085
- configDigest: digest(agentConfig),
4138
+ configDigest: digest2(agentConfig),
4086
4139
  startedAt: nowIso2()
4087
4140
  };
4088
4141
  const writer = createTraceWriter(ref.scratchPath, meta);
@@ -4095,8 +4148,8 @@ function createStageRunner(deps) {
4095
4148
  if (!sink) return;
4096
4149
  const base = { tenantId: job.tenantId, runId, stageId, attempt };
4097
4150
  try {
4098
- for (const name of readdirSync3(join13(writer.dir, "blobs"))) {
4099
- const bytes = readFileSync5(join13(writer.dir, "blobs", name));
4151
+ for (const name of readdirSync3(join14(writer.dir, "blobs"))) {
4152
+ const bytes = readFileSync6(join14(writer.dir, "blobs", name));
4100
4153
  const { url } = await sink.requestBlobUrl({
4101
4154
  ...base,
4102
4155
  sha256: name,
@@ -4110,8 +4163,8 @@ function createStageRunner(deps) {
4110
4163
  }
4111
4164
  let archiveKey;
4112
4165
  try {
4113
- const bytes = readFileSync5(join13(writer.dir, "trace.jsonl"));
4114
- const sha = createHash3("sha256").update(bytes).digest("hex");
4166
+ const bytes = readFileSync6(join14(writer.dir, "trace.jsonl"));
4167
+ const sha = createHash4("sha256").update(bytes).digest("hex");
4115
4168
  const { key, url } = await sink.requestBlobUrl({
4116
4169
  ...base,
4117
4170
  sha256: sha,
@@ -4187,6 +4240,24 @@ function createStageRunner(deps) {
4187
4240
  return finish("fail", `${stageId}: ${msg}`, job.sessionId);
4188
4241
  }
4189
4242
  }
4243
+ const setup = job.setup;
4244
+ if (setup?.command && ref) {
4245
+ const outcome = runRepoSetup({ worktreePath: ref.worktreePath, command: setup.command });
4246
+ if (outcome.status === "failed") {
4247
+ const msg = `repo setup failed (exit ${outcome.exitCode ?? "null"})`;
4248
+ const detail2 = outcome.output ? `${msg}: ${outcome.output}` : msg;
4249
+ writer.append({ seq: 0, ts: nowIso2(), type: "error", runtime: agentConfig.runtime, kind: "setup-failed", message: detail2 });
4250
+ deps.sendProgress({ jobId, kind: "error", ts: nowIso2(), text: detail2 });
4251
+ return finish("fail", `${stageId}: ${msg}`, job.sessionId, void 0, void 0, "harness");
4252
+ }
4253
+ const detail = outcome.status === "cached" ? "setup: cached (already installed)" : `setup: ran (exit 0, ${outcome.output.length} bytes)`;
4254
+ streamEvent(
4255
+ writer.append({ seq: 0, ts: nowIso2(), type: "state", runtime: agentConfig.runtime, event: "setup", detail })
4256
+ );
4257
+ if (outcome.status === "ran") {
4258
+ deps.sendProgress({ jobId, kind: "observation", ts: nowIso2(), text: outcome.output || detail });
4259
+ }
4260
+ }
4190
4261
  let counter = runToolCalls.get(runId);
4191
4262
  if (!counter) {
4192
4263
  counter = { count: 0 };
@@ -4291,9 +4362,8 @@ function createStageRunner(deps) {
4291
4362
  // auth above belongs to, plus the model fallback. The adapter applies nothing for a provider
4292
4363
  // the hint does not name, so without this passthrough `runtimeEnv` arrives and is ignored -
4293
4364
  // a managed node then has no inference auth at all and falls through to whatever provider the
4294
- // runtime defaults to. Read through a narrow cast because the field is not in the published
4295
- // `@dahrk/contracts` (^0.4.0) yet; this line and `readAuthHint` are the only two seams, and
4296
- // both drop the cast when contracts ships.
4365
+ // runtime defaults to. A plain typed read since `@dahrk/contracts` declares `runtimeAuth` on
4366
+ // both `JobRequest` and `RunnerContext`.
4297
4367
  ...job.runtimeAuth ? { runtimeAuth: job.runtimeAuth } : {},
4298
4368
  // The adapter persists each runtime-native record under the attempt's raw/ sidecar
4299
4369
  // and stamps the rawRef onto the emitted event.
@@ -4354,7 +4424,7 @@ function createStageRunner(deps) {
4354
4424
  if (status === "ok" && job.hooks && job.hooks.length > 0) {
4355
4425
  for (const cmd of job.hooks) {
4356
4426
  try {
4357
- execFileSync5("sh", ["-c", cmd], { cwd: ref.worktreePath, stdio: ["pipe", "pipe", "pipe"] });
4427
+ execFileSync6("sh", ["-c", cmd], { cwd: ref.worktreePath, stdio: ["pipe", "pipe", "pipe"] });
4358
4428
  } catch (e) {
4359
4429
  status = "fail";
4360
4430
  writer.append({ seq: 0, ts: nowIso2(), type: "error", runtime, kind: "hook-failed", message: `hook "${cmd}" failed: ${e.message}` });
@@ -4976,7 +5046,7 @@ var PROBES = [
4976
5046
  { runtime: "claude-code", cmd: "claude" },
4977
5047
  { runtime: "pi", cmd: "pi" }
4978
5048
  ];
4979
- var DEFAULT_TIMEOUT_MS = 5e3;
5049
+ var DEFAULT_TIMEOUT_MS2 = 5e3;
4980
5050
  var DEFAULT_ATTEMPTS = 2;
4981
5051
  function probeOnce(cmd, timeoutMs) {
4982
5052
  return new Promise((resolve3) => {
@@ -4998,14 +5068,14 @@ async function probe(cmd, timeoutMs, attempts) {
4998
5068
  }
4999
5069
  return void 0;
5000
5070
  }
5001
- async function probeRuntimeStatuses(timeoutMs = DEFAULT_TIMEOUT_MS, attempts = DEFAULT_ATTEMPTS) {
5071
+ async function probeRuntimeStatuses(timeoutMs = DEFAULT_TIMEOUT_MS2, attempts = DEFAULT_ATTEMPTS) {
5002
5072
  const versions = await Promise.all(PROBES.map((p) => probe(p.cmd, timeoutMs, attempts)));
5003
5073
  return PROBES.map((p, i) => {
5004
5074
  const version = versions[i];
5005
5075
  return version === void 0 ? { runtime: p.runtime, cmd: p.cmd, installed: false } : { runtime: p.runtime, cmd: p.cmd, installed: true, version };
5006
5076
  });
5007
5077
  }
5008
- async function detectRuntimes(timeoutMs = DEFAULT_TIMEOUT_MS, attempts = DEFAULT_ATTEMPTS) {
5078
+ async function detectRuntimes(timeoutMs = DEFAULT_TIMEOUT_MS2, attempts = DEFAULT_ATTEMPTS) {
5009
5079
  const statuses = await probeRuntimeStatuses(timeoutMs, attempts);
5010
5080
  return statuses.filter((s) => s.installed).map((s) => s.runtime);
5011
5081
  }
@@ -5611,8 +5681,8 @@ function usage(bin, command) {
5611
5681
  }
5612
5682
 
5613
5683
  // src/diagnose.ts
5614
- import { existsSync as existsSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync3, writeFileSync as writeFileSync8 } from "fs";
5615
- import { join as join14 } from "path";
5684
+ import { existsSync as existsSync9, mkdirSync as mkdirSync9, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
5685
+ import { join as join15 } from "path";
5616
5686
 
5617
5687
  // src/ui.ts
5618
5688
  import { styleText } from "util";
@@ -5727,7 +5797,7 @@ async function buildBundle(deps) {
5727
5797
  if (deps.exists(deps.crashDir)) {
5728
5798
  for (const name of deps.listDir(deps.crashDir).filter((f) => f.endsWith(".json")).sort()) {
5729
5799
  try {
5730
- crashes.push(JSON.parse(deps.readFile(join14(deps.crashDir, name))));
5800
+ crashes.push(JSON.parse(deps.readFile(join15(deps.crashDir, name))));
5731
5801
  } catch (e) {
5732
5802
  warnings.push(`could not read crash record ${name} (${e.message})`);
5733
5803
  }
@@ -5784,18 +5854,18 @@ var defaultDiagnoseDeps = (paths, clientVersion, doctor) => ({
5784
5854
  ...paths,
5785
5855
  clientVersion,
5786
5856
  ...doctor ? { doctor } : {},
5787
- readFile: (p) => readFileSync6(p, "utf8"),
5857
+ readFile: (p) => readFileSync7(p, "utf8"),
5788
5858
  listDir: (p) => readdirSync4(p),
5789
- exists: (p) => existsSync8(p),
5859
+ exists: (p) => existsSync9(p),
5790
5860
  writeFile: (p, content) => {
5791
- const dir = join14(p, "..");
5792
- if (!existsSync8(dir)) mkdirSync8(dir, { recursive: true });
5793
- writeFileSync8(p, content, { mode: 384 });
5861
+ const dir = join15(p, "..");
5862
+ if (!existsSync9(dir)) mkdirSync9(dir, { recursive: true });
5863
+ writeFileSync9(p, content, { mode: 384 });
5794
5864
  },
5795
5865
  out
5796
5866
  });
5797
5867
  function defaultBundlePath(cwd, now) {
5798
- return join14(cwd, `dahrk-diagnose-${now.toISOString().replace(/[:.]/g, "-")}.json`);
5868
+ return join15(cwd, `dahrk-diagnose-${now.toISOString().replace(/[:.]/g, "-")}.json`);
5799
5869
  }
5800
5870
 
5801
5871
  // src/doctor.ts
@@ -5929,7 +5999,7 @@ async function runDoctor(inputs, deps = {}) {
5929
5999
  }
5930
6000
 
5931
6001
  // src/repo-add.ts
5932
- import { createHash as createHash4 } from "crypto";
6002
+ import { createHash as createHash5 } from "crypto";
5933
6003
  var stripRepoSuffix = (s) => s.replace(/\.git$/i, "").replace(/\/+$/, "");
5934
6004
  function splitOwnerRepo(path) {
5935
6005
  const parts = stripRepoSuffix(path).split("/").filter(Boolean);
@@ -5967,7 +6037,7 @@ var deriveRepoName = (remote) => remote.repo;
5967
6037
  function deriveRepoId(gitUrl) {
5968
6038
  const parsed = parseGitRemote(gitUrl);
5969
6039
  const canonical2 = parsed ? `${parsed.host}/${parsed.owner}/${parsed.repo}`.toLowerCase() : gitUrl.trim().toLowerCase();
5970
- const hash = createHash4("sha256").update(canonical2).digest("hex").slice(0, 12);
6040
+ const hash = createHash5("sha256").update(canonical2).digest("hex").slice(0, 12);
5971
6041
  const slug = (parsed ? parsed.repo : "repo").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
5972
6042
  return `${slug}-${hash}`;
5973
6043
  }
@@ -6015,8 +6085,8 @@ async function registerRepo(deps, args) {
6015
6085
  }
6016
6086
 
6017
6087
  // src/lock.ts
6018
- import { existsSync as existsSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync7, rmSync as rmSync7, writeFileSync as writeFileSync9 } from "fs";
6019
- import { dirname as dirname6 } from "path";
6088
+ import { existsSync as existsSync10, mkdirSync as mkdirSync10, readFileSync as readFileSync8, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "fs";
6089
+ import { dirname as dirname7 } from "path";
6020
6090
  function parseLock(content) {
6021
6091
  if (!content) return void 0;
6022
6092
  const pid = Number(content.trim());
@@ -6048,14 +6118,14 @@ var defaultLockDeps = (file) => ({
6048
6118
  pid: process.pid,
6049
6119
  readFile: (path) => {
6050
6120
  try {
6051
- return readFileSync7(path, "utf8");
6121
+ return readFileSync8(path, "utf8");
6052
6122
  } catch {
6053
6123
  return void 0;
6054
6124
  }
6055
6125
  },
6056
6126
  writeFile: (path, content) => {
6057
- if (!existsSync9(dirname6(path))) mkdirSync9(dirname6(path), { recursive: true, mode: 448 });
6058
- writeFileSync9(path, content);
6127
+ if (!existsSync10(dirname7(path))) mkdirSync10(dirname7(path), { recursive: true, mode: 448 });
6128
+ writeFileSync10(path, content);
6059
6129
  },
6060
6130
  removeFile: (path) => rmSync7(path, { force: true }),
6061
6131
  isAlive
@@ -6063,7 +6133,7 @@ var defaultLockDeps = (file) => ({
6063
6133
 
6064
6134
  // src/logs.ts
6065
6135
  import { spawn } from "child_process";
6066
- import { copyFileSync, existsSync as existsSync10, readFileSync as readFileSync8, statSync as statSync4, truncateSync } from "fs";
6136
+ import { copyFileSync, existsSync as existsSync11, readFileSync as readFileSync9, statSync as statSync4, truncateSync } from "fs";
6067
6137
  var MAX_LOG_BYTES = 10 * 1024 * 1024;
6068
6138
  function logsCommand(inputs) {
6069
6139
  return [
@@ -6144,7 +6214,7 @@ async function runStructuredLogs(inputs, deps) {
6144
6214
  }
6145
6215
  function rotateIfLarge(file, maxBytes = MAX_LOG_BYTES) {
6146
6216
  try {
6147
- if (!existsSync10(file) || statSync4(file).size <= maxBytes) return;
6217
+ if (!existsSync11(file) || statSync4(file).size <= maxBytes) return;
6148
6218
  copyFileSync(file, `${file}.1`);
6149
6219
  truncateSync(file, 0);
6150
6220
  } catch {
@@ -6153,8 +6223,8 @@ function rotateIfLarge(file, maxBytes = MAX_LOG_BYTES) {
6153
6223
  var defaultLogsDeps = (files, jsonlFile) => ({
6154
6224
  files,
6155
6225
  jsonlFile,
6156
- fileExists: (path) => existsSync10(path),
6157
- readFile: (path) => readFileSync8(path, "utf8"),
6226
+ fileExists: (path) => existsSync11(path),
6227
+ readFile: (path) => readFileSync9(path, "utf8"),
6158
6228
  run: (argv) => new Promise((resolve3) => {
6159
6229
  const [cmd, ...args] = argv;
6160
6230
  const child = spawn(cmd, args, { stdio: "inherit" });
@@ -6165,13 +6235,13 @@ var defaultLogsDeps = (files, jsonlFile) => ({
6165
6235
  });
6166
6236
 
6167
6237
  // src/process-safety.ts
6168
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
6169
- import { join as join15 } from "path";
6238
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
6239
+ import { join as join16 } from "path";
6170
6240
  function writeCrashRecord(dir, record) {
6171
6241
  try {
6172
- mkdirSync10(dir, { recursive: true, mode: 448 });
6173
- const file = join15(dir, `${record.at.replace(/[:.]/g, "-")}.json`);
6174
- writeFileSync10(file, `${JSON.stringify(record, null, 2)}
6242
+ mkdirSync11(dir, { recursive: true, mode: 448 });
6243
+ const file = join16(dir, `${record.at.replace(/[:.]/g, "-")}.json`);
6244
+ writeFileSync11(file, `${JSON.stringify(record, null, 2)}
6175
6245
  `, { mode: 384 });
6176
6246
  return file;
6177
6247
  } catch {
@@ -6224,11 +6294,11 @@ function installProcessSafetyNet(opts) {
6224
6294
  }
6225
6295
 
6226
6296
  // src/preflight.ts
6227
- import { execFileSync as execFileSync6 } from "child_process";
6297
+ import { execFileSync as execFileSync7 } from "child_process";
6228
6298
  import { randomUUID as randomUUID2 } from "crypto";
6229
- import { accessSync, constants as fsConstants, existsSync as existsSync11, readdirSync as readdirSync5, statfsSync as statfsSync2 } from "fs";
6299
+ import { accessSync, constants as fsConstants, existsSync as existsSync12, readdirSync as readdirSync5, statfsSync as statfsSync2 } from "fs";
6230
6300
  import { homedir as homedir4 } from "os";
6231
- import { join as join16 } from "path";
6301
+ import { join as join17 } from "path";
6232
6302
  var REPORT_BASE_URL = "https://app.dahrk.ai/r";
6233
6303
  var LOW_DISK_BYTES = 512 * 1024 * 1024;
6234
6304
  var PREFLIGHT_STAGES = [
@@ -6359,7 +6429,7 @@ var defaultDeps2 = () => ({
6359
6429
  });
6360
6430
  function commandPresent(cmd) {
6361
6431
  try {
6362
- execFileSync6("sh", ["-c", `command -v ${cmd}`], { stdio: "ignore" });
6432
+ execFileSync7("sh", ["-c", `command -v ${cmd}`], { stdio: "ignore" });
6363
6433
  return true;
6364
6434
  } catch {
6365
6435
  return false;
@@ -6367,12 +6437,12 @@ function commandPresent(cmd) {
6367
6437
  }
6368
6438
  function sshKeyPresent() {
6369
6439
  try {
6370
- const dir = join16(homedir4(), ".ssh");
6371
- if (existsSync11(dir) && readdirSync5(dir).some((f) => f.endsWith(".pub"))) return true;
6440
+ const dir = join17(homedir4(), ".ssh");
6441
+ if (existsSync12(dir) && readdirSync5(dir).some((f) => f.endsWith(".pub"))) return true;
6372
6442
  } catch {
6373
6443
  }
6374
6444
  try {
6375
- execFileSync6("ssh-add", ["-l"], { stdio: "ignore" });
6445
+ execFileSync7("ssh-add", ["-l"], { stdio: "ignore" });
6376
6446
  return true;
6377
6447
  } catch {
6378
6448
  return false;
@@ -6387,12 +6457,12 @@ function writable(dir) {
6387
6457
  }
6388
6458
  }
6389
6459
  function worktreeRoot(env) {
6390
- return env.DAHRK_WORKTREES_DIR ?? join16(env.DAHRK_STATE_DIR ?? join16(homedir4(), ".dahrk"), "worktrees");
6460
+ return env.DAHRK_WORKTREES_DIR ?? join17(env.DAHRK_STATE_DIR ?? join17(homedir4(), ".dahrk"), "worktrees");
6391
6461
  }
6392
6462
  function nearestExisting(dir) {
6393
6463
  let cur = dir;
6394
- while (!existsSync11(cur)) {
6395
- const parent = join16(cur, "..");
6464
+ while (!existsSync12(cur)) {
6465
+ const parent = join17(cur, "..");
6396
6466
  if (parent === cur) break;
6397
6467
  cur = parent;
6398
6468
  }
@@ -6407,7 +6477,7 @@ function freeDiskBytes(dir) {
6407
6477
  }
6408
6478
  }
6409
6479
  function probeRepo(repoPath) {
6410
- const git = (args) => execFileSync6("git", ["-C", repoPath, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
6480
+ const git = (args) => execFileSync7("git", ["-C", repoPath, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
6411
6481
  try {
6412
6482
  if (git(["rev-parse", "--is-inside-work-tree"]) !== "true") {
6413
6483
  return { path: repoPath, isGitRepo: false, headResolves: false, detail: "not inside a work tree" };
@@ -6453,15 +6523,15 @@ function gatherHostFacts(repoPath) {
6453
6523
  }
6454
6524
 
6455
6525
  // src/service.ts
6456
- import { execFileSync as execFileSync7 } from "child_process";
6457
- import { chmodSync as chmodSync3, existsSync as existsSync13, mkdirSync as mkdirSync12, readFileSync as readFileSync10, realpathSync as realpathSync3, rmSync as rmSync8, writeFileSync as writeFileSync12 } from "fs";
6526
+ import { execFileSync as execFileSync8 } from "child_process";
6527
+ import { chmodSync as chmodSync3, existsSync as existsSync14, mkdirSync as mkdirSync13, readFileSync as readFileSync11, realpathSync as realpathSync3, rmSync as rmSync8, writeFileSync as writeFileSync13 } from "fs";
6458
6528
  import { homedir as homedir6, platform as osPlatform3, userInfo } from "os";
6459
- import { join as join18 } from "path";
6529
+ import { join as join19 } from "path";
6460
6530
 
6461
6531
  // src/state.ts
6462
- import { chmodSync as chmodSync2, existsSync as existsSync12, mkdirSync as mkdirSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync11 } from "fs";
6532
+ import { chmodSync as chmodSync2, existsSync as existsSync13, mkdirSync as mkdirSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync12 } from "fs";
6463
6533
  import { homedir as homedir5 } from "os";
6464
- import { join as join17 } from "path";
6534
+ import { join as join18 } from "path";
6465
6535
  var RUNTIMES = ["claude-code", "codex", "pi"];
6466
6536
  var isRuntime = (v) => RUNTIMES.includes(v);
6467
6537
  var STRING_FIELDS = ["nodeId", "enrolToken", "name", "tenantId", "updateCheckedAt", "updateLatest"];
@@ -6469,37 +6539,37 @@ var isDesired = (v) => v === "running" || v === "stopped";
6469
6539
  var FILE_MODE2 = 384;
6470
6540
  var DIR_MODE2 = 448;
6471
6541
  function stateDir(env) {
6472
- return env.DAHRK_STATE_DIR ?? join17(homedir5(), ".dahrk");
6542
+ return env.DAHRK_STATE_DIR ?? join18(homedir5(), ".dahrk");
6473
6543
  }
6474
6544
  function legacyStateDir(env) {
6475
- return env.DAHRK_STATE_DIR ? void 0 : join17(homedir5(), ".skakel");
6545
+ return env.DAHRK_STATE_DIR ? void 0 : join18(homedir5(), ".skakel");
6476
6546
  }
6477
6547
  function stateFile(env) {
6478
- return join17(stateDir(env), "node.json");
6548
+ return join18(stateDir(env), "node.json");
6479
6549
  }
6480
6550
  function logDir(env) {
6481
- return join17(stateDir(env), "logs");
6551
+ return join18(stateDir(env), "logs");
6482
6552
  }
6483
6553
  function logFiles(env) {
6484
6554
  const dir = logDir(env);
6485
- return { out: join17(dir, "node.out.log"), err: join17(dir, "node.err.log") };
6555
+ return { out: join18(dir, "node.out.log"), err: join18(dir, "node.err.log") };
6486
6556
  }
6487
6557
  function jsonlLogFile(env) {
6488
- return join17(logDir(env), "node.jsonl");
6558
+ return join18(logDir(env), "node.jsonl");
6489
6559
  }
6490
6560
  function crashDir(env) {
6491
- return join17(logDir(env), "crashes");
6561
+ return join18(logDir(env), "crashes");
6492
6562
  }
6493
6563
  function lockFile(env) {
6494
- return join17(stateDir(env), "node.pid");
6564
+ return join18(stateDir(env), "node.pid");
6495
6565
  }
6496
6566
  function setDesired(env, desired) {
6497
6567
  writeState(env, { desired });
6498
6568
  }
6499
6569
  function readState(file) {
6500
- if (!existsSync12(file)) return {};
6570
+ if (!existsSync13(file)) return {};
6501
6571
  try {
6502
- const parsed = JSON.parse(readFileSync9(file, "utf8"));
6572
+ const parsed = JSON.parse(readFileSync10(file, "utf8"));
6503
6573
  const state = {};
6504
6574
  for (const key of STRING_FIELDS) {
6505
6575
  const value = parsed[key];
@@ -6519,9 +6589,9 @@ function writeState(env, patch) {
6519
6589
  const dir = stateDir(env);
6520
6590
  const file = stateFile(env);
6521
6591
  try {
6522
- mkdirSync11(dir, { recursive: true, mode: DIR_MODE2 });
6592
+ mkdirSync12(dir, { recursive: true, mode: DIR_MODE2 });
6523
6593
  const next = { ...readState(file), ...patch };
6524
- writeFileSync11(file, `${JSON.stringify(next, null, 2)}
6594
+ writeFileSync12(file, `${JSON.stringify(next, null, 2)}
6525
6595
  `, { mode: FILE_MODE2 });
6526
6596
  chmodSync2(file, FILE_MODE2);
6527
6597
  } catch (e) {
@@ -6602,9 +6672,9 @@ ${envEntries}
6602
6672
  <key>ThrottleInterval</key>
6603
6673
  <integer>10</integer>
6604
6674
  <key>StandardOutPath</key>
6605
- <string>${xmlEscape(join18(inputs.logDir, "node.out.log"))}</string>
6675
+ <string>${xmlEscape(join19(inputs.logDir, "node.out.log"))}</string>
6606
6676
  <key>StandardErrorPath</key>
6607
- <string>${xmlEscape(join18(inputs.logDir, "node.err.log"))}</string>
6677
+ <string>${xmlEscape(join19(inputs.logDir, "node.err.log"))}</string>
6608
6678
  </dict>
6609
6679
  </plist>
6610
6680
  `;
@@ -6627,8 +6697,8 @@ Type=simple
6627
6697
  ExecStart=${exec}
6628
6698
  ${envLines}
6629
6699
  WorkingDirectory=${inputs.homeDir}
6630
- StandardOutput=append:${join18(inputs.logDir, "node.out.log")}
6631
- StandardError=append:${join18(inputs.logDir, "node.err.log")}
6700
+ StandardOutput=append:${join19(inputs.logDir, "node.out.log")}
6701
+ StandardError=append:${join19(inputs.logDir, "node.err.log")}
6632
6702
  Restart=on-failure
6633
6703
  RestartSec=3
6634
6704
  RestartPreventExitStatus=78
@@ -6639,7 +6709,7 @@ WantedBy=default.target
6639
6709
  }
6640
6710
  function buildPlan(inputs) {
6641
6711
  if (inputs.manager === "launchd") {
6642
- const filePath2 = join18(inputs.homeDir, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
6712
+ const filePath2 = join19(inputs.homeDir, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
6643
6713
  return {
6644
6714
  manager: "launchd",
6645
6715
  label: LAUNCHD_LABEL,
@@ -6656,7 +6726,7 @@ function buildPlan(inputs) {
6656
6726
  logHint: "dahrk logs -f"
6657
6727
  };
6658
6728
  }
6659
- const filePath = join18(inputs.homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
6729
+ const filePath = join19(inputs.homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
6660
6730
  const user = userInfo().username;
6661
6731
  return {
6662
6732
  manager: "systemd",
@@ -6686,7 +6756,7 @@ function unitIsCurrent(plan, onDisk) {
6686
6756
  return onDisk === plan.content;
6687
6757
  }
6688
6758
  function unitPath(manager, homeDir) {
6689
- return manager === "launchd" ? join18(homeDir, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`) : join18(homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
6759
+ return manager === "launchd" ? join19(homeDir, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`) : join19(homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
6690
6760
  }
6691
6761
  function statusCommand(manager) {
6692
6762
  return manager === "launchd" ? ["launchctl", "list", LAUNCHD_LABEL] : ["systemctl", "--user", "show", SYSTEMD_UNIT, "-p", "ActiveState", "-p", "MainPID"];
@@ -6983,29 +7053,29 @@ var defaultDeps3 = () => ({
6983
7053
  // Snapshot the operator's PATH at install time so the daemon finds git + the runtime CLIs (Homebrew /
6984
7054
  // npm-global bins) that a supervisor's minimal PATH would otherwise hide.
6985
7055
  pathEnv: process.env.PATH,
6986
- mkdirp: (dir) => void mkdirSync12(dir, { recursive: true }),
7056
+ mkdirp: (dir) => void mkdirSync13(dir, { recursive: true }),
6987
7057
  // The unit holds no secret any more, but it stays owner-only: it names paths on this host, and there is
6988
7058
  // no reason for it to be world-readable. `writeFileSync`'s `mode` applies only when it CREATES the file,
6989
7059
  // so chmod explicitly too - re-installing over a unit an older client left at 0644 must tighten it.
6990
7060
  writeFile: (path, content) => {
6991
- writeFileSync12(path, content, { mode: UNIT_FILE_MODE });
7061
+ writeFileSync13(path, content, { mode: UNIT_FILE_MODE });
6992
7062
  chmodSync3(path, UNIT_FILE_MODE);
6993
7063
  },
6994
7064
  readFile: (path) => {
6995
7065
  try {
6996
- return readFileSync10(path, "utf8");
7066
+ return readFileSync11(path, "utf8");
6997
7067
  } catch {
6998
7068
  return void 0;
6999
7069
  }
7000
7070
  },
7001
7071
  removeFile: (path) => rmSync8(path, { force: true }),
7002
- fileExists: (path) => existsSync13(path),
7072
+ fileExists: (path) => existsSync14(path),
7003
7073
  // Captured, never inherited. A supervisor's stderr is ours to relay when it matters, not to leak
7004
7074
  // unconditionally: `runCommands` decides who needs to read it.
7005
7075
  run: (argv) => {
7006
7076
  const [cmd, ...args] = argv;
7007
7077
  try {
7008
- const stdout = execFileSync7(cmd, args, {
7078
+ const stdout = execFileSync8(cmd, args, {
7009
7079
  encoding: "utf8",
7010
7080
  stdio: ["ignore", "pipe", "pipe"]
7011
7081
  });
@@ -7020,7 +7090,7 @@ var defaultDeps3 = () => ({
7020
7090
  capture: (argv) => {
7021
7091
  const [cmd, ...args] = argv;
7022
7092
  try {
7023
- const stdout = execFileSync7(cmd, args, {
7093
+ const stdout = execFileSync8(cmd, args, {
7024
7094
  encoding: "utf8",
7025
7095
  stdio: ["ignore", "pipe", "ignore"]
7026
7096
  });
@@ -7034,7 +7104,7 @@ var defaultDeps3 = () => ({
7034
7104
  });
7035
7105
 
7036
7106
  // src/update.ts
7037
- import { execFileSync as execFileSync8 } from "child_process";
7107
+ import { execFileSync as execFileSync9 } from "child_process";
7038
7108
  import { realpathSync as realpathSync4 } from "fs";
7039
7109
  var LATEST_URL = "https://registry.npmjs.org/dahrk-node/latest";
7040
7110
  var CHANNEL_COMMANDS = {
@@ -7166,7 +7236,7 @@ async function fetchLatestVersion(signal) {
7166
7236
  function spawnUpgrade(argv) {
7167
7237
  const [cmd, ...args] = argv;
7168
7238
  try {
7169
- const stdout = execFileSync8(cmd, args, {
7239
+ const stdout = execFileSync9(cmd, args, {
7170
7240
  encoding: "utf8",
7171
7241
  stdio: ["ignore", "pipe", "pipe"]
7172
7242
  });
@@ -7439,7 +7509,7 @@ async function runStatus(inputs, deps) {
7439
7509
  }
7440
7510
 
7441
7511
  // src/main.ts
7442
- var CLIENT_VERSION = "0.1.24";
7512
+ var CLIENT_VERSION = "0.1.25";
7443
7513
  var DEFAULT_HUB_URL = "wss://api.dahrk.ai";
7444
7514
  var list = (v) => (v ?? "").split(",").map((s) => s.trim()).filter(Boolean);
7445
7515
  var RUNTIMES2 = ["claude-code", "codex", "pi"];
@@ -7451,7 +7521,7 @@ function resolveNodeId(env, opts = {}) {
7451
7521
  if (existing) return existing;
7452
7522
  const legacy = legacyStateDir(env);
7453
7523
  if (legacy) {
7454
- const legacyId = readState(join19(legacy, "node.json")).nodeId;
7524
+ const legacyId = readState(join20(legacy, "node.json")).nodeId;
7455
7525
  if (legacyId) return legacyId;
7456
7526
  }
7457
7527
  const nodeId = randomUUID3();
@@ -7719,11 +7789,11 @@ function statusDeps(env) {
7719
7789
  }
7720
7790
  return probeRuntimeStatuses();
7721
7791
  },
7722
- fileExists: (path) => existsSync14(path),
7792
+ fileExists: (path) => existsSync15(path),
7723
7793
  capture: (argv) => {
7724
7794
  const [cmd, ...args] = argv;
7725
7795
  try {
7726
- const stdout = execFileSync9(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
7796
+ const stdout = execFileSync10(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
7727
7797
  return { code: 0, stdout };
7728
7798
  } catch (e) {
7729
7799
  const status = e.status;
@@ -7748,7 +7818,7 @@ function statusDeps(env) {
7748
7818
  }
7749
7819
  function readFileOrUndefined(path) {
7750
7820
  try {
7751
- return readFileSync11(path, "utf8");
7821
+ return readFileSync12(path, "utf8");
7752
7822
  } catch {
7753
7823
  return void 0;
7754
7824
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dahrk-node",
3
- "version": "0.1.24",
3
+ "version": "0.1.25",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -34,7 +34,7 @@
34
34
  "exports": "./dist/main.js",
35
35
  "dependencies": {
36
36
  "@anthropic-ai/claude-agent-sdk": "0.3.183",
37
- "@dahrk/contracts": "^0.6.0",
37
+ "@dahrk/contracts": "^0.7.0",
38
38
  "pino": "^10.3.1",
39
39
  "ws": "^8.18.0",
40
40
  "zod": "^3.23.8"
@@ -42,8 +42,8 @@
42
42
  "devDependencies": {
43
43
  "tsup": "^8.3.5",
44
44
  "tsx": "^4.19.0",
45
- "@dahrk/executor-worktree": "0.1.0",
46
- "@dahrk/edge": "0.1.0"
45
+ "@dahrk/edge": "0.1.0",
46
+ "@dahrk/executor-worktree": "0.1.0"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsup",