@smartkomm/plexus-cli 0.1.0 → 0.1.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 +42 -5
- package/dist/cli.mjs +5127 -178
- package/dist/skill/.managed-by-plexus-cli +1 -1
- package/dist/skill/SKILL.md +39 -0
- package/dist/skill/references/agents/use-shared-tools.md +52 -0
- package/dist/skill/references/config/update-tenant-config.md +5 -1
- package/dist/skill/references/marketing/demo-video-links.md +101 -0
- package/dist/skill/references/resolver/manage-contract-resolver.md +5 -3
- package/dist/skill/references/test-actions/drive-a-test-application.md +11 -1
- package/dist/spec.snapshot.json +35419 -24413
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,12 @@ plexus-cli <command> --help # per-command help (clipanion auto-generates it)
|
|
|
23
23
|
|
|
24
24
|
### The agent skill
|
|
25
25
|
|
|
26
|
+
`plexus-cli agent tools --json` exposes the shared agent tool schemas.
|
|
27
|
+
`plexus-cli agent invoke --tool <name> --json` accepts tool input as JSON on
|
|
28
|
+
stdin. Commands use the same parser as ordinary CLI invocations; workspace
|
|
29
|
+
files are relative to the current directory. See the
|
|
30
|
+
[shared-tools recipe](playbooks/agents/use-shared-tools.md).
|
|
31
|
+
|
|
26
32
|
On every start the installed CLI keeps an agent skill current for Claude Code
|
|
27
33
|
(`~/.claude/skills/plexus-cli/`) and Codex (`~/.codex/skills/plexus-cli/`) — whichever
|
|
28
34
|
of the two exists: `SKILL.md` plus every playbook as `references/`, each marked with the
|
|
@@ -127,16 +133,17 @@ and bootstraps a deterministic platform-admin token with the rdu admin key
|
|
|
127
133
|
| **catalog** | `catalog {plan,apply} --file catalog.json` · `catalog export --out catalog.json` — articles with the programs selling them, packages, need-based tiers and Word templates of a tenant, by stable key; a DOCX is replaced only when its SHA-256 differs; export → plan is `same`. Recipe [playbooks/config/set-up-billing-catalog.md](./playbooks/config/set-up-billing-catalog.md) |
|
|
128
134
|
| **applications** | `applications {list,counts} --offer <slug>` · `applications show <id>` · `applications store <id> [--json]` (the process store, every address resolved — [playbooks/applications/inspect-process-store.md](./playbooks/applications/inspect-process-store.md)) · `applications start-test --offer --run <key\|id> --stage <key\|id> (--applicant <email> \| --party <id>) [--staff-input <key>=true\|false …]` (every staff input the offer declares, once each) · `applications discard-test <id>` — recipe [playbooks/applications/start-a-test-application.md](./playbooks/applications/start-a-test-application.md) |
|
|
129
135
|
| **retention** | `retention plan` (read-only) · `retention apply [--confirm --expect <n>]` — a tenant's applications past their retention period, and their erasure by hand (dry run without `--confirm`; a count other than `--expect` erases nothing). Nothing erases on a schedule; recipe and the DSGVO duty: [playbooks/retention/erase-due-applications.md](./playbooks/retention/erase-due-applications.md). `retention parties plan` · `retention parties apply [--confirm --expect <n>]` — the same for persons past the tenant's deletion rule (hard delete with history and files; blocked persons are listed and skipped, `--expect` counts the deletable ones): [playbooks/retention/erase-due-parties.md](./playbooks/retention/erase-due-parties.md) |
|
|
130
|
-
| **test-actions** | `test-actions list --application <id> [--node]` · `test-actions run --application <id> --action <id> [--node] [--no-auto-submit]` — the test-mode popover of a test application (scenarios, `auto-fill-files`, `submit-form`, …); recipe [playbooks/test-actions/drive-a-test-application.md](./playbooks/test-actions/drive-a-test-application.md) |
|
|
136
|
+
| **test-actions** | `test-actions list --application <id> [--node]` · `test-actions run --application <id> --action <id> [--node] [--no-auto-submit] [--param key=value …]` (`--param`: the action's params, values JSON like `call`'s, e.g. `--param confirmed=true` for an action that asks first) — the test-mode popover of a test application (scenarios, `auto-fill-files`, `submit-form`, …); recipe [playbooks/test-actions/drive-a-test-application.md](./playbooks/test-actions/drive-a-test-application.md) |
|
|
131
137
|
| **migrations** | `migrations status [--recent]` — the deployed release's pending migrations; exit 1 while one is not `success` (recipe [playbooks/worker-ops/verify-migrations.md](./playbooks/worker-ops/verify-migrations.md)) |
|
|
132
|
-
| **tokens** | `tokens list`, `tokens create <name>`, `tokens revoke <id>` — minting needs `_platform.apiTokens.manage` (opt-in) or the tenant right `administration.apiTokens.manage` (every `tenant_admin` holds it); list and revoke your own always work. `tokens create <name> --for <email> [--output <csv>] [--quiet]` mints one FOR a tenant administrator to hand over (`_platform.users.manage` AND `_platform.apiTokens.manage`; the target must hold `administration.apiTokens.manage` in a tenant) — recipe [playbooks/users/cli-access-for-tenant-admin.md](./playbooks/users/cli-access-for-tenant-admin.md) |
|
|
138
|
+
| **tokens** | `tokens list`, `tokens create <name>`, `tokens revoke <id>` — minting needs `_platform.apiTokens.manage` (opt-in) or the tenant right `administration.apiTokens.manage` (every `tenant_admin` holds it); list and revoke your own always work. `tokens create <name> --for <email> [--output <csv>] [--quiet]` mints one FOR a tenant administrator or platform operator to hand over (`_platform.users.manage` AND `_platform.apiTokens.manage`; the target must hold `administration.apiTokens.manage` in a tenant, or the platform right `_platform.apiTokens.manage`) — recipe [playbooks/users/cli-access-for-tenant-admin.md](./playbooks/users/cli-access-for-tenant-admin.md) |
|
|
133
139
|
| **users** | `users {list,show,add,remove,set-group,unset-group,groups,set-platform-admin,set-platform-permission,create,provision,provision-platform-admin,provision-platform-user,set-password,login-trail,set-email,delete,doctor,relink-auth}` — `login-trail <email> [--since 24h]` lists refusals, letters with the relay's answer, sessions and the last password change; `remove` / `unset-group` / `delete` are refused while a `wip` or published workflow's assignment rule names the person (replace them first: „Person ersetzen" in the workflow editor, then publish); `--replace-with <configKey>` hands their active applications over (required while they are responsible for any) and never rewrites a rule |
|
|
134
140
|
| **platform** | `platform {tenants,users,workers}` |
|
|
135
141
|
| **stammdaten** | `stammdaten persons [-q] [--limit] [--all] [--deleted]`, `stammdaten persons purge <partyId> [--confirm]` (the only hard delete of a person, plan unless `--confirm`) |
|
|
136
142
|
| **admission** | `admission laeufe` · `assignment simulate --dir <bundle> --env-json '<json>'\|--env-file <f> [--creator <label>] [--rotation-previous <slot>=<key>]… [--open <key>=<n>]… [--left <key>]…` (evaluate an offer bundle's assignment rule — `graph.assignmentRules` in its `workflow.json`, every slot, the matched row per slot — offline; recipe `playbooks/offer/assignment-rule.md`) |
|
|
137
|
-
| **generator** | Contract generators (`finanzen_vertraege.contracts.manage`): `generator {list,show,usages,runs}` · `generator {create,update,clone,seal,archive,restore,delete-draft}` · `generator source {export,save}` · `generator scenarios {test,approve}` · `generator {export,apply}` (one-file round trip) · `generator template {list,upload}` · `generator setup {plan,apply}` (offer setup by catalog keys). **Combined generators**: `generator combined export <key@rev> [--out]` writes the declaration (mask, parts pinned as `key@revision`, names) · `generator combined save <file>` writes it back — onto the exported revision (guarded by `expectedSourceRevision`; an unedited export writes nothing) or, without `id`, as the first draft of a new key · `generator combined plan <key@rev> --input <json
|
|
143
|
+
| **generator** | Contract generators (`finanzen_vertraege.contracts.manage`): `generator {list,show,usages,runs}` · `generator {create,update,clone,seal,archive,restore,delete-draft}` · `generator source {export,save}` · `generator scenarios {test,approve}` · `generator {export,apply}` (one-file round trip) · `generator template {list,upload}` · `generator setup {plan,apply}` (offer setup by catalog keys). **Combined generators**: `generator combined export <key@rev> [--out]` writes the declaration (mask, parts pinned as `key@revision`, names) · `generator combined save <file>` writes it back — onto the exported revision (guarded by `expectedSourceRevision`; an unedited export writes nothing) or, without `id`, as the first draft of a new key · `generator combined plan <key@rev> --input <json> [--strict]` (sandbox: which parts run, what each misses; exits 0 like `generator test`, with `--strict` 1 when the input would not generate — a missing field, an undecided part, a roster issue, a part's refusal) · `generator combined create --key … --name … --name-en …` (empty draft); seal/clone/archive with the ordinary verbs. The server's `[generator/…]` refusals print verbatim. Recipe [playbooks/resolver/manage-contract-resolver.md](./playbooks/resolver/manage-contract-resolver.md). |
|
|
138
144
|
| **imports** | `imports {status,trigger,trigger-all}` |
|
|
139
145
|
| **feedback** | `feedback {list,screenshot,to-issue,sync,set-status}` |
|
|
146
|
+
| **demo** | `demo videos` (the catalogue: id, date, title, length) · `demo link create (--to <name> [--email] \| --from <utf-8 csv> [--out <csv>]) [--video <id>] [--campaign] [--note]` · `demo link list [--campaign]` · `demo link stats [<code> \| --campaign]` · `demo link revoke <code>` · `demo link delete <code> [--confirm]` (erases the link with everything recorded; a dry run without `--confirm`) — personalised links to the public demo video page and their viewing statistics (a visit counts once the page was visible 5 s or the visitor interacted; watched seconds come from the player, `%` = how much the best single visit actually played). Needs `_platform.demoLinks.manage`; recipe [playbooks/marketing/demo-video-links.md](./playbooks/marketing/demo-video-links.md) |
|
|
140
147
|
| **notifications** | Operator's log (`_platform.notifications.monitor`): `notifications {list,show,retry,sweeper-status,self-test}`; `list` filters by `--status`, `--template`, `--to`, `--since 24h` and shows the relay's answer (`smtp`). Why a sign-in failed: `users login-trail <email> --since 24h` (recipe [playbooks/notifications/trace-a-login.md](./playbooks/notifications/trace-a-login.md)). School's wording (tenant-scoped, `notifications._self.access` / `.mail.configure`): `notifications letters {list,show,set,reset}` · `notifications chrome {show,set}` — see ["The words a school sends"](#the-words-a-school-sends-notifications-letters--chrome). |
|
|
141
148
|
| **offer** | `offer {create,show,set,delete,restore,list,status}` · `offer run {add,set,archive,restore}` · `offer level {add,rename,move,remove,restore}` · `offer capacity set` · `offer unit {create,ensure-pedagogy}` (make a school applyable: create unit + pedagogy bridge) · `offer {export,validate,plan,diff,apply}` |
|
|
142
149
|
| **offer form** | `offer form {list,show,add,set,rm}` · `offer form section {add,set,move,rm}` · `offer form field {add,set,move,rm}` · `offer form outcome {add,set,rm}` · `offer form effect {add,set,rm}` · `offer form repeated {add,set,rm}` · `offer form computed {add,set,rm}` · `offer form scenario {add,set,rm}` (test-mode prefills; `--prefill k=v` typed by field; `add --from <id>` derives a variant) · `offer form env set --keys … --sample <scenario>=<json>` (the `$env` keys the form reads) (offline bundle authoring; every mutator runs the real publish-gate validators before writing). `field set` covers all editable props (bucket/placeholder/help-text/enum/enum-ref/enum-list-key/multiple/required-for/docRef/consent + validation expressions; enum/enum-ref/enum-list-key are mutually exclusive — `--enum-list-key` binds a tenant `custom_field_lists` key, `--multiple` makes it multi-select); `effect set` is per-kind (bucket/identity/orgKind/from/to/relKind/target/map); `section set --parent` reparents; `section set --visible-to <key,…>` restricts who on the school's side reads the section's values (`""` clears); `field/section move --before\|--after\|--to-top\|--to-bottom` reorders. Every SmartForm text is ONE `{ de, en }` field: a German text needs its English in the same call (`--label-en`, `--placeholder-en`, `--help-text-en`, …) — the German is never copied into `en`. |
|
|
@@ -165,7 +172,14 @@ an empty database once, joins an active seed, or preserves a completed seed.
|
|
|
165
172
|
Failed/incomplete seeds and untracked populated databases require an explicit
|
|
166
173
|
rebuild. Without `--if-needed`, `seed` is destructive. `--applicants none` and
|
|
167
174
|
`--finance-showcase none` select the lean fixtures; switching local profiles
|
|
168
|
-
preserves existing data until an explicit rebuild.
|
|
175
|
+
preserves existing data until an explicit rebuild. `--only <cases>` drives just
|
|
176
|
+
those applicant cases and implies `--finance-showcase none` unless
|
|
177
|
+
`--finance-showcase` is given. At most `PLEXUS_SEED_SLOTS` (default 2) seeds run at
|
|
178
|
+
once on one machine, across all checkouts: a seed waits for a free slot (an
|
|
179
|
+
`flock` under `~/.cache/plexus/seed-slots/`, printing who holds them) and keeps it
|
|
180
|
+
until its run is terminal; `--timeout` bounds the wait and the seed together. A
|
|
181
|
+
failed run is reported at once with its phase and error; five unreadable status
|
|
182
|
+
polls in a row end the command with the last error. Recipe:
|
|
169
183
|
[Initialize or rebuild local demo data](playbooks/worker-ops/rebuild-local-data.md).
|
|
170
184
|
|
|
171
185
|
Every command supports `--json` (raw output; default is a table). Network commands
|
|
@@ -513,6 +527,11 @@ argument, an unknown one or a wrong type is named with the expected type
|
|
|
513
527
|
(`q=2026` stays `"2026"`). A function the snapshot does not know (explicit `--kind`) is
|
|
514
528
|
called unchecked, with a note on stderr.
|
|
515
529
|
|
|
530
|
+
A refusal prints as `[CODE] <German sentence>` on stderr (every command, not only
|
|
531
|
+
`call`): the server sends `{ de, en }` and the CLI shows the German, which is
|
|
532
|
+
what playbooks quote. A stored text in a result (a failure, a reason) prints as its German
|
|
533
|
+
in tables and as the raw `{ de, en }` under `--json`.
|
|
534
|
+
|
|
516
535
|
`functions` / `describe` read a committed snapshot (`spec.snapshot.json`).
|
|
517
536
|
Regenerate it with the tool's in-repo `spec` script (run from
|
|
518
537
|
`app/tools/plexus-cli/`) after changing a public function's arguments, return
|
|
@@ -605,11 +624,24 @@ offers/<tenant>/<offerSlug>/
|
|
|
605
624
|
plexus-cli offer export --tenant test --slug grundschule-havelland --out offers/test/gymnasium
|
|
606
625
|
# edit bundle.yaml (slugs/label/unit/stages/runs) + the JSON blobs
|
|
607
626
|
plexus-cli offer validate --dir offers/test/gymnasium # offline, real publish gate
|
|
608
|
-
plexus-cli offer plan --dir offers/test/gymnasium # remote↔local diff (smartform/workflow = ∅ when absent)
|
|
627
|
+
plexus-cli offer plan --dir offers/test/gymnasium # stamp resolver pins from the env + validate + remote↔local diff (smartform/workflow = ∅ when absent)
|
|
609
628
|
plexus-cli --env <env> offer apply [--publish] --dir offers/test/gymnasium
|
|
610
629
|
plexus-cli offer status --tenant test --slug gymnasium-havelland # applyable?
|
|
611
630
|
```
|
|
612
631
|
|
|
632
|
+
**Resolver pins are stamped from the environment.** A contract node pins
|
|
633
|
+
`resolver: { key, revision }`; publish stamps what that sealed revision says
|
|
634
|
+
(`inputSchema`, `parties`, `schemaDigest`, and `parts` for a combined
|
|
635
|
+
generator). `offer plan` and `offer apply` fetch the same stamp
|
|
636
|
+
(`workflow:getResolverPinStamps`) and write it onto the in-memory bundle
|
|
637
|
+
before validating, so a new combined pin produces `$node.<n>.contracts`
|
|
638
|
+
offline exactly as it will after publish, and the generator's parameters are
|
|
639
|
+
checked against the node's inputs. A pin the environment cannot stamp (no such
|
|
640
|
+
revision, not sealed) is a blocking `[resolver/pinNotStamped]` issue.
|
|
641
|
+
`offer validate` stays offline: it warns about each unstamped pin, and its
|
|
642
|
+
`contract` / `contracts` address checks on such a node are only as good as
|
|
643
|
+
that guess.
|
|
644
|
+
|
|
613
645
|
**Stage identity.** `program.stages[]` entries are `{ key, name, gradeLevel? }`; `key`
|
|
614
646
|
is required (`offer validate`). `offer apply` matches levels **by key**: a changed name
|
|
615
647
|
renames the same row, a new key adds a level, a removed key archives it (refused while
|
|
@@ -698,6 +730,11 @@ apply for removals).
|
|
|
698
730
|
### `apply` — the core verb
|
|
699
731
|
- **Dry-run unless `--confirm`.** The dry-run output *is* the plan: aggregate
|
|
700
732
|
`created / updated / deleted / unchanged` counts, plus:
|
|
733
|
+
- `+ create <target> <key>` — each row the apply **inserts** (admission custom fields /
|
|
734
|
+
derived attributes included), so `created` is exactly the number of these rows. A
|
|
735
|
+
member of a permission group is named `<group>/<config key or login address>`
|
|
736
|
+
(`foundation.permissionGroups.members`). A deployment that predates the list prints one
|
|
737
|
+
`+ create (unnamed)` line instead.
|
|
701
738
|
- `~ update <target> <key>` — each config row the apply **patches** (admission custom
|
|
702
739
|
fields / derived attributes included, dry run too); an idempotent row counts as
|
|
703
740
|
unchanged, so `updated` is exactly the number of these rows.
|