c8ctl-plugin-nano 1.39.1 → 1.39.2

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
@@ -208,7 +208,7 @@ c8ctl nano work reviewer --job-type senior:pr-review --job-type senior:triage
208
208
 
209
209
  ```bash
210
210
  c8ctl nano work reviewer # poll for work until Ctrl-C
211
- c8ctl nano work reviewer --max-parallel 2 --recovery-window 300000
211
+ c8ctl nano work reviewer --recovery-window 300000
212
212
  c8ctl nano work reviewer --name reviewer-eu # name this worker (else auto ‹host›-‹profile›-‹random›)
213
213
  ```
214
214
 
@@ -728,7 +728,7 @@ c8ctl nano supervisor
728
728
 
729
729
  # Manage the fleet without the console (any terminal, any time):
730
730
  c8ctl nano supervisor status # id, state, pid, restarts, uptime
731
- c8ctl nano supervisor add reviewer --max-parallel 2 # add + spawn a worker (forwards work flags)
731
+ c8ctl nano supervisor add reviewer # add + spawn a worker (forwards work flags)
732
732
  c8ctl nano supervisor add reviewer --name reviewer-2 # a SECOND reviewer, named so it stays distinct
733
733
  c8ctl nano supervisor add reviewer --instances 3 # add 3 distinct auto-named reviewers in one call
734
734
  c8ctl nano supervisor restart reviewer # by worker id or profile name
@@ -749,12 +749,13 @@ cannot be combined with `--name`; omit `--name` to let them auto-name.
749
749
  `restart`/`remove` accept either a worker id **or** a profile name — targeting a
750
750
  profile affects *every* instance of it.
751
751
 
752
- Each worker takes the **same flags as `nano work`** (`--max-parallel`,
753
- `--recovery-window`, `--idle-timeout`, `--job-timeout`, `--poll-timeout`,
752
+ Each worker takes the **same flags as `nano work`**
753
+ (`--recovery-window`, `--idle-timeout`, `--job-timeout`, `--poll-timeout`,
754
754
  `--sandbox`/`--image`, `--job-type`, `--env`, `--arg`, …); they are forwarded
755
- verbatim to the spawned child, so a supervised worker is byte-identical to a
756
- hand-run `nano work`. In the
757
- interactive console, type the flags after the profile: `add reviewer --max-parallel 2`.
755
+ to the spawned child (reconstructed via `reconstructWorkArgs`, which normalizes
756
+ ordering and coerces booleans), so a supervised worker is semantically
757
+ equivalent to a hand-run `nano work`. In the
758
+ interactive console, type the flags after the profile: `add reviewer --recovery-window 300000`.
758
759
 
759
760
  How it works and where things live:
760
761
 
package/c8ctl-plugin.js CHANGED
@@ -3066,9 +3066,9 @@ function credArgs() {
3066
3066
  // git via GIT_ASKPASS only (never argv/URL/helper), preserving the ephemeral-token
3067
3067
  // guarantee.
3068
3068
  // Memoized for the process lifetime: this is a synchronous spawnSync (up to a
3069
- // 10s timeout) that can be reached per job, and jobs may run concurrently
3070
- // (maxParallelJobs > 1), so consult the CLI at most once per worker run rather
3071
- // than blocking every handler. A sentinel distinguishes "not yet computed" from
3069
+ // 10s timeout) that can be reached per job, so consult the CLI at most once per
3070
+ // worker run rather than blocking a handler on every job. A sentinel
3071
+ // distinguishes "not yet computed" from
3072
3072
  // a cached null (gh missing / not logged in).
3073
3073
  //
3074
3074
  // Memoization alone still lets the *first* job pay the synchronous spawn on the
@@ -4643,7 +4643,12 @@ async function workAgent(req, flags) {
4643
4643
  const n = Number.parseInt(String(v ?? ''), 10);
4644
4644
  return Number.isFinite(n) && n > 0 ? n : dflt;
4645
4645
  };
4646
- const maxParallelJobs = intFlag(flags?.['max-parallel'], 1);
4646
+ // One job per worker, hard-wired (there is deliberately no --max-parallel
4647
+ // flag): an agent harness holds a PTY + a git workspace for the whole life of
4648
+ // a job, so a worker must never lease a second job concurrently. The @camunda8
4649
+ // SDK derives maxJobsToActivate = maxParallelJobs - activeJobs, so 1 means
4650
+ // "activate one job, then stop polling until it completes".
4651
+ const maxParallelJobs = 1;
4647
4652
  // The broker job-activation lock is NOT hardcoded up front. A fixed timeout is
4648
4653
  // impossible to size for an agent: too short reclaims a still-working job (a
4649
4654
  // second agent starts + the stale complete/fail is rejected 409), too long
@@ -4837,12 +4842,13 @@ async function workAgent(req, flags) {
4837
4842
  }
4838
4843
  const extraNote = extraJobTypes.length > 0 ? ` (${extraJobTypes.length} via --job-type)` : '';
4839
4844
  logger.info(` listening on ${jobTypes.length} job type(s)${extraNote}: ${jobTypes.join(' ')}`);
4840
- logger.info(` max parallel: ${maxParallelJobs}; recovery window: ${recoveryWindowMs}ms; idle timeout: ${idleTimeoutMs}ms; hard cap: ${hardCapMs > 0 ? `${hardCapMs}ms` : 'off'}; poll timeout: ${pollTimeoutMs}ms`);
4845
+ logger.info(` one job per worker; recovery window: ${recoveryWindowMs}ms; idle timeout: ${idleTimeoutMs}ms; hard cap: ${hardCapMs > 0 ? `${hardCapMs}ms` : 'off'}; poll timeout: ${pollTimeoutMs}ms`);
4841
4846
  // Warm the gh-token cache now, off the job-handling path: githubCloneToken()
4842
4847
  // may consult `gh auth token` (a synchronous spawn, up to 10s) as its default
4843
- // credential fallback, and doing that inside a job handler would stall sibling
4844
- // handlers + lock heartbeats when maxParallelJobs > 1. Priming here pays that
4845
- // cost once at startup so every later lookup is a warm cache hit.
4848
+ // credential fallback, and doing that inside a job handler would block the
4849
+ // event loop stalling the lock heartbeat and delaying the job itself.
4850
+ // Priming here pays that cost once at startup so every later lookup is a warm
4851
+ // cache hit.
4846
4852
  primeGhAuthToken();
4847
4853
  logger.info('Polling for work — press Ctrl-C to stop.');
4848
4854
 
@@ -5620,10 +5626,10 @@ const SUPERVISOR_MONITOR_INTERVAL_MS = 1_000;
5620
5626
  // extra daemon traffic.
5621
5627
  const SUPERVISOR_LIVE_TICK_MS = 5_000;
5622
5628
 
5623
- // The `nano work` flags forwarded verbatim to each spawned child.
5629
+ // The `nano work` flags forwarded to each spawned child (reconstructed and
5630
+ // normalized by `reconstructWorkArgs`, not passed through byte-for-byte).
5624
5631
  // kind: 'value' → `--flag v`; 'boolean' → `--flag`; 'list' → repeated `--flag v`.
5625
5632
  const WORK_FORWARD_FLAGS = {
5626
- 'max-parallel': 'value',
5627
5633
  'job-timeout': 'value',
5628
5634
  'recovery-window': 'value',
5629
5635
  'idle-timeout': 'value',
@@ -9106,7 +9112,7 @@ export const metadata = {
9106
9112
  { command: 'c8ctl nano supervisor start --worker reviewer --worker coder', description: 'Start a detached supervisor managing several workers from one terminal' },
9107
9113
  { command: 'c8ctl nano supervisor', description: 'Attach an interactive console to the supervisor (detach with Ctrl-D, leaving it running)' },
9108
9114
  { command: 'c8ctl nano supervisor status', description: 'List supervised workers (state, ENGINE + AGENTIC visibility diagnostics, serviced job / idle, pid, restarts, uptime) without the console' },
9109
- { command: 'c8ctl nano supervisor add decider --max-parallel 2', description: 'Add a supervised worker (forwarding work flags) to the running supervisor' },
9115
+ { command: 'c8ctl nano supervisor add decider', description: 'Add a supervised worker (forwarding work flags) to the running supervisor' },
9110
9116
  { command: 'c8ctl nano supervisor add reviewer --instances 3', description: 'Add 3 distinct auto-named instances of a profile in one call' },
9111
9117
  { command: 'c8ctl nano supervisor restart reviewer', description: 'Restart a supervised worker by id or profile' },
9112
9118
  { command: 'c8ctl nano supervisor stop', description: 'Stop the supervisor daemon and all its workers' },
@@ -9168,7 +9174,6 @@ export const commands = {
9168
9174
  'keep-runs': { type: 'boolean', description: 'work: keep per-job workspaces under <state>/agent-runs instead of deleting them after each job (debug)' },
9169
9175
  stream: { type: 'boolean', description: 'work: tee each agent job\'s live stdout/stderr to this console, prefixed with the job type + key (spy/debug)' },
9170
9176
  list: { type: 'boolean', description: 'hire: list existing agent profiles instead of creating one' },
9171
- 'max-parallel': { type: 'string', description: 'work: max concurrent jobs per worker (default 1)' },
9172
9177
  'job-timeout': { type: 'string', description: 'work: OPTIONAL absolute hard cap on total harness runtime per job in ms; the process is killed past this. Default 0 = unlimited (the broker lock is auto-managed — see --recovery-window / --idle-timeout).' },
9173
9178
  'recovery-window': { type: 'string', description: 'work: broker activation-lock window in ms, auto-refreshed while the agent runs; also the node-loss reclaim time (a dead/killed worker\'s job is re-activated within this). Default 300000.' },
9174
9179
  'idle-timeout': { type: 'string', description: 'work: max ms an agent may produce no stdout/stderr before it is killed as wedged (stops lock extension → job reclaimed). Default 300000.' },
@@ -9334,7 +9339,7 @@ function printUsage() {
9334
9339
  console.log(' c8ctl nano update [--check]');
9335
9340
  console.log(' c8ctl nano hire [--name <n>] [--rank <r>] [--command <c>] [--arg <switch> ...] [--model <m>] [--capabilities <a,b>] [--sandbox none|docker|podman] [--image <ref>] [--terminal pty|pipe] [--env NAME=VALUE ...] [--list]');
9336
9341
  console.log(' c8ctl nano assign <profileName> <cap[,cap...]> [--name <n>] [--capabilities <a,b>]');
9337
- console.log(' c8ctl nano work <profileName> [--auto [--auto-scope <p>]] [--arg <switch> ...] [--max-parallel <n>] [--recovery-window <ms>] [--idle-timeout <ms>] [--job-timeout <ms>] [--poll-timeout <ms>] [--job-type <token> ...] [--sandbox none|docker|podman] [--image <ref>] [--env NAME=VALUE ...] [--secret-resolver host] [--min-free-mb <n>] [--clone-timeout <ms>] [--keep-runs] [--stream]');
9342
+ console.log(' c8ctl nano work <profileName> [--auto [--auto-scope <p>]] [--arg <switch> ...] [--recovery-window <ms>] [--idle-timeout <ms>] [--job-timeout <ms>] [--poll-timeout <ms>] [--job-type <token> ...] [--sandbox none|docker|podman] [--image <ref>] [--env NAME=VALUE ...] [--secret-resolver host] [--min-free-mb <n>] [--clone-timeout <ms>] [--keep-runs] [--stream]');
9338
9343
  console.log(' c8ctl nano supervisor [start|status|add|remove|restart|stop|logs|attach] ... (manage many workers from one terminal)');
9339
9344
  console.log('');
9340
9345
  console.log('Subcommands:');
@@ -9379,7 +9384,6 @@ function printUsage() {
9379
9384
  console.log(' --terminal <m> hire: live-terminal mode pty|pipe (default pipe); pty streams a steerable terminal on the relay lane');
9380
9385
  console.log(' --env NAME=VALUE hire/work: static env var for the harness (repeatable); persisted on hire, work extends/overrides');
9381
9386
  console.log(' --list hire: list existing agent profiles instead of creating one');
9382
- console.log(' --max-parallel <n> work: max concurrent jobs per worker (default 1)');
9383
9387
  console.log(' --job-type <token> work: extra job type to service alongside the rank×capability matrix (repeatable)');
9384
9388
  console.log(' --auto work: zero-config enrolment — serve ALL deployed agent job types read from the engine (no capability, no app enrol endpoint, no channel). NO capability gate: serves any deployed agent job on the engine.');
9385
9389
  console.log(' --auto-scope <p> work: with --auto, narrow to agent job types whose bpmn:process id equals or is prefixed by <p> (one app/network); default all');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8ctl-plugin-nano",
3
- "version": "1.39.1",
3
+ "version": "1.39.2",
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",
@@ -57,12 +57,12 @@
57
57
  },
58
58
  "optionalDependencies": {
59
59
  "node-pty": "^1.0.0",
60
- "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.39.1",
61
- "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.39.1",
62
- "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.39.1",
63
- "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.39.1",
64
- "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.39.1",
65
- "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.39.1",
66
- "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.39.1"
60
+ "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.39.2",
61
+ "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.39.2",
62
+ "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.39.2",
63
+ "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.39.2",
64
+ "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.39.2",
65
+ "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.39.2",
66
+ "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.39.2"
67
67
  }
68
68
  }