haansi 0.1.53 → 0.1.54

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/haansi.js +58 -17
  2. package/package.json +1 -1
package/dist/haansi.js CHANGED
@@ -95,7 +95,7 @@ var require_package = __commonJS({
95
95
  "package.json"(exports2, module2) {
96
96
  module2.exports = {
97
97
  name: "haansi",
98
- version: "0.1.53",
98
+ version: "0.1.54",
99
99
  description: "Haansi CLI - Session collector and MCP server for Claude Code & OpenAI Codex",
100
100
  bin: {
101
101
  haansi: "./dist/haansi.js"
@@ -85238,6 +85238,33 @@ async function ensureCommit(deps, sha) {
85238
85238
  return true;
85239
85239
  return (await deps.git(["fetch", "--quiet", "origin", sha], deps.repoDir)).code === 0;
85240
85240
  }
85241
+ async function cleanCheckout(deps, dir, task) {
85242
+ const steps = [
85243
+ [["init", "--quiet", dir], deps.repoDir],
85244
+ [
85245
+ [
85246
+ "fetch",
85247
+ "--quiet",
85248
+ "--no-tags",
85249
+ "--no-write-fetch-head",
85250
+ deps.repoDir,
85251
+ `${task.baseSha}:refs/heads/${REPLAY_BRANCH}`
85252
+ ],
85253
+ dir
85254
+ ],
85255
+ [["checkout", "--quiet", REPLAY_BRANCH], dir]
85256
+ ];
85257
+ for (const [args, cwd] of steps) {
85258
+ if ((await deps.git(args, cwd)).code !== 0)
85259
+ throw new Error(`could not check out ${task.baseSha}`);
85260
+ }
85261
+ const leak = await deps.git(
85262
+ ["cat-file", "-e", `${task.targetSha}^{commit}`],
85263
+ dir
85264
+ );
85265
+ if (leak.code === 0)
85266
+ throw new Error("the fix's commit is readable in the clone: run refused");
85267
+ }
85241
85268
  async function replayArm(deps, options, task, arm, playbook) {
85242
85269
  const started = deps.now();
85243
85270
  const dir = (0, import_node_path9.join)(
@@ -85245,12 +85272,8 @@ async function replayArm(deps, options, task, arm, playbook) {
85245
85272
  `${task.processId.replace(/[^a-zA-Z0-9_-]/g, "")}-${arm}`
85246
85273
  );
85247
85274
  const files = task.testFiles;
85248
- const add = await deps.git(
85249
- ["worktree", "add", "--detach", dir, task.baseSha],
85250
- deps.repoDir
85251
- );
85252
- if (add.code !== 0) throw new Error(`could not check out ${task.baseSha}`);
85253
85275
  try {
85276
+ await cleanCheckout(deps, dir, task);
85254
85277
  const label = `${task.name ?? task.processId} [${arm}]`;
85255
85278
  const since = (from) => `${Math.round((deps.now() - from) / 1e3)}s`;
85256
85279
  deps.log(`\u2026 ${label}: checked out ${task.baseSha.slice(0, 9)}`);
@@ -85291,12 +85314,11 @@ async function replayArm(deps, options, task, arm, playbook) {
85291
85314
  options.timeoutMs
85292
85315
  );
85293
85316
  const own = new Map(files.map((f) => [f, deps.readFile((0, import_node_path9.join)(dir, f))]));
85294
- const checkout = await deps.git(
85295
- ["checkout", task.targetSha, "--", ...files],
85296
- dir
85297
- );
85298
- if (checkout.code !== 0)
85299
- throw new Error("could not check out the fix's tests");
85317
+ for (const f of files) {
85318
+ const content = await deps.showFile(task.targetSha, f);
85319
+ if (content === null) deps.removeFile((0, import_node_path9.join)(dir, f));
85320
+ else deps.writeFile((0, import_node_path9.join)(dir, f), content);
85321
+ }
85300
85322
  const testAt = deps.now();
85301
85323
  deps.log(`\u2026 ${label}: agent done in ${since(agentAt)}, grading`);
85302
85324
  const test = await deps.shell(
@@ -85339,7 +85361,6 @@ async function replayArm(deps, options, task, arm, playbook) {
85339
85361
  revisionId: arm === "haansi" ? playbook?.revisionId ?? null : null
85340
85362
  };
85341
85363
  } finally {
85342
- await deps.git(["worktree", "remove", "--force", dir], deps.repoDir);
85343
85364
  deps.removeDir(dir);
85344
85365
  }
85345
85366
  }
@@ -85424,7 +85445,7 @@ async function runReplays(options, deps) {
85424
85445
  );
85425
85446
  return { results, skipped, recorded: reported.recorded };
85426
85447
  }
85427
- function runCommand(file2, args, cwd, env, timeoutMs) {
85448
+ function runCommand(file2, args, cwd, env, timeoutMs, stdoutOnly = false) {
85428
85449
  return new Promise((resolvePromise) => {
85429
85450
  const child = (0, import_node_child_process4.spawn)(file2, args, {
85430
85451
  cwd,
@@ -85435,8 +85456,16 @@ function runCommand(file2, args, cwd, env, timeoutMs) {
85435
85456
  const keep = (chunk) => {
85436
85457
  output = (output + chunk.toString()).slice(-2e5);
85437
85458
  };
85438
- child.stdout.on("data", keep);
85439
- child.stderr.on("data", keep);
85459
+ if (stdoutOnly) {
85460
+ const chunks = [];
85461
+ child.stdout.on("data", (chunk) => chunks.push(chunk));
85462
+ child.stdout.on("end", () => {
85463
+ output = Buffer.concat(chunks).toString();
85464
+ });
85465
+ } else {
85466
+ child.stdout.on("data", keep);
85467
+ child.stderr.on("data", keep);
85468
+ }
85440
85469
  const timer = setTimeout(() => child.kill("SIGKILL"), timeoutMs);
85441
85470
  child.on("close", (code) => {
85442
85471
  clearTimeout(timer);
@@ -85478,6 +85507,17 @@ async function replay(argv) {
85478
85507
  apiUrl2
85479
85508
  ),
85480
85509
  git: (args, cwd) => runCommand("git", args, cwd, {}, 10 * 6e4),
85510
+ showFile: async (sha, path2) => {
85511
+ const shown = await runCommand(
85512
+ "git",
85513
+ ["show", `${sha}:${path2}`],
85514
+ process.cwd(),
85515
+ {},
85516
+ 6e4,
85517
+ true
85518
+ );
85519
+ return shown.code === 0 ? shown.output : null;
85520
+ },
85481
85521
  shell: (command2, cwd, env, timeoutMs) => runCommand("sh", ["-c", command2], cwd, env, timeoutMs),
85482
85522
  repoDir: process.cwd(),
85483
85523
  workDir: () => work,
@@ -85504,7 +85544,7 @@ Baseline: ${passed("baseline")}/${ran("baseline")} passed \xB7 With Haansi: ${pa
85504
85544
  (0, import_node_fs10.rmSync)(work, { recursive: true, force: true });
85505
85545
  }
85506
85546
  }
85507
- var import_node_child_process4, import_node_fs10, import_node_os9, import_node_path9, SHA, ARMS, FEEDBACK_CHARS, FAILURE_LINES, USAGE;
85547
+ var import_node_child_process4, import_node_fs10, import_node_os9, import_node_path9, SHA, ARMS, FEEDBACK_CHARS, FAILURE_LINES, REPLAY_BRANCH, USAGE;
85508
85548
  var init_replay = __esm({
85509
85549
  "src/commands/replay.ts"() {
85510
85550
  "use strict";
@@ -85518,6 +85558,7 @@ var init_replay = __esm({
85518
85558
  ARMS = ["baseline", "haansi"];
85519
85559
  FEEDBACK_CHARS = 6e3;
85520
85560
  FAILURE_LINES = 8;
85561
+ REPLAY_BRANCH = "replay";
85521
85562
  USAGE = `Usage: haansi replay run --family <id> --agent-cmd "<cmd>" --test-cmd "<cmd>"
85522
85563
  [--setup-cmd "<cmd>"] [--attempts 3] [--arms baseline,haansi] [--limit n]
85523
85564
  [--cutoff <date>] [--timeout-min 30]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haansi",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "description": "Haansi CLI - Session collector and MCP server for Claude Code & OpenAI Codex",
5
5
  "bin": {
6
6
  "haansi": "./dist/haansi.js"