spacecode 2.14.4 → 2.14.5

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/dist/repl.mjs CHANGED
@@ -104840,6 +104840,32 @@ var init_worker_contract = __esm({
104840
104840
  }
104841
104841
  });
104842
104842
 
104843
+ // ../shared/src/core/check-baseline.ts
104844
+ function judgeAgainstBaseline(checks, baseline) {
104845
+ const newChecks = {};
104846
+ const baselineFailed = [];
104847
+ for (const key of Object.keys(checks)) {
104848
+ const code = checks[key];
104849
+ if (code === 0) {
104850
+ newChecks[key] = 0;
104851
+ continue;
104852
+ }
104853
+ const baseCode = baseline[key];
104854
+ if (typeof baseCode === "number" && baseCode !== 0) {
104855
+ newChecks[key] = 0;
104856
+ baselineFailed.push(key);
104857
+ } else {
104858
+ newChecks[key] = code;
104859
+ }
104860
+ }
104861
+ return { checks: newChecks, baselineFailed };
104862
+ }
104863
+ var init_check_baseline = __esm({
104864
+ "../shared/src/core/check-baseline.ts"() {
104865
+ "use strict";
104866
+ }
104867
+ });
104868
+
104843
104869
  // ../shared/src/core/worker-pipeline.ts
104844
104870
  function agentFailure(run) {
104845
104871
  const tail = (run.stderr.trim() || run.stdout.trim()).slice(-300).replace(/\s+/g, " ");
@@ -104910,6 +104936,7 @@ async function runWorkerJob(deps, job) {
104910
104936
  const changedFiles = names.stdout.split("\n").map((l) => l.trim()).filter(Boolean);
104911
104937
  const diffLines = patch.stdout === "" ? 0 : patch.stdout.split("\n").length;
104912
104938
  const checks = {};
104939
+ const baselineFailed = [];
104913
104940
  if (job.task.acceptance.kind === "checks") {
104914
104941
  const pkg = await deps.sandbox.exec(`cd ${shq(dir)} && cat package.json 2>/dev/null`);
104915
104942
  let scripts;
@@ -104931,6 +104958,31 @@ async function runWorkerJob(deps, job) {
104931
104958
  if (r.exitCode !== 0) deps.log("worker check failed", { ...ids, check: c.name, exitCode: r.exitCode, tail: redactSecrets(`${r.stdout}
104932
104959
  ${r.stderr}`.trim().slice(-300).replace(/\s+/g, " ")) });
104933
104960
  }
104961
+ const failing = wanted.filter((c) => checks[c.name] !== 0);
104962
+ if (deps.baseline && failing.length > 0) {
104963
+ const bdir = `${dir}-baseline`;
104964
+ try {
104965
+ const added = await deps.sandbox.exec(`cd ${shq(dir)} && git worktree add --detach ${shq(bdir)} ${base}`);
104966
+ if (added.exitCode !== 0) {
104967
+ deps.log("baseline worktree failed", { ...ids, exitCode: added.exitCode });
104968
+ } else {
104969
+ await deps.baseline.prepare(bdir);
104970
+ const baselineExit = {};
104971
+ for (const c of failing) baselineExit[c.name] = (await deps.sandbox.exec(`cd ${shq(bdir)} && timeout ${slice()} ${c.cmd}`)).exitCode;
104972
+ const judged = judgeAgainstBaseline(checks, baselineExit);
104973
+ Object.assign(checks, judged.checks);
104974
+ for (const name of judged.baselineFailed) {
104975
+ baselineFailed.push(name);
104976
+ deps.log("worker check also fails on the base revision", { ...ids, check: name, exitCode: baselineExit[name] });
104977
+ }
104978
+ }
104979
+ } catch (e) {
104980
+ if (e instanceof TypeError || e instanceof ReferenceError) throw e;
104981
+ deps.log("baseline comparison failed", { ...ids, error: e instanceof Error ? e.message.slice(0, 120) : "unknown" });
104982
+ } finally {
104983
+ await deps.sandbox.exec(`cd ${shq(dir)} && git worktree remove --force ${shq(bdir)}`).catch((e) => deps.log("baseline worktree cleanup failed", { ...ids, error: e instanceof Error ? e.message.slice(0, 100) : "unknown" }));
104984
+ }
104985
+ }
104934
104986
  }
104935
104987
  }
104936
104988
  if (await deps.cancelled()) return "cancelled";
@@ -104947,7 +104999,7 @@ ${r.stderr}`.trim().slice(-300).replace(/\s+/g, " ")) });
104947
104999
  ...patch.stdout !== "" && !tooBig ? { patch: patch.stdout } : {},
104948
105000
  ...tooBig ? { reason: "patch exceeds the size limit" } : {},
104949
105001
  ...digest === "" ? { reason: run.exitCode !== 0 ? agentFailure(run) : noDigestReason(result?.text) } : {},
104950
- verify: { checks, changedFiles, diffLines }
105002
+ verify: { checks, changedFiles, diffLines, ...baselineFailed.length > 0 ? { baselineFailed } : {} }
104951
105003
  });
104952
105004
  deps.log("worker reported", { ...ids, files: changedFiles.length, diffLines });
104953
105005
  return "reported";
@@ -104963,6 +105015,7 @@ var MAX_PATCH_BYTES, shq, clip;
104963
105015
  var init_worker_pipeline = __esm({
104964
105016
  "../shared/src/core/worker-pipeline.ts"() {
104965
105017
  "use strict";
105018
+ init_check_baseline();
104966
105019
  init_worker_contract();
104967
105020
  MAX_PATCH_BYTES = 5e6;
104968
105021
  shq = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
@@ -104982,6 +105035,7 @@ var init_core = __esm({
104982
105035
  init_verify();
104983
105036
  init_worker_contract();
104984
105037
  init_worker_pipeline();
105038
+ init_check_baseline();
104985
105039
  }
104986
105040
  });
104987
105041
 
@@ -104991,6 +105045,15 @@ async function must(shell, cmd, what) {
104991
105045
  if (r.exitCode !== 0) throw new Error(`${what} failed: ${r.stderr.trim() || `exit ${r.exitCode}`}`);
104992
105046
  return r.stdout.trim();
104993
105047
  }
105048
+ async function linkDependencyFolders(shell, top, dir) {
105049
+ const found = await must(shell, `cd ${q2(top)} && find . -maxdepth 4 -name node_modules -type d -prune -not -path './.git/*'`, "listing dependency folders");
105050
+ for (const line of found.split("\n")) {
105051
+ const rel = line.trim().replace(/^\.\//, "");
105052
+ if (rel === "" || rel === ".") continue;
105053
+ const parent = rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : ".";
105054
+ await must(shell, `mkdir -p ${q2(`${dir}/${parent}`)} && { [ -e ${q2(`${dir}/${rel}`)} ] || ln -s ${q2(`${top}/${rel}`)} ${q2(`${dir}/${rel}`)}; }`, `linking ${rel}`);
105055
+ }
105056
+ }
104994
105057
  async function createTaskWorktree(shell, cwd2, base, runId, taskId, attempt, warn = () => {
104995
105058
  }) {
104996
105059
  const top = await must(shell, `cd ${q2(cwd2)} && git rev-parse --show-toplevel`, "finding the repository root");
@@ -105000,13 +105063,7 @@ async function createTaskWorktree(shell, cwd2, base, runId, taskId, attempt, war
105000
105063
  if (sweep.exitCode !== 0) warn(`stale worktree sweep failed: ${sweep.stderr.trim().slice(0, 200) || `exit ${sweep.exitCode}`}`);
105001
105064
  const dir = `${root}/${safe(runId)}/wt-${safe(taskId)}-${attempt}`;
105002
105065
  await must(shell, `git -C ${q2(top)} worktree add --detach ${q2(dir)} ${q2(commit)}`, "creating the task worktree");
105003
- const found = await must(shell, `cd ${q2(top)} && find . -maxdepth 4 -name node_modules -type d -prune -not -path './.git/*'`, "listing dependency folders");
105004
- for (const line of found.split("\n")) {
105005
- const rel = line.trim().replace(/^\.\//, "");
105006
- if (rel === "" || rel === ".") continue;
105007
- const parent = rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : ".";
105008
- await must(shell, `mkdir -p ${q2(`${dir}/${parent}`)} && { [ -e ${q2(`${dir}/${rel}`)} ] || ln -s ${q2(`${top}/${rel}`)} ${q2(`${dir}/${rel}`)}; }`, `linking ${rel}`);
105009
- }
105066
+ await linkDependencyFolders(shell, top, dir);
105010
105067
  return { top, dir };
105011
105068
  }
105012
105069
  async function removeTaskWorktree(shell, top, dir) {
@@ -105057,6 +105114,10 @@ function localPipelineDeps(d, job) {
105057
105114
  chown: () => "true",
105058
105115
  installDependencies: false,
105059
105116
  excludeFromDiff: ["**/node_modules"],
105117
+ // A check that already fails on the base revision (this repo's `lint`: eslint is not installed) is re-run there, so it is not blamed on the task.
105118
+ baseline: { prepare: async (bdir) => {
105119
+ if (created) await linkDependencyFolders(shell, created.top, bdir);
105120
+ } },
105060
105121
  basePatches: async () => {
105061
105122
  const res = await d.fetch(`${base}/base-patches`, { headers: auth, signal: d.signal });
105062
105123
  if (!res.ok) throw new Error(`base patches request failed (${res.status})`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spacecode",
3
- "version": "2.14.4",
3
+ "version": "2.14.5",
4
4
  "description": "SpaceCode - launch cloud dev environments with AI coding agents",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",