c8ctl-plugin-nano 1.42.1 → 1.43.1
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 +139 -2
- package/c8ctl-plugin.js +1119 -29
- package/nanobpmn-binary.json +3 -3
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -473,8 +473,13 @@ c8ctl nano hire --name coder --rank senior --command copilot --protocol acp --pe
|
|
|
473
473
|
# OpenCode — native ACP server (assembles `opencode acp`)
|
|
474
474
|
c8ctl nano hire --name coder --rank senior --command opencode --arg acp --protocol acp --permission yolo
|
|
475
475
|
|
|
476
|
-
#
|
|
477
|
-
|
|
476
|
+
# Qwen — native ACP behind a HIDDEN flag (`qwen --experimental-acp`; present in
|
|
477
|
+
# the shipped cli.js but not in `qwen --help`). Detection recognises the
|
|
478
|
+
# switch, so no second `--acp` is appended.
|
|
479
|
+
c8ctl nano hire --name coder --rank senior --command qwen --arg --experimental-acp --protocol acp --permission yolo
|
|
480
|
+
|
|
481
|
+
# Claude Code — via the `claude-code-acp` adapter (npm @zed-industries/claude-code-acp)
|
|
482
|
+
c8ctl nano hire --name coder --rank senior --command claude-code-acp --protocol acp --permission yolo
|
|
478
483
|
|
|
479
484
|
# Pi — via the `pi-acp` adapter
|
|
480
485
|
c8ctl nano hire --name coder --rank senior --command pi-acp --protocol acp --permission yolo
|
|
@@ -492,6 +497,23 @@ on the host executor; container sandboxes remain **pipe-only** for now). There i
|
|
|
492
497
|
**no change to the Camunda-8 worker⇄engine job protocol** — ACP governs only how a
|
|
493
498
|
worker drives its local agent harness, not how it talks to the engine.
|
|
494
499
|
|
|
500
|
+
**Selecting the model under ACP.** `--model` only exports `AGENT_MODEL` into the
|
|
501
|
+
harness environment; it is **not** injected into the harness argv. And structured
|
|
502
|
+
`--arg` values are POSIX single-quoted by the plugin, so a literal `$AGENT_MODEL`
|
|
503
|
+
in an `--arg` does **not** expand (only the `--command` string is
|
|
504
|
+
shell-interpolated, since the harness is spawned with `shell: true`). The
|
|
505
|
+
deterministic, supported way to pin a model for an ACP hire is therefore to
|
|
506
|
+
**bake it into `--command`**, where the shell does interpolate:
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
# The --command string IS shell-interpolated, so $AGENT_MODEL (or a literal name) works here:
|
|
510
|
+
c8ctl nano hire --name coder --rank senior --command 'copilot --acp --model gpt-5.4' --protocol acp
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
(Equivalently, set a harness-specific env var with `--env` when the harness reads
|
|
514
|
+
the model from its environment.) This is the seam the nano-workforce install
|
|
515
|
+
script uses to route a detected model to each harness deterministically.
|
|
516
|
+
|
|
495
517
|
### Live profile reload (no restart on `assign`)
|
|
496
518
|
|
|
497
519
|
A running `c8ctl nano work <name>` **watches** the profile it is servicing. When
|
|
@@ -857,6 +879,121 @@ How it works and where things live:
|
|
|
857
879
|
- Stopping is SIGTERM → grace → SIGKILL, per worker and for the daemon; `stop`
|
|
858
880
|
always clears `supervisor.json` so a stale marker never wedges a future start.
|
|
859
881
|
|
|
882
|
+
## Composing a workforce: `workforce`
|
|
883
|
+
|
|
884
|
+
`supervisor` is imperative — you compose a fleet with a `start --worker …` plus a
|
|
885
|
+
pile of `add … --instances N` calls that live only in your shell history. A
|
|
886
|
+
**workforce manifest** makes that fleet a **reusable, inspectable artifact**: a
|
|
887
|
+
named set of supervised workers you compose once and bring up convergently with
|
|
888
|
+
one command.
|
|
889
|
+
|
|
890
|
+
```bash
|
|
891
|
+
# Compose a fleet (each add creates/updates one entry; no supervisor needed yet)
|
|
892
|
+
c8ctl nano workforce add copilot --instances 5 --auto
|
|
893
|
+
c8ctl nano workforce add claude --instances 1 --auto
|
|
894
|
+
c8ctl nano workforce add qwen --instances 2 --roles pr-review,feature
|
|
895
|
+
|
|
896
|
+
c8ctl nano workforce list # print the manifest (+ --json)
|
|
897
|
+
c8ctl nano workforce start # ensure the daemon is up, then reconcile
|
|
898
|
+
c8ctl nano workforce status # desired vs actual, per worker (+ --json)
|
|
899
|
+
c8ctl nano workforce stop # remove this manifest's workers (+ stop an empty daemon)
|
|
900
|
+
c8ctl nano workforce remove qwen # drop an entry ("all" clears the manifest)
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
Every subcommand takes `--profile <name>` (default `default`) to select which
|
|
904
|
+
manifest it operates on, so you can keep several — `--profile review-only`,
|
|
905
|
+
`--profile full-fleet` — side by side.
|
|
906
|
+
|
|
907
|
+
### The manifest
|
|
908
|
+
|
|
909
|
+
A manifest is a **separate JSON document per name**, stored at
|
|
910
|
+
`<stateHome>/workforce/<name>.json` (`<stateHome>` is `C8CTL_NANO_HOME` or the
|
|
911
|
+
per-OS app dir). It is deliberately **not** a key in `config.json`: manifests are
|
|
912
|
+
user-curated documents meant to be read, edited by hand, diffed and copied
|
|
913
|
+
between machines; `config.json` is plugin state.
|
|
914
|
+
|
|
915
|
+
```jsonc
|
|
916
|
+
{
|
|
917
|
+
"version": 1,
|
|
918
|
+
"name": "default",
|
|
919
|
+
"workers": [
|
|
920
|
+
{ "profile": "copilot", "instances": 5, "roles": "auto" },
|
|
921
|
+
{ "profile": "claude", "instances": 1, "roles": "auto" },
|
|
922
|
+
{ "profile": "qwen", "instances": 2, "roles": ["pr-review", "feature"] }
|
|
923
|
+
]
|
|
924
|
+
}
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
| Field | Meaning |
|
|
928
|
+
| --- | --- |
|
|
929
|
+
| `profile` | A hired profile name (must exist in `hires`; validated at `add` and again at `start`). |
|
|
930
|
+
| `instances` | How many workers to run for this entry (`1`..`MAX_ADD_INSTANCES`). |
|
|
931
|
+
| `roles` | `"auto"` → run the worker with `--auto`; **or** an array of capability names. |
|
|
932
|
+
| `autoScope` | Optional, only with `roles: "auto"` → forwards `--auto-scope <value>`. |
|
|
933
|
+
| `args` | Optional array of extra `work` flags forwarded verbatim (escape hatch: `--sandbox`, `--stream`, …). |
|
|
934
|
+
|
|
935
|
+
### `roles` → job types
|
|
936
|
+
|
|
937
|
+
`roles` is resolved **at start time from the manifest**, independent of what the
|
|
938
|
+
profile was hired with (the install script hires with `--capabilities ""`):
|
|
939
|
+
|
|
940
|
+
- `"auto"` → `c8ctl nano work <profile> --auto [--auto-scope X]`. No capability
|
|
941
|
+
gate; serves every deployed agent job type. This is what the install script
|
|
942
|
+
sets, and the default when you pass neither `--auto` nor `--roles` to `add`.
|
|
943
|
+
- `["pr-review","feature"]` → repeatable `--job-type <rank>:<role>`, e.g. for a
|
|
944
|
+
`senior` hire: `--job-type senior:pr-review --job-type senior:feature`.
|
|
945
|
+
|
|
946
|
+
`--job-type` is chosen deliberately over `nano assign`: it uses an existing
|
|
947
|
+
work-time flag (no new override surface on `work`) and **does not mutate the
|
|
948
|
+
profile** — the same profile can appear in two manifests with different role
|
|
949
|
+
sets. `--auto` and `--roles` are mutually exclusive; `--auto-scope` requires
|
|
950
|
+
`--auto`.
|
|
951
|
+
|
|
952
|
+
### Reconcile semantics — `start` is convergent, not additive
|
|
953
|
+
|
|
954
|
+
`start` ensures the supervisor daemon is running (starting it if needed), then
|
|
955
|
+
**reconciles** the running workers to the manifest:
|
|
956
|
+
|
|
957
|
+
- Start workers that are missing.
|
|
958
|
+
- Stop workers that belong to this manifest but are no longer desired (entry
|
|
959
|
+
removed, or `instances` reduced).
|
|
960
|
+
- Leave already-running, still-desired workers **untouched** — no restart churn,
|
|
961
|
+
no job interruption. A second `start` with an unchanged manifest starts
|
|
962
|
+
nothing, stops nothing and restarts nothing.
|
|
963
|
+
- Workers **not** owned by this manifest (added by hand with `supervisor add`, or
|
|
964
|
+
owned by another manifest) are never touched.
|
|
965
|
+
|
|
966
|
+
The enabling detail is **deterministic worker names**: workforce-owned workers
|
|
967
|
+
are named `wf-<manifest>-<profile>-<index>` (`wf-default-copilot-1` …
|
|
968
|
+
`wf-default-copilot-5`). Since `--instances` can't combine with `--name`, `start`
|
|
969
|
+
issues N single adds with an explicit `--name` each. The `wf-<manifest>-` prefix
|
|
970
|
+
is also how `status`/`stop` identify ownership; a name collision with a
|
|
971
|
+
hand-added worker running a different profile is skipped with a warning rather
|
|
972
|
+
than clobbered.
|
|
973
|
+
|
|
974
|
+
### Portability
|
|
975
|
+
|
|
976
|
+
A manifest is portable: copy `default.json` to another machine, `hire` the same
|
|
977
|
+
profile names there, and `workforce start`. Because `roles` resolves from the
|
|
978
|
+
manifest (not the hire), the fleet comes up identically even if the profiles were
|
|
979
|
+
hired with `--capabilities ""`.
|
|
980
|
+
|
|
981
|
+
### Validation & errors
|
|
982
|
+
|
|
983
|
+
- `add`: the profile must exist in `hires` (otherwise an error pointing at
|
|
984
|
+
`c8ctl nano hire`); `instances` in `1..MAX_ADD_INSTANCES`; `--roles`/`--auto`
|
|
985
|
+
mutually exclusive; `--auto-scope` requires `--auto`.
|
|
986
|
+
- `start`: an entry whose profile was since deleted → a clear error, the entry is
|
|
987
|
+
skipped, the rest continue, and the command exits non-zero (a partial start
|
|
988
|
+
never leaves a half-reconciled fleet silently).
|
|
989
|
+
- A malformed/torn manifest, or an unknown `version`, is refused with an explicit
|
|
990
|
+
error naming the file path — never silently treated as empty.
|
|
991
|
+
- `start` with an empty/absent manifest → a friendly pointer at `workforce add`,
|
|
992
|
+
exit 0.
|
|
993
|
+
|
|
994
|
+
`--json` on `list`/`status` emits machine-readable output (through the same
|
|
995
|
+
output-mode-aware logger) so the install script and CI can consume it.
|
|
996
|
+
|
|
860
997
|
## Cleaning up disk
|
|
861
998
|
|
|
862
999
|
```bash
|