@jc_stack/ez-agents 0.1.0-beta.12 → 0.1.0-beta.18

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 (132) hide show
  1. package/.dockerignore +4 -0
  2. package/.env.example +16 -1
  3. package/AGENTS.md +16 -4
  4. package/CHANGELOG.md +71 -0
  5. package/CONTRIBUTING.md +37 -4
  6. package/README.md +114 -9
  7. package/SECURITY.md +7 -1
  8. package/bin/ezenciel-agents-schedule +2 -0
  9. package/bin/ezenciel-agents-schedule.mjs +16 -0
  10. package/bin/ezenciel-agents-task +2 -0
  11. package/bin/ezenciel-agents-task.mjs +16 -0
  12. package/compose.yaml +10 -2
  13. package/docker/recovery.ts +2 -2
  14. package/docker/run.ts +2 -2
  15. package/docs/architecture/ai-selection.md +8 -0
  16. package/docs/architecture/authority-boundaries.md +137 -12
  17. package/docs/architecture/event-sources.md +12 -7
  18. package/docs/architecture/telegram-intake.md +1 -1
  19. package/docs/channel-backend.md +36 -0
  20. package/docs/docker-runtime.md +35 -0
  21. package/docs/host-service.md +19 -0
  22. package/docs/local-qa.md +45 -0
  23. package/docs/pagerduty.md +42 -0
  24. package/docs/plugin-catalog.md +71 -0
  25. package/docs/plugin-contributions.md +12 -0
  26. package/docs/plugins.md +61 -1
  27. package/docs/releasing.md +20 -9
  28. package/docs/repair.md +41 -0
  29. package/docs/scheduling.md +153 -0
  30. package/docs/selective-monitoring.md +114 -0
  31. package/docs/setup.md +46 -0
  32. package/docs/standalone-cli.md +62 -0
  33. package/docs/trusted-publishing.md +140 -0
  34. package/docs/upgrades.md +24 -4
  35. package/package.json +12 -4
  36. package/scripts/generate-publish-caller.mjs +60 -0
  37. package/scripts/smoke-busy-reply.ts +58 -0
  38. package/scripts/smoke-scheduler.ts +90 -0
  39. package/scripts/stage-qa.mjs +42 -0
  40. package/scripts/trusted-beta.mjs +289 -0
  41. package/src/agent-guidance.ts +5 -0
  42. package/src/ai-cli.ts +2 -1
  43. package/src/ai.ts +15 -5
  44. package/src/channel-backend.ts +46 -0
  45. package/src/client-defaults.ts +29 -13
  46. package/src/codex-session.ts +98 -0
  47. package/src/config.ts +35 -2
  48. package/src/control-state.ts +24 -7
  49. package/src/desktop-bridge.ts +37 -12
  50. package/src/event-sources.ts +2 -1
  51. package/src/execution-authority.ts +25 -0
  52. package/src/executor.ts +97 -21
  53. package/src/failure.ts +32 -0
  54. package/src/host-executor.ts +48 -19
  55. package/src/identity.ts +8 -3
  56. package/src/inbox.ts +11 -3
  57. package/src/index.ts +315 -91
  58. package/src/install-tools.mjs +2 -2
  59. package/src/menu.ts +6 -4
  60. package/src/model-policy.ts +15 -0
  61. package/src/owner.ts +3 -3
  62. package/src/pagerduty.ts +109 -0
  63. package/src/plugins/exposure.mjs +13 -0
  64. package/src/plugins/manager.mjs +74 -20
  65. package/src/plugins/shared.mjs +76 -0
  66. package/src/process-tree.ts +33 -0
  67. package/src/repair-policy.ts +13 -0
  68. package/src/reply-context.ts +67 -0
  69. package/src/reply-executor.ts +54 -0
  70. package/src/reply-mcp.ts +23 -0
  71. package/src/runs.ts +63 -19
  72. package/src/schedule-cli.ts +98 -0
  73. package/src/schedule-time.ts +85 -0
  74. package/src/scheduler.ts +130 -0
  75. package/src/setup.ts +2 -1
  76. package/src/software-status.ts +5 -5
  77. package/src/source-cli.ts +1 -1
  78. package/src/task-cli.ts +16 -0
  79. package/src/task-executor.ts +65 -0
  80. package/src/task-mcp.ts +36 -0
  81. package/src/task-rpc.ts +45 -0
  82. package/src/task-workspace.ts +22 -0
  83. package/src/tasks.ts +210 -0
  84. package/src/telegram-source.ts +94 -0
  85. package/src/updates/artifact.mjs +16 -0
  86. package/src/updates/binding.mjs +4 -1
  87. package/src/updates/control.mjs +4 -4
  88. package/src/updates/runtime.mjs +3 -1
  89. package/src/updates/status.mjs +7 -1
  90. package/templates/agent/AGENTS.md +10 -2
  91. package/templates/agent/TOOLS.md +60 -1
  92. package/templates/agent-guidance.md +13 -0
  93. package/templates/failure-review.md +9 -0
  94. package/templates/maintainer-purpose.md +15 -0
  95. package/templates/standalone-tools.md +20 -0
  96. package/templates/updates.md +2 -2
  97. package/test/agent-guidance.test.ts +110 -0
  98. package/test/ai-cli.test.ts +7 -6
  99. package/test/ai.test.ts +41 -0
  100. package/test/busy-reply-relay.test.ts +41 -0
  101. package/test/channel-backend.test.ts +100 -0
  102. package/test/client-defaults.test.ts +37 -5
  103. package/test/codex-context.test.ts +39 -1
  104. package/test/codex-session.test.ts +51 -0
  105. package/test/config.test.ts +31 -2
  106. package/test/desktop-bridge.test.ts +19 -0
  107. package/test/event-sources.test.ts +47 -11
  108. package/test/execution-authority.test.ts +42 -0
  109. package/test/executor.test.ts +53 -2
  110. package/test/failure.test.ts +250 -0
  111. package/test/group-owner.test.ts +36 -0
  112. package/test/helpers/owner-run.ts +13 -0
  113. package/test/host-executor.test.ts +47 -10
  114. package/test/intake-relay.test.ts +141 -4
  115. package/test/local-qa.test.mjs +38 -0
  116. package/test/model-policy.test.ts +61 -0
  117. package/test/pagerduty.test.ts +104 -0
  118. package/test/plugin-manager.test.mjs +73 -3
  119. package/test/relay.test.ts +2 -2
  120. package/test/repair-policy.test.ts +23 -0
  121. package/test/reply.test.ts +131 -0
  122. package/test/schedule-cli.test.ts +55 -0
  123. package/test/scheduler-host.test.ts +55 -0
  124. package/test/scheduler-relay.test.ts +67 -0
  125. package/test/scheduler.test.ts +104 -0
  126. package/test/shared-services.test.mjs +98 -0
  127. package/test/software-status.test.ts +5 -5
  128. package/test/task-native.test.ts +87 -0
  129. package/test/tasks.test.ts +187 -0
  130. package/test/telegram-source.test.ts +75 -0
  131. package/test/trusted-beta.test.mjs +224 -0
  132. package/test/updates.test.mjs +35 -3
package/docs/releasing.md CHANGED
@@ -3,7 +3,9 @@
3
3
  Use the same checks for maintainer and external changes. Each repository versions
4
4
  independently with SemVer: patch for compatible fixes, minor for new capabilities;
5
5
  before 1.0, breaking CLI/state changes require a minor bump and migration notes.
6
- No automatic dependency updates, release bot or credentials in pull-request CI.
6
+ No automatic dependency updates or credentials in pull-request CI. The agent
7
+ operates this process under the authorization rules in CONTRIBUTING.md; a
8
+ separate release bot is not required.
7
9
 
8
10
  1. In an isolated release worktree/PR, finalize package version and CHANGELOG.md;
9
11
  update plugin manifest version when present. After lockfile changes, copy
@@ -32,14 +34,20 @@ No automatic dependency updates, release bot or credentials in pull-request CI.
32
34
  fill package.json repository, homepage and bugs with the actual public URLs.
33
35
  Enable GitHub private vulnerability reporting; verify the route. Protect main
34
36
  with CI and independent PR review. Maintainers use the same process.
35
- 7. Record independent review and green CI for the final release PR, then obtain
36
- maintainer merge/release authorization for the exact commit, tarball SHA-256,
37
- license/third-party obligations and known limits. Merge the release PR and
37
+ 7. Record independent review and green CI for the final release PR. The
38
+ maintainer's release request supplies authorization: do not ask for a second
39
+ approval. Record the prepared commit, tarball SHA-256, third-party obligations
40
+ and known limits. If release is outside the request, report readiness without
41
+ publishing. For an authorized release, merge the release PR and
38
42
  verify its tree matches the reviewed source before tagging `v<version>` and
39
43
  publishing that tarball:
40
- `npm publish /absolute/candidate.tgz --access public --tag beta --registry https://registry.npmjs.org/`
41
- for prereleases (use `--tag latest` only for an approved stable release).
42
- Use interactive npm authentication with 2FA; never paste tokens into CI or docs.
44
+ `npm publish /absolute/candidate.tgz --access public --tag latest --registry https://registry.npmjs.org/`
45
+ for approved beta releases as well: `latest` is the default distribution tag,
46
+ not a claim that a SemVer prerelease is stable.
47
+ For unattended beta publication use the [shared trusted publisher](trusted-publishing.md)
48
+ and its exact-artifact staging/readback contract. Initial package publication
49
+ requires authenticated npm with 2FA before trust can be enrolled; never paste
50
+ tokens into CI or docs.
43
51
  8. Create the GitHub release from CHANGELOG.md, attach artifact/checksum, and
44
52
  install the registry version on a clean host. Verify metadata and the same
45
53
  onboarding path before posting launch copy. Stop rollout on failure; publish
@@ -53,13 +61,16 @@ credential revocation; do not delete volumes as a routine rollback.
53
61
  ## Beta channel
54
62
 
55
63
  Use SemVer prereleases (`0.1.0-beta.1`), GitHub's prerelease flag and npm's
56
- `--tag beta`; never mark a beta latest/stable. For this first beta the maintainer
64
+ `--tag latest` so default installs and the package page advance automatically.
65
+ The version and GitHub release remain prereleases; stable-only update policies
66
+ still exclude them. The legacy npm beta tag is no longer advanced. For this first beta the maintainer
57
67
  explicitly deferred real account/reboot acceptance. Keep that limitation in the
58
68
  README and release notes. Source/tarball publication is permitted after the
59
69
  automated gates; deferred live checks remain required for stable release.
60
70
  GitHub repositories use `jdorado`; npm packages use `jc_stack`. Verify
61
71
  `npm whoami --registry https://registry.npmjs.org/` returns `jc_stack` before
62
- publishing. Never infer npm scope ownership from a GitHub login. After publishing,
72
+ interactive publication. OIDC publication instead requires package-owner trust
73
+ enrollment for the exact caller workflow; `whoami` is not its publication gate. Never infer npm scope ownership from a GitHub login. After publishing,
63
74
  read back `npm view @jc_stack/ez-agents@0.1.0-beta.12 name version dist-tags --json`
64
75
  (using the release being published), download it with `npm pack`, and verify its
65
76
  contents/checksum against the reviewed artifact. Keep the npm artifact and
package/docs/repair.md ADDED
@@ -0,0 +1,41 @@
1
+ # Native repair ownership
2
+
3
+ Every deployed agent is a repairer by default. When an agent finds a core or
4
+ plugin defect, it keeps the context and pursues a tested contribution PR. The
5
+ core injects the same mandate into CLI/native and desktop execution, including
6
+ existing workspaces; it does not replace the agent's mind or implement a repair
7
+ workflow engine. Use native Git/GitHub CLI or the installed GitHub plugin.
8
+
9
+ The agent searches for the same cause, registers a sanitized issue, requests a
10
+ claim, then works in an isolated contribution checkout after the coordinator's
11
+ grant. It resumes the same issue/branch/PR after interruption. The installed
12
+ runtime is never the repair checkout. Missing credentials or coordination remain
13
+ recorded blockers; the default does not invent repository access. Public reports
14
+ must exclude private runtime data and use the security reporting route when needed.
15
+
16
+ One coordinator grants claims sequentially per repository. Assignment alone is
17
+ not a lock. All participating agents must use that coordinator; this convention
18
+ cannot prevent an unrelated public contributor from opening a competing PR.
19
+ The discovering agent remains the repairer, including when its work moves to a
20
+ background task. The coordinator reconciles duplicates and stalled claims. The
21
+ maintainer independently reviews and tests, then merges/publishes only within
22
+ separate owner-approved policies. Start from templates/maintainer-purpose.md.
23
+
24
+ ## Disable
25
+
26
+ Set `EZ_REPAIR_ENABLED=false` in the deployment's Docker environment and recreate
27
+ the relay. The resolved setting crosses the host transport and is included in
28
+ every new execution prompt; the default is true and invalid values fail startup.
29
+ This changes the automatic mandate, not filesystem/GitHub permissions, and does
30
+ not cancel an already running task. Explicitly stop active repair work when needed.
31
+ An owner can also disable repairs globally or for a repository in the agent's
32
+ saved USER.md preferences; carry those restrictions into background task context.
33
+
34
+ ## Setup boundary
35
+
36
+ The shipped mandate and maintainer purpose do not provision a GitHub account,
37
+ coordinator service or publishing token. Enroll the allowed repositories and
38
+ configure one maintainer execution lane on the owner's host before unattended
39
+ claims. Reuse authenticated GitHub CLI where authorized. Repository push and PR
40
+ permissions are distinct from package-registry publication and protected-branch
41
+ approval. Never put credentials in prompts, issues or test environments.
@@ -0,0 +1,153 @@
1
+ # Scheduling and background work
2
+
3
+ Ask the agent naturally: “Remind me on September 9 next year at 09:00 Dubai time”
4
+ or “Every Tuesday at 09:00, prepare the report.” The agent translates this into a
5
+ core CLI request. No plugin, database or operating-system cron setup is required.
6
+
7
+ ```sh
8
+ ezenciel-agents-schedule create --name Reminder \
9
+ --at 2027-09-09T09:00:00+04:00 --text 'Remind the owner about the renewal.'
10
+ ezenciel-agents-schedule create --name Weekdays \
11
+ --cron '0 9 * * 1-5' --timezone Asia/Dubai --text 'Prepare the daily report.'
12
+ ezenciel-agents-schedule create --name Research --now \
13
+ --text '/goal Complete the authorized research objective. Save evidence, verify the outcome, and send the owner the result.'
14
+ ezenciel-agents-schedule list
15
+ ezenciel-agents-schedule runs
16
+ ezenciel-agents-schedule pause SCHEDULE_ID
17
+ ezenciel-agents-schedule resume SCHEDULE_ID
18
+ ezenciel-agents-schedule remove SCHEDULE_ID
19
+ ezenciel-agents-schedule cancel RUN_ID
20
+ ```
21
+
22
+ Use `--text-file` for longer instructions. `edit ID` replaces the complete schedule
23
+ with a new revision; use the same trigger/name/text flags as `create`.
24
+ Intervals use `--every-seconds` (minimum 60), optional `--start`, and optional
25
+ `--until`. Cron also supports start/end bounds. All absolute timestamps require
26
+ an explicit offset. `--now` starts on the next relay tick, not synchronously.
27
+
28
+ Cron accepts five numeric fields, comma lists, ranges and steps; Sunday is 0 or 7.
29
+ Restricted day-of-month and weekday fields use standard OR semantics. Set just
30
+ weekday for “Tuesdays.” Calendar jobs retain their explicit IANA timezone when
31
+ the host changes zones. Nonexistent DST wall times are skipped; repeated wall
32
+ times fire once, at the earlier instant. Search is bounded to eight years.
33
+ Public-holiday calendars and arbitrary RRULE syntax are not implemented.
34
+
35
+ New tasks, including work deferred by a busy reply session, default to Codex
36
+ `gpt-5.6-terra` with `high` reasoning independently of the creating chat.
37
+ Use `--cli`, `--model`, and `--effort` to specify another choice; reasoning
38
+ explicitly selected above `high` is rejected for every model. Non-Codex adapters
39
+ inherit native effort when unset. Editing preserves the existing AI
40
+ choice unless those flags override it. Stored choices are checked again at
41
+ launch, including schedules saved before the cap.
42
+
43
+ ## Execution and authority
44
+
45
+ The relay checks due work once per second. Each occurrence enters the durable
46
+ run queue with a stable ID. Background work runs in a fresh native CLI session
47
+ and `work/tasks/RUN_ID/`, with snapshots of the agent's SOUL, USER and TOOLS files.
48
+ Instructions must include any needed context or source paths; full chat history
49
+ is not copied. Task folders remain for inspection and artifact delivery.
50
+
51
+ One writer runs per task directory. Up to four background tasks can run alongside
52
+ the main conversation. When a Codex owner message arrives while work is busy, a separate restricted session reads recent messages and run progress and answers through the normal outbox. It can queue requested work through the scheduler, but cannot run shell commands, access plugins, or edit the agent workspace. Only one reply session runs at a time and it releases its slot after a 60-second reply deadline; this deadline does not apply to writer jobs. Its context is a bounded snapshot, not a shared native transcript. Delivered parallel replies are included as historical context in the next normal conversation turn. Codex 0.153.4 and 0.154.0 are supported for this restricted adapter. Other versions fail closed pending tool-surface validation. A recurring schedule has at most one pending
53
+ or active occurrence. Agents should delegate long work with `create --now`, return
54
+ to chat, and inspect `runs` or task progress when asked. Native subagents can be
55
+ used inside the worker. Sharing provider profiles does not make concurrent CRM,
56
+ file or browser writes safe: the agent must coordinate those resources.
57
+
58
+ Production relay/host execution has no wall-clock timeout. The old
59
+ `EZ_EXECUTOR_TIMEOUT_SECONDS` setting is ignored. Individual network/tool waits
60
+ still have their own limits; those are not overall task deadlines. Native goals
61
+ are an executor capability, configured through instructions. Ez has no goal API,
62
+ continuation loop or rule equating a process exit with goal achievement.
63
+
64
+ Scheduled Codex CLI tasks use a dedicated native app-server session, tested with
65
+ CLI 0.153.4. A leading `/goal` in the instruction text maps to the same native
66
+ goal command used by the interactive CLI. Codex automatically starts subsequent
67
+ turns; the transport stays connected until the native goal is complete or stops
68
+ for attention. It sends no continuation prompts and stores no Ez goal state.
69
+ Goals created by the agent's native tools also keep the session alive. Ordinary
70
+ tasks finish after their turn. A blocked, paused or limited goal is not reported
71
+ as successful. Native RPC requests have a response deadline; running tasks do not.
72
+ Each scheduled task has its own Codex state under `control/cli/codex/tasks/RUN_ID`,
73
+ with a snapshot of the agent's Codex configuration and the existing auth link.
74
+ Foreground chat and background tasks do not initialize or migrate one shared
75
+ native database concurrently.
76
+
77
+ The foreground chat still uses `codex exec`. That invocation exits after one
78
+ requested turn even if a goal is active, so delegate persistent work to the
79
+ scheduler. Desktop and other executor goal lifecycles need separate validation.
80
+
81
+ The CLI binds jobs to the paired owner and the task AI choice. Queued/scheduled
82
+ work retains that choice after the chat switches AI. Revoking/re-pairing an
83
+ owner invalidates their old schedules, including re-pairing the same Telegram ID.
84
+ External event turns cannot use the scheduling CLI. Credentials still pass only
85
+ through the existing whitelist and installed host binding.
86
+
87
+ ## Restart, pause and cancellation
88
+
89
+ Schedule definitions and cursors use protected atomic JSON files. A restart
90
+ between queue creation and cursor persistence does not duplicate an occurrence.
91
+ An overdue one-time job runs on return. Missed recurring occurrences coalesce into
92
+ one pending run; future runs resume at the next eligible time. A paused queued
93
+ occurrence waits for resume. Editing/removing a schedule invalidates its old
94
+ queued occurrence; already-running work continues until explicitly cancelled.
95
+
96
+ `/stop` stops all active work; `cancel RUN_ID` stops one background task. `/cancel`
97
+ clears queued work. Pause/remove a recurring schedule to prevent future runs.
98
+ Stopping the relay also stops its workers. A crashed or interrupted execution is
99
+ 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
100
+ `interrupted: true`; their schedule revision stays held until the agent inspects
101
+ the evidence and explicitly edits the schedule. Inspect the task's files, native session and delivery
102
+ receipts before deciding whether to resume. A clock cannot reconstruct an
103
+ in-flight process or prove whether an external side effect happened.
104
+
105
+ The host and relay must be online. Paused/completed schedule definitions and task
106
+ artifacts are retained. The agent sends through the normal Telegram outbox;
107
+ `completed` means executor exit, while provider delivery is recorded separately.
108
+ A timeout or ambiguous send must not cause blind replay of the whole task.
109
+
110
+ ## QA
111
+
112
+ `pnpm verify` covers recurrence/DST, restart deduplication, authority revocation,
113
+ corrupt state, paths, cancellation and a chat response while a synthetic worker
114
+ is active. Docker tests exercise the packaged host transport and isolation.
115
+
116
+ For an opt-in real CLI probe (consumes model usage):
117
+
118
+ ```sh
119
+ pnpm smoke:scheduler -- 1860 codex
120
+ # Native goal must finish a first turn and continue without another prompt:
121
+ pnpm smoke:scheduler -- 45 codex goal
122
+ ```
123
+
124
+ This uses temporary workspaces and a synthetic Telegram provider, never live
125
+ contacts. A real CLI waits 31 minutes while a second invocation answers 17 × 19.
126
+ It checks responsiveness again after six minutes and requires the worker's final
127
+ message. Evidence is saved in the printed temporary directory. Use `75 codex`
128
+ for a shorter iteration; it does not prove the full duration.
129
+
130
+ Before enabling on a real installation, repeat through its Telegram bot: request
131
+ the 31-minute task, ask the arithmetic question and request status after six
132
+ minutes. Verify `finished.txt` and exactly one completion in Telegram. Separately
133
+ exercise cancellation, downtime catch-up and an explicitly requested native goal
134
+ that needs more than one turn. Synthetic provider evidence does not prove real
135
+ Telegram delivery, and a sleep test does not prove native goal persistence.
136
+
137
+ Busy-chat regression probe (real Codex, synthetic Telegram):
138
+
139
+ ```sh
140
+ pnpm exec tsx scripts/smoke-busy-reply.ts --transport
141
+ ```
142
+
143
+ The probe holds a writer on a shared workspace, asks an owner question through
144
+ the relay and host transport, and requires the restricted reply to complete
145
+ while the writer remains active. It sends no real Telegram messages.
146
+
147
+ ## Optional failure review
148
+
149
+ Create a normal recurring schedule with `--every-seconds 900 --when unreviewed-failures --text-file templates/failure-review.md`. The condition advances empty occurrences without launching an executor. It considers only failures belonging to the paired owner. No separate monitor or automatic retry is introduced.
150
+
151
+ `failures [--all] [--limit N]` returns failedAt, reason, exit code, native session, captured error and runtime versions. Capture keeps at most 4 KiB of redacted stderr; historical failures are not backfilled. `run RUN_ID` reads an owned run. `review RUN_ID --failed-at ISO --status resolved|attention --diagnosis TEXT --recovery TEXT --outcome TEXT` records the investigation without rewriting execution history. A stale timestamp is rejected; a later failure needs a new review. Restricted reply, external and isolated-task callers cannot review failures. An attention review is handed off, not repeatedly relaunched; another new failure wakes the next review.
152
+
153
+ The prompt controls diagnosis, authorized recovery and quiet notification behavior. Inspect prior effects and receipts before retrying anything. A failed review run itself remains visible as a new failure for the next occurrence.
@@ -0,0 +1,114 @@
1
+ # Selective monitoring and replies
2
+
3
+ An owner saying “monitor and answer messages from CONTACT” has selected that
4
+ contact and authorized ordinary replies within the stated scope. Do not ask
5
+ whether they meant selected contacts or demand a special phrase. “If they send,
6
+ reply” means wait for incoming messages; it does not authorize an opening send.
7
+ Resolve only missing identity or disclosure scope. A saved Markdown instruction
8
+ is a reminder, never an activated source, watch or reply permission.
9
+
10
+ ## Speak in jobs, not modes
11
+
12
+ Keep mode names internal. Linking/syncing an account defaults to quiet capture;
13
+ finish connection verification, then at most one short optional prompt such as
14
+ “WhatsApp is connected. Want me to follow up with anyone?” Do not present a
15
+ technical three-mode menu or suggest blanket autonomous replies that v1 cannot
16
+ safely authorize. If the owner already gave a job, continue it without this prompt.
17
+
18
+ Infer the complete job from ordinary language:
19
+
20
+ - “Find out whether they have a table” or “Book me a restaurant”: send the inquiry,
21
+ watch replies from that contact, continue the multi-turn negotiation and report
22
+ the outcome. A send receipt is not completion. Do not ask if follow-up is wanted.
23
+ - Twelve inquiries mean twelve task-scoped contacts, not all-inbox monitoring.
24
+ Maintain one scoped task per correspondent; the same core checks apply to each.
25
+ - “Just send this; I will reply”: one-off send under the explicit owner instruction,
26
+ no new watch or conversational mandate. Use the provider's ordinary send and
27
+ receipt interface; do not create a messaging task that would auto-follow up.
28
+ - “Monitor this person and answer if they message”: incoming-only reply task;
29
+ no opening message and no unrelated contact attention.
30
+ - “Keep these messages for me”: quiet capture/read-on-request. If “monitor” alone
31
+ leaves action intent unclear, ask one plain question: “Should I reply for you,
32
+ or just keep the messages for you to review?” Do not ask when the job resolves it.
33
+
34
+ Apply the required core confirmation to the concrete proposal, not an extra
35
+ questionnaire. Use the owner's existing contact, purpose and disclosure limits.
36
+ For an ongoing incoming-only conversation, use `--until-revoked`; finite tasks remain bounded. Explain the expiry only
37
+ when it matters to that proposed job; never silently expand or renew permission.
38
+
39
+ ## Three capture modes, separate reply authority
40
+
41
+ - Manual: capture for explicit reads, with no general wake-up subscription.
42
+ - Selected: wake for named contacts only. Never turn on all-inbox mode to satisfy
43
+ a one-contact request.
44
+ - All: attention for all eligible incoming contacts; requires that broader
45
+ owner request. Attention alone never grants autonomous reply permission.
46
+
47
+ For an approved core reply task, the provider's task-watch supplies expiring
48
+ selected attention even if its general policy remains manual. That is expected:
49
+ verify the actual task watch and core grant, not only the general policy label.
50
+ Monitoring-only requests grant no sends. Unsupported wake-only reasoning modes
51
+ must be reported as unsupported, not run with owner authority.
52
+
53
+ ## Complete the setup under the owner's request
54
+
55
+ Use the current installed plugin skill and `ez plugins list`/`status`/provider
56
+ doctor to confirm the existing linked account. Installation, source plumbing,
57
+ contact attention and permission are separate checks. A missing source is
58
+ technical work for the agent, not a reason to stop at “saved your instruction.”
59
+ Do not request a second provider instance or re-pair an already linked account.
60
+
61
+ The relay must be able to reach the registered provider service socket. Inspect
62
+ the registered deployment/compose, actual named IPC volume, and relay mounts.
63
+ For the supplied WhatsApp adapter the socket is /plugins/whatsapp/service.sock;
64
+ main compose.whatsapp.yaml supplies a read-only IPC/client override. Use the
65
+ registered plugin's real volume names, preserve existing docker.env/Compose
66
+ settings, and attach only its declared IPC/client volumes (never its profile or
67
+ credentials). Recreate the relay with the existing deployment after a required
68
+ mount change; verify it comes back. Do not expose the Docker socket to it.
69
+
70
+ Register the source INSIDE that relay container using the installed
71
+ `ezenciel-agents-source --name NAME --socket ABSOLUTE_SOCKET` command. Read back
72
+ registration and provider events-head account identity. A socket inside a
73
+ provider command container is not proof the relay can reach it. Do not edit core
74
+ source/grant JSON directly. Other adapters use their declared socket paths;
75
+ provider names do not change authority checks.
76
+
77
+ ## Propose, confirm, verify
78
+
79
+ For an outbound job such as a booking, use `ezenciel-agents-task propose` WITHOUT
80
+ `--incoming-only`: it starts the inquiry and then watches replies. For “answer if
81
+ they message,” use `ezenciel-agents-task propose --incoming-only` with the
82
+ registered source, canonical contact, purpose, explicitly shareable context file
83
+ and expiry. No need to invent a booking objective: “conversational replies to
84
+ this contact, no private disclosures or commitments” is a legitimate purpose.
85
+ If no private facts may be shared, say so in the context file; do not include
86
+ owner memory. Finite jobs support at most 72 hours. For an ongoing conversation requested by
87
+ the owner, add `--incoming-only --until-revoked`. This authorizes that exact
88
+ conversation until owner revocation, without a total reply quota. Do not silently
89
+ convert a finite job into an ongoing permission.
90
+
91
+ For Telegram groups, the relay registers source `telegram` automatically when
92
+ paired. Use the exact negative group ID from discovery, never its display name.
93
+ Keep the shared context limited to what every group member may know. All human
94
+ members of that approved group may converse; this does not grant owner tools.
95
+ The group runs with the existing restricted messaging runner, and its notes are
96
+ separate from private PA memory. Group text is supported; media is not yet.
97
+
98
+ The core presents the exact proposal for owner confirmation. Ordinary messages
99
+ inside that grant need no repeated confirmations. Incoming-only grants create
100
+ no initial run or opening message. They remain active across replies until expiry
101
+ or owner revocation; the worker cannot close a watch by calling `complete`.
102
+ After handling a message, save a task note and finish the run. After approval, verify active core state,
103
+ contact and expiry, source reachability, and the provider's task watch. With
104
+ `--incoming-only`, an empty conversation is correctly idle until a new message.
105
+ If approval is still pending, say pending; if setup failed, name the actual
106
+ failure and continue repair within scope. Never report “active” based on notes,
107
+ installation, connected status or subscription alone.
108
+
109
+ After an authorized test message, inspect the corresponding task run and send
110
+ receipt and compare recipient readback. An accepted send is not proof of delivery.
111
+ After revocation/expiry no subsequent reply may dispatch. Keep these checks
112
+ agent-owned: the owner supplies only necessary confirmation, QR scan if needed,
113
+ and the test contact/message. Do not bypass a missing grant by polling the inbox
114
+ in an unrestricted scheduled owner session or sending through the raw CLI.
package/docs/setup.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Agent-led setup
2
2
 
3
+ ## A group as owner
4
+
5
+ An installer can explicitly approve one Telegram group as the agent's owner.
6
+ Every human member in that group then has owner access, including settings,
7
+ approvals and scheduling. The conversation and replies are shared in that group.
8
+ New members inherit this access. Bots and anonymous sender-chat posts are ignored.
9
+
10
+ Add the bot to the intended group and send it a message addressed to its username.
11
+ `ezenciel-agents-owner status` shows the pending group title and negative chat ID;
12
+ verify the exact group with the installer, then run
13
+ `ezenciel-agents-owner approve-group <negative-chat-id>`. Pairing never happens
14
+ automatically. The existing `approve <user-id>` command approves DMs only.
15
+ An existing owner must be explicitly revoked before replacement; use a fresh
16
+ deployment when its existing workspace contains information unsuitable for the group.
17
+
18
+ Make the bot a group admin so Telegram delivers ordinary member messages and
19
+ allows membership verification for approval and control buttons. Group ownership only authorizes
20
+ the exact approved chat, not other groups or members' private DMs. Telegram group
21
+ migration to a new chat ID requires a new explicit binding. Verify a real group
22
+ reply before considering setup complete. All other groups retain their existing
23
+ restricted conversation-grant behavior.
24
+
25
+ Ez supports two independent, composable uses: an autonomous Telegram agent and
26
+ workspace-scoped plugins called by your existing local CLI/GUI executor.
27
+ For CLI-only requests, follow [standalone setup](standalone-cli.md): no Telegram
28
+ pairing, relay or host executor is required. The main-first Telegram onboarding
29
+ rules below apply only when installing the autonomous relay. When both are
30
+ requested, keep each workspace's authority and registry explicit.
31
+
3
32
  The user starts in their existing CLI and says “install Ezenciel”, then “create
4
33
  an agent as my family shopper”. The installing agent does the technical work.
5
34
  Keep that host CLI and login for every agent; do not request another CLI login.
@@ -23,6 +52,23 @@ owner request for standalone plugin development is a separate workflow.
23
52
 
24
53
  ## Defaults and host prerequisites
25
54
 
55
+ New agents using `codex` or `codex-gui` start with `gpt-5.6-terra` and `high`
56
+ reasoning, including when initialized with `ezenciel-agents-setup init`. This
57
+ Ez default takes precedence over discovered host client defaults. Saved agent
58
+ selections at or below high are preserved; use the AI settings to choose another model or effort.
59
+ Ez rejects explicit reasoning above `high` for every model at selection and execution,
60
+ including old saved or queued choices. Unset Codex model/effort resolves to
61
+ Terra/high at launch. This governs Ez-managed launches; it is not an account-wide
62
+ limit on independently launched native clients or executor-created native subagents.
63
+ Other adapters inherit their native effort when none is selected in Ez. That
64
+ inherited configuration is not capped by Ez; explicit above-high Ez selections
65
+ are still rejected. Only Codex adapters receive the default `high` effort.
66
+
67
+ New scheduled and one-off background tasks default to Codex Terra/high independently
68
+ of the creating chat. Use scheduler `--cli`, `--model`, and `--effort` flags for
69
+ explicit overrides. Editing a schedule preserves its settings unless overridden.
70
+ Restricted messaging tasks also use Terra/high when no settings are supplied.
71
+
26
72
  Use the existing owner's host account. Unless a layout was supplied, use
27
73
  `${XDG_DATA_HOME:-$HOME/.local/share}/ez/packages/<version>/` for extracted main
28
74
  packages and `${XDG_DATA_HOME:-$HOME/.local/share}/ez/agents/` for private deployments.
@@ -0,0 +1,62 @@
1
+ # Use Ez from your existing executor
2
+
3
+ The plugin manager and its Docker plugins work independently of the Telegram
4
+ relay. Use the same absolute launcher from any local executor to share a chosen
5
+ workspace's tools and accounts. The executor owns reasoning and conversation;
6
+ Ez owns the plugin registry and command transport. No provider-specific adapter,
7
+ new model login or GUI plugin installation is involved.
8
+
9
+ ## Setup
10
+
11
+ Install the main package and its dependencies in a permanent location using the
12
+ artifact steps in [setup](setup.md). Node 22+ is needed for the manager; Docker
13
+ and Compose are needed for executable plugins. Do not build/start the relay,
14
+ create a bot, pair an owner or configure a host executor for CLI-only use.
15
+ Create a private tools directory and select the existing company/project workspace:
16
+
17
+ ```sh
18
+ node /absolute/package/bin/ezenciel-agents-tools.mjs init --standalone \
19
+ --home /absolute/private/company-tools --workspace /absolute/company-workspace
20
+ /absolute/private/company-tools/bin/ez --help
21
+ /absolute/private/company-tools/bin/ez status
22
+ /absolute/private/company-tools/bin/ez plugins list
23
+ ```
24
+
25
+ Init starts nothing, uses an empty catalog by default, preserves existing
26
+ TOOLS.md notes and appends the registry's discovery instructions. A registry
27
+ cannot be replaced by rerunning init. Keep the package at its original path:
28
+ the launcher imports it. Status reports `main: null` without a relay binding;
29
+ automated software upgrades currently require a relay deployment.
30
+
31
+ Have each executor read the workspace's TOOLS.md and the installed plugin skills.
32
+ Add that instruction to its existing project instructions without replacing them.
33
+ Use the absolute launcher, or prepend its bin directory to that session's PATH.
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.
37
+
38
+ ## Install and verify a capability
39
+
40
+ The current conversation owns authorized plugin onboarding. Follow the
41
+ [plugin contract](plugins.md#installation-completion-contract), using the bound
42
+ launcher for `plugins inspect <id> --source /absolute/package`, then
43
+ `plugins install <id> --source /absolute/package --revision <inspected-hash>`.
44
+ Read the skill, start the plugin, complete its provider authentication and verify
45
+ the intended account with a supported operation. Deliver any necessary consent
46
+ link or QR in the current client. No Telegram handoff is required.
47
+
48
+ Run `tools list`, the registered alias's help and a harmless account operation
49
+ from each actual executor. Host-shell access alone does not prove a sandboxed
50
+ session can access Docker or the registry. Client permissions still apply.
51
+ Native client plugins/connectors are not converted into Ez plugins automatically.
52
+
53
+ ## Combine with an autonomous agent
54
+
55
+ A relay can coexist with CLI-only registries on the same machine. It retains its
56
+ 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.
60
+
61
+ Continuous monitoring requires a configured event consumer/relay and the plugin's
62
+ supported watcher. CLI-only installation does not create background agent turns.
@@ -0,0 +1,140 @@
1
+ # Verified beta publication
2
+
3
+ The Mac prepares and independently tests the release. GitHub-hosted Actions
4
+ publishes the exact approved tarball using npm OIDC. The shared implementation
5
+ is `.github/workflows/npm-beta-shared.yml` in this repository; each package has a
6
+ small manually dispatched `publish-beta.yml` caller. This setup does not grant
7
+ release authority or establish npm trust automatically.
8
+
9
+ ## Enroll a repository once
10
+
11
+ 1. Verify the source is public and explicitly registered in the current
12
+ [public catalog](plugin-catalog.md), or is core itself. Registration does not
13
+ prove a registry release exists. Excluded or private repositories cannot use
14
+ this publisher.
15
+ 2. Review and merge the shared publisher first. Generate the caller using its
16
+ full immutable commit SHA and the repository's required CI check names:
17
+
18
+ ```sh
19
+ node scripts/generate-publish-caller.mjs jdorado/ez-whatsapp \
20
+ @jc_stack/ez-whatsapp FULL_SHARED_COMMIT_SHA \
21
+ '["test (ubuntu-latest, 22)","test (ubuntu-latest, 24)","test (macos-latest, 22)","test (macos-latest, 24)","docker"]' > publish-beta.yml
22
+ ```
23
+
24
+ Put that file in the plugin's `.github/workflows/` through its own reviewed
25
+ PR. Inspect the actual CI names; the example does not establish the policy.
26
+ Keep the reusable workflow reference and `publisher-sha` on the same reviewed
27
+ commit. Core uses a local reusable workflow at the dispatch commit. The
28
+ generator writes stdout only; it never grants repository scope or edits npm.
29
+ 3. The npm package owner authenticates separately and enrolls the exact caller
30
+ repository and filename `publish-beta.yml` as a trusted publisher. Enable
31
+ **direct publication** explicitly; new trust configurations can default to
32
+ staged publication only. If an environment is configured on npm, add that
33
+ exact environment to the shared publishing job through review before use.
34
+ This workflow currently uses no environment.
35
+ 4. Verify enrollment through npm settings or `npm trust list PACKAGE`. npm
36
+ validates the **calling** workflow for reusable workflows. Both caller and
37
+ publishing job need `id-token: write`; test/validation jobs do not receive it. GitHub requires `contents: write`
38
+ to read unpublished draft assets: only the validation job receives that
39
+ capability and makes GET requests only. The separate OIDC job has
40
+ `contents: read`. No package code or lifecycle scripts run in validation.
41
+ Do not add `NODE_AUTH_TOKEN`, npm tokens, or private profiles to these jobs.
42
+
43
+ An npm package must already exist before trust enrollment. If a registered
44
+ plugin has no registry package, the owner must perform a real, approved initial
45
+ beta publication using authenticated npm, with all release checks and exact
46
+ artifact readback. Then enroll trust. Do not create a dummy release to test
47
+ login. A missing GitHub release likewise remains missing until actually created
48
+ and read back; a catalog link or workflow PR is not publication evidence.
49
+
50
+ Current npm requirements and enrollment fields are documented in
51
+ [npm trusted publishers](https://docs.npmjs.com/trusted-publishers/) and
52
+ [npm trust](https://docs.npmjs.com/cli/v11/commands/npm-trust/).
53
+ The workflow uses Node 24 and npm 11.19.1 on GitHub-hosted Ubuntu runners.
54
+
55
+ ## Prepare and dispatch one beta
56
+
57
+ Follow [releasing](releasing.md), including isolated Mac tests, packed artifact
58
+ inspection, independent review, required CI and authorized merge. The source
59
+ must be the exact current `main` commit; after a merge, verify that its tree
60
+ matches the tested source and renew invalidated evidence. Wait for that commit's
61
+ CI from `.github/workflows/ci.yml`, triggered by a push on `main`. The caller's reviewed list of required checks is a fail-closed minimum;
62
+ update it when repository policy adds checks. The validator selects the newest
63
+ main-push CI run for that source before checking success, then requires the named
64
+ jobs from its latest attempt. Tag, PR and other workflow runs cannot shadow it;
65
+ failed, pending or incomplete main CI cannot fall back to an older success.
66
+
67
+ Create the `vVERSION` tag at that exact source commit and a **draft prerelease**
68
+ with these assets, using native `gh release create --draft --prerelease` and
69
+ `gh release upload` under existing release authority:
70
+
71
+ - `candidate.tgz`: the exact Mac-tested bytes from `npm pack --ignore-scripts`.
72
+ Do not rebuild it on Actions.
73
+ - `release-receipt.json`: a sanitized record with this shape:
74
+
75
+ ```json
76
+ {
77
+ "repository": "jdorado/ez-agents",
78
+ "package": "@jc_stack/ez-agents",
79
+ "version": "0.1.0-beta.14",
80
+ "sourceSha": "FULL_TESTED_MAIN_COMMIT_SHA",
81
+ "sha256": "SHA256_OF_CANDIDATE_TGZ",
82
+ "independentReviewUrl": "https://github.com/jdorado/ez-agents/pull/PR_NUMBER#issuecomment-ID",
83
+ "testEvidenceUrls": ["https://github.com/jdorado/ez-agents/actions/runs/RUN_ID"]
84
+ }
85
+ ```
86
+
87
+ The maintainer verifies those evidence links substantiate independent final-diff
88
+ review, artifact tests and accepted beta limitations before dispatch. The receipt
89
+ binds that attestation to the commit and digest; a syntactically valid URL alone
90
+ cannot prove review quality or release authority.
91
+
92
+ Read the draft's numeric `id` with `gh api repos/OWNER/REPO/releases` (the
93
+ release-by-tag API only returns published releases). Dispatch `publish-beta.yml`
94
+ on `main` with `release-id`, `version`, `source-sha` and
95
+ `artifact-sha256`. Copy the digest from the independently verified Mac receipt,
96
+ not an unreviewed replacement release asset. The validator checks current public
97
+ scope, source/tag identity, required GitHub Actions checks, receipt identity,
98
+ package metadata and tarball hash. It transfers the validated bytes using an
99
+ immutable Actions artifact ID. A fresh job revalidates before publication and
100
+ runs npm from a clean directory without package lifecycle scripts.
101
+
102
+ Only `X.Y.Z-beta.N` versions are supported. Publish to npm `latest` so the
103
+ package page and default installs show the newest approved release. Manifests
104
+ must use `publishConfig.tag: "latest"` (or omit the tag). The version remains a
105
+ SemVer prerelease and the GitHub release remains a prerelease. Private
106
+ packages, wrong package/repository identities and stable versions fail before
107
+ publication. No npm login smoke publication or stable-version release occurs.
108
+
109
+ ## Readback, failure and release completion
110
+
111
+ The publisher reads registry metadata, checks that `latest` identifies the released version and downloads the
112
+ published tarball to compare its SHA-256. Preserve the workflow's readback receipt, run URL and source/artifact
113
+ identity on the release PR. A failed command after the publish call may mean npm
114
+ accepted it: inspect registry state first. A rerun may verify an existing exact
115
+ version; if the version is absent it refuses a second write. Reconcile first,
116
+ then create a fresh authorized dispatch if appropriate. Never repeat or overwrite that version or silently repair tags.
117
+ Missing trust or registry access is an external dependency, not a reason to use
118
+ a token workaround.
119
+
120
+ After successful registry readback, finish the GitHub prerelease with the tested
121
+ artifact/checksum and verify its public availability. Perform the clean-host
122
+ installation and runtime/provider checks required by the package's release
123
+ rules. Actions success proves registry delivery only; it does not prove a
124
+ running agent was upgraded. Respect each installation's saved update policy.
125
+
126
+ ## Migration from the legacy beta tag
127
+
128
+ Existing plugin callers are SHA-pinned: regenerate each caller against the merged
129
+ shared-publisher revision and update its package publishConfig together through
130
+ review. Old pins retain the old behavior. Do not mutate an already staged or
131
+ published artifact; prepare a new version when package metadata changes.
132
+
133
+ The publisher uses one native npm publish operation with OIDC and `--tag latest`.
134
+ It does not synchronize the legacy `beta` tag: npm trusted publishing does not
135
+ support standalone dist-tag changes. No extra registry token is needed. Ez beta
136
+ update discovery considers both latest and legacy beta during migration; stable-only
137
+ policies select non-deprecated stable versions and cannot automatically install a
138
+ prerelease. Older installed updaters still following only beta require an explicit
139
+ exact-version update to a core release containing this discovery change. Existing
140
+ registry versions/tags are not changed by merging the publisher.