@awebai/oats 0.24.13 → 0.25.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 (51) hide show
  1. package/bin/oats.mjs +930 -2820
  2. package/docs/capabilities.md +136 -323
  3. package/docs/configuration.md +68 -533
  4. package/docs/design/2026-09-16-fresh-operator-walkthrough.md +19 -14
  5. package/docs/design/2026-09-16-portable-migration-evidence.md +2 -0
  6. package/docs/design/2026-09-16-portable-onboarding.md +4 -2
  7. package/docs/design/2026-09-20-redesign-program-board.md +1 -1
  8. package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +2 -0
  9. package/docs/design/2026-09-23-simplified-workspace-model.md +711 -0
  10. package/docs/design/2026-09-23-workspace-module-contracts.md +309 -0
  11. package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +65 -0
  12. package/docs/design/README.md +20 -8
  13. package/docs/design/operations-contract.md +1 -0
  14. package/docs/design/package-engine-contract.md +1 -1
  15. package/docs/design/package-runtime-api.md +1 -1
  16. package/docs/desktop-cli-api.md +324 -5
  17. package/docs/desktop-succession.md +3 -4
  18. package/docs/first-team.md +107 -224
  19. package/docs/implementation.md +6 -4
  20. package/docs/integrations.md +45 -44
  21. package/docs/knowledge-capability-authoring.md +10 -4
  22. package/docs/knowledge-migration.md +5 -4
  23. package/docs/knowledge-reference/package-craft.md +11 -3
  24. package/docs/knowledge.md +24 -8
  25. package/docs/layers.md +3 -3
  26. package/docs/oats-local.schema.json +50 -0
  27. package/docs/oats-membership.schema.json +23 -0
  28. package/docs/oats-workspace.schema.json +133 -48
  29. package/docs/official-marketplace.md +9 -6
  30. package/docs/packages.md +229 -440
  31. package/docs/rebuild-to-v2.md +233 -0
  32. package/docs/release-notes/v0.25.0.md +99 -0
  33. package/docs/soul.schema.json +41 -68
  34. package/docs/souls-and-instances.md +175 -108
  35. package/docs/workspace-adoption.md +70 -345
  36. package/docs/workspaces.md +429 -119
  37. package/lib/core.mjs +419 -55
  38. package/lib/instance-resolution.mjs +312 -0
  39. package/lib/materialize.mjs +580 -0
  40. package/lib/packages.mjs +501 -1273
  41. package/lib/remote.mjs +639 -0
  42. package/lib/resolve.mjs +576 -0
  43. package/lib/schedule.mjs +90 -16
  44. package/lib/workspace.mjs +635 -0
  45. package/package.json +1 -1
  46. package/lib/portable-migration-artifacts.mjs +0 -135
  47. package/lib/portable-migration-evidence.mjs +0 -305
  48. package/lib/portable-migration-store.mjs +0 -199
  49. package/lib/portable-migration.mjs +0 -104
  50. package/lib/portable-onboarding-acceptance.mjs +0 -66
  51. package/lib/setup-expert-source.mjs +0 -100
@@ -10,127 +10,196 @@ many tasks. Lifetime does not itself change the soul's identity. See the
10
10
  [canonical knowledge and specialisation model](knowledge-theory.md) for how skills,
11
11
  shared knowledge, working context and state differ.
12
12
 
13
- This operational guide includes the configuration-based soul and lifecycle forms.
14
- Portable source definitions and captured lifecycle have their own versioned scope;
15
- see the [0.24 release notes](release-notes/v0.24.0.md) rather than assuming every
16
- legacy example below applies to a captured instance.
13
+ Souls live in **member repos** of a [workspace](workspaces.md) and are
14
+ discovered over Git; their capabilities are resolved by `from:` and copied whole
15
+ into each instance. This page is the soul's and the instance's anatomy under
16
+ that model.
17
17
 
18
18
  ## Soul anatomy
19
19
 
20
20
  A soul is durable and committed. It is the part you review, improve, and keep.
21
21
 
22
22
  ```text
23
- <agents-root>/<agent>/soul/
24
- soul.yaml # name, repo, work mode, runtime, model
23
+ <member-repo>/souls/<name>/ # discoverable in the workspace by convention
24
+ soul.yaml # schemaVersion 2: name, description, work, team, capabilities, provider payloads
25
25
  AGENTS.md # canonical operating doc
26
26
  CLAUDE.md → AGENTS.md
27
27
  skills/ # skills specific to this expert
28
- okf.json # OKF v2 owner/owns/reads declaration, when selected
29
28
  ```
30
29
 
31
- `soul.yaml` keys:
30
+ (A deployment's own `agents/<name>/soul/` has the same shape; a member soul is
31
+ fetched there at its discovered commit before its first spawn.)
32
+
33
+ ### `soul.yaml` v2
34
+
35
+ ```yaml
36
+ schemaVersion: 2
37
+ name: release-manager # must equal the directory name
38
+ description: Cuts, verifies and announces releases.
39
+ work: worktree # worktree | checkout | directory | workspace
40
+ team: engineering # optional label; else the repo's default (oats-membership.yaml); else unassigned
41
+ private: true # optional: not discoverable; spawnable only from this repo
42
+
43
+ capabilities: # WHERE each capability comes from — a location, never a version
44
+ acme-release-tooling: { from: here } # here = this soul's own repo
45
+ acme-warehouse-access: { from: github.com/acme/data } # a canonical repo key of a confirmed member
46
+ acme-deploy: { from: package } # provided by a package pinned in the workspace's packages:
47
+ acme-house-style: off # removes a workspace/team default
48
+
49
+ knowledge: # provider payloads — opaque to the kernel, consumed by the slot's capability
50
+ owns: release-manager
51
+ reads: [platform-engineer]
52
+ messaging:
53
+ channels: [acme-eng]
54
+ tasks: none # `none` empties the slot (drops the workspace default)
55
+
56
+ compatibility: # optional floors on PACKAGE versions — constraints, not sources
57
+ oats.okf: ">=2.1"
58
+ ```
32
59
 
33
60
  | Key | Meaning |
34
61
  |---|---|
35
- | `name` | Agent name. |
36
- | `kind` | `persistent` for committed agents, `local` for full local souls under `local-agents/` (legacy `tmp` reads as `local`). |
37
- | `description` | Short role description. |
38
- | `repo` | Target repo, absolute or relative to the agents root's parent. |
39
- | `work` | `worktree`, `checkout`, `attached`, `workspace`, or `directory`. |
40
- | `runtime` | `pi` or `claude` — the harness new instances launch on; a spawn can override with `--runtime`. For `claude`, the binary is `claude` unless a local-only `oats-claude-config` file (closest one walking up from the repo; one line naming the binary, e.g. `claude-personal`) selects another — a personal machine preference for account selection, never committed. With the aweb messaging integration active, claude sessions get the `aweb-channel` plugin wired at spawn for real-time push events. |
41
- | `model` | Optional default model — a `provider/id[:thinking]` pattern or a comma-separated preference list (`github-copilot/x:high, anthropic/x:high`); at spawn the first entry whose provider/model is available wins (pi models probed via `pi --list-models`). For the `claude` runtime the value is translated to what the claude CLI accepts: `anthropic/<id>[:thinking]` becomes the bare `<id>`, aliases and bare `claude-*` ids pass through, other providers' entries are dropped, and nothing usable falls back to claude's own default. A spawn can override it. |
42
- | `launch-config` | Optional default launch configuration for new instances (a name declared under `launch-configs:` in the scope's config; see docs/design/launch-configurations.md). `oats spawn --launch-config <name|none>` overrides it; `oats soul set --launch-config <name>` / `--no-launch-config` edit it. |
43
-
44
- A soul is model-agnostic as an artifact. Its files are plain operating docs,
45
- skills and capability-owned declarations. `model` is only the default choice
46
- for new instances, not part of the expert's identity.
62
+ | `name`, `description`, `work` | Required. `work` is the work mode below. |
63
+ | `team` | A label declared in the workspace's `teams:`; may add `defaults.byTeam` capabilities. Never gates or restricts. |
64
+ | `private` | `true` keeps the soul out of workspace discovery; its own repo can still spawn it. |
65
+ | `capabilities` | `<cap>: { from: here \| <repo key> \| package }` or `<cap>: off`. Composed over `defaults.<slot>` ⊕ `defaults.capabilities` ⊕ `defaults.byTeam[team]`; the soul wins. |
66
+ | `knowledge` / `messaging` / `tasks` | The slot's provider payload (true of every instance of the soul), or `none`. Merged with `oats-local.yaml` `settings.<cap>` and `spawn --provider <cap>`; the provider's `binding` contract validates the result. |
67
+ | `compatibility` | `<cap>: <semver range>` checked against the locked package version (`E_COMPATIBILITY`). |
68
+
69
+ Schema: [`soul.schema.json`](soul.schema.json). Not in v2: `kind`, `type`,
70
+ `repo`, `runtime`, `model`, `requires`, `source:`, `stores.inherit`. Model and
71
+ runtime are spawn-time / launch-configuration choices (`--runtime`, `--model`,
72
+ `--launch-config`), not soul identity: a soul is model-agnostic as an artifact.
47
73
 
48
74
  A soul never runs by itself. It is incarnated as an instance. Editing a soul
49
- is a code change.
50
-
51
- Core soul artifacts are `AGENTS.md` and `skills/`, plus any declarations the
52
- selected knowledge integration needs. OKF v2 stores knowledge externally, not
53
- in a soul bundle; see [knowledge](knowledge.md) for its prepared version scope.
54
- Future integrations may add expert-specific artifacts such as rule files or
55
- runtime-specific guidance, while keeping `AGENTS.md` canonical.
56
-
57
- ## OATS operational knowledge is a capability
58
-
59
- New souls declare `requires.capabilities.oats.core` with a Git source resolved
60
- from the official package catalog. `oats create` and new local-soul scaffolds
61
- write that requirement; `--no-oats-core` explicitly omits it. If the catalog has
62
- no published revision yet, creation reports `needs-configuration` (also in JSON
63
- `notes`) and leaves the requirement absent rather than inventing a source.
64
- Declaring a capability is not acquiring, activating or approving it: those remain
65
- normal deployment/preparation steps. The Desktop server currently has no
66
- soul-creation endpoint; `oats soul set` edits existing definitions only.
67
-
68
- The dependency is visible and removable in `soul.yaml`. Updating an existing
69
- local soul preserves its requirements—including a deliberate removal—rather
70
- than applying the creation default again. For the one-release transition,
71
- a declaration of **either `oats.core` or `oats.setup`** suppresses the entire
72
- legacy kernel operational skill list (`oats`, `oats-config`, `oats-packages`)
73
- and `kernel:oats` injection. This also prevents setup's moved skill names from
74
- colliding with the kernel copies; no skill override is needed for this case.
75
- Without either declaration, legacy composition is unchanged.
76
- `oats doctor --soul <name>` reports an absent `oats.core` as an informational
77
- deprecation notice, not an error. Instance-boundary, work-mode and
78
- configuration-declared briefings remain kernel-owned. Existing captured records
79
- keep their retained resources; this does not migrate them or retire the kernel
80
- skill files yet.
75
+ is a code change, reviewed in its repo.
76
+
77
+ ### OATS operational knowledge is a capability
78
+
79
+ An agent's knowledge of OATS itself — status, spawn, retire, finding other
80
+ souls — is ordinary capability content: **`oats.core`** (package
81
+ `oats.framework`). Workspaces give it to every soul through
82
+ `defaults.capabilities: { oats.core: { from: package } }`; a soul may say
83
+ `oats.core: off`. **`oats.setup`** (same package) carries the whole-architecture
84
+ knowledge an onboarding expert needs. Neither is kernel magic; the kernel still
85
+ composes its own instance-boundary and work-mode briefings.
81
86
 
82
87
  ## Instance anatomy
83
88
 
84
89
  An instance has a lifecycle, but need not be short-lived. It is the identity of
85
- one instantiated soul while its assignment is alive. Supported session continuations,
86
- compactions and restarts can preserve that continuity. Model or harness changes must
87
- follow the selected execution profile; they are not permission to reinterpret a
88
- captured recipe. Retirement should account for valuable context and unfinished work,
89
- not assume an experienced instance is cheap to replace.
90
+ one instantiated soul while its assignment is alive. Supported session
91
+ continuations, compactions and restarts can preserve that continuity.
92
+ Retirement should account for valuable context and unfinished work, not assume
93
+ an experienced instance is cheap to replace.
90
94
 
91
95
  An instance has a home directory, a task, and a worktree when the work mode
92
- needs one. Its runtime setup is composed from the canonical soul plus
93
- capabilities selected for that soul by the config scopes governing it.
94
-
95
- A soul can have as many instances as people need. Instances are transient and
96
- normally gitignored (`agents/*/instances/`). That matters for large or open
97
- source repos: the expert souls can travel with the repo, while different
98
- engineering teams instantiate those souls into their own local agent teams.
99
- Their instance homes, logs, notes, branches, and messaging identities do not
100
- collide because they are local runtime state, not shared soul state.
96
+ needs one. Its runtime setup is composed from the canonical soul plus **its own
97
+ full copy** of every capability the soul resolved to:
101
98
 
102
99
  ```text
103
- <agents-root>/<agent>/instances/<instance>/
104
- soul → <agent>/soul/ # the agent setup for this instance
105
- AGENTS.md # generated: canonical soul + selected blocks
100
+ <agents-root>/<soul>/instances/<instance>/
101
+ soul → ../../soul # the soul, for reference (read-only)
102
+ AGENTS.md # generated: soul AGENTS.md + kernel/work-mode blocks + each module's inject
106
103
  CLAUDE.md → AGENTS.md
107
- .agents/skills/ # exact soul + active capability set
104
+ .agents/skills/ # canonical skill tree — soul skills + <capability>/<skill>/ full copies
105
+ <capability>/<skill>/SKILL.md
108
106
  .claude/skills → ../.agents/skills
109
- work/ # worktree, checkout symlink, or attached tree
107
+ .oats/modules/<capability>/ # the whole capability: oats.json, bin/, injects/, skills/ (hooks run from here)
108
+ work/ # worktree, checkout symlink, attached tree, or private directory
110
109
  TASK.md # briefing and task
111
- instance.json # repo/branch, spawn lineage, capabilities, skills, instructions, trust
112
- STATE.md, log.md, notes/ # optional, from the knowledge integration
110
+ instance.json # provenance (below)
111
+ STATE.md, log.md, notes/ # optional, from the knowledge capability
113
112
  ```
114
113
 
115
- Why durable expertise must be incarnation-invariant while task state is local
116
- to this branch and moment is covered in [knowledge theory](knowledge-theory.md).
117
- This distinction does not require knowledge bytes to live in the soul.
114
+ Instances are transient and normally gitignored (`agents/*/instances/`). Expert
115
+ souls travel with the repo; different teams instantiate them into their own
116
+ local agent teams without collisions, because instance homes, logs, notes,
117
+ branches and messaging identities are local runtime state.
118
+
119
+ ### `instance.json` — provenance is recorded, not declared
120
+
121
+ Besides the classic fields (repo, branch, lineage, launch recipe, composed
122
+ skills and instructions), a workspace spawn records:
123
+
124
+ ```json
125
+ {
126
+ "modules": {
127
+ "acme-release-tooling": {
128
+ "from": { "kind": "member", "repoKey": "github.com/acme/agents", "commit": "3f2a9c1e…" },
129
+ "commit": "3f2a9c1e…", "digest": "sha256-…", "materializedAt": "2026-09-24T10:12:44.118Z"
130
+ },
131
+ "oats.okf": {
132
+ "from": { "kind": "package", "package": "oats.okf", "version": "2.1.3", "commit": "b2e16f2e…", "integrity": "sha256-…", "repoKey": "github.com/awebai/oats-okf" },
133
+ "commit": "b2e16f2e…", "digest": "sha256-…", "materializedAt": "2026-09-24T10:12:44.201Z"
134
+ }
135
+ },
136
+ "providers": {
137
+ "oats.okf": { "owns": "release-manager", "reads": ["platform-engineer"], "state-dir": "/Users/ana/.oats/okf" },
138
+ "acme-release-tooling": {}
139
+ },
140
+ "workspace": {
141
+ "key": "github.com/acme/agents", "commit": "3f2a9c1e…", "resolution": "20ec8ec527311d71d0973086",
142
+ "soul": { "repoKey": "github.com/acme/agents", "commit": "3f2a9c1e…", "team": "engineering" }
143
+ }
144
+ }
145
+ ```
118
146
 
119
- The kernel does not define memory files. With `oats.okf` selected under
120
- `capabilities.layers.knowledge`, v2 creates `STATE.md`, `log.md`, `notes/` and an
121
- immutable external-knowledge snapshot. `knowledge: none` creates none of these;
122
- it does not erase pre-existing memory.
147
+ - `modules.<cap>` — where the copy came from, at which commit, and its content
148
+ digest. `oats status` compares these with the workspace's current state and
149
+ shows `moved` / `missing` per module (drift is shown, not prevented).
150
+ - `providers.<cap>` — the merged provider payload the capability was bound with
151
+ (soul ⊕ machine settings ⊕ `--provider`), so a later inspection can tell
152
+ which instance holds a retained seat or a one-off state root.
153
+ - `workspace` — the workspace commit observed at spawn, the soul's repo/commit/
154
+ team, and the **resolution revision** the spawn decision bound.
155
+
156
+ A running instance never changes under itself: a member moving or a package
157
+ bump affects only new spawns.
158
+
159
+ ### The harness starts normally
160
+
161
+ OATS is a skill contributor, not a skill sandbox. The harness (pi, Claude Code,
162
+ Codex) starts with cwd = the instance home and its **own** skill discovery
163
+ intact: it sees, nearest first, the instance's `.agents/skills/` (soul skills
164
+ and the copied capability skills), the repo's own `.agents/skills/` once it
165
+ works in `work/`, and whatever the operator keeps at machine level. All three
166
+ are intended. Two *composed* skills with one name is a spawn error naming both
167
+ capabilities (`E_SKILL_DUPLICATE`); a composed skill versus an ambient one is
168
+ the harness's own precedence. The `CLAUDE.md → AGENTS.md` and
169
+ `.claude/skills → ../.agents/skills` aliases are kept. OATS composes
170
+ instructions and pins model/provider settings; it excludes nothing.
123
171
 
124
172
  ## Lifecycle
125
173
 
126
174
  ### Spawn
127
175
 
128
- The kernel creates the home, links the soul for reference, resolves capability
129
- targets, generates instance instructions, materializes the exact local skill
130
- set, prepares `work/`, runs active capability hooks, writes `TASK.md`, and
131
- launches a full coding agent session in tmux. The committed soul is unchanged.
132
- This is not a Claude Code subagent call; it is a normal agent process with its
133
- own home and tools.
176
+ ```bash
177
+ oats spawn release-manager --purpose cut-3.2 --task "…" # a soul of a confirmed member
178
+ oats spawn release-manager --preview --json # decide everything, create nothing
179
+ oats spawn release-manager --provider oats.aweb identity.source=retained:release-seat # instance-level payload
180
+ ```
181
+
182
+ From a deployment (where `oats-local.yaml` is), a spawn: reads the local file →
183
+ discovers the workspace over its remotes and confirms membership → finds the
184
+ soul among the confirmed members (or `external:`; an ambiguous bare name is
185
+ `E_SOUL_AMBIGUOUS` — say `<repo>/<soul>`) → fetches the soul's source into
186
+ `<agents-root>/<soul>/soul/` at its commit → resolves every capability by
187
+ `from:` (member = latest, package = locked + approved) → creates the home →
188
+ **materializes each module whole** into `.oats/modules/` and copies its skills
189
+ into `.agents/skills/` (a transaction: any failure leaves nothing behind) →
190
+ composes `AGENTS.md` → records `modules`/`providers`/`workspace` in
191
+ `instance.json` → prepares `work/` → runs the modules' spawn hooks (from their
192
+ copies) → writes `TASK.md` → launches the harness in tmux. The committed soul is
193
+ unchanged. This is a normal agent process with its own home and tools, not a
194
+ subagent call.
195
+
196
+ `--preview` reports `modules[]` (`from`, `layer`, `changedSince` the newest
197
+ previous instance of the soul), `team`, the `resolution` revision and the
198
+ decision it would bind; the apply refuses with `E_DECISION_STALE` if a member
199
+ moved in between. `--provider <cap> key=value` (repeatable; dotted keys nest)
200
+ must name a capability the soul resolves (`E_CAPABILITY_MISSING` otherwise) and
201
+ needs a workspace deployment. The full DTOs are in
202
+ [desktop-cli-api.md](desktop-cli-api.md#workspace-model-workspaceapi-2).
134
203
 
135
204
  Examples of spawn hooks:
136
205
 
@@ -138,12 +207,14 @@ Examples of spawn hooks:
138
207
  accepted bases, creates episodic files and an immutable reader view, and
139
208
  registers a durable source plus its per-source schedule definition. Missing
140
209
  knowledge is an error, not permission to bootstrap an empty substitute.
141
- - `oats-aweb` mints a messaging identity.
210
+ - `oats.aweb` mints a messaging identity — or, with
211
+ `--provider oats.aweb identity.source=retained:<seat>`, re-takes a retained
212
+ one for exactly this instance.
142
213
 
143
214
  ### Work
144
215
 
145
- The instance works in `./work`. With oats-okf it also keeps `STATE.md` current,
146
- appends milestones to `log.md`, and captures non-obvious insights in
216
+ The instance works in `./work`. With `oats.okf` it also keeps `STATE.md`
217
+ current, appends milestones to `log.md`, and captures non-obvious insights in
147
218
  `notes/`.
148
219
 
149
220
  It reads accepted external knowledge through `./knowledge/view.json` and
@@ -154,18 +225,13 @@ knowledge until their merge is visible; pending directory publication blocks
154
225
  fresh reads rather than exposing partial bytes.
155
226
 
156
227
  An independent worker judges durable **notes and full record windows**, not only
157
- notes or a watermark left in the live home. V2 working-agent instructions do not
158
- require after-commit harvesting. Each source has a command job rooted in durable
159
- deployment context; the operator may also request `oats okf harvest`. Timer
160
- installation is explicit, and no-launch sources cannot schedule model launches.
161
-
228
+ notes or a watermark left in the live home. Each source has a command job rooted
229
+ in durable deployment context; the operator may also request `oats okf harvest`.
162
230
  Workers use their own `work: directory`, never the source branch or an attached
163
231
  worktree. Validated Git output goes through real PR delivery; non-Git output
164
- uses recoverable directory publication. Workers leave live notes and soul skills
165
- untouched. Captured, processed, delivered and accepted are distinct receipts;
166
- spawning a worker is not successful learning. See [knowledge](knowledge.md) for
167
- inspection, completion and recovery, and [migration](knowledge-migration.md) for
168
- preserving v1 bundles and source cursors before owner/source cutover.
232
+ uses recoverable directory publication. Captured, processed, delivered and
233
+ accepted are distinct receipts; spawning a worker is not successful learning.
234
+ See [knowledge](knowledge.md).
169
235
 
170
236
  ### Spawning and coordinating with other agents
171
237
 
@@ -303,10 +369,9 @@ an attached instance never removes the shared tree. The packaged
303
369
 
304
370
  `work/` is a new instance-owned directory, not a Git repo or a link to a source.
305
371
  Use it explicitly for capability workers that need private execution space
306
- without Git. `repo` (or `--repo`) supplies configuration context only and may be
307
- an ordinary directory; without it, the deployment scope is used. An
308
- `oats-config.yaml` below laptop scope supports package-only deployments before
309
- any local souls exist. No implicit fallback changes the other modes.
372
+ without Git. `repo` (or `--repo`) supplies context only and may be an ordinary
373
+ directory; without it, the deployment directory (where `oats-local.yaml` is) is
374
+ used. No implicit fallback changes the other modes.
310
375
 
311
376
  `--work-dir` and `--branch` are rejected. Canonical instructions, skill
312
377
  composition, provider trust and runtime preflight still apply. No worktree setup
@@ -317,8 +382,8 @@ exchanged for a symlink. Recovery does not replace the worker's delivery protoco
317
382
 
318
383
  ### `workspace` — cross-repo coordinator
319
384
 
320
- `work/` is a symlink to the **whole workspace** (the team scope declared by
321
- `team:`, else the workspace-scope config directory) — not a repo. Every
385
+ `work/` is a symlink to the **whole deployment** (the `<name>-workspace/`
386
+ directory holding `oats-local.yaml` and the member clones) — not a repo. Every
322
387
  member repo is read-context; the instance's product is coordination:
323
388
  routing, analysis, task-writing, messaging, spawning specialists.
324
389
 
@@ -337,9 +402,11 @@ Rules:
337
402
  worker publishes external knowledge through PRs for every Git base,
338
403
  irrespective of the source's work mode or the soul's repository.
339
404
 
340
- Spawning workspace mode requires a declared boundary (a `team:` block or a
341
- workspace-scope config); the instance records no branch — the workspace is
342
- not a git tree.
405
+ Spawning workspace mode requires a deployment boundary for `./work`; the
406
+ instance records no branch — the workspace is not a git tree. *(Open thread:
407
+ the kernel still derives this boundary from the classic `team:` scope; binding
408
+ it to the `oats-local.yaml` directory is tracked in
409
+ [design/README.md](design/README.md).)*
343
410
 
344
411
  ## Agents root
345
412