@awebai/oats 0.24.13 → 0.25.1

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 (58) hide show
  1. package/bin/oats.mjs +994 -2837
  2. package/docs/capabilities.md +136 -323
  3. package/docs/configuration.md +68 -533
  4. package/docs/conventions.md +51 -24
  5. package/docs/design/2026-09-16-fresh-operator-walkthrough.md +19 -14
  6. package/docs/design/2026-09-16-portable-migration-evidence.md +2 -0
  7. package/docs/design/2026-09-16-portable-onboarding.md +4 -2
  8. package/docs/design/2026-09-20-redesign-program-board.md +1 -1
  9. package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +2 -0
  10. package/docs/design/2026-09-23-simplified-workspace-model.md +711 -0
  11. package/docs/design/2026-09-23-workspace-module-contracts.md +460 -0
  12. package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +65 -0
  13. package/docs/design/README.md +20 -8
  14. package/docs/design/operations-contract.md +1 -0
  15. package/docs/design/package-engine-contract.md +1 -1
  16. package/docs/design/package-runtime-api.md +1 -1
  17. package/docs/desktop-cli-api.md +356 -5
  18. package/docs/desktop-succession.md +12 -6
  19. package/docs/desktop.md +9 -4
  20. package/docs/execution-targets.md +16 -4
  21. package/docs/first-team.md +107 -224
  22. package/docs/implementation.md +41 -11
  23. package/docs/integrations.md +50 -47
  24. package/docs/knowledge-capability-authoring.md +10 -4
  25. package/docs/knowledge-migration.md +21 -12
  26. package/docs/knowledge-reference/package-craft.md +11 -3
  27. package/docs/knowledge.md +60 -18
  28. package/docs/layers.md +3 -3
  29. package/docs/migration-from-oas.md +20 -9
  30. package/docs/oats-local.schema.json +50 -0
  31. package/docs/oats-membership.schema.json +23 -0
  32. package/docs/oats-workspace.schema.json +133 -48
  33. package/docs/official-marketplace.md +9 -6
  34. package/docs/packages.md +229 -440
  35. package/docs/rebuild-to-v2.md +347 -0
  36. package/docs/release-notes/v0.25.0.md +99 -0
  37. package/docs/release-notes/v0.25.1.md +94 -0
  38. package/docs/schedules.md +12 -6
  39. package/docs/soul.schema.json +41 -68
  40. package/docs/souls-and-instances.md +175 -108
  41. package/docs/workspace-adoption.md +70 -345
  42. package/docs/workspaces.md +436 -119
  43. package/lib/core.mjs +462 -61
  44. package/lib/instance-resolution.mjs +387 -0
  45. package/lib/materialize.mjs +580 -0
  46. package/lib/operator-dispatch.mjs +117 -0
  47. package/lib/packages.mjs +558 -1269
  48. package/lib/remote.mjs +718 -0
  49. package/lib/resolve.mjs +638 -0
  50. package/lib/schedule.mjs +90 -16
  51. package/lib/workspace.mjs +654 -0
  52. package/package.json +1 -1
  53. package/lib/portable-migration-artifacts.mjs +0 -135
  54. package/lib/portable-migration-evidence.mjs +0 -305
  55. package/lib/portable-migration-store.mjs +0 -199
  56. package/lib/portable-migration.mjs +0 -104
  57. package/lib/portable-onboarding-acceptance.mjs +0 -66
  58. package/lib/setup-expert-source.mjs +0 -100
@@ -1,33 +1,34 @@
1
1
  # Capability packages
2
2
 
3
- A **capability package** is OATS's reusable distribution unit. It can contribute
3
+ A **capability** is OATS's reusable unit of behaviour. It can contribute
4
4
  skills, instance instructions, requirements, namespaced commands, and approved
5
- lifecycle hooks. Configuration—not the package—decides which souls receive it.
5
+ lifecycle hooks. A soul — not the capability — decides which souls receive it,
6
+ by naming it with where it comes from (`from:`; see [workspaces](workspaces.md)).
6
7
 
7
8
  The [official marketplace policy](official-marketplace.md) defines the reviewed
8
- package list and its acceptance criteria. Finding an official capability does not
9
- install, activate or approve it; those remain explicit, separate choices.
9
+ package list and its acceptance criteria. Finding an official package does not
10
+ pin, approve or give it to any soul; those remain explicit, separate choices.
10
11
 
11
- An **integration** is a capability package that implements one exclusive
12
- fundamental layer: `knowledge`, `messaging`, or `tasks`. General capabilities
13
- claim no layer and compose additively.
12
+ An **integration** is a capability that implements one exclusive fundamental
13
+ layer: `knowledge`, `messaging`, or `tasks`. General capabilities claim no
14
+ layer and compose additively.
14
15
 
15
16
  ## Mental model
16
17
 
17
- This is OATS's first public capability-package contract. The unpublished,
18
- pre-release integration prototype has no compatibility promise: its manifest,
19
- config, discovery, and command aliases are intentionally not accepted.
18
+ A capability lives in one of two kinds of source:
20
19
 
21
- The contract is:
20
+ 1. a **member repo** of the workspace, at `capabilities/<name>/oats.json` —
21
+ unversioned, always the member's latest state, trusted by membership;
22
+ 2. a **package** (`oats-package/` in a repo, pinned by version in the
23
+ workspace's `packages:`, locked and approved once per version —
24
+ [packages.md](packages.md)).
22
25
 
23
- 1. **Acquire** a package. External artifacts are pinned in `oats-lock.json`.
24
- 2. **Activate** it for global scope, a config-owned soul group, or one soul.
25
- 3. **Spawn** a soul. OATS resolves the target, creates the exact
26
- `.agents/skills/`, and generates that instance's `AGENTS.md` without
27
- changing the canonical soul.
28
-
29
- Acquired does not mean active. `oats init` activates only the explicit defaults
30
- it writes; it never enables every package merely because it is available.
26
+ A soul says `capabilities: { <name>: { from: here | <repo key> | package } }`
27
+ (or `off`); the workspace supplies defaults. At spawn every resolved
28
+ capability is **copied whole** into the instance (`<home>/.oats/modules/<name>/`,
29
+ skills into `<home>/.agents/skills/<name>/`), and the instance's `AGENTS.md` is
30
+ generated without changing the canonical soul. Nothing is installed or
31
+ activated at a deployment.
31
32
 
32
33
  ## Manifest
33
34
 
@@ -83,10 +84,10 @@ A self-contained package has an `oats.json`:
83
84
  too. Without one, OATS has no way to undo what the spawn hook did and no way to
84
85
  know whether it did anything, so a failure quarantines the home rather than
85
86
  rolling it back — the operator cleans up by hand and removes it with `--force`.
86
- - A required hook must also be **able** to run: if its capability's executable
87
- surface is not trusted, the spawn fails with the `oats trust` remedy rather
88
- than starting without the setup. Advisory executable hooks stay
89
- disabled-with-warning.
87
+ - A required hook must also be **able** to run: a package capability whose
88
+ version is not approved in the lock is refused at resolution
89
+ (`E_PACKAGE_UNAPPROVED`, remedy `oats sync`), so a required hook never
90
+ silently fails to configure an instance.
90
91
  - When a required hook fails and its compensation cannot finish, the instance
91
92
  home is **retained**, not deleted — it holds the credentials and metadata a
92
93
  retry needs, and removing it would turn a transient cleanup failure into
@@ -133,310 +134,126 @@ A self-contained package has an `oats.json`:
133
134
  would mutate the operator's runtime configuration without asking, in the
134
135
  middle of a spawn. A missing, uninstalled or disabled package fails the spawn
135
136
  with the consent command that fixes it.
136
- - OATS never installs a requirement silently. `oats install` prompts per
137
- requirement with the exact argv, source and scope; automation passes
138
- `--accept-requirement <name>` (the name is the command, or
139
- `<runtime>:<package>`), and `--no-requirements` skips the gate. When a plan
140
- has several steps — registering a Claude marketplace before installing from
141
- it — every step is shown, because agreeing to a plugin also means agreeing to
142
- the source it comes from. Declining
143
- leaves an actionable `oats doctor` warning. Consent to install is separate
144
- from capability trust.
137
+ - OATS never installs a host requirement silently. A missing host command is
138
+ the operator's to install; `oats doctor` reports it. Consent to install is
139
+ separate from package approval.
145
140
  - `environment` lists the exact launch variables executable trust approves;
146
141
  spawn hook output must be a subset and use the capability vendor prefix.
147
142
  - Target names never appear in a package manifest.
148
143
 
149
- `capability` is the only manifest identity field. The machine-readable
150
- contract is [`capability-manifest.schema.json`](capability-manifest.schema.json).
144
+ `capability` is the only manifest identity field; it may also carry
145
+ `private: true` (usable only by souls of its own repo) and `team: <label>`
146
+ (a workspace team label). The machine-readable contract is
147
+ [`capability-manifest.schema.json`](capability-manifest.schema.json).
151
148
 
152
- ## Config and targets
149
+ ## Who gets a capability
153
150
 
154
151
  ```yaml
155
- agent-types:
156
- developers:
157
- description: Agents that build the service (souls declare `type: developers`)
158
- reviewers:
159
- description: Agents that review changes
160
-
152
+ # oats-workspace.yaml — shared defaults
153
+ defaults:
154
+ capabilities:
155
+ oats.core: { from: package }
156
+ acme-house-style: { from: github.com/acme/agents }
157
+ knowledge: { oats.okf: { from: package } } # slot default: a layer capability
158
+ messaging: none
159
+ tasks: none
160
+ byTeam:
161
+ engineering:
162
+ capabilities: { acme-release-tooling: { from: github.com/acme/agents } }
163
+
164
+ # souls/release-manager/soul.yaml — the soul's own choices
161
165
  capabilities:
162
- layers:
163
- knowledge:
164
- capability: oats.okf
165
- from: installed
166
- settings:
167
- bindings-file: /absolute/config/okf-bindings.json
168
- # injection-override: .agents/injections/capabilities/oats.okf.md
169
- messaging: none
170
- tasks: none
171
-
172
- additive:
173
- example.code-review:
174
- from: installed
175
- agent-types:
176
- developers:
177
- enabled: true
178
- settings:
179
- depth: normal
180
- souls:
181
- security-reviewer:
182
- enabled: true
183
- settings:
184
- depth: exhaustive
185
-
186
- example.deploy:
187
- from: installed
188
- global: true
189
- agent-types:
190
- reviewers: false # explicit exclusion
191
- souls:
192
- release-reviewer: true # more-specific re-enable
193
-
194
- skill-overrides:
195
- review: example.code-review
166
+ acme-release-tooling: { from: here }
167
+ acme-deploy: { from: package }
168
+ acme-house-style: off
169
+ knowledge:
170
+ owns: release-manager
196
171
  ```
197
172
 
198
- `global` means all souls governed by the config level declaring it—not every
199
- soul on the machine regardless of scope. Laptop, workspace, and repository
200
- configs each govern souls beneath that level.
201
-
202
- Composition is additive across matching global, agent-type, and soul
203
- bindings. Settings use `soul > agent-type > global`, then closer config scope.
204
- Conflicting values at equal specificity and scope are errors.
205
- `enabled: false` follows the same precedence. Agent types are declared by
206
- name in config; each soul opts in via `type:` in its soul.yaml. Tags and
207
- selectors are not implemented, and bindings do not target individual
208
- instances.
209
-
210
- `capabilities` is the only activation map: fundamental integrations live
211
- under `capabilities.layers.<layer>` (an entry or an explicit `none` that
212
- suppresses an inherited integration), everything else under
213
- `capabilities.additive`.
173
+ Composition order: `defaults.<slot>` ⊕ `defaults.capabilities` ⊕
174
+ `defaults.byTeam[<soul team>]` ⊕ `soul.capabilities` — later wins, `off`
175
+ removes, a soul `<slot>: none` drops the workspace's slot default. A resolved
176
+ capability whose manifest says `layer: X` fills slot X; two for one slot are
177
+ `E_SLOT_CONFLICT`. Provider settings come from three homes — the soul's slot
178
+ payload, `oats-local.yaml` `settings.<cap>`, and `oats spawn --provider` — and
179
+ are deep-merged in that order. There are no agent types, no `global`, no
180
+ per-deployment activation or exclusion maps.
214
181
 
215
182
  ## Exact runtime composition
216
183
 
217
184
  Every spawned instance receives:
218
185
 
219
186
  - canonical soul skills;
220
- - the kernel `oats` skill; and
221
- - skills from capabilities active for that soul.
222
-
223
- OATS copies only those skill trees into real directories under
224
- `<instance>/.agents/skills/` and records the names and source capability in
225
- `instance.json`. `.claude/skills` points to
226
- the same canonical directory. Pi launches with this directory as an explicit
227
- skill path; ambient skills (user-level, pi packages, the work tree) coexist
228
- with the OATS-composed set rather than being excluded — `instance.json`
229
- records exactly what OATS composed, not everything the harness may discover.
230
- `oats-getting-started` is the pi adapter's one ambient contribution before a workspace exists.
231
-
232
- Duplicate skill names fail spawn unless `skill-overrides` explicitly names the
233
- winning source. Pi and Claude therefore receive the same OATS-managed set rather
234
- than relying on different ancestor-discovery rules.
235
-
236
- For pi, exact isolation needs the capability-aware versions of both
237
- `@awebai/oats` and `@awebai/oats-pi`. The kernel disables normal skill
238
- discovery at launch. The changed adapter contributes only the instance-local
239
- set instead of the older workspace and package roots. Install matching package
240
- versions and upgrade them together.
187
+ - a **full copy** of every capability the soul resolved to, under
188
+ `<instance>/.oats/modules/<capability>/` (manifest, `bin/`, injects, skills);
189
+ - those capabilities' skills copied to `<instance>/.agents/skills/<capability>/<skill>/`.
190
+
191
+ `instance.json` records per module its source (`from`), commit and content
192
+ digest, and the composed skill names with their source. `.claude/skills` points
193
+ to the same canonical directory. **The harness starts normally**: pi, Claude
194
+ Code and Codex run their own skill discovery with cwd = the instance home;
195
+ ambient skills (user-level, the work tree's `.agents/skills/`) coexist with the
196
+ OATS-composed set. `instance.json` records what OATS composed, not everything
197
+ the harness may discover.
198
+
199
+ Duplicate skill names **within the composed set** fail the spawn naming both
200
+ capabilities (`E_SKILL_DUPLICATE`). A composed skill and an ambient skill with
201
+ one name is the harness's own precedence, not an error.
241
202
 
242
203
  The instance's `AGENTS.md` is a generated regular file containing:
243
204
 
244
205
  1. the canonical soul `AGENTS.md`;
245
206
  2. the kernel and work-mode blocks;
246
- 3. active capability blocks in deterministic order; and
247
- 4. unconditional config instruction blocks.
207
+ 3. each module's inject, in deterministic (name) order.
248
208
 
249
209
  Its `CLAUDE.md` symlinks to `AGENTS.md`. The committed soul remains unchanged.
250
- Edit the canonical soul, injection source, or config, then spawn a new
251
- instance; do not edit generated blocks as source-of-truth changes.
210
+ Edit the canonical soul or the capability's inject in its repo, then spawn a
211
+ new instance; do not edit generated blocks as source-of-truth changes.
252
212
 
253
- Inspect a final composition:
213
+ Inspect a composition before it exists:
254
214
 
255
215
  ```bash
256
- oats doctor /path/to/repo --soul api-expert
257
- oats doctor /path/to/repo --soul api-expert --json
216
+ oats spawn release-manager --preview # modules (from / commit / changedSince), team, resolution revision
217
+ oats spawn release-manager --preview --json
258
218
  ```
259
219
 
260
- Doctor reports active/acquired packages, target provenance, settings, skills,
261
- hooks, trust, instruction sources, and final composed text. It cannot infer
262
- semantic contradictions between two prose injections; review the output.
263
-
264
220
  ## Distribution packages
265
221
 
266
- A **distribution package** is the install/update/review unit above
267
- capabilities: a directory with an `oats-package.json` manifest that explicitly
268
- enumerates one or more capabilities and optional reference config templates
269
- (schema:
270
- `docs/oats-package.schema.json`; contract:
271
- `docs/design/package-engine-contract.md`). A capability remains the
272
- targeting/activation unit — every capability a package exports stays
273
- independently addressable by ID with `from: installed`.
274
-
275
- A Git repository *contains* that directory; `#<path>` selects which one, and
276
- only the selected subtree is installed and hashed. Omitting it selects
277
- `oats-package/` (the convention for every official example and scaffold); `#.`
278
- selects the repository root. Local paths are always exact directories.
279
-
280
- ```bash
281
- oats install git:github.com/org/repo@v1.0.0 --dir /path/to/scope # git shorthand → oats-package/
282
- oats install git:github.com/org/repo@v1.0.0#dist/oats # a custom contained root
283
- oats install https://host/org/repo.git@v1.0.0#. # raw git URL, repository root
284
- oats install ../my-package # local path (exact directory)
285
- oats install oats.okf # official catalog id
286
- oats install # bare: exact restore of this chain's locks
287
- oats list # installed packages, exported capabilities, scopes
288
- oats catalog [--json] # the effective official catalog: packages, refs, aliases, acquire argv (0.24.6+; read-only)
289
- oats update <package> # transactional re-resolve + diff + trust reset
290
- oats remove <package> # refuses while config/dependents reference it
291
- oats migrate [--dry-run] # map v1 capability locks to package locks
292
- ```
293
-
294
- Installing a package materializes each capability into the owning scope's
295
- `.agents/capabilities/installed/<id>/` (gitignored, like the capability store).
296
- There is no persistent package store. `oats-lock.json` uses `lockfileVersion: 2`
297
- with two maps: `packages` (exact source, commit, selected path, payload
298
- integrity, and dependencies) and `capabilities` (each artifact's version,
299
- provider package, path, integrity, and trust) — schema
300
- `docs/oats-lock.schema.json`. Dependencies are pinned (official selector,
301
- tag/commit, or local path — no semver solver). Cycles and two sources claiming
302
- one package identity at a scope are errors with provenance. Acquisition
303
- **activates nothing** and adopts no config template; an unpinned git source
304
- resolves once and never advances on restore.
305
-
306
- Trust binds to each materialized capability artifact at its exact integrity.
307
- `oats trust <capability>` approves only that capability's commands, hooks, and
308
- declared launch environment.
309
- `oats trust <package> --all-capabilities` is the explicit bulk path and prints
310
- the full executable surface first. Any artifact integrity change (including
311
- `oats update`) resets that capability's trust.
312
- Skill/instruction/config-only capabilities need lock integrity but no
313
- executable approval, and official-catalog identity grants **no** executable
314
- trust. A capability may carry a checked-in `package-lock.json` for JS runtime
315
- dependencies; OATS materializes it with `npm ci --ignore-scripts` only — npm
316
- lifecycle scripts never run at acquisition, and capability code/hook paths
317
- must resolve inside the materialized capability root.
318
-
319
- `oats migrate` converts a scope's v1 marketplace/git/path capability locks to
320
- the revised v2 lock, preserving `from: installed` activation. It is
321
- all-or-nothing per scope: a scope converts only when every entry maps to a
322
- package. If any entry is held, manual, or retained, the whole scope stays
323
- byte-identical v1 and keeps working. There is no residue container, and
324
- executable approvals are never carried over.
325
-
326
- All package operations are agent-callable: every command above supports
327
- `--json` (one stdout envelope; failures carry the contract's stable error
328
- codes) and noninteractive operation. Agents never hand-edit `oats-lock.json`
329
- or the stores — the kernel-owned **oats-packages** skill (composed into every
330
- instance) teaches the full lifecycle.
331
-
332
- ## Acquisition, lock, restore, and trust (single capabilities)
333
-
334
- ```bash
335
- oats install oats.jira --dir /path/to/repo # official catalog id; approve executable surfaces with `oats trust`
336
- oats install https://example.invalid/team-chat.git --dir /path/to/repo
337
- oats install ../team-chat --dir /path/to/repo
338
- oats install # bare: restore locked-but-missing artifacts
339
- ```
340
-
341
- Every acquired artifact lands in the owning scope's
342
- `.agents/capabilities/installed/`, beside the `oats-config.yaml` and
343
- `oats-lock.json` that govern it. Install maintains a one-line
344
- `.agents/capabilities/.gitignore` so acquired artifacts stay uncommitted, like
345
- `node_modules`. A fresh clone with a committed config and lock runs bare
346
- `oats install` to reacquire everything; each restored artifact must hash to the
347
- locked integrity or the restore fails and removes the fetched copy.
348
-
349
- Installation acquires and locks; it does **not** activate. `oats-lock.json`
350
- records:
351
-
352
- - source;
353
- - exact package version and git commit when available; and
354
- - SHA-256 integrity of the artifact.
355
-
356
- OATS never pulls an existing package silently. Changed integrity blocks use
357
- until the package is deliberately reacquired. For external packages containing
358
- commands, hooks, or launch-environment authority, approve that exact locked
359
- artifact:
360
-
361
- ```bash
362
- oats trust example.team-chat --dir /path/to/repo
363
- ```
364
-
365
- Changing integrity invalidates approval. Skill/instruction-only packages still
366
- require a valid lock but do not require executable approval. Manifest paths in
367
- external packages must remain inside the locked artifact (including after
368
- symlink resolution), so approved hooks and commands cannot execute unhashed
369
- files. The trust boundary is structural: anything under `installed/` must have
370
- a matching lock entry, so an installed artifact cannot masquerade as scope-owned
371
- by dropping its lock. A committed lock's approval survives restore when the
372
- restored artifact hashes to the locked integrity.
373
-
374
- One narrow exception exists for the kernel's own marketplace, kept only until
375
- official packages replace legacy `marketplace:` installs. A capability whose
376
- lock source is `marketplace:<id>@<version>` may declare resources that live
377
- outside its installed copy — `oats.authoring` selects framework skills with
378
- `../../skills/<name>` — and those declarations are resolved against the
379
- capability's directory in the kernel marketplace
380
- (`<kernel>/capabilities/<slug>`), located by capability id rather than by the
381
- lock selector's spelling. If that declared path names an npm dependency hoisted
382
- by npm, OATS also checks the equivalent path from the kernel root; this is the
383
- published `oats.aweb` layout (`node_modules/@awebai/pi/skills/...`). The shipped source must still have the same
384
- capability identity, while its version may advance with an explicitly installed
385
- kernel upgrade: framework-hoisted resources belong to that trusted kernel, and
386
- this preserves valid older v1 installs until official-package migration. The
387
- installed copy and its lock must still agree on version and integrity. If they
388
- do not, recovery is to delete the installed copy the error names and then run
389
- `oats install <id> --dir <scope>`, which re-acquires and rewrites the lock entry;
390
- run with the copy still in place, that command reports `Already acquired` and
391
- changes nothing, and legacy v1 capability entries are not removable with
392
- `oats remove`, which services packages. Such a tree may leave the
393
- installed copy but never the kernel package: `..` segments and symlinks that
394
- resolve outside it are rejected exactly like any other escape. Capabilities
395
- exported by packages, authored at a scope, or referenced by path never receive
396
- this resolution — they stay inside their own artifact.
397
-
398
- Bundled framework packages are trusted. Packages you author at a scope live in
399
- `.agents/capabilities/owned/` and are config-owned trusted — trusting the
400
- scope trusts them; review them like other repository instructions and code.
401
- In a git-managed scope they are committed; at a non-git scope (the laptop
402
- level, a plain workspace root) they are ordinary files whose durability is the
403
- scope's own — they have no lock and are not restorable by `oats install`, so
404
- back them up with whatever backs up that scope. Capabilities directly
405
- under `.agents/capabilities/` are rejected — move them into `installed/` or
406
- `owned/`.
407
-
408
- ## Activation and exclusions
409
-
410
- ```bash
411
- oats use oats.okf --global --settings bindings-file=/absolute/config/okf-bindings.json --dir /path/to/repo
412
- oats use example.code-review --type developers --dir /path/to/repo
413
- oats use example.deploy --type reviewers --disable --dir /path/to/repo
414
- oats use example.deploy --soul release-reviewer --dir /path/to/repo
415
- ```
416
-
417
- `--global` is the default. Choose only one target. An integration's manifest
418
- declares its layer, so activation does not repeat it. Disable an inherited
419
- fundamental layer with `oats use none --layer <layer>`.
420
-
421
- OKF v2 also requires explicit soul owners and accepted external nodes before
422
- working-source spawn. Global activation is appropriate only when every source is
423
- ready; see [knowledge provisioning](knowledge.md#acquire-bind-and-provision-explicitly).
222
+ A **package** is the versioned tier: a directory with an `oats-package.json`
223
+ that enumerates one or more capabilities (schema
224
+ [`oats-package.schema.json`](oats-package.schema.json)). It is pinned once in
225
+ the workspace's `packages:`, resolved to an exact commit + integrity by
226
+ `oats sync` into `oats-lock.json` (lockfileVersion 3), and its executables are
227
+ approved once per version. A soul names a package capability with
228
+ `from: package`. Everything about declaring, syncing, locking, approving and
229
+ publishing packages is in [packages.md](packages.md). There is no installed
230
+ copy at a deployment and no `oats install`/`trust`/`update`/`remove`.
231
+
232
+ ## Member capabilities
233
+
234
+ A capability at `<member repo>/capabilities/<name>/oats.json` is discoverable
235
+ by every soul in the workspace (`oats capabilities` lists it with origin
236
+ `member <repo key> @ <commit>`) and is named with `from: <repo key>` — or
237
+ `from: here` by souls of the same repo. It is trusted by **membership**: the
238
+ repo's access control is the boundary and its latest default-branch state is
239
+ what is copied. `private: true` in the manifest keeps it usable only from its
240
+ own repo. A member's `oats-package/` is **not** a member capability: it is
241
+ reported as `publishes` and consumed only as a package.
424
242
 
425
243
  ## Capability-defined agents
426
244
 
427
245
  A manifest may declare `agents: ["agents/<name>"]` — package-relative soul
428
- directories (`soul.yaml` + `AGENTS.md` directly inside). Wherever the
429
- capability is **declared** in the config chain, `oats spawn <name>` resolves
430
- these like local souls: the canonical soul stays read-only inside the package
431
- (a fresh identity every spawn — by design for service agents like reviewers),
432
- while instances home under the scope's `local-agents/`. Capability agents
433
- carry their own `model:`/`runtime:` defaults in soul.yaml.
246
+ directories (`soul.yaml` + `AGENTS.md` directly inside). *(Open thread: under
247
+ the workspace model these are re-based on member souls — a package repo's
248
+ expert soul is an ordinary `souls/<name>-expert/` in the member; the classic
249
+ lookup still exists for 0.24 layouts.)*
434
250
 
435
251
  ## Commands and hooks
436
252
 
437
- Operational commands resolve only when their package is active in the current
438
- instance or soul context. Package-management commands (`install`, `trust`,
439
- `use`, `doctor`) remain available globally.
253
+ Operational commands resolve only when their capability is one of the current
254
+ instance's modules (or the soul's resolved set). Workspace commands (`sync`,
255
+ `package`, `workspace status`, `capabilities`, `souls`, `doctor`) are always
256
+ available.
440
257
 
441
258
  Hooks receive `OATS_EVENT`, `OATS_CAPABILITY`, `OATS_LAYER`, `OATS_INSTANCE`,
442
259
  `OATS_HOME`, `OATS_AGENT`, `OATS_SOUL`, `OATS_CONTEXT`, `OATS_WORKSPACE`,
@@ -455,14 +272,11 @@ hyphen to `_` would let `aweb-evil.*` collide with names already inside
455
272
  `aweb.*`'s `AWEB_*` namespace.
456
273
 
457
274
  A hook may return only names in its manifest's exact `environment` declaration.
458
- For acquired packages that declaration is part of the integrity-locked artifact.
459
- Third-party install previews the future request, and `oats trust` prints the
460
- exact request before persisting executable authority. Marketplace automatic
461
- trust likewise prints it before writing the trusted lock. Undeclared output is
462
- fatal. Config-owned packages receive the same exact-subset enforcement under
463
- their existing config-owned trust. This positive authority is the contract
464
- boundary — adding a new launch variable requires a visible manifest/trust
465
- change.
275
+ For package capabilities that declaration is part of the integrity-locked tree
276
+ and of what the per-version approval showed; for member capabilities it is
277
+ part of what membership trusts. Undeclared output is fatal. This positive
278
+ authority is the contract boundary — adding a new launch variable requires a
279
+ visible manifest change (and, for a package, a new approved version).
466
280
 
467
281
  `OATS_*`, `PI_AGENT_*`, kernel launch variables, and known shell/bootstrap/loader
468
282
  names are also rejected as defense in depth. The denylist includes current Node,
@@ -494,31 +308,30 @@ this mechanism must never copy or expose that global identity's root keys to the
494
308
  worker process. Session-scoped execution credentials need a separate lifecycle
495
309
  and must not be encoded into this persisted spawn command.
496
310
 
497
- Spawn/scaffold order is outer scope to inner scope, then capability ID;
498
- retirement reverses successful spawn order. Scaffold hooks cannot modify or
499
- delete canonical or another package's files. OATS records ownership, restores
500
- the pre-hook snapshot, and raises a conflict instead of accepting destructive
501
- or last-writer-wins behavior.
502
-
503
- ## Bundled packages
504
-
505
- | Capability | Kind | Provides |
506
- |---|---|---|
507
- | `oats.okf` | knowledge integration | External owned OKF bases, durable notes/record custody, independent judgment and inspection |
508
- | `oats.aweb` | messaging integration | aweb identity lifecycle and messaging skills |
509
- | `oats.jira` | tasks integration | Jira task protocol via `acli` |
510
- | `oats.linear` | tasks integration | Linear GraphQL task commands and workflow |
511
- | `oats.authoring` | additive | capability, skill, and soul authoring guidance |
512
-
513
- Bundled mirrors live under `capabilities/`. The prepared OKF v2 mirror follows
514
- the standalone package's sole export, `oats-package/capabilities/oats-okf/`.
515
- Acquire it through the catalog Git package: the npm mirror is **not** a
516
- self-contained distribution, because npm drops the source worker's canonical
517
- `CLAUDE.md` symlink. Do not manufacture aliases to bypass package integrity.
518
- See [prepared release gates](release-notes/v0.23.1.md). Acquired packages live under
519
- `<level>/.agents/capabilities/installed/` (gitignored, restorable); packages
520
- authored at a scope live under `<level>/.agents/capabilities/owned/`
521
- (committed where the scope is a git repo). Within one scope `owned/` overrides `installed/` on ID collision.
311
+ Spawn/scaffold order is by capability name; retirement reverses successful
312
+ spawn order. Hooks run from the instance's own copy
313
+ (`<home>/.oats/modules/<cap>/`). Scaffold hooks cannot modify or delete
314
+ canonical or another capability's files. OATS records ownership, restores the
315
+ pre-hook snapshot, and raises a conflict instead of accepting destructive or
316
+ last-writer-wins behavior.
317
+
318
+ ## Official packages
319
+
320
+ | Capability | Kind | Provides | Package |
321
+ |---|---|---|---|
322
+ | `oats.core` | additive | day-to-day OATS operation for an instance | `oats.framework` |
323
+ | `oats.setup` | additive | whole-architecture knowledge for an onboarding expert | `oats.framework` |
324
+ | `oats.okf` | knowledge integration | External owned OKF bases, durable notes/record custody, independent judgment and inspection | `oats.okf` |
325
+ | `oats.aweb` | messaging integration | aweb identity lifecycle and messaging skills | `oats.aweb` |
326
+ | `oats.jira` | tasks integration | Jira task protocol via `acli` | `oats.jira` |
327
+ | `oats.linear` | tasks integration | Linear GraphQL task commands and workflow | `oats.linear` |
328
+ | `oats.authoring` | additive | capability, skill, and soul authoring guidance | `oats.authoring` |
329
+
330
+ Each is pinned by a bare version in `packages:` and resolved through the
331
+ [official catalog](official-marketplace.md); each package repo is also a member
332
+ of the OATS workspace carrying its expert soul (`okf-expert`, `aweb-expert`, …).
333
+ The framework's own souls say `oats.okf: { from: package }` — membership never
334
+ turns a package into a latest-state capability.
522
335
 
523
336
  ## Operations a capability declares
524
337