@devrouter/cli 0.0.63 → 0.0.64

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.
@@ -240,7 +240,9 @@ function tryReclaimStaleLock(lockPath, staleLinkPath, livenessCache) {
240
240
  function acquireFileLock(lockPath, options) {
241
241
  const processBirth = processBirthIdentity(process.pid);
242
242
  if (!processBirth) {
243
- throw new Error(`could not determine process identity for ${options.activity} lock`);
243
+ throw new Error(
244
+ `could not determine process identity for ${options.activity} lock: process inspection may be unavailable or sandbox-denied; run the canonical command in a permitted host context`
245
+ );
244
246
  }
245
247
  const ownerId = (0, import_node_crypto2.randomUUID)();
246
248
  const owner = `${process.pid}:${Buffer.from(processBirth).toString("base64url")}:${ownerId}`;
@@ -4705,7 +4707,7 @@ function loadRepoConfig(repoPath, read = (file) => import_node_fs14.default.read
4705
4707
  const config = parseConfig(parsed ?? {}, configPath);
4706
4708
  const requiredVersion = config.devrouter?.version;
4707
4709
  if (requiredVersion && !hasWarnedVersionMismatch) {
4708
- const cliVersion = true ? "0.0.63" : "0.0.0-dev";
4710
+ const cliVersion = true ? "0.0.64" : "0.0.0-dev";
4709
4711
  if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
4710
4712
  hasWarnedVersionMismatch = true;
4711
4713
  process.stderr.write(
@@ -9442,7 +9444,7 @@ var cancelled = false;
9442
9444
  var lockHeld = false;
9443
9445
  var stopProjects = [];
9444
9446
  var stopBaselineState;
9445
- var BUSY_EXEC_WAIT_MS = 30 * 60 * 1e3;
9447
+ var BUSY_LIFECYCLE_WAIT_MS = 30 * 60 * 1e3;
9446
9448
  function matchesFence(record4, fence) {
9447
9449
  return Object.entries(reliabilityFence(record4.state)).every(
9448
9450
  ([key, value]) => value === fence[key]
package/dist/devrouter.js CHANGED
@@ -671,7 +671,9 @@ function tryReclaimStaleLock(lockPath, staleLinkPath, livenessCache) {
671
671
  function acquireFileLock(lockPath, options) {
672
672
  const processBirth = processBirthIdentity(process.pid);
673
673
  if (!processBirth) {
674
- throw new Error(`could not determine process identity for ${options.activity} lock`);
674
+ throw new Error(
675
+ `could not determine process identity for ${options.activity} lock: process inspection may be unavailable or sandbox-denied; run the canonical command in a permitted host context`
676
+ );
675
677
  }
676
678
  const ownerId = (0, import_node_crypto2.randomUUID)();
677
679
  const owner = `${process.pid}:${Buffer.from(processBirth).toString("base64url")}:${ownerId}`;
@@ -2450,7 +2452,7 @@ function loadRepoConfig(repoPath, read = (file) => import_node_fs6.default.readF
2450
2452
  const config = parseConfig(parsed ?? {}, configPath);
2451
2453
  const requiredVersion = config.devrouter?.version;
2452
2454
  if (requiredVersion && !hasWarnedVersionMismatch) {
2453
- const cliVersion = true ? "0.0.63" : "0.0.0-dev";
2455
+ const cliVersion = true ? "0.0.64" : "0.0.0-dev";
2454
2456
  if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
2455
2457
  hasWarnedVersionMismatch = true;
2456
2458
  process.stderr.write(
@@ -7169,7 +7171,7 @@ function buildOnboardingPrompt(options = {}) {
7169
7171
  "- TLS: namespaced hosts (`web.<ws>.localhost`) are not covered by the `*.localhost` wildcard; devrouter auto-extends the mkcert cert SANs for active hosts when TLS is enabled.",
7170
7172
  "- Lifecycle: after one-time setup, use `devrouter ensure .` for both primary and linked checkouts; never branch on checkout kind or use live verify as startup. Managed consumer images contain no devrouter package/helper: ensure delivers its matching helper at runtime and invokes an exact captured snapshot of the repository-owned post-start adapter. Keep `.devrouter.yml` as the only consumer-side version pin. Use `devrouter stop .` for a non-destructive pause, `devrouter stop . --delete` only for explicit exact-owner cleanup without removing the checkout, and `devrouter exec . -- <command...>` for container commands. Never substitute raw DevPod/Devsy mutations; they bypass the machine-global ownership lock, which serializes provider mutations in a fair arrival-order queue and lets contenders wait up to thirty minutes with throttled stderr progress before failing with the queue position or holder PID and true durations. `workspace up` creates linked worktrees; destructive worktree removal and GC remain ledger-scoped.",
7171
7173
  "- After a drained interrupted ensure, manual exec can use an exactly proven retained Devsy runtime with the plain local Docker command. Revalidate identity for each tooling command until later preparation reconciles startup; preserve configuration, data and interrupted history. This does not repair absent stop baselines or provide OOM protection.",
7172
- "- Busy exec waits up to thirty minutes for a positively identified active lifecycle worker on the same checkout, with stderr progress. Do not stop healthy work to make room. Commands stay serial; timeout or cancellation before admission leaves prior work untouched. A lifecycle fence change cancels admission, and uncertain execution is never replayed.",
7174
+ "- Busy ensure and exec wait up to thirty minutes for a positively identified active lifecycle worker on the same checkout, with stderr progress. Do not stop healthy work to make room. Commands stay serial; timeout or cancellation before admission leaves prior work untouched. A lifecycle fence change cancels admission, and uncertain execution is never replayed.",
7173
7175
  "- Ensure reconciles interrupted or never-dispatched ensure after positive worker drainage. Unknown arbitrary exec never replays; use explicit stop to reconcile that uncertainty. Preserve journals and generated configuration if evidence is unavailable. This does not prevent OOM or activate capacity-managed recovery.",
7174
7176
  "- Devsy agent readiness: run `devrouter setup --yes --workspace-runtime devsy` once so Devrouter acquires and verifies the pinned agent in its own machine cache. `doctor` reports `ready`, `missing`, `stale`, or `invalid` without network access, and `ensure` fails before the provider queue when readiness is not `ready`. An explicit `DEVSY_AGENT_BINARY` remains authoritative and must match a pinned official asset.",
7175
7177
  "- A managed adapter plus `postCreateCommand` requires `waitFor` exactly `postCreateCommand` or `postStartCommand`; managed selective config preserves lifecycle fields and changes only `runServices`.",
@@ -12158,7 +12160,7 @@ async function buildDoctorReport(options = {}) {
12158
12160
  const config = runtimeConfig.config;
12159
12161
  loadedConfig = config;
12160
12162
  loadedWorkspace = runtimeConfig.workspace;
12161
- const cliVersion = true ? "0.0.63" : "0.0.0-dev";
12163
+ const cliVersion = true ? "0.0.64" : "0.0.0-dev";
12162
12164
  const configVersion = config.devrouter?.version;
12163
12165
  if (configVersion && cliVersion !== "0.0.0-dev" && compareSemver(configVersion, cliVersion) > 0) {
12164
12166
  addCheck(checks, {
@@ -14050,9 +14052,9 @@ function reconcileDrained(record4) {
14050
14052
  record4.worker = null;
14051
14053
  }
14052
14054
  }
14053
- function reportBusyExecWait(operationId, waitedMs) {
14055
+ function reportBusyLifecycleWait(kind, operationId, waitedMs) {
14054
14056
  process.stderr.write(
14055
- `Lifecycle exec ${operationId} is waiting for the existing worker (${Math.ceil(waitedMs / 1e3)}s).
14057
+ `Lifecycle ${kind} ${operationId} is waiting for the existing worker (${Math.ceil(waitedMs / 1e3)}s).
14056
14058
  `
14057
14059
  );
14058
14060
  }
@@ -14091,16 +14093,16 @@ async function superviseLifecycle(kind, repoPath, options = {}, command) {
14091
14093
  }
14092
14094
  const initial = readReliabilityOperation(identity2) ?? updateReliabilityOperation(identity2, (record4) => record4);
14093
14095
  const expectedFence = reliabilityFence(initial.state);
14094
- const deadline = Date.now() + BUSY_EXEC_WAIT_MS;
14096
+ const deadline = Date.now() + BUSY_LIFECYCLE_WAIT_MS;
14095
14097
  const cancellation = { requested: false };
14096
14098
  const removeSignals = installLifecycleWaitSignals(cancellation);
14097
14099
  let lastProgress = -Infinity;
14098
14100
  const assertWaiting = () => {
14099
14101
  if (cancellation.requested)
14100
- throw new Error(`Lifecycle exec ${ids.operationId} cancelled before dispatch.`);
14102
+ throw new Error(`Lifecycle ${kind} ${ids.operationId} cancelled before dispatch.`);
14101
14103
  if (Date.now() >= deadline)
14102
14104
  throw new Error(
14103
- `Lifecycle exec ${ids.operationId} admission timed out; command was not launched.`
14105
+ `Lifecycle ${kind} ${ids.operationId} admission timed out; command was not launched.`
14104
14106
  );
14105
14107
  };
14106
14108
  try {
@@ -14126,15 +14128,17 @@ async function superviseLifecycle(kind, repoPath, options = {}, command) {
14126
14128
  throw new Error(
14127
14129
  "Existing lifecycle worker identity or completion is uncertain; preserve its evidence."
14128
14130
  );
14129
- if (kind !== "exec")
14130
- throw new Error("A lifecycle worker is active; wait for its completion before ensure.");
14131
14131
  const now = Date.now();
14132
- if (now - lastProgress >= BUSY_EXEC_PROGRESS_MS) {
14133
- reportBusyExecWait(ids.operationId, now - (deadline - BUSY_EXEC_WAIT_MS));
14132
+ if (now - lastProgress >= BUSY_LIFECYCLE_PROGRESS_MS) {
14133
+ reportBusyLifecycleWait(
14134
+ kind,
14135
+ ids.operationId,
14136
+ now - (deadline - BUSY_LIFECYCLE_WAIT_MS)
14137
+ );
14134
14138
  lastProgress = now;
14135
14139
  }
14136
14140
  await new Promise(
14137
- (resolve) => setTimeout(resolve, Math.min(BUSY_EXEC_POLL_MS, deadline - now))
14141
+ (resolve) => setTimeout(resolve, Math.min(BUSY_LIFECYCLE_POLL_MS, deadline - now))
14138
14142
  );
14139
14143
  continue;
14140
14144
  }
@@ -14176,16 +14180,16 @@ async function superviseLifecycle(kind, repoPath, options = {}, command) {
14176
14180
  assertWaiting
14177
14181
  );
14178
14182
  } catch (error) {
14179
- if (!(error instanceof LifecycleWorkerAdmissionBusyError) || kind !== "exec") throw error;
14183
+ if (!(error instanceof LifecycleWorkerAdmissionBusyError)) throw error;
14180
14184
  assertWaiting();
14181
- await new Promise((resolve) => setTimeout(resolve, BUSY_EXEC_POLL_MS));
14185
+ await new Promise((resolve) => setTimeout(resolve, BUSY_LIFECYCLE_POLL_MS));
14182
14186
  }
14183
14187
  }
14184
14188
  } finally {
14185
14189
  removeSignals();
14186
14190
  }
14187
14191
  }
14188
- var import_node_path41, activeWorker, lockHeld, BUSY_EXEC_WAIT_MS, BUSY_EXEC_POLL_MS, BUSY_EXEC_PROGRESS_MS;
14192
+ var import_node_path41, activeWorker, lockHeld, BUSY_LIFECYCLE_WAIT_MS, BUSY_LIFECYCLE_POLL_MS, BUSY_LIFECYCLE_PROGRESS_MS;
14189
14193
  var init_reliability_lifecycle = __esm({
14190
14194
  "src/core/reliability-lifecycle.ts"() {
14191
14195
  "use strict";
@@ -14208,9 +14212,9 @@ var init_reliability_lifecycle = __esm({
14208
14212
  init_workspace_runtime();
14209
14213
  init_reliability_context();
14210
14214
  lockHeld = false;
14211
- BUSY_EXEC_WAIT_MS = 30 * 60 * 1e3;
14212
- BUSY_EXEC_POLL_MS = 250;
14213
- BUSY_EXEC_PROGRESS_MS = 1e4;
14215
+ BUSY_LIFECYCLE_WAIT_MS = 30 * 60 * 1e3;
14216
+ BUSY_LIFECYCLE_POLL_MS = 250;
14217
+ BUSY_LIFECYCLE_PROGRESS_MS = 1e4;
14214
14218
  }
14215
14219
  });
14216
14220
 
@@ -18902,7 +18906,7 @@ var init_version = __esm({
18902
18906
 
18903
18907
  // src/cli.ts
18904
18908
  var import_commander = require("commander");
18905
- var CLI_VERSION = true ? "0.0.63" : "0.0.0-dev";
18909
+ var CLI_VERSION = true ? "0.0.64" : "0.0.0-dev";
18906
18910
  var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
18907
18911
  function withErrorHandling(action2) {
18908
18912
  return async (...args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrouter/cli",
3
- "version": "0.0.63",
3
+ "version": "0.0.64",
4
4
  "description": "Local dev routing CLI with shared Traefik reverse proxy",
5
5
  "author": "Roland Schlaefli",
6
6
  "homepage": "https://github.com/rschlaefli/devrouter#readme",
@@ -0,0 +1,34 @@
1
+ # Upgrade to devrouter 0.0.64
2
+
3
+ This patch lets canonical ensure wait for healthy lifecycle work on the same
4
+ checkout and clarifies process-inspection permission failures.
5
+
6
+ ## Task
7
+
8
+ Install the published patch and update `.devrouter.yml` devrouter.version to
9
+ 0.0.64. No schema migration or runtime restart is required. Refresh distributed
10
+ agent guidance through the existing repository workflow.
11
+
12
+ ## Validation
13
+
14
+ Confirm the installed version. On an authorized runtime, invoke ensure while a
15
+ bounded tooling command is active. Verify waiting, preserved tooling exit status
16
+ and successful ensure after completion when the lifecycle fence stays unchanged.
17
+ Verify the exact runtime stops with zero routes and retained data when finished.
18
+ A waiting exec refreshes runtime proof before admission; ensure establishes its
19
+ runtime inside the worker. Stop or another fence change cancels the waiting
20
+ invocation. Never replay an uncertain command.
21
+
22
+ ## Limits
23
+
24
+ Waiting is bounded to thirty minutes, with no FIFO guarantee or persistent queue.
25
+ Permission diagnostics direct agents to a permitted host context; they do not
26
+ repair operating-system permissions or authorize lock removal. This patch does
27
+ not solve network exhaustion, activate capacity admission, or claim complete OOM
28
+ protection or autonomous agent recovery.
29
+
30
+ ## Report
31
+
32
+ Report installed version, exact checkout/provider, command outcomes, retained
33
+ runtime/data evidence and final runtime/route state. Separate published source,
34
+ synthetic checks and live consumer acceptance.