@awebai/oats 0.22.17 → 0.23.0

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 (45) hide show
  1. package/README.md +7 -2
  2. package/bin/oats.mjs +365 -31
  3. package/docs/configuration.md +65 -0
  4. package/docs/design/2026-09-07-mobile-agent-management-proposal.md +228 -0
  5. package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +558 -0
  6. package/docs/design/2026-09-13-knowledge-and-memory-direction.md +744 -0
  7. package/docs/design/2026-09-13-knowledge-implementation.md +127 -0
  8. package/docs/design/2026-09-13-knowledge-location-contract.md +340 -0
  9. package/docs/design/launch-configurations.md +164 -0
  10. package/docs/design/package-runtime-api.md +177 -3
  11. package/docs/desktop-cli-api.md +68 -2
  12. package/docs/desktop-instance-start.md +39 -3
  13. package/docs/execution-targets.md +16 -0
  14. package/docs/knowledge-capability-authoring.md +98 -0
  15. package/docs/knowledge-reference/acceptance.md +108 -0
  16. package/docs/knowledge-reference/adoption.md +61 -0
  17. package/docs/knowledge-reference/harvester.md +107 -0
  18. package/docs/knowledge-reference/model.md +84 -0
  19. package/docs/knowledge-reference/package-craft.md +126 -0
  20. package/docs/knowledge-reference/provider-mapping.md +77 -0
  21. package/docs/knowledge-reference/reader-capture.md +87 -0
  22. package/docs/knowledge-theory.md +20 -6
  23. package/docs/layers.md +8 -7
  24. package/docs/oats-config.schema.json +33 -2
  25. package/docs/release-notes/v0.22.18.md +101 -0
  26. package/docs/release-notes/v0.22.19.md +115 -0
  27. package/docs/release-notes/v0.23.0.md +93 -0
  28. package/docs/souls-and-instances.md +18 -1
  29. package/injects/work-directory.md +18 -0
  30. package/lib/core.mjs +1109 -187
  31. package/lib/schedule.mjs +12 -2
  32. package/lib/servers.mjs +89 -4
  33. package/package.json +2 -2
  34. package/packages/record/README.md +19 -0
  35. package/packages/record/bin/capture.mjs +144 -53
  36. package/packages/record/bin/recall.mjs +17 -11
  37. package/packages/record/bin/record-native-start.mjs +11 -0
  38. package/packages/record/lib/capture-cc.mjs +82 -27
  39. package/packages/record/lib/capture-lock.mjs +81 -5
  40. package/packages/record/lib/formats.mjs +108 -21
  41. package/packages/record/lib/native-history.mjs +87 -0
  42. package/packages/record/lib/session-roots.mjs +90 -0
  43. package/packages/record/lib/session-snapshot.mjs +61 -0
  44. package/packages/record/lib/sessions-for-home.mjs +88 -56
  45. package/skills/oats/SKILL.md +3 -1
@@ -241,6 +241,71 @@ runs inside each fresh worktree after creation (a lot of teams prefer a
241
241
  script that sets up the environment: installs, .env copying, direnv/mise).
242
242
  Its failure warns without hiding the instance.
243
243
 
244
+ ### `launch-configs`
245
+
246
+ A named way to start a harness, independent of any soul: which runtime, an
247
+ executable (a wrapper, another binary), literal arguments, environment, a
248
+ model and yolo. Souls keep their own defaults; a launch configuration is
249
+ selected by name at spawn or when an existing instance is started or
250
+ restarted, so the same home can move between configurations without
251
+ being replaced.
252
+
253
+ ```yaml
254
+ launch-configs:
255
+ personal:
256
+ runtime: claude
257
+ executable: ./bin/claude-personal # relative: against THIS scope's directory
258
+ args:
259
+ - "--settings"
260
+ - "/Users/me/.claude-personal/settings.json" # a native config file is an ordinary
261
+ # argument the harness reads from the
262
+ # INSTANCE HOME it starts in: absolute
263
+ env:
264
+ ANTHROPIC_API_KEY:
265
+ fromEnv: PERSONAL_ANTHROPIC_KEY # resolved on the execution host at start
266
+ CLAUDE_CONFIG_DIR: "/Users/me/.claude-personal"
267
+ model: claude-opus-5
268
+ yolo: true
269
+ fast:
270
+ runtime: codex
271
+ model: gpt-5.5
272
+ ```
273
+
274
+ - The closest scope declaring a name provides the **whole** entry; a farther
275
+ declaration of the same name is shadowed, never merged into.
276
+ - `executable`: a bare name is looked up on `PATH` on the execution host; a
277
+ path with a slash is resolved against the declaring scope when relative.
278
+ It must exist and be executable; it is never run just to probe it.
279
+ - `args` and literal `env` values are passed byte-exact: spaces, quotes and
280
+ shell metacharacters are literal, never interpreted. A path among them is
281
+ read by the harness from the instance home it starts in, not from the
282
+ declaring scope: write native configuration paths absolute.
283
+ - `env` values are either literals (non-secret by contract, but no answer ever
284
+ shows them: `oats launch-config list` and `preview` redact them) or
285
+ `{fromEnv: NAME}` references, which is the way to hand a secret to a
286
+ harness. Only the reference is recorded in an instance's launch recipe and
287
+ receipts; the value is read from the execution host's environment at start
288
+ time, and a missing reference refuses the start before anything stops.
289
+ - `model` and `yolo` override the soul's defaults when the configuration is
290
+ selected; explicit `--model`/`--yolo` flags override the configuration.
291
+
292
+ The CLI authors the block:
293
+
294
+ ```sh
295
+ oats launch-config list [--dir <scope> | --home <abs> | --soul <name>] --json
296
+ oats launch-config set personal --file personal.json [--keep-env] --dir <scope>
297
+ oats launch-config remove personal --dir <scope>
298
+ ```
299
+
300
+ `set` and `remove` rewrite only the `launch-configs` block of that scope's
301
+ `oats-config.yaml`; every other byte stays. `--keep-env` copies the
302
+ environment of the definition effective at that scope for the name (its own,
303
+ or the inherited one being overridden) into the complete new entry, once: an
304
+ editor that saw only redacted values omits `env` from its definition. It is a
305
+ copy at save time, not inheritance; the new entry shadows whole. `list --home`
306
+ reads the home's recorded context; `list --soul` reads the soul's own member
307
+ scope.
308
+
244
309
  ## Acquisition and lockfile
245
310
 
246
311
  External acquisition writes `oats-lock.json` beside the declaring config in
@@ -0,0 +1,228 @@
1
+ # Proposal: manage server agents from an iPhone
2
+
3
+ Status: proposed, September 7, 2026. Requested by Juan following a feasibility
4
+ assessment. This document authorizes no implementation, deployment, or changes
5
+ to running teams. Recommendations below are not shipped functionality.
6
+
7
+ ## Purpose and recommendation
8
+
9
+ Let an operator manage OATS agents on a server and talk to them from an iPhone.
10
+ Agents keep working when the phone is locked, disconnected, or switched off.
11
+ Screenshots and files are part of the first useful experience.
12
+
13
+ Start with one server reached privately through Tailscale and a mobile web app
14
+ that can be installed on the iPhone Home Screen. Build on the existing OATS
15
+ control and session contracts. A native iPhone app can consume the same service
16
+ later if sharing, voice, notifications, or other native integration justify it.
17
+
18
+ The substantial work is making the client/server boundary explicit and making
19
+ conversation delivery reliable. A narrow management and terminal client is
20
+ feasible without rewriting the kernel. A polished conversation experience is
21
+ more than embedding the Desktop terminal in a small screen.
22
+
23
+ This extends the [architecture reassessment](2026-09-07-architecture-reassessment.md)
24
+ and its interpretation of Juan's KB direction: standard components with clear
25
+ contracts, replaceable service providers, and preserved identity and knowledge
26
+ across runtime changes. It does not supersede those contracts.
27
+
28
+ ## What exists and what is missing
29
+
30
+ Assessment baseline: source main `d20f082`, with Desktop behavior inspected in
31
+ the lead worktree containing that main. These are reusable pieces, not a claim
32
+ that a remote mobile API already exists.
33
+
34
+ | Area | Existing basis | Work needed for mobile |
35
+ | --- | --- | --- |
36
+ | Lifecycle and configuration | CLI-backed roster, spawn/start, model choices, retirement and schedule operations | Authenticated network access with exact target selection and truthful results |
37
+ | Terminal access | Session adapters, HTTP pane capture/input, Electron PTY attachment | Network streaming, resize, reconnect and bounded viewer lifetime outside Electron |
38
+ | Attachments | Desktop file/image ingestion and execution-host upload | Browser or native file selection, authenticated upload and visible transfer state |
39
+ | Provider operations | Scoped inspection and declared capability operations | Reuse the same discovery and invocation routes in mobile views |
40
+ | Conversations | aweb is the intended owner of durable identity, messages and delivery | Qualify the human/agent conversation, reply and replay contracts before promising chat |
41
+ | Background operation | Durable agent sessions and OATS scheduling mechanisms | Qualify service, scheduler and message wake operation with every GUI closed |
42
+
43
+ The current [Desktop HTTP backend](../../packages/desktop/server/oats-web.mjs)
44
+ binds to loopback and checks local Host/Origin values. It assumes a trusted
45
+ local client; it is not an authenticated remote service. Live terminal data,
46
+ resize and attachment calls currently cross
47
+ [Electron IPC](../../packages/desktop/main.mjs). Exposing the current port
48
+ unchanged or running Electron headlessly would not complete the required work.
49
+
50
+ ## Architecture and ownership
51
+
52
+ ```mermaid
53
+ flowchart TD
54
+ Phone[iPhone: mobile web or native client] -->|HTTPS over Tailscale| Service[OATS host control service]
55
+ Desktop[Desktop client] -->|Shared control contracts| Service
56
+ Service --> Kernel[Existing OATS CLI and kernel]
57
+ Kernel --> Sessions[Session adapters: tmux or Herdr]
58
+ Service --> Messaging[Selected messaging provider: aweb initially]
59
+ Kernel --> Providers[Selected knowledge and task capabilities]
60
+ ```
61
+
62
+ The service is a proposed independently runnable form of the existing control
63
+ backend, with the necessary terminal transport moved out of Electron. It
64
+ delegates lifecycle mutations to the supported OATS CLI. Desktop adoption can
65
+ be incremental; mobile must not introduce a second lifecycle implementation.
66
+
67
+ | Component | Responsibility |
68
+ | --- | --- |
69
+ | OATS kernel | Construction, lifecycle, runtime/model configuration, host placement, schedules and capability resolution |
70
+ | Host control service | Authenticated client access, scoped command dispatch, bounded live observations, attachments and terminal viewers |
71
+ | Session backend | Durable execution, attach/detach, literal input, resize and terminal observation |
72
+ | Messaging provider | Durable identity, conversations, events, delivery and any missing human/agent messaging semantics |
73
+ | Knowledge provider | Knowledge representation, access, harvest and promotion policy |
74
+ | Phone and Desktop | Operator interaction and presentation of the same contracts |
75
+
76
+ Use one control service for the selected deployment on a host, not a process
77
+ per agent or client. Existing schedulers and message wake mechanisms remain
78
+ responsible for their work; do not build another scheduler or wake broker in
79
+ the mobile client. Share bounded subscriptions and roster refreshes where
80
+ possible. Open terminal viewers only when needed, apply output backpressure,
81
+ and detach abandoned viewers without stopping agents.
82
+
83
+ tmux and Herdr remain interchangeable session adapters. Mobile access does not
84
+ require a Herdr migration. Start with a direct connection to one execution
85
+ host; later add saved server endpoints or reuse OATS registered-host routing.
86
+ SSH credentials for routed hosts stay on the routing server, not the phone.
87
+
88
+ ## Private access through Tailscale
89
+
90
+ Install the ordinary Tailscale app on the iPhone and connect the server to the
91
+ same tailnet. Use Tailscale Serve to proxy the loopback service over HTTPS,
92
+ accessible only through the tailnet's access rules. No embedded VPN or public
93
+ Funnel endpoint is needed. This is a proposed deployment choice, not a current
94
+ OATS installation instruction. [Tailscale Serve documentation](https://tailscale.com/docs/features/tailscale-serve)
95
+
96
+ Network membership must map to an explicit authorized operator. For an initial
97
+ single-owner deployment, choose a simple revocable application session or
98
+ validated Tailscale identity; do not add a second account platform. If trusting
99
+ Serve's identity headers, keep the backend reachable only through the trusted
100
+ local proxy path and follow its header-handling requirements. Configure the
101
+ actual HTTPS Host/Origin rather than removing the existing checks.
102
+ [Tailscale identity headers](https://tailscale.com/docs/features/tailscale-serve#identity-headers)
103
+
104
+ Authorize every action, terminal attachment and upload against a registered
105
+ workspace and exact instance home. Keep runtime permission settings such as
106
+ `yolo` separate from who may control the agent. Exclude multi-tenant hosting
107
+ and elaborate permissions administration from the first version.
108
+
109
+ ## Phone experience
110
+
111
+ The primary screen lists workspaces and their agents, with readable names and
112
+ running, stopped, needs-input or unknown states. A disconnected server is
113
+ unreachable, not evidence that its agents stopped. Do not infer needs-input
114
+ or task completion solely from terminal activity.
115
+
116
+ An agent page offers conversation, start controls and session details. Starting
117
+ a stopped agent uses its existing home and shows runtime/model options and
118
+ effective permission mode. Make a launch override distinct from editing future
119
+ defaults. A running agent's model does not silently change because a setting
120
+ was edited. Interrupt and retirement are explicit actions with their existing
121
+ semantics; retirement is not relabeled as a harmless Stop button.
122
+
123
+ The composer supports text and selected photos/files with visible upload state.
124
+ Upload to the agent's execution host, preserve the destination while a transfer
125
+ is in flight, and submit only when attachments are ready. Failed transfers stay
126
+ visible and must not silently redirect to another agent. Start with a file/photo
127
+ picker; system dictation can supply text. A native share extension and realtime
128
+ spoken conversation are later options.
129
+
130
+ Terminal access is a secondary view for interactive harness prompts and tools.
131
+ Provide touch-accessible Escape, interrupt and other essential terminal keys.
132
+ Avoid exposing tmux session names, Desktop split layouts or backend chrome.
133
+ Pasting or uploading into a terminal does not automatically press Enter; a
134
+ conversation Send action is an explicit submission.
135
+
136
+ ## Reliable conversations and background behavior
137
+
138
+ Terminal input is useful across harnesses, but a pane transcript is not a
139
+ durable conversation model. Rich chat should use the selected messaging
140
+ provider, initially aweb. Missing durable reply, read-state or replay semantics
141
+ belong in that provider's contract, not an OATS-specific message database or an
142
+ ANSI-output parser. An installation without those capabilities can still offer
143
+ management and a terminal, with chat availability described honestly.
144
+
145
+ Before qualifying chat, establish the following behavior:
146
+
147
+ - The operator has their own sender identity; the client does not impersonate
148
+ the destination agent. Replies remain associated with the conversation.
149
+ - Stable message IDs and replay cursors allow reconnect and missed-message
150
+ retrieval. Retry after an uncertain send does not submit the same request
151
+ twice. Offline text remains a draft until explicitly sent; do not queue
152
+ terminal keystrokes or destructive controls for automatic replay.
153
+ - Accepted, delivered and acted-on are different observations. An input write
154
+ or agent wake is not proof of a completed task. Unknown outcomes remain
155
+ unknown until the existing operation can be reconciled.
156
+ - Delivery and wake continue on the server while clients are absent. Waking a
157
+ running harness and starting a stopped instance are different actions;
158
+ follow explicit policy before a message starts an agent or consumes compute.
159
+
160
+ iOS normally suspends background apps. Do not depend on an always-connected
161
+ phone SSE, WebSocket or SSH session. The server retains state; a notification
162
+ signals new activity, and reopening the client fetches authoritative updates.
163
+ Notifications can be delayed or disabled and are not delivery receipts.
164
+ [Apple background execution documentation](https://developer.apple.com/documentation/uikit/extending-your-app-s-background-execution-time)
165
+
166
+ Home Screen web apps support Web Push on iOS/iPadOS 16.4 and later, with
167
+ permission requested through user interaction. Native applications can use
168
+ APNs. Both require a server-side notification path and device testing. Keep
169
+ sensitive message bodies out of lock-screen notifications by default. Private
170
+ application access can remain on Tailscale while the server makes outbound
171
+ connections to the push service; test this combination on a real phone rather
172
+ than assuming VPN reconnection or notification behavior.
173
+ [WebKit Web Push documentation](https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/)
174
+ [Apple remote notification documentation](https://developer.apple.com/documentation/usernotifications/setting-up-a-remote-notification-server)
175
+
176
+ ## Proposed delivery sequence
177
+
178
+ 1. **Prove the service boundary.** Extract only what an independent client
179
+ needs, retain existing CLI dispatch and add authenticated network access.
180
+ Qualify one server over Tailscale, including operation with Desktop closed.
181
+ 2. **Deliver mobile management and terminal access.** Workspace/agent list,
182
+ start with model choices, explicit lifecycle actions, terminal input/output,
183
+ screenshots/files and reconnect. Reuse existing schedule controls and
184
+ provider inspection. This is useful without claiming polished chat.
185
+ 3. **Qualify conversations and notifications.** Resolve the messaging-provider
186
+ contract gaps, then implement conversation presentation, replay, send
187
+ deduplication and opt-in notifications. Prove delivery while the app sleeps.
188
+ 4. **Decide on native and broader hosting.** Use actual phone experience to
189
+ choose whether native sharing, voice and polish justify another client.
190
+ Expand to multiple servers through existing routes or explicit endpoints;
191
+ avoid adding a fleet control platform as a prerequisite.
192
+
193
+ The browser client is the recommended first delivery vehicle, not an
194
+ architectural dependency. If native is chosen first, the same server and
195
+ messaging requirements apply. No calendar estimate is justified until the
196
+ service extraction and conversation-contract gaps have been scoped.
197
+
198
+ ## Acceptance before calling it usable
199
+
200
+ - With Desktop closed and the phone locked or disconnected, existing agents
201
+ keep running and an explicitly enabled test schedule and message wake work.
202
+ No production team or harvest schedule is changed to demonstrate this.
203
+ - Start the intended stopped home with the chosen runtime/model. Same-named
204
+ instances elsewhere cannot receive its actions. Unreachable hosts display
205
+ uncertainty and retrying an interrupted mutation does not blindly repeat it.
206
+ - Upload an actual iPhone screenshot and a file to the execution host; verify
207
+ complete bytes and destination, and demonstrate a visible transfer failure.
208
+ - Switch Wi-Fi/cellular, lock/unlock, and reconnect. Conversation history catches
209
+ up without duplicate sends. A terminal reconnect can show a bounded current
210
+ capture; it must not pretend to recover a durable conversation transcript.
211
+ - Close terminal views and disconnect abruptly without killing agent sessions
212
+ or accumulating PTYs. Repeated reconnects and slow clients leave bounded
213
+ memory/process use; share observations instead of polling each agent per view.
214
+ - Test a real notification, denied notification permission, expired client
215
+ access and tailnet disconnection. The UI preserves drafts and accurately
216
+ states what it knows, without showing an unsuccessful send as delivered.
217
+ - A different knowledge provider's declared operations remain usable without
218
+ mobile code assuming OKF, a particular file layout or a universal harvester.
219
+
220
+ Open implementation decisions are the initial operator authentication method,
221
+ the existing aweb contracts that need extension, notification ownership under
222
+ the messaging provider, and the precise terminal stream protocol. Settle them
223
+ with narrow proofs before expanding scope. This proposal changes neither
224
+ current deployment defaults nor the priority of ongoing reliability work.
225
+
226
+ Related contracts: [provider operations](operations-contract.md),
227
+ [Desktop CLI API](../desktop-cli-api.md), [servers](../servers.md),
228
+ [schedules](../schedules.md), and [Desktop](../desktop.md).