@devrouter/cli 0.6.2 → 0.6.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.
@@ -5589,7 +5589,7 @@ function retain(session, previous) {
5589
5589
 
5590
5590
  // src/core/reliability-operation-store.ts
5591
5591
  function installedCliVersion() {
5592
- return true ? "0.6.2" : "0.0.0-dev";
5592
+ return true ? "0.6.3" : "0.0.0-dev";
5593
5593
  }
5594
5594
  function compareCliVersions(left, right) {
5595
5595
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -7772,7 +7772,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs19.default.rea
7772
7772
  const config = parseRepoConfigSource(raw, configPath);
7773
7773
  const requiredVersion = config.devrouter?.version;
7774
7774
  if (requiredVersion && !hasWarnedVersionMismatch) {
7775
- const cliVersion = true ? "0.6.2" : "0.0.0-dev";
7775
+ const cliVersion = true ? "0.6.3" : "0.0.0-dev";
7776
7776
  if (cliVersion !== "0.0.0-dev" && compareSemver2(requiredVersion, cliVersion) > 0) {
7777
7777
  hasWarnedVersionMismatch = true;
7778
7778
  process.stderr.write(
@@ -11776,9 +11776,9 @@ function createFreshBootstrap(options) {
11776
11776
  return {
11777
11777
  prepare(providerId, network) {
11778
11778
  assertFreshBootstrapRequest(options.identity, { initializeNew: true });
11779
- if (requireReadyDevsyAgent().version !== "1.19.0")
11779
+ if (!["1.19.0", "1.24.0"].includes(requireReadyDevsyAgent().version))
11780
11780
  throw new Error(
11781
- "Fresh bootstrap is qualified for Devsy 1.19.0; ordinary startup is unchanged."
11781
+ "Fresh bootstrap is qualified for Devsy 1.19.0 or 1.24.0; ordinary startup is unchanged."
11782
11782
  );
11783
11783
  const declaration = loadRepoConfig(repoPath).managedRuntime?.devcontainer.freshBootstrap;
11784
11784
  if (!declaration) throw new Error("Fresh-bootstrap declaration disappeared.");
@@ -14105,7 +14105,11 @@ function reliabilityRecovery(reason2, repoPath, variant) {
14105
14105
  switch (reason2) {
14106
14106
  case "stop-incomplete":
14107
14107
  case "operation-unknown":
14108
- return [`Run: devrouter stop ${checkout}`, `Run: devrouter ensure ${checkout} --repair`];
14108
+ return [
14109
+ `Run: devrouter stop ${checkout}`,
14110
+ "Verify the repository startup hooks preserve retained data and startup is authorized before continuing.",
14111
+ `Run: devrouter ensure ${checkout}${variantOption}`
14112
+ ];
14109
14113
  case "start-refused":
14110
14114
  return [
14111
14115
  `Run: devrouter doctor --repo ${checkout} to read the refused fixed host-port claim and its holder`,
@@ -16319,6 +16323,8 @@ function recoverUnattachedNetworkReservation(repoPath, managedRuntime) {
16319
16323
  var DEVCONTAINER_OVERLAY = "docker-compose.devrouter.yml";
16320
16324
  var DEFAULT_READINESS_TIMEOUT_MS = 12e4;
16321
16325
  var POLL_INTERVAL_MS = 1e3;
16326
+ var WorkspaceEnsureRefusalError = class extends Error {
16327
+ };
16322
16328
  function assertOverlay(container, repoPath) {
16323
16329
  const workingDir = container.labels["com.docker.compose.project.working_dir"];
16324
16330
  if (!workingDir || !sameWorkspacePath(workingDir, import_node_path42.default.join(repoPath, ".devcontainer"))) {
@@ -18016,6 +18022,17 @@ async function workspaceEnsure(requestedRepoPath, options = {}) {
18016
18022
  return withLifecycleOperationLock(repoPath, async () => {
18017
18023
  preflightRuntimeVariant(repoPath, options);
18018
18024
  const preparationConfig = loadRepoConfig(repoPath);
18025
+ if (options.repair) {
18026
+ const workspace2 = linked ? readPersistedWorkspace(repoPath) : void 0;
18027
+ if (linked && !workspace2) throw new Error("Repair requires an existing workspace identity.");
18028
+ const retained2 = readManagedRuntimeState(repoPath, workspace2);
18029
+ if (retained2?.status !== "degraded") {
18030
+ const checkout = `'${repoPath.replaceAll("'", "'\\''")}'`;
18031
+ throw new WorkspaceEnsureRefusalError(
18032
+ `Repair requires a persisted degraded managed runtime. Inspect this checkout with: devrouter doctor --repo ${checkout} --json. Ordinary ensure may run repository startup hooks; verify their preservation contract before startup.`
18033
+ );
18034
+ }
18035
+ }
18019
18036
  if (!options.repair)
18020
18037
  recoverUnattachedNetworkReservation(repoPath, Boolean(preparationConfig.managedRuntime));
18021
18038
  assertRetainedNetworkConfiguration({
@@ -18432,6 +18449,19 @@ function recordLifecycleUnknown(result) {
18432
18449
  if (result !== void 0) record5.result = result;
18433
18450
  });
18434
18451
  }
18452
+ function recordLifecycleRefusal(result) {
18453
+ const request = activeWorker;
18454
+ if (request?.kind !== "ensure") return;
18455
+ updateReliabilityOperation(request.identity, (record5) => {
18456
+ if (!matchesFence(record5, request.fence) || record5.worker?.id !== request.workerId || record5.state.operation?.id !== request.operationId || record5.state.operation.status !== "RUNNING")
18457
+ return;
18458
+ stepRecord(
18459
+ record5,
18460
+ request.options.repair && !cancelled && process.connected ? { ...request.fence, type: "completion", operationId: request.operationId, exitCode: 1 } : { ...request.fence, type: "interrupted", operationId: request.operationId }
18461
+ );
18462
+ record5.result = result;
18463
+ });
18464
+ }
18435
18465
  function proveLifecycleStopped() {
18436
18466
  const request = activeWorker;
18437
18467
  if (request?.kind !== "stop")
@@ -19092,6 +19122,7 @@ process.once("message", async (message) => {
19092
19122
  message: error instanceof Error ? error.message : String(error)
19093
19123
  };
19094
19124
  if (error instanceof ExecutionOutcomeError) recordLifecycleOutcome(error.outcome, failure);
19125
+ else if (error instanceof WorkspaceEnsureRefusalError) recordLifecycleRefusal(failure);
19095
19126
  else recordLifecycleUnknown(failure);
19096
19127
  } catch {
19097
19128
  }
package/dist/devrouter.js CHANGED
@@ -4898,7 +4898,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs8.default.read
4898
4898
  const config = parseRepoConfigSource(raw, configPath);
4899
4899
  const requiredVersion = config.devrouter?.version;
4900
4900
  if (requiredVersion && !hasWarnedVersionMismatch) {
4901
- const cliVersion = true ? "0.6.2" : "0.0.0-dev";
4901
+ const cliVersion = true ? "0.6.3" : "0.0.0-dev";
4902
4902
  if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
4903
4903
  hasWarnedVersionMismatch = true;
4904
4904
  process.stderr.write(
@@ -7171,7 +7171,7 @@ var init_reliability_contract = __esm({
7171
7171
 
7172
7172
  // src/core/reliability-operation-store.ts
7173
7173
  function installedCliVersion() {
7174
- return true ? "0.6.2" : "0.0.0-dev";
7174
+ return true ? "0.6.3" : "0.0.0-dev";
7175
7175
  }
7176
7176
  function compareCliVersions(left, right) {
7177
7177
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -17631,7 +17631,11 @@ function reliabilityRecovery(reason2, repoPath, variant) {
17631
17631
  switch (reason2) {
17632
17632
  case "stop-incomplete":
17633
17633
  case "operation-unknown":
17634
- return [`Run: devrouter stop ${checkout}`, `Run: devrouter ensure ${checkout} --repair`];
17634
+ return [
17635
+ `Run: devrouter stop ${checkout}`,
17636
+ "Verify the repository startup hooks preserve retained data and startup is authorized before continuing.",
17637
+ `Run: devrouter ensure ${checkout}${variantOption}`
17638
+ ];
17635
17639
  case "start-refused":
17636
17640
  return [
17637
17641
  `Run: devrouter doctor --repo ${checkout} to read the refused fixed host-port claim and its holder`,
@@ -23495,7 +23499,7 @@ function buildOnboardingPrompt(options = {}) {
23495
23499
  "- Managed process reuse fingerprints command argv, workspace identity, and the exact adapter snapshot. Variant and current host-port identity always compose with an explicit --fingerprint. If a non-secret runtime value also affects reuse, set `DEVROUTER_PROCESS_FINGERPRINT_ENV` to its comma-separated environment names; secret-like names are rejected and raw values are never persisted.",
23496
23500
  "- Managed adapters may use devrouter-process ensure --prepare-command <command> for synchronous dependency preparation under the process lock before app launch. Unchanged owned processes skip preparation; it participates in default fingerprints and must not daemonize or detach.",
23497
23501
  "- Host-generated Compose inputs may use managedRuntime.devcontainer.prepareCommand as literal argv. Ensure runs it once from the checkout root before Compose inspection, with a 60-second bound and no implicit shell. Keep .devrouter.yml unchanged. Diagnostics never run it; changed warm mounts require separate verification.",
23498
- "- Explicit first initialization: managedRuntime.devcontainer.freshBootstrap declares literal command argv, dataVolumes and optional sharedCaches keys. ensure <new-checkout> --initialize-new requires qualified Devsy 1.19.0, new local data volumes and repository-owned database identity/emptiness checks. A durable attempt prevents replay after failure, unknown completion, cancellation, stop, replacement or settlement. Ordinary hooks must preserve data. Consult docs/DEVCONTAINER.md for context and mount prerequisites; never clear the attempt fence or infer reset authority.",
23502
+ "- Explicit first initialization: managedRuntime.devcontainer.freshBootstrap declares literal command argv, dataVolumes and optional sharedCaches keys. ensure <new-checkout> --initialize-new requires qualified Devsy 1.19.0 or 1.24.0, new local data volumes and repository-owned database identity/emptiness checks. A durable attempt prevents replay after failure, unknown completion, cancellation, stop, replacement or settlement. Ordinary hooks must preserve data. Consult docs/DEVCONTAINER.md for context and mount prerequisites; never clear the attempt fence or infer reset authority.",
23499
23503
  "- Managed Devsy startup on supported local Unix Docker endpoints captures exact stop ownership before application readiness. With that baseline, canonical stop tolerates changed or missing repository configuration and preserves containers and volumes. Older records without a baseline retain configuration-dependent stop; installing a new CLI does not establish historical ownership. Invalid or changed ownership never falls back. Do not replay destructive bootstrap hooks to obtain a baseline.",
23500
23504
  "- Owner status is `present`, `missing`, `locked`, or `conflict`. Dirty or locked full down fails before side effects. `workspace gc` is a dry run; only `--yes` deletes exact eligible missing resources and records, never Git worktrees, branches, or prune state.",
23501
23505
  "- `devrouter workspace cleanup --repo . --inactive-for 30d --check-merged --json` is report-only and never mutates the workspace runtime, routes, ownership, Git, Docker, applications, worktrees, or branches. It reports ownership, workspace runtime registration, runtime state (`running|stopped|busy|not-found|absent|unknown`), checkout, advisory activity, route, and integration evidence. Local DevPod/Devsy list/status checks always run; `--check-merged` alone enables read-only origin and matching GitHub/GitLab checks. Treat `not-found` as stale runtime after Docker pruning; busy, unavailable, or conflicting evidence suppresses destructive suggestions. Explicit `gc`/`down` can remove exact stale registration only after expected-ID `NotFound` proof and ownership revalidation. Runtime `lastUsed` remains advisory.",
@@ -25652,7 +25656,7 @@ function probeInstalledCliVersion(executable) {
25652
25656
  }
25653
25657
  function buildCliPathCheck(options = {}) {
25654
25658
  const id5 = "global.cli-path";
25655
- const runningVersion = options.runningVersion ?? (true ? "0.6.2" : "0.0.0-dev");
25659
+ const runningVersion = options.runningVersion ?? (true ? "0.6.3" : "0.0.0-dev");
25656
25660
  if (runningVersion === "0.0.0-dev") {
25657
25661
  return {
25658
25662
  id: id5,
@@ -26550,7 +26554,7 @@ async function buildDoctorReport(options = {}) {
26550
26554
  suggestion: `Remedy ${expansionNotice.remedy.code}: set a named default profile other than '${expansionNotice.profile}'${remedyCandidates}.`
26551
26555
  });
26552
26556
  }
26553
- const cliVersion = true ? "0.6.2" : "0.0.0-dev";
26557
+ const cliVersion = true ? "0.6.3" : "0.0.0-dev";
26554
26558
  const configVersion = config.devrouter?.version;
26555
26559
  const installedKnown = cliVersion !== "0.0.0-dev";
26556
26560
  const versionComparison = installedKnown && configVersion ? compareSemver(configVersion, cliVersion) : void 0;
@@ -42227,7 +42231,7 @@ var init_version = __esm({
42227
42231
 
42228
42232
  // src/cli.ts
42229
42233
  var import_commander = require("commander");
42230
- var CLI_VERSION = true ? "0.6.2" : "0.0.0-dev";
42234
+ var CLI_VERSION = true ? "0.6.3" : "0.0.0-dev";
42231
42235
  var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
42232
42236
  function withErrorHandling(action2) {
42233
42237
  return async (...args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrouter/cli",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
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,51 @@
1
+ # Upgrade to devrouter 0.6.3
2
+
3
+ This patch qualifies explicit fresh managed initialization on Devsy 1.24.0 in
4
+ addition to 1.19.0. The operation and its data, context and ownership guarantees
5
+ are unchanged. Early ineligible repair now refuses before repository preparation
6
+ and records a known failure; cancellation and uncertain completion stay distinct.
7
+ Use ordinary ensure for startup and inspect exact-checkout diagnostics when an
8
+ explicit recorded-profile repair is ineligible. Qualify preserving source hooks
9
+ before starting a retained environment. Ordinary startup retains its existing provider support.
10
+
11
+ ## Task
12
+
13
+ Within an authorized consumer adaptation, install the published CLI, verify its
14
+ executable/version, bump `devrouter.version` in `.devrouter.yml`, and refresh
15
+ existing guidance with `devrouter repo agents`. Explicitly managed controllers
16
+ must use the matching initialization protocol. No configuration migration is
17
+ required for ordinary startup.
18
+
19
+ Before adopting a changed Devsy release, follow the explicit agent preparation
20
+ in `docs/GETTING_STARTED.md`: `devrouter setup --yes --workspace-runtime devsy`.
21
+ That machine setup needs its own authority. A host-governed readiness result
22
+ without a verified matching agent does not prove replacement can acquire one.
23
+ The 1.24.0 replacement qualification uses the matching verified Linux agent;
24
+ ordinary lifecycle calls never substitute an unverified inherited binary.
25
+
26
+ For a new disposable checkout, follow the current `docs/DEVCONTAINER.md`
27
+ `freshBootstrap` contract and request `ensure <path> --initialize-new` only
28
+ within existing consumer authority. Qualify the complete selected composition,
29
+ new local data volumes, explicit shared caches and repository-owned database
30
+ identity/emptiness checks. Unqualified provider versions and contexts refuse.
31
+
32
+ The durable attempt is consumed before provider creation. Failure, cancellation,
33
+ unknown completion, stop, replacement, registration loss and settlement never
34
+ rearm it. Preserve partial data and use supported preserving recovery. Never
35
+ clear the attempt or treat this operation as an existing-environment reset.
36
+
37
+ ## Validation
38
+
39
+ 1. Run the consumer's static configuration and bootstrap checks for actual edits.
40
+ 2. With runtime authority, initialize a new disposable fixture on the exact
41
+ qualified provider version; verify actual work, retained synthetic data
42
+ through preserving stop/resume, and refusal of a repeated initialization.
43
+ 3. Check failure/cancellation retention and replay refusal. End with canonical
44
+ `devrouter stop <path>` and verify stopped provider state and zero exact routes
45
+ unless the user explicitly retains the environment.
46
+
47
+ ## Report
48
+
49
+ Report exact source/package/executable and provider identities, actual checks,
50
+ retained-data evidence, remaining consumer prerequisites and final runtime state.
51
+ A compatible release or installation alone does not prove consumer recovery.