harnessed 4.1.2 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -186,6 +186,20 @@ var init_schemaVersion = __esm({
186
186
  ]);
187
187
  }
188
188
  });
189
+ async function writeFileAtomic(path, data) {
190
+ const tmp = `${path}.tmp`;
191
+ await writeFile(tmp, data, "utf8");
192
+ await rename(tmp, path);
193
+ }
194
+ function writeFileSyncAtomic(path, data) {
195
+ const tmp = `${path}.tmp`;
196
+ writeFileSync(tmp, data, "utf8");
197
+ renameSync(tmp, path);
198
+ }
199
+ var init_atomicWrite = __esm({
200
+ "src/checkpoint/atomicWrite.ts"() {
201
+ }
202
+ });
189
203
  var CheckpointStatus, CheckpointV1;
190
204
  var init_checkpoint_v1 = __esm({
191
205
  "src/checkpoint/schema/checkpoint.v1.ts"() {
@@ -305,7 +319,7 @@ async function writeCurrentWorkflow(s) {
305
319
  const path = statePath();
306
320
  await mkdir(dirname(path), { recursive: true });
307
321
  await withLock(async () => {
308
- await writeFile(path, JSON.stringify(s, null, 2), "utf8");
322
+ await writeFileAtomic(path, JSON.stringify(s, null, 2));
309
323
  });
310
324
  }
311
325
  async function activate(phase, checkpointPath = null) {
@@ -332,6 +346,7 @@ var init_state = __esm({
332
346
  "src/checkpoint/state.ts"() {
333
347
  init_harnessedRoot();
334
348
  init_schemaVersion();
349
+ init_atomicWrite();
335
350
  init_schema();
336
351
  WorkflowStateError = class extends Error {
337
352
  constructor(message) {
@@ -375,13 +390,14 @@ function writeCheckpoint(c, customPath) {
375
390
  const enforced = enforceBudget(c);
376
391
  const path = join(harnessedSubdir("checkpoints"), `${enforced.phase}.json`);
377
392
  mkdirSync(dirname(path), { recursive: true });
378
- writeFileSync(path, JSON.stringify(enforced, null, 2), "utf8");
393
+ writeFileSyncAtomic(path, JSON.stringify(enforced, null, 2));
379
394
  return path;
380
395
  }
381
396
  var BUDGET_TOKEN, CheckpointTooLargeError, CheckpointWriteError;
382
397
  var init_template = __esm({
383
398
  "src/checkpoint/template.ts"() {
384
399
  init_harnessedRoot();
400
+ init_atomicWrite();
385
401
  init_schema();
386
402
  BUDGET_TOKEN = 1e3;
387
403
  CheckpointTooLargeError = class extends Error {
@@ -1271,7 +1287,7 @@ var init_auto_install = __esm({
1271
1287
 
1272
1288
  // package.json
1273
1289
  var package_default = {
1274
- version: "4.1.2"};
1290
+ version: "4.1.3"};
1275
1291
 
1276
1292
  // src/manifest/errors.ts
1277
1293
  function instancePathToKeyPath(instancePath) {
@@ -2808,7 +2824,7 @@ ${t("gc.invalid_duration.fix")}`
2808
2824
  return;
2809
2825
  }
2810
2826
  const cutoff = Date.now() - olderMs;
2811
- const kept = new Set(dirs.slice(-keepLast));
2827
+ const kept = new Set(keepLast > 0 ? dirs.slice(-keepLast) : []);
2812
2828
  const candidates = [];
2813
2829
  for (const ts of dirs) {
2814
2830
  if (kept.has(ts)) continue;
@@ -6176,21 +6192,21 @@ ${t("rollback.metadata_unreadable.fix")}`
6176
6192
  process.exit(1);
6177
6193
  return;
6178
6194
  }
6179
- for (const entry of [...meta.files].reverse()) {
6195
+ const ordered = [...meta.files].reverse();
6196
+ const planned = [];
6197
+ for (const entry of ordered) {
6180
6198
  if (entry.backup === "") {
6181
- try {
6182
- await unlink(entry.target);
6183
- } catch (err2) {
6184
- const code = err2.code;
6185
- if (code !== "ENOENT") {
6186
- console.error(`error: cannot unlink ${entry.target}: ${err2.message}`);
6187
- process.exit(1);
6188
- return;
6189
- }
6190
- }
6199
+ planned.push({ target: entry.target, action: "unlink" });
6191
6200
  continue;
6192
6201
  }
6193
- const buf = await readFile(entry.backup);
6202
+ let buf;
6203
+ try {
6204
+ buf = await readFile(entry.backup);
6205
+ } catch (err2) {
6206
+ console.error(`error: cannot read backup ${entry.backup}: ${err2.message}`);
6207
+ process.exit(1);
6208
+ return;
6209
+ }
6194
6210
  const sha1 = createHash("sha1").update(buf).digest("hex");
6195
6211
  if (sha1 !== entry.sha1) {
6196
6212
  console.error(
@@ -6203,7 +6219,23 @@ ${t("rollback.metadata_unreadable.fix")}`
6203
6219
  process.exit(1);
6204
6220
  return;
6205
6221
  }
6206
- await writeFile(entry.target, normalizeEol(buf, entry.eol));
6222
+ planned.push({ target: entry.target, action: "write", data: normalizeEol(buf, entry.eol) });
6223
+ }
6224
+ for (const op of planned) {
6225
+ if (op.action === "unlink") {
6226
+ try {
6227
+ await unlink(op.target);
6228
+ } catch (err2) {
6229
+ const code = err2.code;
6230
+ if (code !== "ENOENT") {
6231
+ console.error(`error: cannot unlink ${op.target}: ${err2.message}`);
6232
+ process.exit(1);
6233
+ return;
6234
+ }
6235
+ }
6236
+ } else {
6237
+ await writeFile(op.target, op.data);
6238
+ }
6207
6239
  }
6208
6240
  console.log(t("rollback.restored", { count: meta.files.length, timestamp }));
6209
6241
  });