@jc_stack/ez-agents 0.1.0-beta.34 → 0.1.0-beta.36
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/.dockerignore +1 -0
- package/.env.example +5 -16
- package/AGENTS.md +17 -9
- package/CHANGELOG.md +67 -0
- package/Dockerfile +7 -9
- package/README.md +10 -13
- package/bin/ez +97 -0
- package/bin/ezenciel-agents-plugin-broker.mjs +16 -0
- package/bin/ezenciel-agents-provision-telegram.mjs +13 -0
- package/bin/ezenciel-agents.mjs +1 -1
- package/compose.yaml +40 -4
- package/docker/entrypoint.sh +1 -1
- package/docker/healthcheck.mjs +12 -4
- package/docker/run.ts +5 -6
- package/docker/smoke.mjs +28 -6
- package/docs/application-channel.md +32 -10
- package/docs/architecture/authority-boundaries.md +2 -2
- package/docs/channel-backend.md +4 -3
- package/docs/docker-runtime.md +79 -11
- package/docs/local-qa.md +2 -2
- package/docs/plugin-guide.md +202 -0
- package/docs/plugins.md +48 -2
- package/docs/releasing.md +13 -0
- package/docs/responsive-channels.md +1 -1
- package/docs/scheduling.md +4 -4
- package/docs/setup.md +11 -5
- package/docs/upgrades.md +46 -23
- package/package.json +5 -5
- package/scripts/smoke-scheduler.ts +10 -3
- package/scripts/smoke.ts +14 -11
- package/src/agent-guidance.ts +6 -9
- package/src/agent-install.ts +28 -7
- package/src/application-channel.ts +78 -7
- package/src/application-cli.ts +2 -2
- package/src/approval-cli.ts +14 -7
- package/src/approval.ts +27 -37
- package/src/channel-backend.ts +2 -3
- package/src/config.ts +12 -27
- package/src/control-state.ts +175 -8
- package/src/conversation-menu.ts +6 -17
- package/src/delivery-socket-client.d.mts +4 -0
- package/src/delivery-socket-client.mjs +104 -0
- package/src/delivery-socket.ts +354 -0
- package/src/execution-authority.ts +21 -5
- package/src/executor.ts +20 -23
- package/src/files.ts +38 -11
- package/src/host-executor.ts +28 -14
- package/src/inbox.ts +15 -49
- package/src/index.ts +95 -52
- package/src/install-tools.mjs +97 -22
- package/src/ledger-endpoint.d.mts +2 -0
- package/src/ledger-endpoint.mjs +17 -0
- package/src/menu.ts +7 -2
- package/src/message-history.ts +13 -18
- package/src/message.ts +35 -18
- package/src/plugin-broker.mjs +396 -0
- package/src/plugins/connection.mjs +2 -2
- package/src/plugins/manager.mjs +132 -23
- package/src/plugins/native-tasks.mjs +2 -2
- package/src/prompt-suffix.ts +12 -0
- package/src/react.ts +6 -4
- package/src/runs.ts +156 -243
- package/src/schedule-cli.ts +29 -10
- package/src/scheduled-tasks.ts +53 -10
- package/src/scheduler.ts +20 -7
- package/src/service.ts +3 -3
- package/src/software-status.ts +36 -4
- package/src/task-executor.ts +2 -2
- package/src/task-workspace.ts +4 -3
- package/src/tasks.ts +1 -1
- package/src/telegram-provisioning-cli.ts +22 -0
- package/src/telegram-provisioning.ts +214 -0
- package/src/updates/control.mjs +77 -7
- package/src/updates/runtime.mjs +28 -8
- package/src/updates/status.mjs +25 -3
- package/src/updates/supervisor.mjs +15 -16
- package/src/version.ts +20 -0
- package/src/workspace.ts +3 -9
- package/templates/failure-review.md +1 -1
- package/templates/maintainer-purpose.md +1 -1
- package/test/agent-guidance.test.ts +14 -80
- package/test/agent-install.test.ts +14 -0
- package/test/ai.test.ts +36 -0
- package/test/application-channel.test.ts +61 -13
- package/test/application-only.test.ts +14 -13
- package/test/channel-backend.test.ts +3 -7
- package/test/channel-delivery.test.ts +4 -1
- package/test/channel-owner.test.ts +6 -3
- package/test/codex-context.test.ts +2 -2
- package/test/config.test.ts +38 -43
- package/test/control-state.test.ts +83 -4
- package/test/conversation-menu.test.ts +2 -4
- package/test/delivery-transport.test.ts +72 -0
- package/test/docker-runtime.test.ts +27 -14
- package/test/engine-handoff.test.ts +7 -6
- package/test/event-sources.test.ts +2 -2
- package/test/execution-authority.test.ts +9 -9
- package/test/executor.test.ts +10 -11
- package/test/failure.test.ts +12 -5
- package/test/files.test.ts +2 -2
- package/test/helpers/ledger.ts +18 -0
- package/test/host-executor.test.ts +74 -0
- package/test/inbox.test.ts +8 -10
- package/test/install-config.test.ts +1 -0
- package/test/install-tools.test.mjs +74 -7
- package/test/intake-relay.test.ts +58 -11
- package/test/message-history.test.ts +39 -47
- package/test/native-tasks.test.ts +1 -1
- package/test/plugin-broker.test.mjs +172 -0
- package/test/plugin-manager.test.mjs +119 -2
- package/test/reaction.test.ts +4 -0
- package/test/relay.test.ts +5 -7
- package/test/repair-policy.test.ts +1 -4
- package/test/schedule-cli.test.ts +14 -9
- package/test/scheduled-tasks.test.ts +29 -6
- package/test/scheduler-host.test.ts +5 -5
- package/test/scheduler-relay.test.ts +15 -9
- package/test/security.test.ts +6 -3
- package/test/software-status.test.ts +21 -3
- package/test/telegram-provisioning.test.ts +160 -0
- package/test/updates.test.mjs +93 -13
- package/test/workspace.test.ts +4 -1
- package/bin/ezenciel-agents-watch.mjs +0 -8
- package/compose.workforce-watch.yaml +0 -33
- package/docker/recovery.ts +0 -11
- package/docs/pagerduty.md +0 -42
- package/docs/workforce-watch.md +0 -101
- package/src/pagerduty.ts +0 -109
- package/src/reply-context.ts +0 -43
- package/src/update-attention.ts +0 -18
- package/src/workforce-watch-cli.ts +0 -14
- package/src/workforce-watch.ts +0 -155
- package/templates/agent/AGENTS.md +0 -5
- package/templates/agent-guidance.md +0 -17
- package/test/pagerduty.test.ts +0 -104
- package/test/update-attention.test.ts +0 -20
- package/test/workforce-watch.test.ts +0 -180
|
@@ -277,13 +277,30 @@ This works without Telegram and requires no transcript replay or new runner.
|
|
|
277
277
|
Scoped application conversations remain separate when the flag is omitted.
|
|
278
278
|
Owner identity does not automatically merge histories or grant learner access.
|
|
279
279
|
|
|
280
|
-
To link Telegram, enable its ordinary bot configuration,
|
|
281
|
-
|
|
280
|
+
To link Telegram, enable its ordinary bot configuration, then use the
|
|
281
|
+
application-initiated handoff below or send a real DM and approve the observed
|
|
282
|
+
pending identity using `ezenciel-agents-owner approve ID`.
|
|
282
283
|
`ezenciel-agents-owner unlink-telegram` removes that channel without removing the
|
|
283
284
|
owner, application bindings or native sessions. Relinking does not authorize old
|
|
284
285
|
Telegram deliveries. Linking other providers requires an authenticated adapter;
|
|
285
286
|
registering the label `phone` does not install a phone service.
|
|
286
287
|
|
|
288
|
+
### Application-initiated Telegram handoff
|
|
289
|
+
|
|
290
|
+
An already-authorized `--share-owner` application binding can make the ordinary
|
|
291
|
+
Telegram link easy without becoming a Telegram backend. `GET /v1/telegram`
|
|
292
|
+
returns the current `connected` state. `POST /v1/telegram/link` either returns
|
|
293
|
+
`{connected:true}` or a single-use, short-lived `https://t.me/BOT?start=TOKEN`
|
|
294
|
+
link. The bot accepts that token only from the matching application's current
|
|
295
|
+
owner, then persists the normal Telegram owner/channel record and consumes the
|
|
296
|
+
ticket. The raw token is never stored in control state.
|
|
297
|
+
|
|
298
|
+
This is a launch handoff, not a UI-owned connection: the application does not
|
|
299
|
+
store Telegram identity, bot credentials, or the ticket, and the Ez agent keeps
|
|
300
|
+
working when that application is unavailable. There is deliberately no
|
|
301
|
+
application disconnect endpoint. Administrative unlink remains the explicit
|
|
302
|
+
owner control above.
|
|
303
|
+
|
|
287
304
|
The legacy `--share-telegram`, `--share-active` and `followTelegram:true` spellings remain supported.
|
|
288
305
|
|
|
289
306
|
### Existing scoped Telegram sharing
|
|
@@ -325,12 +342,17 @@ a generic HTTP error or revoked credential alone is not proof of termination.
|
|
|
325
342
|
|
|
326
343
|
## Application-only deployment (no Telegram bot)
|
|
327
344
|
|
|
328
|
-
For a private per-user native runtime,
|
|
345
|
+
For a private per-user native runtime, omit `TELEGRAM_BOT_TOKEN` and set
|
|
329
346
|
`EZ_APPLICATION_PORT` (plus `EZ_APPLICATION_HOST` when other containers connect).
|
|
330
|
-
|
|
347
|
+
This mode runs the existing native executor,
|
|
331
348
|
application queue and application outbox without creating a Telegram client,
|
|
332
|
-
starting Telegram sources/polling, or registering bot commands.
|
|
333
|
-
|
|
349
|
+
starting Telegram sources/polling, or registering bot commands. Telegram becomes
|
|
350
|
+
active as soon as the agent receives its private bot token.
|
|
351
|
+
|
|
352
|
+
Upgrade note: the removed `EZ_TELEGRAM_ENABLED` flag is no longer read. A stale
|
|
353
|
+
flag that contradicts the token (disabled flag with a token present, or enabled
|
|
354
|
+
flag with no token) refuses to start — unset the flag, and remove any stale
|
|
355
|
+
`TELEGRAM_BOT_TOKEN` to stay application-only.
|
|
334
356
|
|
|
335
357
|
The installing administrator can initialize empty control authority and register
|
|
336
358
|
an application in one local command:
|
|
@@ -385,14 +407,14 @@ up to 10 MiB decoded; empty files and other types are rejected. Core detects fil
|
|
|
385
407
|
content rather than trusting a client MIME label. This same limit and staging
|
|
386
408
|
contract apply to Telegram photo/document input.
|
|
387
409
|
|
|
388
|
-
Authentication precedes staging. Core stages the file privately
|
|
389
|
-
|
|
390
|
-
Telegram. The existing run queue, native executor, selected AI and native session
|
|
410
|
+
Authentication precedes staging. Core stages the file privately under the
|
|
411
|
+
deployment control directory and uses the same attachment metadata and literal
|
|
412
|
+
comment as Telegram. The existing run queue, native executor, selected AI and native session
|
|
391
413
|
remain authoritative; applications must not extract, summarize, convert or build
|
|
392
414
|
attachment prompts. Use `followOwner:true` for the shared owner conversation.
|
|
393
415
|
Retry the same request ID, filename, bytes and literal comment; conflicts return
|
|
394
416
|
409 and successful retries do not stage another file. A failed admission removes
|
|
395
|
-
its staged file; a process crash may leave an unused
|
|
417
|
+
its staged file; a process crash may leave an unused staged file, never a runnable
|
|
396
418
|
partial request. Separate owner runtimes must retain separate workspace mounts.
|
|
397
419
|
|
|
398
420
|
This is inbound file support. Application replies currently deliver text only;
|
|
@@ -127,8 +127,8 @@ Native configuration reference: [Codex configuration](https://learn.chatgpt.com/
|
|
|
127
127
|
Task notes live under protected `control/tasks/`, separate from the owner mind.
|
|
128
128
|
Exact-contact task reports currently use the linked Telegram owner outbox and
|
|
129
129
|
are visibly labelled; any-conversation runs have no report tool. Reports are not
|
|
130
|
-
inserted as owner instructions or trusted memory. The owner mind
|
|
131
|
-
|
|
130
|
+
inserted as owner instructions or trusted memory. The owner mind is the workspace `AGENTS.md` and files the agent creates.
|
|
131
|
+
No prescribed `inbox/` or `work/` layout is required. No database or general memory
|
|
132
132
|
index is introduced.
|
|
133
133
|
|
|
134
134
|
## Provider protocol
|
package/docs/channel-backend.md
CHANGED
|
@@ -21,16 +21,17 @@ The response is `{status,reply}`. `queued` or `running` yields and resubmits the
|
|
|
21
21
|
same event after four seconds. `complete` or `failed` supplies a final string
|
|
22
22
|
reply, queued once with a deterministic outbox ID. Backend completion and
|
|
23
23
|
Telegram delivery are separate; an uncertain send never replays the operation.
|
|
24
|
-
|
|
24
|
+
A relay restart drops in-flight relay runs by design; the backend's resubmit of
|
|
25
|
+
the same event is the recovery path. Permanent
|
|
25
26
|
4xx responses leave a failed relay run for operator inspection; transient
|
|
26
27
|
failures back off. No response body or credential is logged.
|
|
27
28
|
|
|
28
29
|
Native `/new` and AI settings belong to the application. `/stop` cannot cancel
|
|
29
30
|
an application job and explicitly reports that limitation. `/cancel` removes
|
|
30
31
|
pending relay work only; it does not undo work already accepted by a backend.
|
|
31
|
-
External plugin
|
|
32
|
+
External plugin wakes do not dispatch through this channel backend.
|
|
32
33
|
|
|
33
34
|
Backend mode handles owner Telegram intake only. Existing native schedules,
|
|
34
|
-
restricted messaging tasks
|
|
35
|
+
restricted messaging tasks and plugin events are not
|
|
35
36
|
forwarded to the application and cannot launch a fallback CLI. Their scheduling
|
|
36
37
|
and authority remain separate from the application's own job lifecycle.
|
package/docs/docker-runtime.md
CHANGED
|
@@ -23,6 +23,18 @@ on the same CLI. Each agent gets its own purpose and native conversation IDs.
|
|
|
23
23
|
relay. `host-capable` sets `host` and reuses the installer UID; unlabeled
|
|
24
24
|
existing host transports stay host-capable so they are not flipped.
|
|
25
25
|
|
|
26
|
+
On Docker Desktop/OrbStack the control volume's Unix socket is not connectable
|
|
27
|
+
from the macOS host, so a host-capable agent also publishes an authenticated
|
|
28
|
+
loopback ledger endpoint (generated `ledger.compose.yaml` plus
|
|
29
|
+
`EZ_DELIVERY_TCP_PORT` in `docker.env`). The relay writes
|
|
30
|
+
`control/delivery-endpoint.json` (mode 600) with the port and per-start token;
|
|
31
|
+
host CLIs fall back to it when the socket is unreachable, and every request is
|
|
32
|
+
still re-authorized server-side. Isolated agents publish no endpoint. Existing
|
|
33
|
+
host-capable deployments created before this endpoint run
|
|
34
|
+
`ezenciel-agents-install migrate-ledger --deployment <absolute-directory>` once;
|
|
35
|
+
it is idempotent and does not restart services. If the chosen port is taken,
|
|
36
|
+
recreate the agent or edit `EZ_DELIVERY_TCP_PORT` and re-run Compose.
|
|
37
|
+
|
|
26
38
|
`docker.env` contains explicit absolute paths, never token values:
|
|
27
39
|
|
|
28
40
|
```dotenv
|
|
@@ -34,8 +46,19 @@ EZ_AGENT_WORKSPACE=/absolute/private/agents/family/mind
|
|
|
34
46
|
EZ_CONTROL_DIR=/absolute/private/agents/family/control
|
|
35
47
|
EZ_RELAY_ENV_FILE=/absolute/private/agents/family/relay.env
|
|
36
48
|
EZ_AGENT_PURPOSE_FILE=/absolute/private/agents/family/purpose.md
|
|
49
|
+
EZ_TOOLS_HOME=/absolute/private/agents/family/tools
|
|
50
|
+
EZ_PLUGIN_BROKER_SOCKET=/absolute/private/agents/family/control/plugin-broker.sock
|
|
51
|
+
EZ_PLUGIN_BROKER_HOST_CONFIG=/absolute/private/agents/family/host-executor.json
|
|
37
52
|
```
|
|
38
53
|
|
|
54
|
+
`ezenciel-agents-provision-telegram --config <private-config>` attaches Telegram
|
|
55
|
+
to an existing deployment. The private config names only the compose file,
|
|
56
|
+
project, secret and override paths; it never selects a relay image. The command
|
|
57
|
+
loads the deployment's own `docker.env`, so the relay restarts on its installed
|
|
58
|
+
image and version, then writes only the bot-token secret and a small override
|
|
59
|
+
that enables Telegram. That file must define `EZ_RELAY_IMAGE`; a shell export
|
|
60
|
+
never overrides it, and an incomplete record fails closed.
|
|
61
|
+
|
|
39
62
|
Host-capable agents run `ezenciel-agents-host` under the host's service manager
|
|
40
63
|
with `EZ_DEPLOYMENT_DIR` bound to that deployment. This small transport invokes
|
|
41
64
|
the existing CLI; it is not a second relay or model loop. Isolated agents do not
|
|
@@ -52,10 +75,14 @@ Only that agent's directories are mounted into its relay. Host-capable CLI reuse
|
|
|
52
75
|
state home with linked authentication; global memory/configuration is excluded.
|
|
53
76
|
Host-capable is not an OS security boundary between agents running as the same user.
|
|
54
77
|
Isolated agents use the relay mounts; sibling host paths are not present.
|
|
55
|
-
Plugin setup also binds `toolsHome` in the host configuration.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
Plugin setup also binds `toolsHome` in the host configuration. The isolated
|
|
79
|
+
runtime uses a separate `plugin-broker` Compose service: the relay receives only
|
|
80
|
+
the socket client and its normal mind/control mounts, while the broker receives
|
|
81
|
+
that agent's exact tools/workspace/control paths and the Docker socket. The
|
|
82
|
+
broker has no network, validates the host binding and registry owner, and is the
|
|
83
|
+
only service allowed to launch plugin containers. The relay never receives the
|
|
84
|
+
Docker socket or a tools registry mount. Host-capable agents keep the existing
|
|
85
|
+
host executor path instead.
|
|
59
86
|
|
|
60
87
|
## Operate and verify
|
|
61
88
|
|
|
@@ -86,19 +113,28 @@ bin/ezenciel-agents-docker up -d --wait
|
|
|
86
113
|
|
|
87
114
|
The owner supplies a real DM; verify the pending numeric sender before pairing.
|
|
88
115
|
Live smoke uses the same host CLI and requires an actual Telegram receipt.
|
|
89
|
-
Restart preserves pairing and files.
|
|
90
|
-
|
|
116
|
+
Restart preserves pairing and files. On boot the relay binds the live delivery
|
|
117
|
+
socket as the single-relay guard: a second relay refuses to start while that
|
|
118
|
+
address answers. Do not remove a live socket to bypass the guard.
|
|
91
119
|
Health requires recent polling and host-transport heartbeats, not just a process.
|
|
92
120
|
Relay replacement retains the existing 30-second startup grace and deployment
|
|
93
121
|
layout, so compatible releases remain eligible for agent-owned upgrades.
|
|
94
|
-
An interrupted Telegram poller keeps authorized work and in-flight
|
|
95
|
-
alive while it retries intake.
|
|
96
|
-
|
|
97
|
-
and uncertain
|
|
98
|
-
|
|
122
|
+
An interrupted Telegram poller keeps authorized work and in-flight deliveries
|
|
123
|
+
alive while it retries intake. Run and delivery records are relay memory: a
|
|
124
|
+
relay process restart drops in-flight work by design, Telegram redelivery is the
|
|
125
|
+
intake replay path, and uncertain sends report unknown instead of success.
|
|
126
|
+
A `409 Conflict` still requires the operator to stop the competing poller; it
|
|
127
|
+
remains unhealthy after the startup grace. Pending and uncertain deliveries keep
|
|
128
|
+
their existing receipt semantics; executor stdout is not replayed as a reply.
|
|
99
129
|
Signal and fatal-error paths share one shutdown; a secondary cleanup error is
|
|
100
130
|
reported without replacing the original startup/polling failure.
|
|
101
131
|
|
|
132
|
+
For an isolated agent, `COMPOSE_PROFILES=isolated` starts both `relay` and
|
|
133
|
+
`plugin-broker`; the `up` command above must not be narrowed to `relay`. The
|
|
134
|
+
broker socket is private to the agent's control directory. Its per-run receipt
|
|
135
|
+
is written under `control/plugin-receipts/<run-id>/`; a plugin's stdout remains
|
|
136
|
+
the provider/API receipt and is not treated as a relay message.
|
|
137
|
+
|
|
102
138
|
The separate `control-state.lock` serializes authority JSON updates across CLI
|
|
103
139
|
processes. A forced kill or host crash can orphan this exclusive-create sentinel.
|
|
104
140
|
It deliberately has no age/PID-based auto-reclamation: expiry cannot prove that a
|
|
@@ -126,6 +162,38 @@ and volume bindings. Never add standalone provider launchers or deployments.
|
|
|
126
162
|
Read the installed skill from the registry before onboarding; do not re-pair
|
|
127
163
|
an already connected account. Monitoring and sends require their own authority.
|
|
128
164
|
|
|
165
|
+
### Isolated plugin commands
|
|
166
|
+
|
|
167
|
+
The relay-side `ez` client sends only declared aliases, literal argument arrays,
|
|
168
|
+
bounded stdin, and the active run ID to the broker. The broker re-reads owner
|
|
169
|
+
authority and the registry before every call, pins the discovered revision, and
|
|
170
|
+
passes only the installed plugin's `run.application.context.plugins[plugin-id]`
|
|
171
|
+
object as `EZ_PLUGIN_CONTEXT`. Missing, revoked, cross-agent, expired, or reused
|
|
172
|
+
admissions fail closed. Timeouts, cancellation and bounded output produce a
|
|
173
|
+
failed broker receipt rather than a retry.
|
|
174
|
+
|
|
175
|
+
Source-based `plugins inspect`, `catalog-add`, and `install` management calls are
|
|
176
|
+
accepted only for an existing path inside that agent's mounted workspace, with a
|
|
177
|
+
literal SHA-256 revision where the command requires one. The same management
|
|
178
|
+
surface permits data-preserving `plugins uninstall` and local candidate
|
|
179
|
+
`updates prepare/apply/recover`; candidate archives must also be inside the
|
|
180
|
+
workspace. Public update discovery stays with the host supervisor because the
|
|
181
|
+
broker has no network. The broker never turns an arbitrary host path into a
|
|
182
|
+
plugin mount.
|
|
183
|
+
|
|
184
|
+
Each agent has one registry and one broker binding. Registries, plugin source
|
|
185
|
+
snapshots, shared workers and Library/embedding state are not implicitly shared
|
|
186
|
+
between agents or organizations. A reviewed shared worker or an application
|
|
187
|
+
backend must be attached through its own explicit per-agent binding; it does not
|
|
188
|
+
grant the relay or Library containers Docker access.
|
|
189
|
+
|
|
190
|
+
An isolated agent created before this change has no `tools/` directory, broker
|
|
191
|
+
socket environment, or `COMPOSE_PROFILES` entry: recreate the agent (or backfill
|
|
192
|
+
`tools/`, `EZ_TOOLS_HOME`, `EZ_PLUGIN_BROKER_SOCKET`,
|
|
193
|
+
`EZ_PLUGIN_BROKER_HOST_CONFIG`, and the isolated profile) before its plugins
|
|
194
|
+
will run. Until then the broker refuses to start and health reports
|
|
195
|
+
`PLUGIN_BROKER_UNREADABLE` — fail-closed, never half-provisioned.
|
|
196
|
+
|
|
129
197
|
For event intake, mount only the registered plugin project's socket/client
|
|
130
198
|
exports into the relay, read-only. The event source stores a cursor and policy
|
|
131
199
|
binding; it is not a second plugin installation. Provider credentials remain in
|
package/docs/local-qa.md
CHANGED
|
@@ -6,7 +6,7 @@ an immutable candidate in the PA's local tools directory. The agent reads its
|
|
|
6
6
|
manifest and uses `ez updates prepare main --file ...` and `apply` on the owner's
|
|
7
7
|
request. Automatic public update policy stays unchanged.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Commit, push and open a PR first — then stage only from that PR's exact commit. The staging script refuses dirty checkouts, so uncommitted work can never become a candidate. If QA finds issues, fix forward in the same PR (or a new PR) and stage a new versioned candidate; never leave a QA-only copy lingering outside the PR:
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
12
|
node scripts/stage-qa.mjs --source /absolute/feature-checkout \
|
|
@@ -32,7 +32,7 @@ Add the catalog path and the following instructions to the PA's local policy fil
|
|
|
32
32
|
> If no local entry exists, report that; do not silently substitute a public beta.
|
|
33
33
|
> Follow an explicit request for a public npm release separately.
|
|
34
34
|
|
|
35
|
-
For every feature, the developer handoff includes the beta label, exact private
|
|
35
|
+
For every feature, the developer handoff includes the PR URL, beta label, exact private
|
|
36
36
|
version, source commit, checks completed and a short user-facing QA flow with
|
|
37
37
|
expected results. Include any limitations. A prepared archive or healthy service
|
|
38
38
|
does not prove the feature works; read back its result through the PA.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Build, install, and publish an Ez plugin
|
|
2
|
+
|
|
3
|
+
This is the shareable guide for open-source Ez plugin authors. It covers the
|
|
4
|
+
smallest path from a plugin checkout to a working private installation, and
|
|
5
|
+
the separate path for publishing and listing a public product.
|
|
6
|
+
|
|
7
|
+
The detailed documents linked below remain the normative references for release
|
|
8
|
+
and security edge cases. This page is the front door.
|
|
9
|
+
|
|
10
|
+
## The important distinction
|
|
11
|
+
|
|
12
|
+
An Ez plugin can be useful before it is published. These are separate states:
|
|
13
|
+
|
|
14
|
+
| State | What it means | What is required |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Local-only | You install your own reviewed checkout or tarball on your agent. | A valid package, an inspected content hash, and real executor verification. No npm publication or catalog entry. |
|
|
17
|
+
| Catalog-listed | Ez publicly records the plugin as a product capability. | A catalog PR with the canonical repository, package identity, capability, and release links. Registration does not prove that a release exists. |
|
|
18
|
+
| Released | Other users can install an immutable package from npm/GitHub. | Release checks, exact artifact/hash readback, a tagged GitHub release, registry publication, and clean-host verification. |
|
|
19
|
+
|
|
20
|
+
Do not treat a catalog entry, a GitHub workflow, or a package name as proof that
|
|
21
|
+
an artifact was published. Read back the actual npm and GitHub release records.
|
|
22
|
+
|
|
23
|
+
## 1. Define the plugin boundary
|
|
24
|
+
|
|
25
|
+
Use a plugin when the capability needs provider or domain authentication,
|
|
26
|
+
deterministic validation, private state, or provider receipts. The native AI
|
|
27
|
+
engine owns inference, sessions, context, reasoning, tool choice, and
|
|
28
|
+
continuation. Ez core owns authorization, transport, scheduling, cancellation,
|
|
29
|
+
session binding, and delivery receipts.
|
|
30
|
+
|
|
31
|
+
Keep provider behavior out of the relay and do not add another agent runner,
|
|
32
|
+
model router, conversation engine, prompt-history store, or competing queue.
|
|
33
|
+
General plugins live in the Ez plugin repositories; a product-specific plugin
|
|
34
|
+
stays with the product that owns its canonical data and policy. See the
|
|
35
|
+
[plugin architecture](../../planning/docs/architecture-plugins.md).
|
|
36
|
+
|
|
37
|
+
## 2. Build the smallest valid package
|
|
38
|
+
|
|
39
|
+
At minimum, provide:
|
|
40
|
+
|
|
41
|
+
- `package.json` with a unique scoped package name, SemVer version, repository
|
|
42
|
+
URLs, `files` allowlist, and supported Node/package-manager versions.
|
|
43
|
+
- A frozen lockfile, `LICENSE`, and `THIRD_PARTY_NOTICES.md`.
|
|
44
|
+
- `README.md` explaining purpose, requirements, exact install/start/onboarding
|
|
45
|
+
commands, one working read example, identity/account binding, limitations,
|
|
46
|
+
and troubleshooting.
|
|
47
|
+
- `Dockerfile` and `.dockerignore` when the plugin has a managed service.
|
|
48
|
+
- `ez-plugin.json` with the stable plugin id, matching version, commands, and
|
|
49
|
+
skill paths. Declare command exposure for external content, external sends,
|
|
50
|
+
record changes, and requested review.
|
|
51
|
+
- `ez-deployment.json` when the plugin has managed services, volumes,
|
|
52
|
+
healthchecks, exports, or deployment dependencies.
|
|
53
|
+
- A skill such as `skills/<plugin>/SKILL.md` covering required inputs, private
|
|
54
|
+
credential handling, external handoffs, resumption/recovery, and readiness
|
|
55
|
+
evidence.
|
|
56
|
+
- Offline contract/negative tests, `--help`, a read-only doctor, bounded
|
|
57
|
+
machine-readable commands, stable exit codes, and readback for writes.
|
|
58
|
+
|
|
59
|
+
The manager snapshots the package according to `package.json.files` plus the
|
|
60
|
+
required manifests and Docker inputs. Keep one canonical checkout; do not keep
|
|
61
|
+
permanent packaged copies or a second registry. See the full
|
|
62
|
+
[plugin contribution requirements](plugin-contributions.md) and the
|
|
63
|
+
[plugin manager contract](plugins.md#deployment-descriptors).
|
|
64
|
+
|
|
65
|
+
A typical package layout is:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
plugin/
|
|
69
|
+
├── bin/ # executable entry points
|
|
70
|
+
├── skills/<plugin>/SKILL.md
|
|
71
|
+
├── src/
|
|
72
|
+
├── test/
|
|
73
|
+
├── Dockerfile # if a service is managed
|
|
74
|
+
├── ez-plugin.json
|
|
75
|
+
├── ez-deployment.json # if a service is managed
|
|
76
|
+
├── package.json
|
|
77
|
+
├── pnpm-lock.yaml
|
|
78
|
+
├── README.md
|
|
79
|
+
├── LICENSE
|
|
80
|
+
└── THIRD_PARTY_NOTICES.md
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 3. Test and install it before publishing
|
|
84
|
+
|
|
85
|
+
From the plugin checkout, run the package's documented checks. The standard
|
|
86
|
+
baseline is:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
pnpm install --frozen-lockfile
|
|
90
|
+
pnpm verify
|
|
91
|
+
npm run release:check
|
|
92
|
+
git diff --check
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Run the plugin's Docker/manager smoke test when it has a managed service.
|
|
96
|
+
Verify installation, start/stop, the registered command, restart persistence,
|
|
97
|
+
and non-destructive uninstall using synthetic data. Then run one authorized,
|
|
98
|
+
supported operation through the actual bound executor and verify its canonical
|
|
99
|
+
result or provider receipt.
|
|
100
|
+
|
|
101
|
+
### Install from local source or an unpublished tarball
|
|
102
|
+
|
|
103
|
+
Publication is not required. Inspect the exact source first:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
ez plugins inspect <id> --source /absolute/plugin
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Use the returned revision for either a one-off install:
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
ez plugins install <id> --source /absolute/plugin --revision sha256:<inspected-hash>
|
|
113
|
+
ez plugins start <id>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Or save the reviewed source in the agent's local catalog, then install it by
|
|
117
|
+
the catalog entry:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
ez plugins catalog-add <id> --source /absolute/plugin --revision sha256:<inspected-hash>
|
|
121
|
+
ez plugins install <id>
|
|
122
|
+
ez plugins start <id>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
After startup, verify the installed command from the actual executor:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
ez plugins status <id>
|
|
129
|
+
ez tools list
|
|
130
|
+
ez <command> doctor --json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use the plugin's real supported operation as the acceptance test. Health,
|
|
134
|
+
registration, or a successful `--help` command alone is not completion. A
|
|
135
|
+
changed source must be inspected again; never install a stale catalog hash.
|
|
136
|
+
|
|
137
|
+
## 4. Prepare a public release
|
|
138
|
+
|
|
139
|
+
Use an isolated release worktree and reviewed PR. Then:
|
|
140
|
+
|
|
141
|
+
1. Bump the package and plugin manifest to the same new SemVer version. Add
|
|
142
|
+
changelog and migration notes for breaking CLI or state changes.
|
|
143
|
+
2. Run frozen dependency installation, package tests, release checks, Docker
|
|
144
|
+
checks, `git diff --check`, dependency/license review, and the actual manager
|
|
145
|
+
smoke test.
|
|
146
|
+
3. Create the candidate with `npm pack --ignore-scripts`. Inspect its file list,
|
|
147
|
+
compute and record its SHA-256, extract it into a fresh directory, reinstall
|
|
148
|
+
from the artifact, and repeat the CLI/runtime checks there.
|
|
149
|
+
4. For a first release or onboarding change, install that exact candidate on a
|
|
150
|
+
disposable clean host and verify the real executor, restart/boot behavior,
|
|
151
|
+
account binding, and first supported operation.
|
|
152
|
+
5. With explicit release authorization, tag the reviewed source, publish the
|
|
153
|
+
exact tested artifact, create the matching GitHub prerelease/release, and
|
|
154
|
+
read back npm metadata, the downloaded tarball hash, release assets, and
|
|
155
|
+
source/tag identity.
|
|
156
|
+
6. Install the published version on a clean host and repeat the relevant
|
|
157
|
+
verification before calling the release complete.
|
|
158
|
+
|
|
159
|
+
For the complete release checklist, use [Releasing](releasing.md). For
|
|
160
|
+
unattended beta publication, use [Verified beta publication](trusted-publishing.md);
|
|
161
|
+
it defines the immutable GitHub asset, sanitized receipt, OIDC trust, dispatch,
|
|
162
|
+
and failure-reconciliation rules. Do not put npm tokens in CI or publish merely
|
|
163
|
+
to test authentication.
|
|
164
|
+
|
|
165
|
+
## 5. List it as a public product
|
|
166
|
+
|
|
167
|
+
Catalog registration is a discovery and product step, not installation
|
|
168
|
+
authority. Open a PR updating [Available plugins](plugin-catalog.md) with:
|
|
169
|
+
|
|
170
|
+
- the product name and one concrete capability description;
|
|
171
|
+
- the canonical public source repository;
|
|
172
|
+
- the exact npm package identity; and
|
|
173
|
+
- canonical npm and GitHub release links.
|
|
174
|
+
|
|
175
|
+
Only advertise a version as installable after verifying that it exists in the
|
|
176
|
+
registry and in the matching GitHub release. A public catalog entry may exist
|
|
177
|
+
while its first release is still pending; label that state clearly and do not
|
|
178
|
+
present it as an installable version. Keep local/private plugins out of the
|
|
179
|
+
public catalog; they can still be installed by reviewed source and an inspected
|
|
180
|
+
hash.
|
|
181
|
+
|
|
182
|
+
## The short checklist
|
|
183
|
+
|
|
184
|
+
### Own agent / unpublished
|
|
185
|
+
|
|
186
|
+
- [ ] Package, manifests, skill, README, license/notices, and tests exist.
|
|
187
|
+
- [ ] `pnpm verify`, release checks, and the manager/Docker smoke pass.
|
|
188
|
+
- [ ] Source or tarball is inspected and installed with its returned hash.
|
|
189
|
+
- [ ] The actual bound executor performs a real supported operation.
|
|
190
|
+
|
|
191
|
+
### Public product
|
|
192
|
+
|
|
193
|
+
- [ ] The exact candidate is packed, inspected, hashed, and clean-host tested.
|
|
194
|
+
- [ ] Release authorization, tag, GitHub asset, npm publication, and readback
|
|
195
|
+
all refer to the same source and bytes.
|
|
196
|
+
- [ ] A clean installation of the published version is verified.
|
|
197
|
+
- [ ] The public catalog is updated only with verified repository/package/release
|
|
198
|
+
records.
|
|
199
|
+
|
|
200
|
+
For contribution, security, and removal details, follow the links above and the
|
|
201
|
+
plugin's own `CONTRIBUTING.md`, `SECURITY.md`, and README.
|
|
202
|
+
|
package/docs/plugins.md
CHANGED
|
@@ -48,6 +48,31 @@ Job requests cannot override this host binding. Filesystem access remains
|
|
|
48
48
|
`workspace-write`; other agents' directories are not added. Docker access is
|
|
49
49
|
host administration under the existing trusted-host model, not OS isolation.
|
|
50
50
|
|
|
51
|
+
For an isolated Codex agent, this binding is consumed by the per-agent
|
|
52
|
+
`plugin-broker` service, not by a host executor. Start the deployment only after
|
|
53
|
+
initialization with `COMPOSE_PROFILES=isolated`; Compose then starts the relay
|
|
54
|
+
and broker together. The relay-side `ez` command has no tools-home or Docker
|
|
55
|
+
socket mount. It sends a declared alias, literal arguments, bounded stdin and
|
|
56
|
+
the active run ID over the private control-directory Unix socket. The broker
|
|
57
|
+
revalidates the exact registry/host/workspace ownership, pinned revision and
|
|
58
|
+
owner-authorized run before launching the plugin container.
|
|
59
|
+
|
|
60
|
+
The broker writes bounded invocation metadata to
|
|
61
|
+
`control/plugin-receipts/<run-id>/`. Plugin stdout/stderr and exit status remain
|
|
62
|
+
available to the native command, including provider/API receipts. Application
|
|
63
|
+
context is narrowed to the installed plugin ID and forwarded as opaque
|
|
64
|
+
`EZ_PLUGIN_CONTEXT`; it is absent from ordinary native commands. No registry,
|
|
65
|
+
plugin container, shared worker, Library index or embedding store is shared
|
|
66
|
+
across agents unless an operator adds an explicit reviewed binding.
|
|
67
|
+
|
|
68
|
+
The same broker accepts source-based `plugins inspect`, `catalog-add`, and
|
|
69
|
+
`install` only when the source is an existing path under the bound workspace and
|
|
70
|
+
the revision is literal and pinned. It also exposes data-preserving
|
|
71
|
+
`plugins uninstall` and the local-file `updates prepare/apply/recover` lifecycle.
|
|
72
|
+
Candidate archives must be staged inside the bound workspace; public registry
|
|
73
|
+
discovery remains host-supervisor work because the broker has no network. Paths
|
|
74
|
+
outside that workspace are rejected.
|
|
75
|
+
|
|
51
76
|
## Installation completion contract
|
|
52
77
|
|
|
53
78
|
For initial Ez onboarding, plugin requests happen in the working Telegram
|
|
@@ -255,6 +280,26 @@ never retries a provider operation. Service startup/restart is explicit; command
|
|
|
255
280
|
never implicitly start a stopped provider service. Plugin data does not enter the
|
|
256
281
|
relay. The manager sends only a whitelist of Docker client environment variables.
|
|
257
282
|
|
|
283
|
+
### Application plugin context
|
|
284
|
+
|
|
285
|
+
An authenticated application can attach opaque domain data under
|
|
286
|
+
`context.plugins.<plugin-id>` when it submits a run. During that active,
|
|
287
|
+
authorized application run, the matching plugin command container receives only
|
|
288
|
+
that object as JSON in `EZ_PLUGIN_CONTEXT`. No other plugin context, core control
|
|
289
|
+
state, owner identity, or application context is forwarded. Ordinary native runs
|
|
290
|
+
and commands launched outside an application run receive no such environment
|
|
291
|
+
variable. The manager authorizes the active run and application binding at command
|
|
292
|
+
admission (prepare time) and rejects revoked authority there; revocation between
|
|
293
|
+
admission and container start is a documented residual window. Transport is a
|
|
294
|
+
`0o600` one-shot compose override consumed via `--file` that sets the command
|
|
295
|
+
service environment directly, never process arguments; the value remains
|
|
296
|
+
visible in `docker inspect` while the container runs.
|
|
297
|
+
|
|
298
|
+
Use this for a short-lived, domain-scoped capability or an application service
|
|
299
|
+
address. It is not prompt text, a general secret channel, or an environment
|
|
300
|
+
override. Plugin code must validate the object, avoid printing it, and send it
|
|
301
|
+
only to its authoritative service over the reviewed transport.
|
|
302
|
+
|
|
258
303
|
## Verification
|
|
259
304
|
|
|
260
305
|
`npm run verify` runs offline negative/contract tests. Explicit Docker integration:
|
|
@@ -343,8 +388,9 @@ on the next read, without hooks, LLM calls or a cached inventory file.
|
|
|
343
388
|
|
|
344
389
|
`ez tools list` retains its alias mapping for existing clients. Native AGENTS.md
|
|
345
390
|
contains only the agent-bound discovery shortcut. New workspaces do not seed
|
|
346
|
-
TOOLS.md
|
|
347
|
-
|
|
391
|
+
TOOLS.md, SOUL.md, USER.md, or an `inbox/`/`work/` layout; upgrades preserve
|
|
392
|
+
legacy notes without rewriting them. Keep owner/account policies in agent
|
|
393
|
+
instructions or linked policy files, separate from plugin metadata.
|
|
348
394
|
|
|
349
395
|
Folder bindings default to read-only. For an explicitly authorized plugin that
|
|
350
396
|
updates the existing source, add `--writable` to `folder-bind` while the plugin
|
package/docs/releasing.md
CHANGED
|
@@ -77,7 +77,20 @@ read back `npm view @jc_stack/ez-agents@0.1.0-beta.12 name version dist-tags --j
|
|
|
77
77
|
contents/checksum against the reviewed artifact. Keep the npm artifact and
|
|
78
78
|
GitHub tag on the same reviewed commit. Do not create a new token to bypass 2FA.
|
|
79
79
|
|
|
80
|
+
Source-checkout images for a deployment are RC builds of the unreleased commit:
|
|
81
|
+
`ezenciel-agents-install build --label X.Y.Z-beta.N.rc.M` (increasing `.rc.N`)
|
|
82
|
+
from the clean reviewed commit after the PR is open. The label and commit SHA are
|
|
83
|
+
baked into the image; `/status` shows the RC tag first. Never install an
|
|
84
|
+
unlabeled source build or reuse an RC label for different contents.
|
|
85
|
+
|
|
80
86
|
## Agent-owned upgrades
|
|
81
87
|
|
|
82
88
|
This beta includes owner-policy release checks and durable
|
|
83
89
|
main/plugin replacement. See [upgrade setup, tools and recovery](upgrades.md). Earlier main upgrade/rollback VM QA passed; final-release fresh-host/reboot and live plugin upgrade acceptance remain pending.
|
|
90
|
+
|
|
91
|
+
Automatic main upgrades are gated on deployment compatibility: the candidate's
|
|
92
|
+
`compose.yaml` and `compose.whatsapp.yaml` must match the release the agent
|
|
93
|
+
already runs, or that installed release must carry the reviewed migration.
|
|
94
|
+
Before publishing a release, confirm no compose change slipped in since the
|
|
95
|
+
previous tag; otherwise bootstrap the agents or ship the migration in the
|
|
96
|
+
release they already run.
|
|
@@ -15,4 +15,4 @@ Authorization, sandboxing and tool handlers enforce contact and lifecycle limits
|
|
|
15
15
|
An owner-approved channel capability adds only a fixed installed alias declared
|
|
16
16
|
as a read-only channel query; it does not expose the workspace, shell, owner
|
|
17
17
|
session or other installed tools.
|
|
18
|
-
|
|
18
|
+
Group notifications carry event data; CLI help owns operations.
|
package/docs/scheduling.md
CHANGED
|
@@ -94,10 +94,10 @@ queued occurrence; already-running work continues until explicitly cancelled.
|
|
|
94
94
|
|
|
95
95
|
`/stop` stops all active work; `cancel RUN_ID` stops one background task. `/cancel`
|
|
96
96
|
clears queued work. Pause/remove a recurring schedule to prevent future runs.
|
|
97
|
-
Stopping the relay also stops its workers.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
the evidence and explicitly edits the schedule. Inspect the task's files, native session and delivery
|
|
97
|
+
Stopping the relay also stops its workers. Run and delivery records are relay
|
|
98
|
+
memory: a process restart drops in-flight runs and queued deliveries by design,
|
|
99
|
+
so the next eligible occurrence dispatches normally and nothing is replayed from
|
|
100
|
+
disk. Status labels failed runs as history and shows recent reasons; new failures retain their exit code or interruption cause. Typing indicators stop after 30 seconds even when work continues. A failed run that cannot prove whether an external side effect happened stays visible until the agent inspects the evidence and explicitly edits the schedule. Inspect the task's files, native session and delivery
|
|
101
101
|
receipts before deciding whether to resume. A clock cannot reconstruct an
|
|
102
102
|
in-flight process or prove whether an external side effect happened.
|
|
103
103
|
|
package/docs/setup.md
CHANGED
|
@@ -125,6 +125,8 @@ pnpm install --frozen-lockfile
|
|
|
125
125
|
export PATH="$PWD/bin:$PATH"
|
|
126
126
|
export EZ_AGENTS_HOME=/absolute/private/agents
|
|
127
127
|
node bin/ezenciel-agents-install build
|
|
128
|
+
# Source checkout only: commit, open the PR, then build
|
|
129
|
+
# node bin/ezenciel-agents-install build --label X.Y.Z-beta.N.rc.M
|
|
128
130
|
# Set EZ_RELAY_IMAGE to the exact image returned by build for create/start.
|
|
129
131
|
export EZ_RELAY_IMAGE='<returned-image>'
|
|
130
132
|
```
|
|
@@ -132,7 +134,10 @@ export EZ_RELAY_IMAGE='<returned-image>'
|
|
|
132
134
|
Node 22+ and pnpm 10.30.3 are needed by the host transport. The tarball carries
|
|
133
135
|
its lockfile under docker/ because npm excludes the root pnpm lockfile. Do not
|
|
134
136
|
move this package directory after binding a service to its absolute paths.
|
|
135
|
-
For a source checkout the root lockfile is already present.
|
|
137
|
+
For a source checkout the root lockfile is already present. A source checkout is
|
|
138
|
+
an RC: commit and open the PR first, then `build --label X.Y.Z-beta.N.rc.M`; the
|
|
139
|
+
command refuses a dirty tree and bakes the RC tag and commit into the image so
|
|
140
|
+
`/status` never reports the bare package version. Do not run a second
|
|
136
141
|
copy of an existing bot token. Continue with the per-agent configuration below.
|
|
137
142
|
|
|
138
143
|
Verify the tarball against its adjacent `.sha256` or the kit's `SHA256SUMS` before
|
|
@@ -270,8 +275,9 @@ the plugin skill through onboarding and verified use under that same request.
|
|
|
270
275
|
Never silently reuse a global `ez` from the old sandbox runtime.
|
|
271
276
|
|
|
272
277
|
4. Isolated agents skip host transport. Run `bin/ezenciel-agents-docker up -d --wait`
|
|
273
|
-
from the deployment directory.
|
|
274
|
-
|
|
278
|
+
from the deployment directory. This starts the local relay and its per-agent
|
|
279
|
+
isolated plugin broker; do not narrow the command to `relay`. Do not register
|
|
280
|
+
`ezenciel-agents-host` for them; starting it fails closed.
|
|
275
281
|
|
|
276
282
|
Host-capable agents follow [host startup templates](host-service.md). Register
|
|
277
283
|
`bin/ezenciel-agents-host` with the host's native service manager, binding
|
|
@@ -330,9 +336,9 @@ default. Existing queued jobs retain their captured execution choice.
|
|
|
330
336
|
| Symptom | Inspect and recover |
|
|
331
337
|
|---|---|
|
|
332
338
|
| Docker unavailable | Check engine and Compose, start the supported installation; complete any required OS consent. |
|
|
333
|
-
| Bot stays silent | Check pending owner identity, relay health, host heartbeat (host-capable only) and
|
|
339
|
+
| Bot stays silent | Check pending owner identity, relay health, host heartbeat (host-capable only) and delivery receipts; approve only the verified owner. |
|
|
334
340
|
| CLI exits without reply | Inspect the actual tool result and delivery receipt; stdout is not Telegram output. |
|
|
335
|
-
|
|
|
341
|
+
| Second relay refuses to start | A live relay already owns this deployment's delivery socket; stop the exact duplicate, never remove a live socket. |
|
|
336
342
|
| Plugin absent | Check the bound catalog and install/start the reviewed package explicitly; no plugin ships by default. |
|
|
337
343
|
| Plugin revision mismatch | Reinspect stable source, review the changed hash and explicitly update its catalog pin. |
|
|
338
344
|
| Interrupted CLI cannot resume | Use the explicit new-conversation command after inspecting the failure; no automatic fallback. |
|