@devrouter/cli 0.6.7 → 0.6.8

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.
@@ -5592,7 +5592,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs16.default.rea
5592
5592
  const config = parseRepoConfigSource(raw, configPath);
5593
5593
  const requiredVersion = config.devrouter?.version;
5594
5594
  if (requiredVersion && !hasWarnedVersionMismatch) {
5595
- const cliVersion = true ? "0.6.7" : "0.0.0-dev";
5595
+ const cliVersion = true ? "0.6.8" : "0.0.0-dev";
5596
5596
  if (cliVersion !== "0.0.0-dev" && compareSemver2(requiredVersion, cliVersion) > 0) {
5597
5597
  hasWarnedVersionMismatch = true;
5598
5598
  process.stderr.write(
@@ -7979,7 +7979,7 @@ function advanceAppReplacementAttempt(identity2, authority, stage, newPrimaryId)
7979
7979
  });
7980
7980
  }
7981
7981
  function installedCliVersion() {
7982
- return true ? "0.6.7" : "0.0.0-dev";
7982
+ return true ? "0.6.8" : "0.0.0-dev";
7983
7983
  }
7984
7984
  function compareCliVersions(left, right) {
7985
7985
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -14468,7 +14468,9 @@ function reliabilityRecovery(reason2, repoPath, variant) {
14468
14468
  `Run: devrouter ensure ${checkout}${variantOption} (still queued until capacity frees up)`
14469
14469
  ];
14470
14470
  default:
14471
- return [];
14471
+ return [
14472
+ `Inspect: devrouter status --repo ${checkout} --json; wait for the current lifecycle owner to finish or cancel it before retrying.`
14473
+ ];
14472
14474
  }
14473
14475
  }
14474
14476
  function refusedManagedStart(result) {
@@ -14493,7 +14495,10 @@ function readReliabilityStatus(options) {
14493
14495
  workspace: options.workspace ?? null,
14494
14496
  provider
14495
14497
  });
14496
- } catch {
14498
+ } catch (error) {
14499
+ options.drift.push(
14500
+ error instanceof ReliabilityJournalError ? error.cause : "journal-unreadable"
14501
+ );
14497
14502
  return void 0;
14498
14503
  }
14499
14504
  if (!record5) return void 0;
@@ -14913,6 +14918,12 @@ function collectManagedRuntimeStatus(options) {
14913
14918
  if (inspection.activeProcesses.some((process2) => !desiredProcesses.includes(process2))) {
14914
14919
  drift.push("one or more active processes are outside the selected profile");
14915
14920
  }
14921
+ const reliability = readReliabilityStatus({
14922
+ repoPath: options.repoPath,
14923
+ variant: state?.variant,
14924
+ drift,
14925
+ ...options.workspace !== void 0 ? { workspace: options.workspace } : {}
14926
+ });
14916
14927
  const positivelyStopped = !inspection.primaryActive && Object.values(inspection.baseStatuses).every(isStoppedOrMissingResourceStatus) && Object.values(inspection.serviceStatuses).every(isStoppedOrMissingResourceStatus) && activeApps.length === 0;
14917
14928
  const onlyDegradedIncident = state?.status === "degraded" && drift.length === 1;
14918
14929
  const requiredServicesReady = desiredServices.every(
@@ -14930,11 +14941,11 @@ function collectManagedRuntimeStatus(options) {
14930
14941
  services: inspection.activeServices,
14931
14942
  processes: inspection.activeProcesses
14932
14943
  };
14933
- const reliability = readReliabilityStatus({
14934
- repoPath: options.repoPath,
14935
- variant: state?.variant,
14936
- ...options.workspace !== void 0 ? { workspace: options.workspace } : {}
14937
- });
14944
+ if (status === "failed-transition" && reliability?.attention) {
14945
+ reliability.attention.recovery = [
14946
+ `Inspect: devrouter status --repo ${recoveryPath(options.repoPath)}; resolve the reported drift before retrying ensure.`
14947
+ ];
14948
+ }
14938
14949
  return {
14939
14950
  mode: "managed",
14940
14951
  status,
package/dist/devrouter.js CHANGED
@@ -4944,7 +4944,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs8.default.read
4944
4944
  const config = parseRepoConfigSource(raw, configPath);
4945
4945
  const requiredVersion = config.devrouter?.version;
4946
4946
  if (requiredVersion && !hasWarnedVersionMismatch) {
4947
- const cliVersion = true ? "0.6.7" : "0.0.0-dev";
4947
+ const cliVersion = true ? "0.6.8" : "0.0.0-dev";
4948
4948
  if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
4949
4949
  hasWarnedVersionMismatch = true;
4950
4950
  process.stderr.write(
@@ -7266,7 +7266,7 @@ function validateAppReplacementAttempt(value, identity2) {
7266
7266
  return attempt;
7267
7267
  }
7268
7268
  function installedCliVersion() {
7269
- return true ? "0.6.7" : "0.0.0-dev";
7269
+ return true ? "0.6.8" : "0.0.0-dev";
7270
7270
  }
7271
7271
  function compareCliVersions(left, right) {
7272
7272
  const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -17876,6 +17876,29 @@ function recoveryPath(repoPath) {
17876
17876
  if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(repoPath)) return repoPath;
17877
17877
  return `'${repoPath.replaceAll("'", "'\\''")}'`;
17878
17878
  }
17879
+ function managedRuntimeRecovery(runtime, repoPath) {
17880
+ const checkout = recoveryPath(repoPath);
17881
+ const historyCause = runtime.drift.find((entry) => Object.hasOwn(HISTORY_CAUSES, entry));
17882
+ if (historyCause) {
17883
+ return [
17884
+ historyCause === "journal-writer-newer" ? "Preserve lifecycle history and use a matching or newer devrouter CLI before retrying lifecycle commands." : "Preserve lifecycle history and inspect its unreadable or unsafe evidence before retrying lifecycle commands.",
17885
+ `Inspect: devrouter status --repo ${checkout} --json`
17886
+ ];
17887
+ }
17888
+ if (runtime.status === "failed-transition") {
17889
+ return [
17890
+ `Inspect: devrouter status --repo ${checkout}; resolve the reported drift before retrying ensure.`
17891
+ ];
17892
+ }
17893
+ const attention = runtime.reliability?.attention;
17894
+ if (attention?.recovery.length) return attention.recovery;
17895
+ if (attention || runtime.reliability?.operation?.drained === false) {
17896
+ return [
17897
+ `Inspect: devrouter status --repo ${checkout} --json; wait for the current lifecycle owner to finish or cancel it before retrying.`
17898
+ ];
17899
+ }
17900
+ return void 0;
17901
+ }
17879
17902
  function reliabilityRecovery(reason2, repoPath, variant) {
17880
17903
  const checkout = recoveryPath(repoPath);
17881
17904
  const variantOption = variant && variant !== "default" ? ` --variant ${variant}` : "";
@@ -17908,7 +17931,9 @@ function reliabilityRecovery(reason2, repoPath, variant) {
17908
17931
  `Run: devrouter ensure ${checkout}${variantOption} (still queued until capacity frees up)`
17909
17932
  ];
17910
17933
  default:
17911
- return [];
17934
+ return [
17935
+ `Inspect: devrouter status --repo ${checkout} --json; wait for the current lifecycle owner to finish or cancel it before retrying.`
17936
+ ];
17912
17937
  }
17913
17938
  }
17914
17939
  function refusedManagedStart(result) {
@@ -17933,7 +17958,10 @@ function readReliabilityStatus(options) {
17933
17958
  workspace: options.workspace ?? null,
17934
17959
  provider
17935
17960
  });
17936
- } catch {
17961
+ } catch (error) {
17962
+ options.drift.push(
17963
+ error instanceof ReliabilityJournalError ? error.cause : "journal-unreadable"
17964
+ );
17937
17965
  return void 0;
17938
17966
  }
17939
17967
  if (!record6) return void 0;
@@ -18348,6 +18376,12 @@ function collectManagedRuntimeStatus(options) {
18348
18376
  if (inspection.activeProcesses.some((process2) => !desiredProcesses.includes(process2))) {
18349
18377
  drift.push("one or more active processes are outside the selected profile");
18350
18378
  }
18379
+ const reliability = readReliabilityStatus({
18380
+ repoPath: options.repoPath,
18381
+ variant: state?.variant,
18382
+ drift,
18383
+ ...options.workspace !== void 0 ? { workspace: options.workspace } : {}
18384
+ });
18351
18385
  const positivelyStopped = !inspection.primaryActive && Object.values(inspection.baseStatuses).every(isStoppedOrMissingResourceStatus) && Object.values(inspection.serviceStatuses).every(isStoppedOrMissingResourceStatus) && activeApps.length === 0;
18352
18386
  const onlyDegradedIncident = state?.status === "degraded" && drift.length === 1;
18353
18387
  const requiredServicesReady = desiredServices.every(
@@ -18365,11 +18399,11 @@ function collectManagedRuntimeStatus(options) {
18365
18399
  services: inspection.activeServices,
18366
18400
  processes: inspection.activeProcesses
18367
18401
  };
18368
- const reliability = readReliabilityStatus({
18369
- repoPath: options.repoPath,
18370
- variant: state?.variant,
18371
- ...options.workspace !== void 0 ? { workspace: options.workspace } : {}
18372
- });
18402
+ if (status === "failed-transition" && reliability?.attention) {
18403
+ reliability.attention.recovery = [
18404
+ `Inspect: devrouter status --repo ${recoveryPath(options.repoPath)}; resolve the reported drift before retrying ensure.`
18405
+ ];
18406
+ }
18373
18407
  return {
18374
18408
  mode: "managed",
18375
18409
  status,
@@ -18397,7 +18431,7 @@ function collectManagedRuntimeStatus(options) {
18397
18431
  ...state?.transitionPhase ? { transitionPhase: state.transitionPhase } : {}
18398
18432
  };
18399
18433
  }
18400
- var EMPTY_RESOURCES;
18434
+ var HISTORY_CAUSES, EMPTY_RESOURCES;
18401
18435
  var init_managed_runtime_status = __esm({
18402
18436
  "src/core/managed-runtime-status.ts"() {
18403
18437
  "use strict";
@@ -18413,6 +18447,20 @@ var init_managed_runtime_status = __esm({
18413
18447
  init_reliability_output();
18414
18448
  init_workspace();
18415
18449
  init_workspace_runtime();
18450
+ HISTORY_CAUSES = {
18451
+ "journal-directory-unreadable": true,
18452
+ "journal-directory-unsafe": true,
18453
+ "journal-entry-unsupported": true,
18454
+ "journal-enumeration-limit": true,
18455
+ "journal-enumeration-timeout": true,
18456
+ "journal-unreadable": true,
18457
+ "journal-entry-unsafe": true,
18458
+ "journal-invalid": true,
18459
+ "journal-writer-newer": true,
18460
+ "journal-identity-mismatch": true,
18461
+ "journal-unstable": true,
18462
+ "journal-enumeration-failed": true
18463
+ };
18416
18464
  EMPTY_RESOURCES = {
18417
18465
  apps: [],
18418
18466
  services: [],
@@ -25492,17 +25540,15 @@ async function collectRouterStatus(repoPath) {
25492
25540
  );
25493
25541
  } else if (repo?.valid) {
25494
25542
  const repoArgument = `'${repo.path.replaceAll("'", `'\\''`)}'`;
25495
- const failedTransition = repo.managedRuntime?.status === "failed-transition";
25543
+ const recovery = repo.managedRuntime ? managedRuntimeRecovery(repo.managedRuntime, repo.path) : void 0;
25496
25544
  if (repo.managedRuntime?.mode === "managed") {
25497
- nextSteps.push(
25498
- failedTransition ? `Inspect: devrouter status --repo ${repoArgument}; resolve the reported drift before retrying ensure.` : `Run: devrouter ensure ${repoArgument}`
25499
- );
25545
+ nextSteps.push(...recovery ?? [`Run: devrouter ensure ${repoArgument}`]);
25500
25546
  } else {
25501
25547
  nextSteps.push(`Run: dev app ls --repo ${repo.path}`);
25502
25548
  nextSteps.push("Run: dev app run <name> --repo <path> --yes");
25503
25549
  }
25504
25550
  nextSteps.push("Run: dev ls");
25505
- if (!failedTransition && repo.managedRuntime?.mountNesting?.status === "unwound") {
25551
+ if (!recovery && repo.managedRuntime?.mountNesting?.status === "unwound") {
25506
25552
  nextSteps.push(
25507
25553
  `Run: devrouter stop ${repoArgument} and then devrouter ensure ${repoArgument} to re-apply the unwound nested mount`
25508
25554
  );
@@ -25946,7 +25992,7 @@ function probeInstalledCliVersion(executable) {
25946
25992
  }
25947
25993
  function buildCliPathCheck(options = {}) {
25948
25994
  const id5 = "global.cli-path";
25949
- const runningVersion = options.runningVersion ?? (true ? "0.6.7" : "0.0.0-dev");
25995
+ const runningVersion = options.runningVersion ?? (true ? "0.6.8" : "0.0.0-dev");
25950
25996
  if (runningVersion === "0.0.0-dev") {
25951
25997
  return {
25952
25998
  id: id5,
@@ -26768,6 +26814,7 @@ async function buildDoctorReport(options = {}) {
26768
26814
  });
26769
26815
  if (repo.managedRuntime) {
26770
26816
  const managedRuntime = repo.managedRuntime;
26817
+ const recovery = managedRuntimeRecovery(managedRuntime, repo.path);
26771
26818
  const repoArgument = `'${repo.path.replaceAll("'", `'\\''`)}'`;
26772
26819
  const variantOption = managedRuntime.activeVariant && managedRuntime.activeVariant !== "default" ? ` --variant ${managedRuntime.activeVariant}` : "";
26773
26820
  const level = managedRuntime.mode === "legacy" || managedRuntime.status === "ready" ? "ok" : managedRuntime.status === "starting" || managedRuntime.status === "stopped" ? "warn" : "error";
@@ -26782,7 +26829,7 @@ async function buildDoctorReport(options = {}) {
26782
26829
  level,
26783
26830
  summary: summary2,
26784
26831
  ...details ? { details } : {},
26785
- suggestion: managedRuntime.mode === "legacy" ? void 0 : managedRuntime.status === "failed-transition" ? `Inspect: devrouter status --repo ${repoArgument}; resolve the reported drift before retrying ensure.` : managedRuntime.status === "ready" ? void 0 : `Run: devrouter ensure ${repoArgument}${variantOption}`
26832
+ suggestion: managedRuntime.mode === "legacy" ? void 0 : recovery ? recovery.join(" ") : managedRuntime.status === "ready" ? void 0 : `Run: devrouter ensure ${repoArgument}${variantOption}`
26786
26833
  });
26787
26834
  const mountNesting = managedRuntime.mountNesting;
26788
26835
  if (mountNesting && mountNesting.status !== "not-applicable") {
@@ -26800,7 +26847,7 @@ async function buildDoctorReport(options = {}) {
26800
26847
  (entry) => `unwound=${entry.destination} (source ${entry.source} inside ${entry.nestedWithin})`
26801
26848
  )
26802
26849
  ].join("; "),
26803
- suggestion: managedRuntime.status === "failed-transition" ? void 0 : `Run: devrouter stop ${repoArgument} and then devrouter ensure ${repoArgument}${variantOption} to restart the exact container, which re-applies the nested mount.`
26850
+ suggestion: recovery ? void 0 : `Run: devrouter stop ${repoArgument} and then devrouter ensure ${repoArgument}${variantOption} to restart the exact container, which re-applies the nested mount.`
26804
26851
  });
26805
26852
  } else if (mountNesting.status === "unverified") {
26806
26853
  addCheck(checks, {
@@ -26811,7 +26858,7 @@ async function buildDoctorReport(options = {}) {
26811
26858
  `container=${container}`,
26812
26859
  `reason=${mountNesting.reason ?? "unknown"}`
26813
26860
  ].join("; "),
26814
- suggestion: `Run: devrouter exec ${repoArgument} -- cat /proc/self/mountinfo to read the container's own mount table.`
26861
+ suggestion: recovery ? void 0 : `Run: devrouter exec ${repoArgument} -- cat /proc/self/mountinfo to read the container's own mount table.`
26815
26862
  });
26816
26863
  } else {
26817
26864
  addCheck(checks, {
@@ -26845,7 +26892,7 @@ async function buildDoctorReport(options = {}) {
26845
26892
  suggestion: `Remedy ${expansionNotice.remedy.code}: set a named default profile other than '${expansionNotice.profile}'${remedyCandidates}.`
26846
26893
  });
26847
26894
  }
26848
- const cliVersion = true ? "0.6.7" : "0.0.0-dev";
26895
+ const cliVersion = true ? "0.6.8" : "0.0.0-dev";
26849
26896
  const configVersion = config.devrouter?.version;
26850
26897
  const installedKnown = cliVersion !== "0.0.0-dev";
26851
26898
  const versionComparison = installedKnown && configVersion ? compareSemver(configVersion, cliVersion) : void 0;
@@ -27081,6 +27128,7 @@ var init_doctor = __esm({
27081
27128
  init_capacity_store();
27082
27129
  init_docker();
27083
27130
  init_host_routes();
27131
+ init_managed_runtime_status();
27084
27132
  init_reliability_operation_store();
27085
27133
  init_repo_config();
27086
27134
  init_devcontainer_diagnostics();
@@ -42524,7 +42572,7 @@ var init_version = __esm({
42524
42572
 
42525
42573
  // src/cli.ts
42526
42574
  var import_commander = require("commander");
42527
- var CLI_VERSION = true ? "0.6.7" : "0.0.0-dev";
42575
+ var CLI_VERSION = true ? "0.6.8" : "0.0.0-dev";
42528
42576
  var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
42529
42577
  function withErrorHandling(action2) {
42530
42578
  return async (...args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrouter/cli",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
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,53 @@
1
+ # Upgrade to devrouter 0.6.8
2
+
3
+ Managed status reports unreadable lifecycle history as drift. Newer-writer history
4
+ requires a matching or newer reader while preserving the journal; other unreadable
5
+ history requires inspection. Status and doctor prioritize that remedy, failed
6
+ transition inspection, durable operation attention and live-owner guidance before
7
+ ordinary startup or nested-mount restart advice. Ordinary readable-history drift
8
+ retains normal ensure guidance. No configuration schema, command surface,
9
+ dependency, ownership or admission guard changes are introduced.
10
+
11
+ ## Task
12
+
13
+ Within approved installation/adaptation scope, select the integrity-verified exact
14
+ package, update `devrouter.version` in `.devrouter.yml` and refresh existing agent
15
+ guidance through `devrouter repo agents`. Verify selected/PATH executables and
16
+ concrete package, source, harness and controller pins sharing the affected journal
17
+ namespace or mixed caller chain. Owners confirm compatible adoption or explicit
18
+ non-use; a PATH listing alone does not prove participation. Independent remote
19
+ state is a separate adoption boundary. Unknown affected participation holds
20
+ activation. Do not alter dormant harness checks or replay consumed attempts.
21
+
22
+ A new reader accepts older supported history. Older 0.6.7 readers refuse actual
23
+ 0.6.8-written journals through direct read, update, enumeration and admission even
24
+ without a schema change. Installing alone writes no lifecycle journal. Before
25
+ any separately authorized new lifecycle write, coordinate affected clients; keep
26
+ inactive older pins unused until compatibility is established. After newer writes,
27
+ use a matching or newer CLI and preserve all journal bytes and durable
28
+ initialization/replacement receipts. Never erase, downgrade or replay history to
29
+ bypass refusal or rearm an attempt.
30
+
31
+ Publication, installation and notices authorize no consumer startup, repair,
32
+ replacement, initialization, reset or extra attempt. Inspection is read-only
33
+ and does not establish application readiness. A live owner must finish or be
34
+ explicitly cancelled within its own authority before another operation.
35
+
36
+ ## Validation
37
+
38
+ 1. Verify registry integrity, selected package/member bytes and executable
39
+ versions. Run native checks for actual consumer edits; preserve journals and
40
+ receipts when only selecting a CLI.
41
+ 2. Use `devrouter status --repo <checkout> --json` and existing diagnostic evidence
42
+ within authorized inspection scope. Check the reported reason and actual
43
+ next-command preconditions; do not infer permission from generic advice.
44
+ 3. Any separately authorized runtime work ends with canonical stop and exact
45
+ worker, provider, container and route proof unless the user keeps it running.
46
+
47
+ ## Report
48
+
49
+ Report selected package/executable identities, affected-client adoption or holds,
50
+ remaining unknowns and relevant checks. Any consumer recovery claim needs its
51
+ actual useful-work, retained-data, neighbour and stopped-terminal evidence.
52
+ Synthetic qualification and package identity alone do not prove receiving-host
53
+ adoption, consumer recovery or retained-maintenance acceptance.