agentwheel 0.20.9 → 0.20.11

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/README.md CHANGED
@@ -427,6 +427,22 @@ apply journal that embeds and exactly correlates the missing manifest and graph
427
427
  discoverable for recovery. Legacy SSH state is also preserved and refused because the old records do
428
428
  not prove which endpoint owned it.
429
429
 
430
+ After reviewing `agentwheel ownership recovery-plan`, use `--recover-legacy-state` only for an
431
+ invalid local candidate whose historical files must remain preserved. The recovery plan ignores
432
+ that candidate when constructing the new stable state; it does not authorize runtime replacement.
433
+ Adopting matching unmanaged files still requires `--force-conflict`, while replacing differing files
434
+ still requires `--replace-conflict`. Review the resulting plan before applying the same flags:
435
+
436
+ ```bash
437
+ agentwheel plan --fleet example-fleet --agent lab-claude \
438
+ --recover-legacy-state --force-conflict --replace-conflict
439
+ agentwheel install --fleet example-fleet --agent lab-claude \
440
+ --recover-legacy-state --force-conflict --replace-conflict
441
+ ```
442
+
443
+ Once the stable manifest exists, normal status and planning use it while retaining the invalid
444
+ historical candidate for explicit later cleanup.
445
+
430
446
  ## Core Ideas
431
447
 
432
448
  **Three places, one direction:**
@@ -5,9 +5,9 @@ import {
5
5
  commitManifestMetadataJournal,
6
6
  recoverPendingApply,
7
7
  uninstall
8
- } from "./chunk-E7Z2YB2C.js";
9
- import "./chunk-SHPNLNBR.js";
10
- import "./chunk-7VPI5J5Y.js";
8
+ } from "./chunk-A44XYLUT.js";
9
+ import "./chunk-FP26KSBM.js";
10
+ import "./chunk-GE7F76AC.js";
11
11
  export {
12
12
  applyCombinedInstallPlan,
13
13
  applyInstallPlan,
@@ -24,11 +24,11 @@ import {
24
24
  rollbackCompletedOperations,
25
25
  sourceLockPath,
26
26
  writeApplyJournal
27
- } from "./chunk-SHPNLNBR.js";
27
+ } from "./chunk-FP26KSBM.js";
28
28
  import {
29
29
  pathExists,
30
30
  writeJsonAtomic
31
- } from "./chunk-7VPI5J5Y.js";
31
+ } from "./chunk-GE7F76AC.js";
32
32
 
33
33
  // src/install/apply.ts
34
34
  import { execFile } from "child_process";
@@ -2407,6 +2407,7 @@ export {
2407
2407
  assertOperationContained,
2408
2408
  MergeAdoptionMismatchError,
2409
2409
  assertExactMergeContribution,
2410
+ assertMergedSourceContribution,
2410
2411
  combineMergeRemovals,
2411
2412
  hasMergeRemovalContent,
2412
2413
  mergeRemovalForInstall,
@@ -4,7 +4,7 @@ import {
4
4
  hashPath,
5
5
  pathExists,
6
6
  writeJsonAtomic
7
- } from "./chunk-7VPI5J5Y.js";
7
+ } from "./chunk-GE7F76AC.js";
8
8
 
9
9
  // src/install/transaction.ts
10
10
  import { createHash as createHash6 } from "crypto";
@@ -2865,8 +2865,8 @@ async function recoverMutationRuntime(operationId, options = {}) {
2865
2865
  }
2866
2866
  mutation = GovernedMutation.activateExisting(receipt, baseline, lock);
2867
2867
  const [{ recoverPendingApply }, { readLinkedLocalApplyJournal: readLinkedLocalApplyJournal2, removeApplyJournal: removeApplyJournal2, localPathExists: localPathExists2 }] = await Promise.all([
2868
- import("./apply-JBULQGW5.js"),
2869
- import("./transaction-EPP7GHXD.js")
2868
+ import("./apply-ZGCJLZMZ.js"),
2869
+ import("./transaction-4KBNHDQX.js")
2870
2870
  ]);
2871
2871
  let missingReservation = false;
2872
2872
  for (const entry of pending) {
@@ -90,6 +90,7 @@ async function withFilesystemLock(lockPath, timeoutMs, fn, description = "cache"
90
90
  break;
91
91
  } catch (error) {
92
92
  if (!isAlreadyExists(error)) throw error;
93
+ if (await removeStaleFilesystemLock(lockPath)) continue;
93
94
  if (Date.now() - started > timeoutMs) {
94
95
  throw new Error(`Timed out waiting for ${description} lock at ${lockPath}`);
95
96
  }
@@ -102,6 +103,26 @@ async function withFilesystemLock(lockPath, timeoutMs, fn, description = "cache"
102
103
  await rm(lockPath, { recursive: true, force: true });
103
104
  }
104
105
  }
106
+ async function removeStaleFilesystemLock(lockPath) {
107
+ try {
108
+ const owner = JSON.parse(await readFile(join(lockPath, "owner.json"), "utf8"));
109
+ if (typeof owner.pid !== "number" || !Number.isSafeInteger(owner.pid) || owner.pid <= 0 || isProcessAlive(owner.pid)) return false;
110
+ const stalePath = `${lockPath}.stale-${process.pid}-${Date.now()}`;
111
+ await rename(lockPath, stalePath);
112
+ await rm(stalePath, { recursive: true, force: true });
113
+ return true;
114
+ } catch {
115
+ return false;
116
+ }
117
+ }
118
+ function isProcessAlive(pid) {
119
+ try {
120
+ process.kill(pid, 0);
121
+ return true;
122
+ } catch (error) {
123
+ return typeof error === "object" && error !== null && "code" in error && error.code !== "ESRCH";
124
+ }
125
+ }
105
126
  function isAlreadyExists(error) {
106
127
  return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
107
128
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  pathExists
4
- } from "./chunk-7VPI5J5Y.js";
4
+ } from "./chunk-GE7F76AC.js";
5
5
 
6
6
  // src/source/identify.ts
7
7
  import { homedir } from "os";
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  inferSourceDriverName,
4
4
  isExplicitSource
5
- } from "./chunk-EMDIG24I.js";
6
- import "./chunk-7VPI5J5Y.js";
5
+ } from "./chunk-U2GRG4UI.js";
6
+ import "./chunk-GE7F76AC.js";
7
7
  export {
8
8
  inferSourceDriverName,
9
9
  isExplicitSource