c8ctl-plugin-nano 1.13.2 → 1.14.0

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.
Files changed (2) hide show
  1. package/c8ctl-plugin.js +43 -1
  2. package/package.json +8 -8
package/c8ctl-plugin.js CHANGED
@@ -120,6 +120,15 @@ const PROCESSOS_STATE_FILE = 'processos.json';
120
120
  const PROCESSOS_DEFAULT_PORT = 8090;
121
121
  const DEFAULT_NANO_URL = 'http://localhost:8080';
122
122
 
123
+ // Guided-journey deep links (ADR 0049 §2). The console renders a first-run tour
124
+ // chosen by `…/console?tour=<journeyId>`, and the *command the user ran* already
125
+ // encodes the persona — so the CLI bakes the journey into the console URL it
126
+ // prints rather than making the console guess. These ids are a contract with the
127
+ // console (`console/src/lib/tour`): an unknown id is silently ignored, so they
128
+ // are asserted verbatim in the tests.
129
+ const JOURNEY_LOCALDEV = 'localdev';
130
+ const JOURNEY_AGENTIC_AUTHOR = 'agentic-author';
131
+
123
132
  // Passive update notifier (npm-style): refresh the latest published version
124
133
  // from the registry in a detached background process at most once per day, and
125
134
  // surface a one-line "update available" notice at most once per day. Never
@@ -449,6 +458,30 @@ function liveNodeCount(state) {
449
458
  return state.nodes.filter((n) => isPidAlive(n.pid)).length;
450
459
  }
451
460
 
461
+ /**
462
+ * Compose a web-console URL for a node's base URL, optionally carrying a guided
463
+ * journey (`?tour=<id>`, ADR 0049 §2). Never hardcodes a port: `baseUrl` is the
464
+ * real address the node came up on.
465
+ */
466
+ function webConsoleUrl(baseUrl, journey) {
467
+ const base = `${baseUrl}/console`;
468
+ return journey ? `${base}?tour=${encodeURIComponent(journey)}` : base;
469
+ }
470
+
471
+ /**
472
+ * Base URL of the running cluster the user would actually open: the first
473
+ * still-alive node, falling back to the first recorded node, then to the default
474
+ * gateway URL when no cluster has been started. Used by hire/work, which surface
475
+ * a console link for the agentic-SDLC journey.
476
+ */
477
+ function runningConsoleBaseUrl(state = readState()) {
478
+ if (state && Array.isArray(state.nodes) && state.nodes.length > 0) {
479
+ const alive = state.nodes.find((n) => isPidAlive(n.pid));
480
+ return (alive || state.nodes[0]).url;
481
+ }
482
+ return DEFAULT_NANO_URL;
483
+ }
484
+
452
485
  /** Probe a node's always-on GET /v2/topology endpoint for reachability. */
453
486
  async function probeHealthy(url) {
454
487
  const controller = new AbortController();
@@ -828,7 +861,7 @@ async function printSummary(state) {
828
861
  console.log(` REST API ${entry.url}/v2`);
829
862
  console.log(` Topology ${entry.url}/v2/topology`);
830
863
  if (hasConsole) {
831
- console.log(` Web console ${entry.url}/console`);
864
+ console.log(` Web console ${webConsoleUrl(entry.url, JOURNEY_LOCALDEV)}`);
832
865
  console.log(` User guide ${entry.url}/docs`);
833
866
  }
834
867
  if (state.workspaceDir) {
@@ -1600,6 +1633,7 @@ async function hireWorker(req, flags) {
1600
1633
  if (envKeys.length > 0) logger.info(` env: ${envKeys.join(', ')}`);
1601
1634
  logger.info(` job types (${matrix.length}): ${matrix.join(' ')}`);
1602
1635
  logger.info(`Put it to work with: c8ctl nano work ${name}`);
1636
+ logger.info(`Open the console: ${webConsoleUrl(runningConsoleBaseUrl(), JOURNEY_AGENTIC_AUTHOR)}`);
1603
1637
  }
1604
1638
 
1605
1639
  /**
@@ -2633,6 +2667,7 @@ async function workAgent(req, flags) {
2633
2667
  if (profileEnvKeys.length > 0) logger.info(` harness env: ${profileEnvKeys.join(', ')}`);
2634
2668
  logger.info(` listening on ${matrix.length} job type(s): ${matrix.join(' ')}`);
2635
2669
  logger.info(` max parallel: ${maxParallelJobs}; job timeout: ${jobTimeoutMs}ms`);
2670
+ logger.info(` console: ${webConsoleUrl(runningConsoleBaseUrl(), JOURNEY_AGENTIC_AUTHOR)}`);
2636
2671
  logger.info('Polling for work — press Ctrl-C to stop.');
2637
2672
 
2638
2673
  const workers = matrix.map((jobType) =>
@@ -4163,6 +4198,13 @@ function parseProcessosRequest(args, flags) {
4163
4198
  // `metadata` and `commands`; these named exports are inert to it.
4164
4199
  export { resolveBinary, findBinary, launcherEnvMarkers };
4165
4200
  export { buildNpmInvocation };
4201
+ export {
4202
+ webConsoleUrl,
4203
+ runningConsoleBaseUrl,
4204
+ hireWorker,
4205
+ JOURNEY_LOCALDEV,
4206
+ JOURNEY_AGENTIC_AUTHOR,
4207
+ };
4166
4208
  export {
4167
4209
  normalizeTaskEnvelope,
4168
4210
  collectEnvelopeFrom,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8ctl-plugin-nano",
3
- "version": "1.13.2",
3
+ "version": "1.14.0",
4
4
  "type": "module",
5
5
  "description": "c8ctl plugin to start, inspect, and stop a local Nano BPM (nanobpmn) cluster",
6
6
  "main": "c8ctl-plugin.js",
@@ -49,12 +49,12 @@
49
49
  "semantic-release": "^25.0.3"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.13.2",
53
- "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.13.2",
54
- "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.13.2",
55
- "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.13.2",
56
- "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.13.2",
57
- "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.13.2",
58
- "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.13.2"
52
+ "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.14.0",
53
+ "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.14.0",
54
+ "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.14.0",
55
+ "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.14.0",
56
+ "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.14.0",
57
+ "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.14.0",
58
+ "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.14.0"
59
59
  }
60
60
  }