@awebai/oats 0.22.1 → 0.22.3

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.
@@ -68,6 +68,45 @@ knowledge; if instances should RUN it the same way every time, it wants to
68
68
  be a skill instead. Souls also grow role-specific types and sections — list
69
69
  new sections in the bundle index and log the growth.
70
70
 
71
+ ## Record-fed candidates
72
+
73
+ Your briefing may name **record windows** beside (or instead of) notes: the
74
+ source instance's own captured session turns since the last harvest, each
75
+ window given as an exact `oats recall --thread <t> --json --after <id>
76
+ --until <id>` command. Standing roles that write few notes still learn; this
77
+ is how what they learned reaches the soul.
78
+
79
+ - Run each command exactly as given, never wider: the ids are the boundary
80
+ two harvests agree on, and each window is sized for one full reading (the
81
+ rest of a long backlog comes in later harvests). Read every window in full.
82
+ If your tool output truncates, redirect the command's output to a file in
83
+ your home and read the file in parts; that is a complete reading, not a
84
+ wider one. If you still could not read a window completely, this harvest
85
+ has FAILED: judge nothing from it and leave the watermark files untouched. If a command is rejected because its
86
+ `--after` id is no longer in the thread (a pruned or redacted record), run
87
+ it again without `--after` and read from the start; if its `--until` id is
88
+ rejected, this harvest has failed (leave the watermark files alone; the next
89
+ `oats okf harvest` replans). Read the `text` parts;
90
+ `tool_use` and `tool_result` are context, not lessons.
91
+ - Extract **candidates** in the shape of notes: one candidate per insight, a
92
+ one-line title, the claim, and its provenance as the turn ids it came from.
93
+ A candidate is something the instance learned or decided, stated in the
94
+ turns, not something you infer it should have learned.
95
+ - Then judge every candidate exactly as a note: promote, merge, or drop
96
+ against the same bar. Expect most to drop: session trivia, tool noise,
97
+ restated repo facts and task-scoped decisions all fail it. Promoted
98
+ concepts cite the turn ids in their frontmatter or body so the claim can be
99
+ traced back.
100
+ - **The watermark records what you read, not what you promoted.** The
101
+ package prepared the exact next watermark beside the current one; your
102
+ briefing gives the one `mv` that advances it. Run it once your judgement of
103
+ every window is complete: after the commit, PR, or direct edit when
104
+ something was promoted, and just the same when everything dropped, which
105
+ is the normal outcome. Never retype it. Only a harvest that fails or is
106
+ abandoned leaves both files untouched, so the next harvester reads the same
107
+ window again; a completed judgement that never advanced the watermark would
108
+ be re-read forever.
109
+
71
110
  ## Bookkeeping (non-negotiable)
72
111
 
73
112
  1. Every promoted concept: correct frontmatter, listed in its section's
@@ -92,7 +131,9 @@ what your custody allows:
92
131
  `memory-harvest: 2 lessons + 1 skill gotcha from worker-x notes`.
93
132
  2. **Worktree of the soul's home repo** (workspace-mode source): the same single
94
133
  commit on your own branch, then push it and open a PR. Never merge it, and
95
- never push to that repo's main branch — its owners review soul changes.
134
+ never push to that repo's main branch — its owners review soul changes. A
135
+ harvest that promoted nothing has no commit, push or PR to make; it is
136
+ complete, not failed, and still advances the watermark.
96
137
  3. **Uncommitted local soul**: nothing to commit. Your edits to the soul ARE the
97
138
  delivery; they take effect for the next instance immediately.
98
139
 
@@ -119,6 +119,20 @@
119
119
  "marketplace": {
120
120
  "type": "string",
121
121
  "description": "Optional source to register before installing (Claude marketplaces). Shown at the consent prompt, since registering a third-party source is part of what is being agreed to."
122
+ },
123
+ "when": {
124
+ "type": "object",
125
+ "description": "Applies only when every named capability setting has the given effective value (a requirement conditional on configuration, e.g. delivery: channel).",
126
+ "additionalProperties": {}
127
+ },
128
+ "minVersion": {
129
+ "type": "string",
130
+ "description": "Lowest acceptable installed version of the package, read from the package.json under the install directory the runtime's listing names; an older or absent manifest fails the requirement with the install remedy.",
131
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+"
132
+ },
133
+ "ifInstalled": {
134
+ "type": "boolean",
135
+ "description": "When true, an absent package satisfies the row; the row's minVersion and loadability checks apply only to a package that is installed (an ambient extension that must honour a contract if present)."
122
136
  }
123
137
  },
124
138
  "additionalProperties": false
@@ -217,6 +231,33 @@
217
231
  "type": "string"
218
232
  },
219
233
  "description": "Package-relative soul directories (soul.yaml + AGENTS.md) \u2014 capability-defined agents; they resolve like local souls where the capability is active, souls stay read-only in the package, instances home under the scope's local-agents/."
234
+ },
235
+ "settings": {
236
+ "type": "object",
237
+ "description": "Declared capability settings: name to { default, values?, description }. Documentation for `oats use --settings`; undeclared settings are still accepted.",
238
+ "additionalProperties": {
239
+ "type": "object",
240
+ "properties": {
241
+ "default": {},
242
+ "values": {
243
+ "type": "array",
244
+ "description": "Accepted scalar values; an effective value outside the list is refused at resolution.",
245
+ "items": {}
246
+ },
247
+ "description": {
248
+ "type": "string"
249
+ }
250
+ },
251
+ "additionalProperties": false
252
+ }
253
+ },
254
+ "environmentNamespaces": {
255
+ "type": "array",
256
+ "description": "Additional environment-name prefixes this capability may declare besides its vendor's own (e.g. AWEB_ for the official oats.aweb integration). Each is an uppercase prefix ending in an underscore; the reserved core (OATS_, PI_AGENT_) and process bootstrap namespaces cannot be claimed. Disclosed at trust time with the environment list.",
257
+ "items": {
258
+ "type": "string",
259
+ "pattern": "^[A-Z][A-Z0-9]*_$"
260
+ }
220
261
  }
221
262
  },
222
263
  "additionalProperties": false
@@ -0,0 +1,210 @@
1
+ # Execution targets and shared wake delivery
2
+
3
+ Implementation agreement, 2026-09-05. Lead owns native runtime launch,
4
+ local tmux/Herdr adapters and terminal input; oats owns server registration,
5
+ remote CLI routing and Desktop target selection. Aweb owns the event listener,
6
+ notification state and delivery policy through OATS terminal input. This is the implementation
7
+ contract, not a claim that these features have shipped.
8
+
9
+ OATS manages composition, worktrees, capability lifecycle and retirement on the execution
10
+ host. A session backend manages the persistent terminal. Desktop is a client;
11
+ closing it must stop neither the agent nor notification delivery.
12
+
13
+ ```mermaid
14
+ flowchart LR
15
+ UI[Desktop] --> CLI[OATS CLI]
16
+ CLI --> Local[Local OATS]
17
+ CLI --> SSH[OpenSSH]
18
+ SSH --> Remote[Remote OATS]
19
+ Local --> Sessions[tmux or Herdr]
20
+ Remote --> RemoteSessions[tmux or Herdr]
21
+ Events[aweb SSE] --> Wake[aweb wake service on execution host]
22
+ Wake --> Local
23
+ RemoteWake[aweb wake service on remote host] --> Remote
24
+ ```
25
+
26
+ Server registrations live in the operator's machine configuration, outside
27
+ repository configuration. Each entry has an id, label, OpenSSH host alias,
28
+ absolute workspace path and OATS/Herdr executable paths. SSH owns key selection,
29
+ host verification and authentication. Registration stores no private keys.
30
+ Remote lifecycle calls invoke the remote installed OATS CLI with argument-safe
31
+ quoting and the same JSON envelope as local calls. Version/envelope compatibility
32
+ is checked before mutation. Repository operations always run on that host.
33
+
34
+ The local representation of a remote instance snapshots its route:
35
+
36
+ ```json
37
+ {
38
+ "serverId": "build-server",
39
+ "target": {
40
+ "sshHost": "build-server",
41
+ "workspace": "/srv/team",
42
+ "oatsPath": "/usr/local/bin/oats",
43
+ "herdrPath": "/usr/local/bin/herdr"
44
+ },
45
+ "instance": "developer-fix",
46
+ "home": "/srv/team/agents/developer/instances/developer-fix"
47
+ }
48
+ ```
49
+
50
+ `serverId` is for display. Later inspect/retire operations use the snapshot,
51
+ never silently resolve a changed registry entry. A local cache is not authority
52
+ for the remote instance's state. Remote status is pulled from its owning kernel.
53
+
54
+ The host's instance and independent retirement baseline retain the same local
55
+ session receipt. Existing `tmux: {session, window, socket}` remains readable.
56
+ New Herdr instances use:
57
+
58
+ ```json
59
+ {
60
+ "backend": "herdr",
61
+ "binary": "/usr/local/bin/herdr",
62
+ "socket": "/home/operator/.config/herdr/sessions/oats/herdr.sock",
63
+ "workspaceId": "w1",
64
+ "paneId": "w1:p1",
65
+ "terminalId": "term_65ab9108c6c301",
66
+ "protocol": 20
67
+ }
68
+ ```
69
+
70
+ The terminal id distinguishes a replacement occupant after a server restart.
71
+ Backend operations allocate, start, inspect, stop and attach a viewer. Retirement
72
+ compares the receipt with its baseline and proves the original session absent.
73
+ An unavailable server or failed inspection is not proof of absence. The same
74
+ rule applies to spawn compensation and detached self-retirement. Lifecycle
75
+ operations run on the target host, so the local backend does not implement SSH.
76
+
77
+ Herdr 0.8.2 exposes snapshots, socket commands, agent-state inspection and JSONL
78
+ terminal observation/control. Its protocol is versioned. Agent prompts reject
79
+ approval-blocked agents, but prompting a working agent does not prove the new
80
+ message was processed. The adapter must retain this distinction. See the
81
+ [Herdr socket API](https://herdr.dev/docs/socket-api/) and
82
+ [remote connections](https://herdr.dev/docs/persistence-remote/).
83
+
84
+ An aweb host service owns event streams for managed instances; the GUI displays
85
+ and controls it. Reuse aweb's existing authenticated event/run loop rather than copying credential
86
+ and SSE parsing into OATS or Desktop. OATS exposes backend-neutral session
87
+ inspection and literal terminal input; aweb supplies delivery policy. Current authorization is
88
+ per identity: one long-lived stream per active identity, coalesced per instance,
89
+ with bounded retries. A single team stream requires an explicit server API.
90
+ Reconnect also checks pending state so a lost edge does not strand unread work.
91
+
92
+ Delivery is a fixed instruction to check `aw` mail/chat from the instance home,
93
+ not arbitrary sender content typed into a shell. The service never acknowledges
94
+ mail or chat on the agent's behalf. Aweb pending hints survive reconnect and service
95
+ restart, coalesce while busy and defer at approval prompts. A stopped harness,
96
+ an unknown occupant or a fallback shell is not a delivery target. Do not call a
97
+ successful terminal write an agent acknowledgement.
98
+
99
+ Native channels remain selectable during qualification; session delivery must
100
+ be exclusive with them for each instance. Removal follows real tests of Pi,
101
+ Claude and Codex receiving mail/chat, a busy turn, an approval prompt, reconnect,
102
+ service restart, GUI closure and a stopped runtime. The OATS Pi tool extension
103
+ and the aweb Pi channel are separate packages; replacing notification transport
104
+ does not silently remove unrelated tools.
105
+
106
+ Acceptance includes local CLI/Desktop spawn, reattach, preserved work and
107
+ retirement through both backends; then the same operations on a user-designated
108
+ SSH target. Registering a host without a successful remote agent run does not
109
+ qualify remote support.
110
+
111
+ ## Session CLI contract
112
+
113
+ Run on the execution host:
114
+
115
+ ```sh
116
+ oats session attach --home /absolute/instance
117
+ oats session inspect --home /absolute/instance --json
118
+ oats session input --home /absolute/instance --text-file /path/to/message --json
119
+ printf '%s' 'Check your pending work.' | oats session input --home /absolute/instance --json
120
+ ```
121
+
122
+ `attach` is interactive and does not accept `--json`. It validates the saved
123
+ endpoint on the execution host, then opens a Herdr terminal viewer or an
124
+ isolated tmux session linked to that agent's window alone. Closing its terminal
125
+ cleans the viewer without stopping the agent; retiring the agent ends the viewer
126
+ instead of switching it to a sibling. This host-local command is also the
127
+ remote Desktop attachment seam over an SSH PTY.
128
+
129
+ Input accepts UTF-8 text up to 256 KiB, with no NUL bytes. The CLI uses the
130
+ independent lifecycle receipt and refuses metadata disagreement. Tmux uses
131
+ literal bracketed paste followed by Enter. Herdr uses pane input followed by
132
+ Enter. Neither path interprets message text as a shell command. A fallback
133
+ shell or ambiguous split tmux window refuses automatic input.
134
+
135
+ Success uses the existing envelope:
136
+
137
+ ```json
138
+ {"schemaVersion":1,"ok":true,"result":{"home":"/absolute/instance","backend":"herdr","present":true,"state":"idle","submitted":true}}
139
+ ```
140
+
141
+ Inspect omits `submitted`; optional backend identifiers describe the observed
142
+ terminal. `state` is the Herdr agent state when available, `unknown` for a live
143
+ unclassified harness, `shell` for a fallback shell, `stopped` for an absent/dead
144
+ terminal, or `not-launched`. Errors use `ok:false,error:{code,message}` and a
145
+ nonzero exit. An unavailable backend is an error, never a stopped result.
146
+ Tmux receipts identify socket/session/window; automatic input requires one live
147
+ pane in that exact window. Herdr additionally verifies the original terminal ID.
148
+ The broker owns busy/approval policy and must not interpret `submitted` as
149
+ processing acknowledgement.
150
+
151
+ Capability spawn hooks register a pending home before runtime allocation;
152
+ inspection becomes available once its receipt is persisted. Retire hooks
153
+ unregister after quiescence. The broker must tolerate this lifecycle order and
154
+ missing homes, and persist pending hints until handled. Kernel session operations
155
+ contain no aweb identity, credentials, stream or notification logic.
156
+
157
+ The portable integration belongs to the official `oats.aweb` capability.
158
+ The aweb development deployment currently selects its owned `aweb.identity`
159
+ capability; that deployment-specific choice does not change the broker interface
160
+ and needs equivalent registration glue when switched to session delivery.
161
+
162
+ ## Shared permission setting
163
+
164
+ Set `yolo: true` in an `oats-config.yaml` to apply it to that scope. The closest
165
+ scope wins; an optional `yolo` in soul.yaml overrides it; `oats spawn --yolo` or
166
+ `--no-yolo` overrides both. `oats create` accepts those flags too. Desktop offers
167
+ the same per-launch choice. With no setting, native policy is retained.
168
+
169
+ Codex receives `--yolo` plus a launch-local trust setting for the generated
170
+ instance home; Claude receives `--dangerously-skip-permissions`. Pi's existing
171
+ project trust behavior is unchanged. `--no-yolo` removes the OATS bypass flags;
172
+ it leaves the operator's native harness settings in force. Instance metadata
173
+ records an explicitly resolved setting. This choice applies when starting an
174
+ agent, not retroactively to running sessions.
175
+
176
+ Desktop remote terminal requests contain only the server id and instance name.
177
+ The selected installed CLI resolves the saved route and performs remote
178
+ inspection before attaching over SSH. Pending inspections share the terminal
179
+ resource limit and duplicate requests share one inspection. Remote status and
180
+ instance keys must include the server so identical paths on different hosts
181
+ remain distinct.
182
+
183
+ ## Desktop remote roster and lifecycle
184
+
185
+ Desktop uses the installed CLI's `server roster --json` feature when advertised.
186
+ It refreshes one aggregate roster at a time, independently of terminal traffic;
187
+ the CLI owns SSH deadlines, server registration and saved routes. Each target
188
+ appears in the workspace selector with its souls and instances. An unreachable
189
+ target stays visible with unknown runtime state and an error. A saved route
190
+ remains visible after its registration is removed or changed.
191
+
192
+ Choose the server workspace to spawn one of its souls. A successful launch
193
+ switches to that workspace and opens the instance terminal once it appears in
194
+ the roster. The instance action menu offers harvest and retirement, including
195
+ for stopped agents. Remote harvest runs in the saved home on the execution host;
196
+ retirement uses the same saved route and work-preservation rules as the CLI.
197
+ Closing a viewer leaves the agent running.
198
+
199
+ Desktop retirement requires the CLI's `retire-home` feature and always sends
200
+ the exact selected home. The remote kernel must support that feature too;
201
+ older kernels require an upgrade before the GUI can retire an instance.
202
+ This keeps same-named instances distinct. Retirement feedback reports every
203
+ preserved recovery path and its classes, including an incomplete cleanup.
204
+
205
+ This first projection enables terminal and lifecycle actions only for remote
206
+ instances with a route saved on this machine. Other observed instances are
207
+ listed, but require the execution host's CLI to manage them. Remote brain files
208
+ are accessed through the terminal. The roster and remote harvest require CLI
209
+ feature tokens `roster` and `harvest`; the published 0.22.2 kernel has remote
210
+ spawn, status, retirement and terminals, but not these two additions.
@@ -158,7 +158,20 @@ instance homed inside a repository with its own `.claude/skills` sees those
158
158
  too. Project *settings* — hooks, plugins, permissions, custom agents — resolve
159
159
  from the instance home rather than from ancestors.
160
160
 
161
- Both runtimes record what they actually expose in `instance.json` under
161
+ Codex is available with `--runtime codex`. It starts in the instance home,
162
+ reads `AGENTS.md` and `.agents/skills` natively, and receives `TASK.md` as its
163
+ initial prompt. User configuration, approval policy, ancestor instructions and
164
+ ambient skill sources remain native. Worktrees are already below the instance
165
+ home; checkout/attached paths outside it use Codex's normal approval handling
166
+ and may require approval for writes, depending on the operator's policy.
167
+ OATS does not pass `--add-dir`, which Codex refuses under some native policies.
168
+ OpenAI-prefixed model preferences are translated to
169
+ Codex ids; other provider preferences fall back to its configured default.
170
+ The Desktop model field accepts a native id without using Pi's model catalog.
171
+ This launch support does not supply an aweb channel for Codex: agents can use
172
+ `aw` from their home, with automatic wake delivery tracked separately.
173
+
174
+ All runtimes record what they actually expose in `instance.json` under
162
175
  `composition.materialized.runtimePosture`: the OATS-composed set, what is
163
176
  curtailed, and what remains ambient. The deviation from strict composition is
164
177
  auditable rather than implied.
@@ -139,3 +139,39 @@ contract design, and the `integration-authoring` skill routes work to it.
139
139
  Test an integration as a capability package: acquire, lock, trust, activate,
140
140
  spawn, retire, with the golden fixtures as the behavior oracle for the kernel
141
141
  side.
142
+
143
+ ## oats.aweb settings (1.10.0)
144
+
145
+ Set with `oats use oats.aweb --settings <key>=<value>` at a scope, or per
146
+ soul through the binding's `settings:` map.
147
+
148
+ - `delivery: channel | session` (default `channel`). `session` hands
149
+ notification delivery to the host wake broker: `AWEB_DELIVERY=session` in
150
+ the launch environment (declared by the manifest), no Claude channel flag,
151
+ a pi extension that honours the opt-out (`@awebai/pi` 0.3.10 or later,
152
+ enforced as a conditional requirement with a version floor), and a briefing
153
+ and registration of the home with the host wake broker (`aw wake register`).
154
+ Until an aw that ships `aw wake` exists (aweb-abil), session mode REFUSES
155
+ to spawn rather than leave an instance that nothing wakes: it is for broker
156
+ qualification only; leave the default otherwise.
157
+ - `identity: { source: "/abs/path/to/legacy/.aw" }`, per soul, explicit and
158
+ never inferred. The spawned instance becomes the retained seat of that
159
+ existing identity (same did:aw and address). The aweb service URL comes
160
+ from the source's `workspace.yaml` (`aweb_url`); a hosted-init source has
161
+ none, so set `OATS_AWEB_URL` (for example `https://app.aweb.ai/api`) in
162
+ the spawn environment when the source lacks it: the identity-authority files
163
+ are copied into the home's `.aw` (never `workspace.yaml` or caches), the
164
+ coordination binding is reconnected with `aw workspace connect`, and the
165
+ seat is verified online before the instance is briefed. A lock beside the
166
+ source (`.aw-retained-seat.json`) refuses a second seat while a holder is
167
+ live. Retire releases the lock and touches neither the identity nor the
168
+ source; removing the legacy `.aw` is a human step. Rehearse on a disposable
169
+ global identity first: a send, a claim and a heartbeat from the new home
170
+ must all work before any real seat moves.
171
+
172
+ Requirement rows in a manifest may carry `when: { <setting>: <value> }` (the
173
+ row applies only when the capability's effective setting matches) and
174
+ `minVersion` (the version is read from the package.json under the install
175
+ directory the runtime's listing names; an older or absent manifest fails the
176
+ requirement with the install remedy). `ifInstalled: true` makes an absent
177
+ package satisfy the row, so the floor applies only to an ambient extension.
@@ -29,7 +29,7 @@ version has a supported replacement. When the plan is correct:
29
29
 
30
30
  ```bash
31
31
  oats migrate --from-oas --dir /path/to/scope
32
- oats doctor --dir /path/to/scope
32
+ oats doctor /path/to/scope
33
33
  ```
34
34
 
35
35
  Run the exact `oats trust <capability> --dir <scope>` commands printed by
@@ -72,6 +72,7 @@
72
72
  },
73
73
  "type": "object",
74
74
  "properties": {
75
+ "yolo": { "type": "boolean", "description": "Skip Codex/Claude permission prompts. Closest scope wins; soul and launch overrides take precedence." },
75
76
  "name": { "type": "string" },
76
77
  "team": {
77
78
  "type": "object",