@awebai/oats 0.25.8 → 0.26.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 (185) hide show
  1. package/README.md +8 -6
  2. package/bin/oats.mjs +576 -1714
  3. package/capabilities/oats-authoring/oats-package.json +2 -2
  4. package/capabilities/oats-authoring/oats.json +2 -2
  5. package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +46 -25
  6. package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +13 -6
  7. package/capabilities/oats-aweb/bin/oats-aweb.mjs +334 -72
  8. package/capabilities/oats-aweb/injects/aweb.md +7 -2
  9. package/capabilities/oats-aweb/lib/binding-wire.mjs +107 -5
  10. package/capabilities/oats-aweb/lib/captured-native.mjs +1 -1
  11. package/capabilities/oats-aweb/lib/grant-custody.mjs +38 -0
  12. package/capabilities/oats-aweb/oats.json +14 -4
  13. package/capabilities/oats-jira/bin/oats-jira.mjs +4 -4
  14. package/capabilities/oats-jira/oats.json +2 -2
  15. package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +6 -3
  16. package/capabilities/oats-linear/bin/oats-linear-hook.mjs +6 -4
  17. package/capabilities/oats-linear/oats.json +2 -2
  18. package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +6 -0
  19. package/capabilities/oats-okf/bin/oats-okf.mjs +1 -1
  20. package/capabilities/oats-okf/lib/binding-wire.mjs +1 -1
  21. package/capabilities/oats-okf/lib/migration.mjs +2 -2
  22. package/capabilities/oats-okf/lib/sources.mjs +5 -4
  23. package/capabilities/oats-okf/lib/stores.mjs +40 -9
  24. package/capabilities/oats-okf/lib/worker.mjs +3 -3
  25. package/capabilities/oats-okf/oats.json +1 -1
  26. package/capabilities/oats-review/oats.json +3 -2
  27. package/docs/capabilities.md +218 -47
  28. package/docs/capability-manifest.schema.json +13 -4
  29. package/docs/configuration.md +17 -5
  30. package/docs/conventions.md +16 -26
  31. package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +1 -1
  32. package/docs/design/2026-09-13-knowledge-and-memory-direction.md +3 -3
  33. package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +2 -2
  34. package/docs/design/2026-09-15-portable-souls-handoff.md +2 -2
  35. package/docs/design/2026-09-15-portable-souls-implementation.md +1 -1
  36. package/docs/design/2026-09-20-redesign-program-board.md +2 -2
  37. package/docs/design/2026-09-23-workspace-module-contracts.md +1 -1
  38. package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +1 -1
  39. package/docs/design/2026-09-24-desktop-phase-f-boundary.md +54 -10
  40. package/docs/design/2026-09-24-phase-d-plan.md +77 -0
  41. package/docs/design/2026-09-25-teams-contract.md +226 -0
  42. package/docs/design/README.md +3 -3
  43. package/docs/design/launch-configurations.md +20 -16
  44. package/docs/design/operations-contract.md +27 -10
  45. package/docs/desktop-cli-api.md +546 -264
  46. package/docs/desktop-instance-start.md +1 -1
  47. package/docs/desktop.md +7 -13
  48. package/docs/execution-targets.md +16 -18
  49. package/docs/first-team.md +14 -17
  50. package/docs/implementation.md +28 -59
  51. package/docs/integrations.md +88 -32
  52. package/docs/knowledge-capability-authoring.md +1 -1
  53. package/docs/knowledge-reference/package-craft.md +10 -8
  54. package/docs/knowledge-theory.md +1 -1
  55. package/docs/knowledge.md +10 -11
  56. package/docs/layers.md +16 -17
  57. package/docs/oats-local.schema.json +29 -1
  58. package/docs/oats-membership.schema.json +5 -3
  59. package/docs/oats-package.schema.json +2 -2
  60. package/docs/oats-workspace.schema.json +1 -1
  61. package/docs/{official-marketplace.md → official-catalog.md} +15 -16
  62. package/docs/packages.md +75 -52
  63. package/docs/release-notes/v0.22.0.md +1 -1
  64. package/docs/release-notes/v0.23.1.md +1 -1
  65. package/docs/release-notes/v0.25.9.md +23 -0
  66. package/docs/release-notes/v0.26.0.md +670 -0
  67. package/docs/schedules.md +48 -126
  68. package/docs/soul.schema.json +11 -4
  69. package/docs/souls-and-instances.md +56 -43
  70. package/docs/workspaces.md +80 -58
  71. package/injects/instance-boundary.md +1 -1
  72. package/injects/work-attached.md +1 -1
  73. package/injects/work-workspace.md +2 -2
  74. package/lib/{portable-files.mjs → bounded-read.mjs} +6 -6
  75. package/lib/{portable-values.mjs → canonical-json.mjs} +3 -12
  76. package/lib/capability-contract.mjs +110 -0
  77. package/lib/config-data.mjs +2 -2
  78. package/lib/core.mjs +700 -4824
  79. package/lib/digest.mjs +12 -0
  80. package/lib/instance-inspect.mjs +396 -0
  81. package/lib/instance-lifecycle.mjs +3 -4
  82. package/lib/instance-resolution.mjs +212 -26
  83. package/lib/instruction-composition.mjs +0 -20
  84. package/lib/materialize.mjs +6 -4
  85. package/lib/operator-dispatch.mjs +33 -13
  86. package/lib/packages.mjs +25 -190
  87. package/lib/provider-binding.mjs +4 -2
  88. package/lib/provider-reasons.mjs +3 -68
  89. package/lib/resolve.mjs +204 -68
  90. package/lib/schedule.mjs +97 -272
  91. package/lib/servers.mjs +13 -13
  92. package/lib/{portable-shape.mjs → shape.mjs} +4 -3
  93. package/lib/tree-copy.mjs +44 -0
  94. package/lib/workspace.mjs +125 -20
  95. package/package-catalog.json +7 -7
  96. package/package.json +1 -1
  97. package/skills/integration-authoring/SKILL.md +48 -40
  98. package/skills/oats-getting-started/SKILL.md +105 -110
  99. package/skills/oats-support/SKILL.md +2 -2
  100. package/skills/soul-craft/SKILL.md +13 -6
  101. package/bin/oats-pi-sdk-host.mjs +0 -17
  102. package/docs/2026-09-03-architecture-proposal.md +0 -642
  103. package/docs/artifact-approvals.schema.json +0 -7
  104. package/docs/captured-invocation-context.schema.json +0 -7
  105. package/docs/captured-resolution.schema.json +0 -7
  106. package/docs/design/package-engine-contract.md +0 -813
  107. package/docs/design/package-runtime-api.md +0 -588
  108. package/docs/desktop-succession.md +0 -57
  109. package/docs/execution-capsule.schema.json +0 -108
  110. package/docs/first-team-demo.md +0 -92
  111. package/docs/knowledge-migration.md +0 -147
  112. package/docs/migration-from-oas.md +0 -103
  113. package/docs/oats-config.schema.json +0 -172
  114. package/docs/oats-lock-v3.schema.json +0 -7
  115. package/docs/oats-lock.schema.json +0 -175
  116. package/docs/operating-team-migration.md +0 -470
  117. package/docs/portable.schema.json +0 -2512
  118. package/docs/provider-check-input.schema.json +0 -7
  119. package/docs/rebuild-to-v2.md +0 -511
  120. package/docs/workspace-adoption.md +0 -74
  121. package/injects/framework-workspace.md +0 -7
  122. package/injects/local-soul.md +0 -19
  123. package/injects/oats-portable.md +0 -20
  124. package/injects/oats.md +0 -11
  125. package/injects/portable-instance-boundary.md +0 -39
  126. package/injects/portable-work-directory.md +0 -29
  127. package/lib/artifact-approvals.mjs +0 -120
  128. package/lib/artifact-tree.mjs +0 -141
  129. package/lib/capability-artifacts.mjs +0 -179
  130. package/lib/capability-execution.mjs +0 -15
  131. package/lib/capability-inputs.mjs +0 -39
  132. package/lib/capability-provenance.mjs +0 -231
  133. package/lib/captured-action-shape.mjs +0 -21
  134. package/lib/captured-admission-shape.mjs +0 -20
  135. package/lib/captured-binding-file.mjs +0 -36
  136. package/lib/captured-dispatch.mjs +0 -66
  137. package/lib/captured-instance-index.mjs +0 -277
  138. package/lib/captured-invocation-context.mjs +0 -130
  139. package/lib/captured-launch-request.mjs +0 -66
  140. package/lib/captured-operation-process.mjs +0 -15
  141. package/lib/captured-pi-custody.mjs +0 -29
  142. package/lib/captured-pi-host.mjs +0 -167
  143. package/lib/captured-pi-outcome.mjs +0 -172
  144. package/lib/captured-resolutions.mjs +0 -275
  145. package/lib/captured-scaffold.mjs +0 -87
  146. package/lib/captured-selector.mjs +0 -28
  147. package/lib/captured-session-backend.mjs +0 -52
  148. package/lib/captured-source-receipt-file.mjs +0 -72
  149. package/lib/helper-injection-policy.mjs +0 -104
  150. package/lib/legacy-lock-codec.mjs +0 -106
  151. package/lib/manifest-settings.mjs +0 -84
  152. package/lib/package-closure.mjs +0 -48
  153. package/lib/package-materialization.mjs +0 -83
  154. package/lib/pi-sdk-host.mjs +0 -229
  155. package/lib/portable-artifacts.mjs +0 -115
  156. package/lib/portable-choices.mjs +0 -82
  157. package/lib/portable-composition.mjs +0 -136
  158. package/lib/portable-digest.mjs +0 -105
  159. package/lib/portable-identity.mjs +0 -40
  160. package/lib/portable-lock.mjs +0 -117
  161. package/lib/portable-onboarding-request.mjs +0 -49
  162. package/lib/portable-onboarding.mjs +0 -256
  163. package/lib/portable-package-preparation.mjs +0 -188
  164. package/lib/portable-policy.mjs +0 -44
  165. package/lib/portable-soul.mjs +0 -42
  166. package/lib/portable-state.mjs +0 -80
  167. package/lib/prepare-composition.mjs +0 -170
  168. package/lib/prepared-bindings.mjs +0 -92
  169. package/lib/prepared-resources.mjs +0 -127
  170. package/lib/provider-binding-broker.mjs +0 -65
  171. package/lib/provider-binding-wire.mjs +0 -116
  172. package/lib/readiness.mjs +0 -225
  173. package/lib/repository-observation.mjs +0 -226
  174. package/lib/resolution-shape.mjs +0 -393
  175. package/lib/schedule-capsule.mjs +0 -206
  176. package/lib/soul-constraints.mjs +0 -40
  177. package/lib/source-projection.mjs +0 -84
  178. package/lib/source-spec.mjs +0 -189
  179. package/lib/workspace-definition.mjs +0 -126
  180. package/lib/workspace-discovery.mjs +0 -146
  181. package/skills/oats/SKILL.md +0 -162
  182. package/skills/oats-config/SKILL.md +0 -164
  183. package/skills/oats-packages/SKILL.md +0 -184
  184. package/skills/oats-portable/SKILL.md +0 -115
  185. package/skills/oats-portable-artifacts/SKILL.md +0 -63
@@ -43,7 +43,7 @@ wrapper saves all of its in-flight conversation state. Wrappers should
43
43
  **Preview invocation** asks the execution host for the resolved command and
44
44
  displays it as text, with environment values redacted. It never launches an
45
45
  agent. **Manage launch configurations** in the dialog creates or updates named
46
- configurations at the displayed scope, including executable/wrapper, a JSON
46
+ configurations in the deployment's `oats-local.yaml`, including executable/wrapper, a JSON
47
47
  argument list, environment references, model and permissions. Saving a
48
48
  configuration changes its definition; applying it to an existing home requires
49
49
  an explicit Start or Restart. When editing redacted environment values, keep
package/docs/desktop.md CHANGED
@@ -85,20 +85,14 @@ The probe/mutation contract is specified in
85
85
  The app starts on the directory it was launched with (its own folder by
86
86
  default). To view a deployment, open the workspace switcher in the sidebar
87
87
  and choose **Add workspace → Browse**, then point it at an OATS deployment —
88
- a directory containing `agents/` (under the 0.25 workspace model that is the
89
- deployment directory (the operator's choice) holding `oats-local.yaml` and `agents/`;
90
- under 0.24, an `agents/` root, a `local-agents/` root for machine-local souls,
91
- or a team scope whose `oats-config.yaml` declares `team:`). *The Desktop's own
92
- multi-repo roster ("team scopes show every member repo's agents under one
93
- roster") still keys on the 0.24 `oats-config.yaml` `team:` declaration; reading
94
- the member set from `oats-local.yaml` / `oats workspace status` is the Phase F
95
- follow-up named in the [0.25.0 notes](release-notes/v0.25.0.md#desktop).*
88
+ the directory (the operator's choice) holding `oats-local.yaml` and `agents/`.
89
+ A picked folder without `oats-local.yaml` is offered onboarding instead. The
90
+ Desktop never parses the deployment: its members, lock state and header come
91
+ from `oats workspace status`, and its instances from the deployment's one
92
+ `agents/` root. There is no team scope and no `oats-config.yaml`.
96
93
  Added workspaces are remembered and offered as suggestions next time.
97
94
 
98
- Local souls (uncommitted, machine-local agents under `local-agents/`) are
99
- first-class: they appear in the roster with a `local` chip, their brains
100
- and knowledge render, and they spawn like any other soul. Launch flags for
101
- scripted use: `--dir <workspace>` and `OATS_DESKTOP_PORT`.
95
+ Launch flags for scripted use: `--dir <workspace>` and `OATS_DESKTOP_PORT`.
102
96
 
103
97
  ## Scheduling agents and wake messages
104
98
 
@@ -164,7 +158,7 @@ The full breaking-change list is in the
164
158
  | Terminals fail to open ("could not attach") | tmux missing, or no live session for that instance. Install tmux (`tmux -V`); check `tmux ls`. |
165
159
  | Can't select/copy text in a terminal tab | The terminal runs with tmux mouse handling, so a plain drag scrolls/passes through. Hold **Option** (macOS) or **Shift** while dragging to make a local selection, then copy (Cmd+C / right-click → Copy). |
166
160
  | macOS "app is damaged / can't be opened" | Ad-hoc-signed (not notarized) build + quarantine. Right-click → Open, or clear the quarantine attribute (above). If it persists, verify the bundle: `codesign --verify --deep --strict --verbose=2 "/Applications/OATS Desktop.app"` — a non-zero exit means a broken artifact, report it. |
167
- | Roster empty | The opened directory isn't an OATS workspace (needs `agents/` or `local-agents/`, or a team scope). Use the workspace switcher → Add workspace to select the right root. |
161
+ | Roster empty | The opened directory isn't an OATS workspace (needs `agents/`, or a team scope). Use the workspace switcher → Add workspace to select the right root. |
168
162
 
169
163
  For bugs, attach the terminal output of the app (`OATS Desktop` prints
170
164
  server and CLI-discovery logs to stdout) and your platform/arch.
@@ -160,9 +160,7 @@ These pathname checks are not OS-level exclusion against a concurrent hostile
160
160
  filesystem mutation between validation and use.
161
161
 
162
162
  Managed execution also records independent native transcript-location history;
163
- the recipe remains a template, not provenance. See
164
- [Native roots](design/package-runtime-api.md)
165
- for the exact source and standalone-fallback semantics.
163
+ the recipe remains a template, not provenance.
166
164
 
167
165
  The start opens a new harness conversation on the instance's `TASK.md`; the
168
166
  instance resumes its work from its own `STATE.md`, as the knowledge protocol
@@ -231,21 +229,21 @@ and needs equivalent registration glue when switched to session delivery.
231
229
 
232
230
  ## Shared permission setting
233
231
 
234
- The opt-in is per launch or per soul: `oats spawn --yolo` / `--no-yolo`
235
- (`oats create` accepts the same flags), an optional `yolo` in `soul.yaml`
236
- (0.24 schema; the v2 `soul.yaml` schema does not carry it — use the spawn flag
237
- or a launch configuration), and the Desktop's per-launch choice. With no
238
- setting, native policy is retained.
239
-
240
- *0.24 classic deployments* may also set `yolo: true` in an `oats-config.yaml`
241
- to apply it to that scope; the closest scope wins, soul overrides scope, the
242
- spawn flag overrides both. *Under the workspace model* `oats-config.yaml` is
243
- not configuration ([configuration.md](configuration.md)); the kernel's
244
- `composeInstance` still consults the classic chain for the machine-level knobs
245
- `yolo` and `launch-configs` when such a file happens to sit above the
246
- deployment, but nothing writes one and the rebuild guide tells you to delete
247
- it — treat a scope-level `yolo` as a 0.24 feature and prefer the explicit
248
- spawn flag.
232
+ The opt-in is per launch: `oats spawn --yolo` / `--no-yolo`, the `yolo` of a
233
+ named launch configuration (`oats launch-config set <name> --file <json>`),
234
+ or the Desktop's per-launch choice. A soul does not carry it: `soul.yaml` has
235
+ no `yolo`. With no setting, native policy is retained, and the spawn flag
236
+ overrides any configured value.
237
+
238
+ Launch configurations are host-level: `oats launch-config set` writes them to
239
+ the `launch-configs:` block of the deployment's `oats-local.yaml`, the one
240
+ place the kernel reads them from ([configuration.md](configuration.md)). A
241
+ scope's `oats-config.yaml` declaring `launch-configs:` is refused with a message
242
+ naming the move. The scope-level `yolo:` of `oats-config.yaml` is removed in
243
+ 0.26.0 with the config chain (lead decision c3-4): yolo is chosen only by
244
+ `--yolo` / `--no-yolo` on `oats spawn`, `oats session start` and
245
+ `oats session restart`, or by the `yolo` of a named launch configuration. It is
246
+ not a soul field either (lead decision c3-q Q6): `soul.yaml` has no `yolo`.
249
247
 
250
248
  Autonomous or unattended execution is not permission to synthesize `yolo: true`.
251
249
  Explicit user CLI/UI input or a user-selected configuration is the opt-in; explicit
@@ -5,17 +5,15 @@
5
5
  > `use` / `trust`, the 0.24 `oats onboard --dir` bootstrap that created a local
6
6
  > `oats-setup-expert`) no longer exists; those verbs answer `E_UNKNOWN_COMMAND`
7
7
  > naming their replacement. Model: [workspaces.md](workspaces.md) ·
8
- > packages: [packages.md](packages.md) · moving a 0.24 deployment:
9
- > [rebuild-to-v2.md](rebuild-to-v2.md) (§5 is the deployment layout this page
10
- > creates). The [qualification example](first-team-demo.md) records real v1
11
- > tasks on 0.23 and is not v2 acceptance.
8
+ > packages: [packages.md](packages.md) · the deployment layout this page
9
+ > creates: [configuration.md](configuration.md).
12
10
 
13
11
  Start with one workspace, one member repository and one small, real task. A
14
12
  soul keeps the role and its curated skills; an instance gets a working session
15
13
  and a repository view; every capability the instance runs is copied whole into
16
14
  its home at spawn from a **member** repository (latest state, trusted by
17
- membership) or from a **package** (a pinned version, executables approved once
18
- per version in the lock). Nothing is installed.
15
+ membership) or from a **package** (a pinned version, trusted by its
16
+ declaration and locked to a commit and integrity). Nothing is installed.
19
17
 
20
18
  ## 0. Prerequisites
21
19
 
@@ -30,8 +28,7 @@ node --version && tmux -V && oats version --json # features must list workspac
30
28
 
31
29
  ## 1. Declare the workspace (shared, in Git)
32
30
 
33
- Three files, all committed ([rebuild-to-v2.md](rebuild-to-v2.md) §§2–4 show
34
- each field):
31
+ Three files, all committed ([workspaces.md](workspaces.md) shows each field):
35
32
 
36
33
  - `oats-workspace.yaml` (`schemaVersion: 2`) in **one** host repository: `name`,
37
34
  `members: [<repo ref>, …]`, `teams:`, `packages: { oats.framework: v<x>, … }`,
@@ -52,7 +49,7 @@ one soul and, optionally, one capability. Every soul gets `oats.core` from the
52
49
  ## 2. Realize it on this machine — `oats onboard`
53
50
 
54
51
  `oats onboard` is the bootstrap: it writes a minimal `oats-local.yaml`, creates
55
- `agents/` and runs the first `sync` ([rebuild-to-v2.md](rebuild-to-v2.md) §5 is
52
+ `agents/` and runs the first `sync` ([configuration.md](configuration.md) is
56
53
  the resulting layout).
57
54
 
58
55
  ```bash
@@ -62,16 +59,16 @@ oats onboard ~/acme --workspace git:github.com/acme/agents # any directory
62
59
  ```
63
60
  ~/acme/ # the directory you chose; these three entries are what the kernel needs
64
61
  ├── oats-local.yaml # { schemaVersion: 2, workspace: git:github.com/acme/agents }
65
- ├── oats-lock.json # lockfileVersion 3: commit + integrity + approval per package
62
+ ├── oats-lock.json # lockfileVersion 3: commit + integrity per package
66
63
  ├── agents/ # instance homes
67
64
  └── <member>/ # clones of the members you work IN — here or anywhere named in oats-local.yaml clones:
68
65
  ```
69
66
 
70
67
  Read the report it prints: every member row must be `✓↔` (confirmed) — fix
71
- `no-backlink` / `backlink-elsewhere` / `cannot-read` before going on. If it
72
- exits `2`, a package needs executable approval: run `oats sync` in a terminal
73
- and answer `approve <id> <version>? [y/N]`. Approval is per package version,
74
- once, recorded in the lock; member capabilities need none. Then clone the
68
+ `no-backlink` / `backlink-elsewhere` / `cannot-read` before going on. Every
69
+ package in `packages:` is resolved, fetched, integrity-checked and locked; a
70
+ package is trusted because the workspace declares it, so review what a package
71
+ runs before adding its pin. Then clone the
75
72
  member you will work in beside `oats-local.yaml` (only a soul's work target
76
73
  needs a clone — discovery and resolution run over the remotes).
77
74
 
@@ -91,13 +88,13 @@ them. Do not commit `oats-local.yaml`.
91
88
  ```bash
92
89
  oats souls # every non-private soul of every confirmed member, with origin and team
93
90
  oats capabilities # member (origin: member <key> @ <commit>) and package (package <id> v<ver>) capabilities
94
- oats workspace status # membership table, packages, approval state
91
+ oats workspace status # membership table, locked packages
95
92
  oats spawn backend-expert --preview # modules[] with from/commit/changedSince, composed skill names, team
96
93
  ```
97
94
 
98
95
  The preview is where a skill-name clash between two composed capabilities
99
- (`E_SKILL_DUPLICATE`) or an unapproved package (`E_PACKAGE_UNAPPROVED`) shows
100
- up, before anything is created.
96
+ (`E_SKILL_DUPLICATE`) or a package missing from the lock (`E_PACKAGE_MISSING`)
97
+ shows up, before anything is created.
101
98
 
102
99
  ## 4. Give an instance a real task
103
100
 
@@ -3,7 +3,7 @@
3
3
  The reference implementation publishes two npm packages:
4
4
 
5
5
  - **`@awebai/oats`**: runtime-neutral kernel, universal `oats` CLI,
6
- bootstrap skills, instruction sources, and the official capability marketplace.
6
+ bootstrap skills, instruction sources, and the official package catalog.
7
7
  - **`@awebai/oats-pi`**: minimal pi adapter for instance-local resource
8
8
  exposure and memory session events. It registers no agent tools.
9
9
 
@@ -18,7 +18,7 @@ own Claude configuration is deliberately left enabled.
18
18
  |---|---|
19
19
  | `lib/core.mjs` | Souls, instances, config/target resolver, capability discovery, composition, locks/trust, hooks. |
20
20
  | `bin/oats.mjs` | Agent lifecycle, config, acquisition/trust/activation, doctor, and operational command dispatch. |
21
- | `capabilities/` | Bundled additive packages and layer integrations, each with `oats.json`. |
21
+ | `capabilities/` | Bundled package copies — core capabilities and others — each with `oats.json`. |
22
22
  | `skills/` | Kernel/bootstrap and package-authoring skills. |
23
23
  | `injects/` | Kernel and work-mode instruction sources. |
24
24
  | `packages/pi/` | Thin pi adapter. |
@@ -49,7 +49,6 @@ and the `oats.web` browser panel were retired in its favor.)
49
49
  CLAUDE.md -> AGENTS.md
50
50
  skills/ # soul-private skills
51
51
  instances/<instance>/
52
- soul -> ../../soul
53
52
  AGENTS.md # generated composition (regular file)
54
53
  CLAUDE.md -> AGENTS.md
55
54
  .agents/skills/ # exact materialized set
@@ -59,7 +58,7 @@ and the `oats.web` browser panel were retired in its favor.)
59
58
  instance.json # capabilities, skills, instruction sources, lifecycle metadata
60
59
  ```
61
60
 
62
- Knowledge integration hooks may add memory files. The kernel does not assume
61
+ The knowledge capability's hooks may add memory files. The kernel does not assume
63
62
  their names.
64
63
 
65
64
  ## Resolution
@@ -77,21 +76,10 @@ the slot). `lib/materialize.mjs` then copies every module whole into the home.
77
76
  The normative contract is
78
77
  [docs/design/2026-09-23-workspace-module-contracts.md](design/2026-09-23-workspace-module-contracts.md).
79
78
 
80
- **Classic 0.24 (superseded; still carried for homes without `oats-local.yaml`).**
81
- `configChain(context)` loads `oats-config.yaml` from closest scope outward.
82
- `resolveCapabilities(context, soulName)`:
83
-
84
- 1. resolves explicit group definitions;
85
- 2. collects matching global/group/soul bindings;
86
- 3. composes settings by target specificity then config closeness;
87
- 4. applies explicit enable/exclusion;
88
- 5. validates equal-specificity conflicts, IDs, command namespaces, lock
89
- integrity, and skill/layer collisions; and
90
- 6. returns deterministic active capability records with provenance.
91
-
92
- `resolveOatsConfig` maps active packages declaring `layer` into the exclusive
93
- knowledge/messaging/tasks slots. `layers.<layer>: none` explicitly suppresses
94
- an inherited slot and remains distinct from absence.
79
+ **Classic 0.24 (removed in 0.26.0).** The `oats-config.yaml` chain and its
80
+ resolvers are gone. A legacy `oats-config.yaml` between the invocation
81
+ directory and the deployment is refused with `E_CONFIG_BROKEN`
82
+ (`reason: "legacy-config"`), and the message names the files that replace it.
95
83
 
96
84
  ## Spawn composition
97
85
 
@@ -130,9 +118,9 @@ work-mode block it frames: `<instance-home>` (`$OATS_INSTANCE_HOME`) holds the
130
118
  brain, task, provenance and working state, and is where OATS operational/lifecycle
131
119
  commands are run from — together with the commands of whatever capabilities are
132
120
  active, `aw` among them when aweb messaging is — since they resolve scope from
133
- the working directory (`--dir <path>` reaches another deliberately); the home's
134
- `soul` link is to be treated as read-only because writes through it bypass the
135
- branch and review path; and `<instance-home>/work` is the repository or workspace
121
+ the working directory (`--dir <path>` reaches another deliberately); the home
122
+ carries no soul link (the composed AGENTS.md holds the soul's instructions, and
123
+ hooks receive the recorded soul directory as `OATS_SOUL`); and `<instance-home>/work` is the repository or workspace
136
124
  view where repository reading, editing, building, testing, git and commits
137
125
  happen. It bounds *repository* work rather than forbidding all output elsewhere —
138
126
  episodic state lives in the home, and a service agent's own artifacts (a report
@@ -198,11 +186,10 @@ The generated order is:
198
186
 
199
187
  1. canonical soul content;
200
188
  2. kernel OATS block;
201
- 3. local-soul block (local souls only);
202
- 4. **home/work boundary block** — runtime-neutral, every mode and every kind;
203
- 5. actual spawn work-mode block;
204
- 6. active capability blocks in resolver order; and
205
- 7. unconditional config blocks outermost to innermost.
189
+ 3. **home/work boundary block** — runtime-neutral, every mode and every kind;
190
+ 4. actual spawn work-mode block;
191
+ 5. active capability blocks in resolver order; and
192
+ 6. unconditional config blocks outermost to innermost.
206
193
 
207
194
  Every generated block carries its source path. `oats doctor --soul <name>` uses
208
195
  the same composer and prints/returns the final text. Config-dependent prose is
@@ -214,40 +201,26 @@ never reconciled into committed souls.
214
201
  (`lib/packages.mjs#resolvePackages`) resolves every `packages:` entry of
215
202
  `oats-workspace.yaml` to a commit, computes the package tree's integrity and
216
203
  writes `oats-lock.json` **lockfileVersion 3** (`packages.<id>: { source, url,
217
- path, version, commit, integrity, capabilities[], approved }`). Executable
218
- approval is **per package version**, recorded in the lock as
219
- `approved: { executables: sha256-…, at }` after `oats sync` shows the
220
- executables and the operator says yes; a spawn of a soul using an unapproved
221
- package is `E_PACKAGE_UNAPPROVED`, and 0.25.1 re-verifies the approved digest
222
- against the package tree at the locked commit at every spawn. Member-tier
223
- capabilities need no approval: membership is the trust (decision 2). The
204
+ path, version, commit, integrity, capabilities[] }`). A package is trusted by
205
+ its declaration in `packages:` (human decision, 2026-09-24); member-tier
206
+ capabilities are trusted by membership (decision 2). The lock is
207
+ reproducibility: a moved tag or drifted content is `E_PACKAGE_INTEGRITY`, at
208
+ spawn the lock's capability list must match what the package declares at the
209
+ locked commit, and a spawn uses only packages the workspace still declares. The
224
210
  verbs `oats install|trust|list|restore|use|migrate` are removed
225
211
  (`E_UNKNOWN_COMMAND` naming the replacement).
226
212
 
227
- **Classic 0.24 (superseded).** External installation copies/clones one exact
228
- artifact and writes `oats-lock.json` with source, version/commit, and SHA-256
229
- tree integrity. An existing destination is never pulled silently. Resolution
230
- rejects changed locked artifacts and unlocked installed/path packages.
231
-
232
- Executable package hooks, commands, and launch-environment authority are omitted
233
- until `oats trust <id>` (0.24) marks the exact locked integrity approved.
234
- Bundled packages are framework-trusted.
235
- Packages under a scope's `owned/` subtree are config-owned. Anything under
236
- `installed/` requires a matching lock entry, so an acquired artifact cannot
237
- bypass executable trust by its directory location.
238
-
239
- Distribution packages generalize this: a package materializes each capability it
240
- exports into `.agents/capabilities/installed/<id>/`, each independently
241
- addressable and independently trusted at its own artifact integrity. There is no
242
- persistent package store. The 0.24 `lockfileVersion: 2` lock records package
243
- provenance (`packages`) and materialized capability identity (`capabilities`)
244
- separately. See `docs/design/package-engine-contract.md` for the resolver/lock
245
- API and error taxonomy.
213
+ **Classic 0.24 (removed in 0.26).** The installed tier
214
+ (`.agents/capabilities/installed/`, the `lockfileVersion: 2` lock, per-artifact
215
+ approval) and its last writer went with the captured path; the
216
+ [0.24 release notes](release-notes/v0.24.0.md) describe what it was.
246
217
 
247
218
  ## Hooks and scaffold ownership
248
219
 
249
- Only `soul-scaffold`, `spawn`, and `retire` manifest hooks are accepted.
250
- Spawn/scaffold use outer-scope then capability-ID order; retire reverses it.
220
+ Only `soul-scaffold`, `spawn`, and `retire` manifest hooks are accepted. The
221
+ kernel no longer runs `soul-scaffold`: it ran when `oats create` wrote a soul,
222
+ and souls are now authored in member repositories.
223
+ Spawn uses outer-scope then capability-ID order; retire reverses it.
251
224
  Each hook receives package identity/layer plus structured OATS environment and
252
225
  may emit a final JSON object containing `meta`, `brief`, `warning`, or `launch`.
253
226
  Only a spawn hook may add `env`; other lifecycle events reject it rather than
@@ -269,10 +242,6 @@ removes and verifies rollback-owned Git topology, and removes the home only
269
242
  when cleanup completed. Failed compensation or reported state with no retire
270
243
  hook uses the same retryable quarantine as every other incomplete spawn.
271
244
 
272
- Soul scaffolding snapshots files around each package hook and records new-file
273
- ownership in `.oats-scaffold-owners.json`. Overwriting canonical or another
274
- package's file restores the prior bytes and raises a conflict.
275
-
276
245
  ## Commands
277
246
 
278
247
  Kernel/package-management commands are always available. Operational
@@ -83,7 +83,7 @@ directory delivery is recoverable and needs no Git/gh. Explicit bindings,
83
83
  `soul/okf.json` and accepted base metadata are required before a working source
84
84
  can spawn. `owns`/`reads` are responsibility/context, not ACLs. See
85
85
  [knowledge](knowledge.md) for the **prepared** version scope, provisioning and
86
- commands, and [migration](knowledge-migration.md) before updating v1.
86
+ commands.
87
87
 
88
88
  **`oats.aweb`** fills `messaging`: mints an instance identity at spawn (local
89
89
  mode) or grants an instance an expiring session as a resident global identity
@@ -103,12 +103,14 @@ secrets never belong in OATS config. See
103
103
  > favor of the OATS Desktop app (`packages/desktop/`), which bundles the same
104
104
  > zero-dependency loopback server. If an `oats-workspace.yaml` (`packages:`,
105
105
  > `defaults.capabilities`) or a `soul.yaml` still names `oats.web`, remove that
106
- > entry and `oats sync`; on a 0.24 classic deployment, remove it from
107
- > `oats-lock.json` / `oats-config.yaml`. Full migration steps:
108
- > [desktop-succession](desktop-succession.md).
106
+ > entry and `oats sync`.
109
107
 
110
108
  ## Building an integration
111
109
 
110
+ A slot provider that declares `binding` answers `oats readiness` through its
111
+ `binding.check` command; the request, environment and answer are specified in
112
+ [capabilities.md](capabilities.md#readiness-check-bindingcheck).
113
+
112
114
  Building an integration is implementing a contract. The checklist per slot:
113
115
 
114
116
  **Any slot.** A namespaced capability manifest with exactly one `layer`; an
@@ -143,7 +145,7 @@ implementation. **This is a messaging-layer contract, not an oats.aweb
143
145
  detail** (decision 27): from kernel 0.25.6 the kernel copies it through as
144
146
  the principal the instance *acts as* — `oats status --json
145
147
  instances[].identity`, the roster's `identity:` line, `oats inspect --home …
146
- selected.identity` — preferring the capability whose captured layer is
148
+ selected.identity` — preferring the capability whose recorded layer is
147
149
  `messaging`, adding `provider: <capability id>`, and never interpreting
148
150
  `grant`. The kernel offers no `--identity` flag: the choice travels as
149
151
  `--provider <cap> identity.mode=… identity.resident=…` and is bound by the
@@ -218,27 +220,64 @@ warning naming the fresh-purpose remedy. On an older `aw` the pre-1.36.1
218
220
  report stands (`aliasReusable: false`, warning naming aweb-abim), because
219
221
  that CLI cannot revoke the certificate.
220
222
 
221
- ## oats.aweb settings (1.12.0)
223
+ ## oats.aweb settings (1.12.2)
222
224
 
223
- Set in `oats-local.yaml` under `settings.oats.aweb.<key>` (host-owned), in the
224
- soul's `messaging:` payload (true of every instance), or per spawn with
225
- `oats spawn … --provider oats.aweb <key>=<value>`. The effective payload is
226
- merged in order: workspace messaging, `byTeam[team]`, soul messaging,
227
- `oats-local.yaml` `settings.oats.aweb`, then per-spawn `--provider` values.
228
- `residents` is host-file-only: put custody paths only in `oats-local.yaml`,
229
- never in a committed workspace or soul file (current kernels document this rule
230
- but do not yet enforce provenance in the hook payload).
225
+ Set portable team policy in the workspace/soul `messaging:` payload; set host
226
+ facts in `oats-local.yaml` under `settings.oats.aweb.<key>`. Per-spawn
227
+ `oats spawn … --provider oats.aweb <key>=<value>` is for non-host settings only.
228
+ The effective payload is merged in order: workspace messaging, `byTeam[<primary label>]`,
229
+ soul messaging, `oats-local.yaml` `settings.oats.aweb`, then per-spawn
230
+ `--provider` values. `root`, `roots`, and `residents` are manifest-declared
231
+ `hostOnly: true`: absolute root/custody paths are accepted only from
232
+ `oats-local.yaml`; kernels since 0.25.6 refuse those keys in the workspace file,
233
+ `byTeam`, soul payloads and `--provider` flags with `E_WORKSPACE_SCHEMA` reason
234
+ `host-only-key`.
231
235
 
232
236
  - `team: <team id>`. The payload team wins over `OATS_TEAM_ID`/
233
237
  `OATS_TEAM_NAME`; if both are set and differ, the hook warns and uses the
234
238
  payload. Workspace v2 spawns can have an empty `OATS_TEAM_ID`, so set this in
235
- the payload for global grants.
239
+ the workspace file's `messaging:` / `messaging.byTeam.<label>.team`, or in
240
+ `settings.oats.aweb.team` for a host override.
241
+ - `root: /absolute/dir`. Host-owned absolute directory whose `.aw` is the aweb
242
+ minting root. A declared root without `.aw` is fatal; run `oats aweb setup`
243
+ there or set `settings.oats.aweb.root` to the initialized root.
244
+ - `roots: { <team id>: /absolute/dir }`. Host-owned map for deployments that
245
+ mint into several aweb teams. When a team is known, `roots[team]` wins over
246
+ `root`.
247
+ - Minting root resolution for spawn and setup is: `roots[team]` when the team is
248
+ known and present, else `root`. With no declared root, workspace v2 uses
249
+ `<OATS_WORKSPACE>` (the deployment directory whose `.aw` is used) and never
250
+ searches above it; classic deployments with `OATS_TEAM_SCOPE` keep the
251
+ historical bounded candidate search order exactly (team scope, home, home git
252
+ root, context, context git root, then workspace).
253
+ - `binding-check` answers `needs-configuration` before spawn with one problem
254
+ per missing item: `no messaging root at <dir>: run oats aweb setup there or
255
+ set settings.oats.aweb.root`; `no team: set messaging.byTeam.<label>.team in
256
+ the workspace file or settings.oats.aweb.team`. With both present it answers
257
+ `ready`.
258
+ In classic deployments this readiness check approximates the full bounded
259
+ spawn search by checking `OATS_TEAM_SCOPE` before `OATS_WORKSPACE`; the spawn
260
+ hook itself still keeps the exact 1.12.0 bounded candidate order. With no
261
+ explicit team and no workspace team label, readiness follows spawn: an active
262
+ aweb team at the root is enough to answer ready; an unmapped workspace team
263
+ label still reports the team-setting remedy above.
264
+ - `oats aweb setup` is idempotent and uses existing aw primitives. With
265
+ `--username <u>` it runs `aw init --username <u>` at the messaging root and
266
+ tells the operator to map the workspace team to `default:<u>.aweb.ai` when
267
+ that team is not already the configured target. With `AWEB_API_KEY` in the
268
+ environment it runs `aw init` at the root for the hosted team behind the key.
269
+ With `--invite <token>` it runs `aw team join <token>`. It never prints the
270
+ API key or invite token, re-reads `aw team list --json` after the action, and
271
+ prints the same ready/needs-configuration verdict as binding-check.
236
272
  - `identity.mode: local | global` (default `local`). Any other value is fatal.
237
273
  Local mode is the historical behavior: a spawned team identity is minted for
238
274
  the instance, or `identity.source` uses the existing retained-seat flow below.
239
275
  Its spawn meta includes `identity: { mode: "local", alias, team, address:
240
276
  null, resident: null }` beside the existing top-level `alias`, `team`, and
241
- `delivery` keys.
277
+ `delivery` keys. Local-mode spawn output contributes
278
+ `env.AWEB_IDENTITY_HOME=<home>/.aw` (and retained-seat local mode contributes
279
+ the same path) so `aw mail`, `aw chat`, `aw whoami`, `aw wake`, and
280
+ `aw workspace status` work from the instance's `work/` or any other cwd.
242
281
  - `identity.mode: global` makes the instance act as a resident global identity
243
282
  through an aweb session grant; it never mints a new global identity and never
244
283
  copies root keys into the instance home. `identity.resident` is required and
@@ -247,24 +286,41 @@ but do not yet enforce provenance in the hook payload).
247
286
  the `oats-local.yaml settings.oats.aweb.residents.<name>` key to set. Optional
248
287
  `identity.scopes` defaults to exactly `[mail.read, mail.send, chat.read,
249
288
  chat.send]`; optional `identity.ttl` defaults to `8h` (aw accepts `60s` to
250
- `720h`). Spawn runs `aw id grant mint --scope <comma-list> --ttl <ttl>
251
- --label oats:<instance> --out <home>/.aweb-identity --json` from the custody
252
- directory with `AWEB_IDENTITY_HOME` removed from the child environment: in aw
253
- 1.36.1, grant commands are not identity-home-aware and intentionally refuse
254
- both `--identity-home` and external `AWEB_IDENTITY_HOME`, so cwd selects the
255
- custody identity. The hook parses the whole JSON document because aw `--json`
256
- output is indented across lines, with a fallback to the first brace-prefixed
257
- block when progress lines precede it; it then verifies the minted grant's
258
- `team_id` and returns
259
- `env.AWEB_IDENTITY_HOME=<home>/.aweb-identity`. If the minted team differs,
260
- the hook revokes the grant and keeps nothing. As of aw 1.36.1, receiving,
261
- wake registration and `aw whoami` work through a grant, but sending mail or
262
- chat through a grant is rejected by the server with 422 (`from_did must match
263
- the authenticated sender`) because the aw client signs with the grant-key DID
264
- where the server expects the resident's. Retire revokes
289
+ `720h`). Spawn first runs `aw custody status --json` in the resident custody
290
+ directory and uses exactly the reported `socket_path`; a status without a
291
+ socket is refused. It then runs `aw id grant mint --team <team-id> --scope
292
+ <comma-list> --ttl <ttl> --label oats:<instance> --out
293
+ <home>/.aweb-identity --custody-socket <preflight-socket> --json` from the
294
+ custody directory when aw is 1.36.2 or later for `--team`; grants need aw >=
295
+ 1.36.3 (`CUSTODY_ATTACH_MIN`) with aweb server >= 1.27.5 for
296
+ `--custody-socket`. `AWEB_IDENTITY_HOME`
297
+ is removed from mint/revoke child environments: grant commands are not
298
+ identity-home-aware and intentionally refuse both `--identity-home` and
299
+ external `AWEB_IDENTITY_HOME`, so cwd selects the custody identity. The hook
300
+ parses the whole JSON document because aw `--json` output is indented across
301
+ lines, with a fallback to the first brace-prefixed block when progress lines
302
+ precede it; it then verifies the minted grant's `team_id`, reads back
303
+ `<grantHome>/grant.yaml` (not `encryption.yaml`) and requires
304
+ `custody.socket_path` to equal the preflight socket, and runs
305
+ `aw custody status --json` with `AWEB_IDENTITY_HOME=<grantHome>` from the grant
306
+ home to verify the resident alias and ready team row. Missing or mismatched
307
+ custody attachment revokes the grant, removes the grant home and fails the
308
+ spawn. It returns `env.AWEB_IDENTITY_HOME=<home>/.aweb-identity`. If the minted
309
+ team differs, the hook revokes the grant and keeps nothing. Receiving, wake registration,
310
+ and `aw whoami` work through a grant. On aw 1.36.1 the server rejected mail
311
+ or chat sent through a grant with 422 (`from_did must match the authenticated
312
+ sender`) because the client signed with the grant-key DID. aw 1.36.2 with
313
+ aweb server 1.27.5, the floor, fixes this; grant mail and chat sends passed
314
+ real-server acceptance there. A hosted team whose server has not yet adopted
315
+ 1.27.5 still refuses grant sends; the custody preflight reports that as
316
+ needs-configuration before spawn through `grant_status_endpoint_ready`.
317
+ Retire revokes
265
318
  `meta.identity.grant.id` through the custody directory; with no grant id it
266
319
  reports `nothing-to-revoke`. A failed revoke exits nonzero and reports the TTL
267
- expiry.
320
+ expiry. A binding-less home readiness check for global mode never reports ready
321
+ for a grant home whose `grant.yaml` lacks `custody.socket_path`; it reports
322
+ `needs-configuration` / code `custody` and tells the operator to retire and
323
+ respawn on an aw new enough to attach custody.
268
324
  - `residents: { <name>: /abs/custody/dir }` is the host-owned map for global
269
325
  mode. Each custody directory's `.aw` holds the resident identity root keys and
270
326
  team certificate. Do not put this map in committed source; the hook cannot
@@ -58,7 +58,7 @@ v0.23.1 is published, an explicit initial Git acquisition at that tag selects
58
58
  the patch instead. It does not silently change the catalog's 1.0.0 selection
59
59
  or an existing lock. For local development, use an explicit complete source
60
60
  package path instead. Activation exposes the expert and targets
61
- the authoring skill, without selecting or replacing a knowledge integration.
61
+ the authoring skill, without selecting or replacing a knowledge capability.
62
62
  There are no executable surfaces to trust in this package. Installed experts
63
63
  use their materialized local curriculum, not this repository at runtime.
64
64
 
@@ -19,7 +19,7 @@ A minimal distribution shape (replace example identities/descriptions):
19
19
  {
20
20
  "package": "example.knowledge",
21
21
  "version": "1.0.0",
22
- "description": "Example knowledge integration.",
22
+ "description": "Example knowledge capability.",
23
23
  "compatibility": { "oats": ">=0.22.19" },
24
24
  "capabilities": ["capabilities/knowledge"]
25
25
  }
@@ -31,7 +31,7 @@ A knowledge implementation's capability manifest might begin:
31
31
  {
32
32
  "capability": "example.knowledge",
33
33
  "version": "1.0.0",
34
- "description": "Native knowledge integration.",
34
+ "description": "Native knowledge capability.",
35
35
  "compatibility": { "oats": ">=0.22.19" },
36
36
  "layer": "knowledge",
37
37
  "skills": ["skills/native-reader", "skills/native-harvest"],
@@ -115,16 +115,18 @@ defaults:
115
115
  ```
116
116
 
117
117
  ```bash
118
- oats sync --dir /path/to/test-workspace # resolve, lock, approve once
118
+ oats sync --dir /path/to/test-workspace # resolve, fetch, verify integrity, lock
119
119
  oats spawn <soul> --preview --json # the module as it would be materialized
120
120
  ```
121
121
 
122
122
  These are illustrative user operations, not instructions to change a live
123
- deployment. The `oats`, `oats-config` and `oats-packages` kernel skills describe
124
- the installed kernel's operational commands. Installation exact-locks the
125
- package closure and activates nothing. Capabilities with executable commands or
126
- hooks require per-artifact trust before execution. A skills-only package needs
127
- lock integrity, not executable approval. Official catalog identity is not trust.
123
+ deployment. The `oats.setup` capability's **oats-package-pins** skill describes
124
+ the operational commands. Declaring the package in `packages:` is the trust
125
+ decision: its commands and hooks run at spawn, so whoever adds the pin reviews
126
+ them first. Syncing exact-locks the package (commit and integrity) and activates
127
+ nothing; a soul receives a capability only when it or a workspace default
128
+ selects it. Official catalog identity is a reviewed listing, not trust on the
129
+ operator's behalf.
128
130
  Targets belong in config, not manifests. A manifest with `layer: knowledge`
129
131
  occupies that exclusive slot; an additive authoring aid must not replace it.
130
132
 
@@ -279,7 +279,7 @@ The kernel supplies the common boundary; it must not contain one mandatory knowl
279
279
  |---|---|
280
280
  | Source, soul and instance identity | Knowledge organisation and destination semantics |
281
281
  | Configuration resolution and declared requirements | Storage, retrieval and reading context |
282
- | Selected resources and exact executable approval | Capture conventions and evidence selection |
282
+ | Selected resources, exactly locked | Capture conventions and evidence selection |
283
283
  | Lifecycle/invocation context and provenance | Judgment, harvesting and maintenance where used |
284
284
  | Safe helper/job execution when required | Proposals, delivery, acceptance and recovery policies |
285
285
  | Retained-artifact integrity and truthful outcomes | Its complete runtime instructions, skills and tools |