@jc_stack/ez-agents 0.1.0-beta.33 → 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.
Files changed (157) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.example +9 -16
  3. package/AGENTS.md +17 -9
  4. package/CHANGELOG.md +92 -0
  5. package/Dockerfile +11 -9
  6. package/README.md +32 -27
  7. package/THIRD_PARTY_NOTICES.md +4 -4
  8. package/bin/ez +97 -0
  9. package/bin/ezenciel-agents-plugin-broker.mjs +16 -0
  10. package/bin/ezenciel-agents-provision-telegram.mjs +13 -0
  11. package/bin/ezenciel-agents.mjs +1 -1
  12. package/compose.yaml +42 -5
  13. package/docker/entrypoint.sh +1 -1
  14. package/docker/healthcheck.mjs +12 -4
  15. package/docker/run.ts +5 -6
  16. package/docker/smoke.mjs +32 -7
  17. package/docs/application-channel.md +38 -10
  18. package/docs/architecture/ai-selection.md +3 -1
  19. package/docs/architecture/authority-boundaries.md +2 -2
  20. package/docs/channel-backend.md +4 -3
  21. package/docs/docker-runtime.md +106 -21
  22. package/docs/host-service.md +17 -6
  23. package/docs/local-qa.md +2 -2
  24. package/docs/plugin-guide.md +202 -0
  25. package/docs/plugins.md +63 -2
  26. package/docs/releasing.md +13 -0
  27. package/docs/repair.md +1 -1
  28. package/docs/responsive-channels.md +1 -1
  29. package/docs/scheduling.md +4 -4
  30. package/docs/setup.md +96 -16
  31. package/docs/standalone-cli.md +6 -5
  32. package/docs/upgrades.md +46 -23
  33. package/package.json +5 -5
  34. package/scripts/smoke-scheduler.ts +12 -4
  35. package/scripts/smoke.ts +14 -11
  36. package/src/agent-guidance.ts +6 -9
  37. package/src/agent-install.ts +44 -9
  38. package/src/ai-cli.ts +9 -7
  39. package/src/ai.ts +7 -7
  40. package/src/application-channel.ts +88 -17
  41. package/src/application-cli.ts +2 -2
  42. package/src/approval-cli.ts +14 -7
  43. package/src/approval.ts +27 -37
  44. package/src/channel-backend.ts +2 -3
  45. package/src/codex-session.ts +5 -3
  46. package/src/config.ts +18 -28
  47. package/src/control-state.ts +187 -9
  48. package/src/conversation-menu.ts +6 -17
  49. package/src/delivery-socket-client.d.mts +4 -0
  50. package/src/delivery-socket-client.mjs +104 -0
  51. package/src/delivery-socket.ts +354 -0
  52. package/src/execution-authority.ts +21 -5
  53. package/src/executor.ts +110 -31
  54. package/src/files.ts +38 -11
  55. package/src/host-executor.ts +50 -17
  56. package/src/inbox.ts +15 -49
  57. package/src/index.ts +96 -52
  58. package/src/install-config.ts +2 -2
  59. package/src/install-tools.mjs +100 -23
  60. package/src/isolation.ts +25 -0
  61. package/src/ledger-endpoint.d.mts +2 -0
  62. package/src/ledger-endpoint.mjs +17 -0
  63. package/src/menu.ts +16 -8
  64. package/src/message-history.ts +13 -18
  65. package/src/message.ts +35 -18
  66. package/src/plugin-broker.mjs +396 -0
  67. package/src/plugins/connection.mjs +2 -2
  68. package/src/plugins/manager.mjs +178 -26
  69. package/src/plugins/native-tasks.mjs +2 -2
  70. package/src/prompt-suffix.ts +12 -0
  71. package/src/react.ts +6 -4
  72. package/src/runs.ts +156 -243
  73. package/src/schedule-cli.ts +29 -10
  74. package/src/scheduled-tasks.ts +53 -10
  75. package/src/scheduler.ts +20 -7
  76. package/src/service.ts +3 -3
  77. package/src/setup.ts +11 -7
  78. package/src/software-status.ts +36 -4
  79. package/src/task-executor.ts +6 -3
  80. package/src/task-workspace.ts +4 -3
  81. package/src/tasks.ts +1 -1
  82. package/src/telegram-provisioning-cli.ts +22 -0
  83. package/src/telegram-provisioning.ts +214 -0
  84. package/src/updates/control.mjs +77 -7
  85. package/src/updates/runtime.mjs +29 -9
  86. package/src/updates/status.mjs +25 -3
  87. package/src/updates/supervisor.mjs +31 -18
  88. package/src/version.ts +20 -0
  89. package/src/workspace-confine.ts +38 -0
  90. package/src/workspace.ts +24 -20
  91. package/templates/agent-purpose.md +1 -0
  92. package/templates/failure-review.md +1 -1
  93. package/templates/maintainer-purpose.md +1 -1
  94. package/test/agent-guidance.test.ts +18 -88
  95. package/test/agent-install.test.ts +48 -0
  96. package/test/ai-cli.test.ts +18 -0
  97. package/test/ai.test.ts +84 -0
  98. package/test/application-channel.test.ts +66 -15
  99. package/test/application-controls.test.ts +56 -3
  100. package/test/application-only.test.ts +16 -13
  101. package/test/channel-backend.test.ts +3 -7
  102. package/test/channel-delivery.test.ts +4 -1
  103. package/test/channel-owner.test.ts +6 -3
  104. package/test/codex-context.test.ts +63 -3
  105. package/test/codex-session.test.ts +6 -1
  106. package/test/config.test.ts +47 -37
  107. package/test/control-state.test.ts +83 -4
  108. package/test/conversation-menu.test.ts +2 -4
  109. package/test/delivery-transport.test.ts +72 -0
  110. package/test/docker-runtime.test.ts +27 -14
  111. package/test/engine-handoff.test.ts +12 -8
  112. package/test/event-sources.test.ts +2 -2
  113. package/test/execution-authority.test.ts +9 -9
  114. package/test/executor.test.ts +47 -11
  115. package/test/failure.test.ts +18 -5
  116. package/test/files.test.ts +2 -2
  117. package/test/helpers/ledger.ts +18 -0
  118. package/test/host-executor.test.ts +80 -0
  119. package/test/inbox.test.ts +8 -10
  120. package/test/install-config.test.ts +18 -6
  121. package/test/install-tools.test.mjs +80 -7
  122. package/test/intake-relay.test.ts +58 -11
  123. package/test/message-history.test.ts +39 -47
  124. package/test/native-tasks.test.ts +1 -1
  125. package/test/plugin-broker.test.mjs +172 -0
  126. package/test/plugin-manager.test.mjs +143 -5
  127. package/test/reaction.test.ts +4 -0
  128. package/test/relay.test.ts +5 -7
  129. package/test/repair-policy.test.ts +1 -4
  130. package/test/schedule-cli.test.ts +14 -9
  131. package/test/scheduled-tasks.test.ts +29 -6
  132. package/test/scheduler-host.test.ts +5 -5
  133. package/test/scheduler-relay.test.ts +15 -9
  134. package/test/scheduler.test.ts +2 -2
  135. package/test/security.test.ts +6 -3
  136. package/test/software-status.test.ts +21 -3
  137. package/test/telegram-provisioning.test.ts +160 -0
  138. package/test/updates.test.mjs +102 -13
  139. package/test/workspace-confine.test.ts +47 -0
  140. package/test/workspace.test.ts +27 -11
  141. package/bin/ezenciel-agents-watch.mjs +0 -8
  142. package/compose.workforce-watch.yaml +0 -33
  143. package/docker/recovery.ts +0 -11
  144. package/docs/pagerduty.md +0 -42
  145. package/docs/workforce-watch.md +0 -101
  146. package/src/pagerduty.ts +0 -109
  147. package/src/reply-context.ts +0 -44
  148. package/src/update-attention.ts +0 -18
  149. package/src/workforce-watch-cli.ts +0 -14
  150. package/src/workforce-watch.ts +0 -155
  151. package/templates/agent/AGENTS.md +0 -15
  152. package/templates/agent/SOUL.md +0 -11
  153. package/templates/agent/USER.md +0 -5
  154. package/templates/agent-guidance.md +0 -114
  155. package/test/pagerduty.test.ts +0 -104
  156. package/test/update-attention.test.ts +0 -20
  157. package/test/workforce-watch.test.ts +0 -180
@@ -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:
@@ -291,6 +336,21 @@ already exist on the host. Keep indexes and writable metadata in the plugin's
291
336
  normal volume. This uses Docker bind mounts; it copies no source bytes and
292
337
  starts no provider sync. Read-only is the default.
293
338
 
339
+ For a relay-bound agent, the source must be inside its workspace/shared workspace
340
+ or under a plugin-specific root granted in the agent's external host configuration:
341
+
342
+ ```json
343
+ {
344
+ "pluginFolderRoots": {
345
+ "library": ["/absolute/existing/notes"]
346
+ }
347
+ }
348
+ ```
349
+
350
+ The agent cannot add this grant through its registry. A missing grant fails before
351
+ Compose or registry state changes. Standalone registries remain operator-owned and
352
+ do not use a relay host allowlist.
353
+
294
354
  Stop the plugin before changing a binding:
295
355
 
296
356
  ```sh
@@ -328,8 +388,9 @@ on the next read, without hooks, LLM calls or a cached inventory file.
328
388
 
329
389
  `ez tools list` retains its alias mapping for existing clients. Native AGENTS.md
330
390
  contains only the agent-bound discovery shortcut. New workspaces do not seed
331
- TOOLS.md; upgrades preserve legacy notes without rewriting them. Keep owner/account
332
- policies in agent instructions or linked policy files, separate from plugin metadata.
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.
333
394
 
334
395
  Folder bindings default to read-only. For an explicitly authorized plugin that
335
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.
package/docs/repair.md CHANGED
@@ -30,7 +30,7 @@ True makes the capability available; it does not itself grant a repair mandate.
30
30
  The setting does not change filesystem/GitHub permissions and does
31
31
  not cancel an already running task. Explicitly stop active repair work when needed.
32
32
  An owner can also disable repairs globally or for a repository in the agent's
33
- saved USER.md preferences; carry those restrictions into background task context.
33
+ saved AGENTS.md preferences; carry those restrictions into background task context.
34
34
 
35
35
  ## Setup boundary
36
36
 
@@ -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
- Maintenance and group notifications carry event data; CLI help owns operations.
18
+ Group notifications carry event data; CLI help owns operations.
@@ -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. A crashed or interrupted execution is
98
- not automatically replayed. 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. Runs found active at startup are marked failed with
99
- `interrupted: true`; their schedule revision stays held until the agent inspects
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
@@ -67,8 +67,23 @@ not imported into restricted sessions. No workflow prompt is added to input.
67
67
  Use the existing owner's host account. Unless a layout was supplied, use
68
68
  `${XDG_DATA_HOME:-$HOME/.local/share}/ez/packages/<version>/` for extracted main
69
69
  packages and `${XDG_DATA_HOME:-$HOME/.local/share}/ez/agents/` for private deployments.
70
- Never overwrite an existing package/deployment or extract over its state. Infer
71
- the agent name and purpose from the owner's request; ask only when missing.
70
+ Never overwrite an existing package/deployment or extract over its state.
71
+
72
+ Before creation, use your own reasoning and the context already available from
73
+ the owner to write the agent's initial brief. This is not a label or a copy of
74
+ the request. Describe, in concrete language, who the agent serves, what product
75
+ or environment it works in, the outcomes it should help produce, the capabilities
76
+ currently available to it, and important scope boundaries. Include material facts
77
+ you already know about the application; do not invent unknown facts. Omit generic
78
+ personality prose and sections irrelevant to this agent. Keep the result compact
79
+ enough to read on every turn. Ask the owner only when a missing fact would
80
+ materially change the agent being installed.
81
+
82
+ Pass that generated brief as the purpose. For example, a request to create a
83
+ personal assistant should produce a brief tailored to that person's stated work,
84
+ preferences and connected capabilities—not merely `Personal assistant`. A product
85
+ agent should identify the product, user, current product scope and available
86
+ actions without embedding product-specific behavior in Ez Core.
72
87
 
73
88
  Before running Node commands, check `command -v node` and `node --version`.
74
89
  If Node 22+ or this package's pinned pnpm is missing, provision it using the
@@ -110,6 +125,8 @@ pnpm install --frozen-lockfile
110
125
  export PATH="$PWD/bin:$PATH"
111
126
  export EZ_AGENTS_HOME=/absolute/private/agents
112
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
113
130
  # Set EZ_RELAY_IMAGE to the exact image returned by build for create/start.
114
131
  export EZ_RELAY_IMAGE='<returned-image>'
115
132
  ```
@@ -117,7 +134,10 @@ export EZ_RELAY_IMAGE='<returned-image>'
117
134
  Node 22+ and pnpm 10.30.3 are needed by the host transport. The tarball carries
118
135
  its lockfile under docker/ because npm excludes the root pnpm lockfile. Do not
119
136
  move this package directory after binding a service to its absolute paths.
120
- For a source checkout the root lockfile is already present. Do not run a second
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
121
141
  copy of an existing bot token. Continue with the per-agent configuration below.
122
142
 
123
143
  Verify the tarball against its adjacent `.sha256` or the kit's `SHA256SUMS` before
@@ -163,20 +183,72 @@ so later service starts use the same build without depending on shell environmen
163
183
 
164
184
  ```sh
165
185
  export EZ_AGENTS_HOME=/absolute/private/agents
166
- bin/ezenciel-agents-create --name family-shopper --purpose 'Help my family plan shopping.' < /private/bot-token
186
+ bin/ezenciel-agents-create --name family-shopper --purpose 'You are the shopping assistant for the owner and their family. Help plan shared shopping, organize confirmed requests, and use only the installed shopping and messaging capabilities. Do not purchase, message others, or infer household preferences without owner authority.' < /private/bot-token
167
187
  export EZ_DEPLOYMENT_DIR="$EZ_AGENTS_HOME/family-shopper"
168
188
  ```
169
189
 
190
+ Creation records an isolation class. Packaged Codex defaults to `isolated`: the
191
+ native CLI runs inside the relay, which only has that agent's workspace and control mounts.
192
+ Sibling host paths are absent (`ENOENT`), not merely unreadable. Pass
193
+ `--isolation host-capable` only when the owner needs the installer UID (host
194
+ browser, local git, host files). Other installed CLIs default to `host-capable`
195
+ because they are not packaged in the relay; requesting isolated execution for
196
+ them fails closed. Host-capable reuses the host CLI login and is not an OS tenant
197
+ boundary. The class cannot be changed later by flipping Compose; recreate the agent.
198
+
199
+ Isolated Codex uses the pinned CLI in the relay image and
200
+ `EZ_CODEX_SANDBOX=external` so Codex does not nest a sandbox inside the
201
+ container. Provision that agent's `control/cli/codex/auth.json`; do not bind-mount
202
+ the operator `~/.codex`. The host LaunchAgent is not started. Host-capable agents
203
+ still need [host startup](host-service.md).
204
+
170
205
  Agent creation defaults to the CLI recorded when the initial package was
171
206
  installed. It needs no `--cli` argument. A later shell or different available CLI
172
207
  does not change that saved default. No installed-binary ranking or Grok fallback
173
208
  is used.
209
+
210
+ Custom Codex providers such as OpenRouter currently require an explicitly
211
+ host-capable agent: their keys are supplied by the private host-service
212
+ environment. The isolated relay has no custom-provider key injection path.
213
+ Register the provider and initial model set as non-secret installation metadata;
214
+ repeat `--codex-model` for every model the agent may select:
215
+
216
+ ```sh
217
+ bin/ezenciel-agents-create \
218
+ --name family-shopper \
219
+ --purpose 'Help my family plan shopping.' \
220
+ --isolation host-capable \
221
+ --codex-provider openrouter \
222
+ --codex-provider-name OpenRouter \
223
+ --codex-base-url https://openrouter.ai/api/v1 \
224
+ --codex-env-key OPENROUTER_API_KEY \
225
+ --codex-model google/gemini-3.8-flash \
226
+ --codex-model deepseek/deepseek-v4.1-flash \
227
+ < /private/bot-token
228
+ ```
229
+
230
+ This stores provider configuration and model IDs in `host-executor.json`, never
231
+ the API key. The key belongs only in the private host-service environment. The
232
+ agent or owner can later change the active provider/model through the existing
233
+ runtime control without reinstalling or editing an environment file:
234
+
235
+ ```sh
236
+ ezenciel-agents-ai list
237
+ ezenciel-agents-ai select --cli codex --provider openrouter \
238
+ --model google/gemini-3.8-flash
239
+ ```
240
+
241
+ Changing provider starts a fresh native session so a session is never resumed
242
+ against a different backend. Queued work retains the provider/model captured
243
+ when it was admitted.
174
244
  The creator writes `host-executor.json`, private secrets, mind/control paths,
175
245
  purpose and unique plugin volume names. Duplicate names fail without overwriting.
176
246
  `ezenciel-agents-create --list` lists deployments without secrets.
177
247
 
178
- Before starting that host transport, initialize the main package’s built-in plugin manager. It runs on the host
248
+ Before starting a host-capable transport, initialize the main package’s built-in plugin manager. It runs on the host
179
249
  for Docker access and adds no separate package or provider library. The packaged catalog is empty so the relay installs independently.
250
+ Isolated agents still initialize this registry for plugin discovery; they do not
251
+ start `ezenciel-agents-host`.
180
252
  Use its empty default catalog. Plugin preparation follows the verified Telegram
181
253
  handoff, not this step. Run:
182
254
 
@@ -202,16 +274,22 @@ the plugin skill through onboarding and verified use under that same request.
202
274
  Registry initialization itself does not connect accounts or start plugins.
203
275
  Never silently reuse a global `ez` from the old sandbox runtime.
204
276
 
205
- 4. Follow [host startup templates](host-service.md). Register `bin/ezenciel-agents-host` with the host's native service manager,
206
- binding `EZ_DEPLOYMENT_DIR` and the user's existing CLI PATH/HOME. On macOS use
207
- a LaunchAgent; on Linux use a user service. Use the absolute Node/package
277
+ 4. Isolated agents skip host transport. Run `bin/ezenciel-agents-docker up -d --wait`
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.
281
+
282
+ Host-capable agents follow [host startup templates](host-service.md). Register
283
+ `bin/ezenciel-agents-host` with the host's native service manager, binding
284
+ `EZ_DEPLOYMENT_DIR` and the user's existing CLI PATH/HOME. On macOS use a
285
+ LaunchAgent; on Linux use a user service. Use the absolute Node/package
208
286
  paths. This generic transport is the only host execution bridge. Do not start
209
287
  another host relay or install another CLI. Verify its heartbeat, then run
210
288
  `bin/ezenciel-agents-docker up -d --wait`.
211
289
 
212
290
  `ezenciel-agents-setup service` is Docker-only startup: run it from the
213
291
  deployment directory containing `docker.env`. It starts the relay and does
214
- not install or start the host-executor user service. Complete the host
292
+ not install or start the host-executor user service. Complete host-capable
215
293
  registration above separately.
216
294
 
217
295
  5. Ask the owner to message the exact bot. Verify the pending numeric identity,
@@ -224,8 +302,8 @@ Never silently reuse a global `ez` from the old sandbox runtime.
224
302
  stopped to verify repairs, then restore the poller; never replay uncertain
225
303
  user actions merely to test delivery.
226
304
 
227
- The main runtime is fully installer-owned: build it, register its host
228
- transport, bring its Compose project up, and verify restart persistence. Plugins
305
+ The main runtime is fully installer-owned: build it, register host transport
306
+ only for host-capable agents, bring its Compose project up, and verify restart persistence. Plugins
229
307
  are installed by the working Telegram agent when the owner requests their
230
308
  capability there; account onboarding and provider confirmation follow that request.
231
309
  Never use a missing plugin as a reason
@@ -238,9 +316,11 @@ current heartbeats and owner-bound completed-run delivery receipts without sendi
238
316
  messages or exposing tokens. Receipt evidence is historical: separately verify
239
317
  the current conversation and restart persistence before declaring setup complete.
240
318
 
241
- Purpose seeds SOUL.md once; future customization survives restart. Conversations,
242
- pairing, files and plugin accounts are separate. The existing host CLI login is
243
- shared, so this is not a security sandbox against other agents under that user.
319
+ Purpose scopes AGENTS.md once; future customization survives restart. Conversations,
320
+ pairing, files and plugin accounts are separate. Isolated agents use the relay
321
+ mount namespace as the filesystem boundary. Host-capable agents share the
322
+ installer UID and CLI login; that class is not a security sandbox against other
323
+ agents under that user.
244
324
  Plugins run in their own containers and own their authentication. Install and
245
325
  register them only for the requested agent. Never clone another agent's plugin
246
326
  credentials. See [runtime, migration and QA](docker-runtime.md).
@@ -256,9 +336,9 @@ default. Existing queued jobs retain their captured execution choice.
256
336
  | Symptom | Inspect and recover |
257
337
  |---|---|
258
338
  | Docker unavailable | Check engine and Compose, start the supported installation; complete any required OS consent. |
259
- | Bot stays silent | Check pending owner identity, relay health, host heartbeat and outbox; approve only the verified owner. |
339
+ | Bot stays silent | Check pending owner identity, relay health, host heartbeat (host-capable only) and delivery receipts; approve only the verified owner. |
260
340
  | CLI exits without reply | Inspect the actual tool result and delivery receipt; stdout is not Telegram output. |
261
- | Exit 73 | An existing writer holds this deployment; stop the exact duplicate, never delete the kernel lock. |
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. |
262
342
  | Plugin absent | Check the bound catalog and install/start the reviewed package explicitly; no plugin ships by default. |
263
343
  | Plugin revision mismatch | Reinspect stable source, review the changed hash and explicitly update its catalog pin. |
264
344
  | Interrupted CLI cannot resume | Use the explicit new-conversation command after inspecting the failure; no automatic fallback. |
@@ -32,8 +32,9 @@ Use `ez tools list --details` for generated installed-plugin descriptions, help
32
32
  Add that instruction to its existing project instructions without replacing them.
33
33
  Use the absolute launcher, or prepend its bin directory to that session's PATH.
34
34
  Never overwrite another global `ez`; it may belong to a different installation.
35
- A company registry remains explicit even when invoked from a different directory.
36
- Other projects/accounts should use separate registries and private plugin state.
35
+ A standalone company registry remains explicit even when invoked from a different
36
+ directory. A relay-bound registry rejects calls from outside its workspace. Other
37
+ projects/accounts must use separate registries and private plugin state.
37
38
 
38
39
  ## Install and verify a capability
39
40
 
@@ -54,9 +55,9 @@ Native client plugins/connectors are not converted into Ez plugins automatically
54
55
 
55
56
  A relay can coexist with CLI-only registries on the same machine. It retains its
56
57
  own pairing, single-writer queue, mind and plugin registry. Calling its existing
57
- bound launcher explicitly reuses that registry and its accounts; never initialize
58
- over it or silently select it from another workspace. Coordinate writes with its
59
- active jobs. Separate registries do not automatically share credentials or data.
58
+ bound launcher must be run from the owning agent workspace. Never initialize over
59
+ it or select it from another workspace. Coordinate writes with its active jobs.
60
+ Separate registries do not automatically share credentials or data.
60
61
 
61
62
  Continuous monitoring requires a configured event consumer/relay and the plugin's
62
63
  supported watcher. CLI-only installation does not create background agent turns.