@awebai/oats 0.22.0 → 0.22.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 (41) hide show
  1. package/README.md +30 -47
  2. package/bin/oats.mjs +11 -6
  3. package/capabilities/oats-authoring/LICENSE +21 -0
  4. package/capabilities/oats-authoring/oats-package.json +11 -0
  5. package/capabilities/oats-authoring/oats.json +4 -4
  6. package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +63 -0
  7. package/capabilities/oats-authoring/skills/skill-craft/SKILL.md +109 -0
  8. package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +109 -0
  9. package/capabilities/oats-aweb/oats.json +6 -6
  10. package/capabilities/oats-aweb/skills/LICENSE +21 -0
  11. package/capabilities/oats-aweb/skills/VENDORED.md +26 -0
  12. package/capabilities/oats-aweb/skills/aweb-identity/SKILL.md +201 -0
  13. package/capabilities/oats-aweb/skills/aweb-messaging/SKILL.md +161 -0
  14. package/capabilities/oats-aweb/skills/aweb-messaging/references/messaging-scenarios.md +61 -0
  15. package/capabilities/oats-aweb/skills/aweb-team-membership/SKILL.md +328 -0
  16. package/capabilities/oats-aweb/skills/aweb-team-membership/references/team-membership-reference.md +74 -0
  17. package/capabilities/oats-jira/oats.json +1 -1
  18. package/capabilities/oats-linear/oats.json +1 -1
  19. package/capabilities/oats-okf/agents/memory-harvest/soul.yaml +6 -0
  20. package/capabilities/oats-okf/bin/oats-okf.mjs +82 -51
  21. package/capabilities/oats-okf/oats.json +4 -1
  22. package/capabilities/oats-review/oats.json +1 -1
  23. package/docs/2026-09-03-architecture-proposal.md +642 -0
  24. package/docs/first-team-demo.md +87 -0
  25. package/docs/first-team.md +179 -0
  26. package/docs/integrations.md +83 -65
  27. package/docs/layers.md +356 -80
  28. package/docs/migration-from-oas.md +80 -116
  29. package/docs/release-notes/v0.22.1.md +106 -0
  30. package/lib/core.mjs +255 -363
  31. package/package.json +1 -1
  32. package/packages/record/README.md +76 -16
  33. package/packages/record/docs/turn-record-sot.md +1 -1
  34. package/packages/record/lib/store.mjs +207 -43
  35. package/capabilities/oats-aweb/package.json +0 -20
  36. package/capabilities/oats-jira/package.json +0 -25
  37. package/capabilities/oats-linear/README.md +0 -234
  38. package/capabilities/oats-linear/package.json +0 -29
  39. package/capabilities/oats-linear/test/oats-linear.test.mjs +0 -168
  40. package/capabilities/oats-okf/package.json +0 -22
  41. /package/capabilities/oats-okf/agents/{memory-harvest.md → memory-harvest/AGENTS.md} +0 -0
package/docs/layers.md CHANGED
@@ -1,110 +1,386 @@
1
- # The five layers of agent specialization
1
+ # The OATS contracts
2
2
 
3
- A capable model in a fresh session is not a specialist. A specialist has
4
- identity, habits, memory, teammates, and work to track. OATS names those needs
5
- as five layers.
3
+ Status: contracts on paper (migration step 2 of
4
+ [the 2026-09-03 architecture proposal](2026-09-03-architecture-proposal.md)).
5
+ Every section says what is **shipped** today and what is **proposed**. A
6
+ proposed clause describes the contract the kernel will be refactored toward;
7
+ it is not a claim about current behavior, and the shipped documents
8
+ ([souls and instances](souls-and-instances.md),
9
+ [capabilities](capabilities.md), [implementation](implementation.md)) remain
10
+ authoritative for what the code does now.
6
11
 
7
- Two layers are the OATS pattern itself: **soul** and **instances**. The kernel
8
- implements them directly. The other three are formally defined, exclusive
9
- contracts: **knowledge**, **messaging**, and **tasks**. An integration is the
10
- capability package selected to bind one contract to a real tool; general
11
- capability packages remain additive.
12
+ The rule the contracts serve:
12
13
 
13
- ## The layers at a glance
14
+ > Every main component is replaceable by another that offers the same
15
+ > contract, with the exception of OATS itself. OATS knows only contracts.
14
16
 
15
- | Layer | Question it answers | Owner |
16
- |---|---|---|
17
- | **Soul** | Who is this agent, and how does it grow? | Kernel |
18
- | **Knowledge** | Where does learning live, and how is it promoted? | Integration |
19
- | **Instances** | How does a soul run work in the world? | Kernel |
20
- | **Messaging** | How can this instance be reached by the team? | Integration |
21
- | **Tasks** | Where does shared work state live? | Integration |
17
+ A contract is finished when two implementations satisfy it and a soul runs
18
+ unchanged behind each. Each section ends with that test.
22
19
 
23
- ## 1. Soul durable expert identity
20
+ ## How the pieces fit
24
21
 
25
- A soul is what an agent *is* when no session is running. It contains the
26
- agent's operating doc (`AGENTS.md`), its own skills, and any long-term
27
- knowledge its knowledge layer provides.
22
+ ```text
23
+ soul ─────────── declares which contracts it needs, never which implementation
24
+
25
+ ├── soul type ── the policy unit: capabilities, knowledge scope, reach
26
+
27
+ └── capabilities ── implementations bound by configuration
28
+ ├── knowledge (exclusive slot)
29
+ ├── tasks (exclusive slot)
30
+ ├── communication (exclusive slot; called "messaging" in config today)
31
+ ├── capture (proposed slot)
32
+ └── additive capabilities (any number)
28
33
 
29
- A soul is committed and reviewed like code. It has no terminal, no network
30
- identity, and no current task. It is the expert template that compounds over
31
- many incarnations.
34
+ instance = (soul, runtime provider, work target?, task)
35
+ ```
32
36
 
33
- The kernel owns this layer. The shape of a soul is the pattern itself:
34
- `soul.yaml`, canonical files, symlinks, and directory layout. Deployment
35
- capabilities compose into instances and never redefine or mutate the soul.
37
+ The kernel owns the soul format, the soul type, the capability manifest and
38
+ lifecycle events, and instantiation. Everything else is an implementation
39
+ behind one of the contracts below.
36
40
 
37
- ## 2. Knowledge — learning that survives sessions
41
+ ## Soul format
38
42
 
39
- Specialization requires memory. The knowledge layer decides where memory
40
- lives, what kinds exist, and how learning moves from an instance into the
41
- soul.
43
+ **Shipped.** A soul is a directory: `soul.yaml` (name, kind, description,
44
+ repo, work, runtime, model, type), `AGENTS.md` (the operating definition),
45
+ `skills/`, and whatever a knowledge implementation adds. It is committed and
46
+ reviewed like code, and it never runs by itself.
42
47
 
43
- The kernel is memory-agnostic. It only provides lifecycle events such as
44
- `soul-scaffold`, `spawn`, and `retire`. A knowledge integration
45
- uses those events to create memory files, teach the protocol, and run
46
- promotion.
48
+ **Contract.** A soul declares *which contracts it needs*, not which
49
+ implementation fills them. Its `AGENTS.md` speaks of "your knowledge", "your
50
+ task layer", "your messaging"; the bound capability's injected block says
51
+ what those are in this installation. A soul that names a tracker, a mail
52
+ system, or a knowledge format in its own text is not portable and is
53
+ malformed under this contract.
47
54
 
48
- The default `oats-okf` integration creates an OKF bundle in the soul and
49
- `STATE.md`, `log.md`, and `notes/` in instances. Instances capture what they
50
- learn, and after committing with pending notes run `oats okf harvest`, which
51
- spawns a memory-harvest agent that judges notes and promotes
52
- what belongs in the soul.
55
+ A soul is runtime-neutral as an artifact. Anything derived from it for one
56
+ runtime (a compiled native session, a finetune reference) is a realization
57
+ artifact attached to the (soul, runtime) pair, never soul content.
53
58
 
54
- If config resolves `knowledge: none`, none of this exists. The agent works
55
- with whatever memory its harness or repo already provides.
59
+ **Test.** One packaged soul runs in an installation bound to Jira and in one
60
+ bound to Linear with no change to its files.
56
61
 
57
- See [Knowledge](knowledge.md).
62
+ ## Soul type
58
63
 
59
- ## 3. Instances the soul doing work
64
+ **Shipped.** Config declares agent types by name under `agent-types:`; a soul
65
+ opts in with `type: <name>` in `soul.yaml`; capability entries target
66
+ `global`, `agent-types`, or `souls`, and settings resolve soul over type over
67
+ global, then by config closeness.
60
68
 
61
- An instance is one running incarnation of a soul. It has a home directory, a
62
- work tree, a task briefing, metadata, and possibly episodic memory.
69
+ **Contract.** The soul type is the policy unit. It decides:
63
70
 
64
- Instances are disposable by design. Sessions crash, context windows fill, and
65
- models change. The soul survives. With a knowledge integration, what matters
66
- feeds back into the soul as the instance works.
71
+ - which capabilities a soul of that type receives, and with which settings;
72
+ - what knowledge it may read (custody scope) and whether it may write
73
+ knowledge (a harvester is a type permitted to write);
74
+ - its communication **reach**, in both directions.
67
75
 
68
- The kernel owns this layer: spawn, exact skill/instruction composition,
69
- retire, work modes, tmux windows, metadata, and lifecycle hook points.
70
- (There is no resume command; a retired instance is gone — its session
71
- transcript survives in the turn record if capture is running.)
76
+ `reach` is one field with a monotone ladder, each level including the ones
77
+ below:
72
78
 
73
- See [Souls and instances](souls-and-instances.md).
79
+ ```text
80
+ reach: owner # only agents owned by the same human
81
+ reach: team # any agent in the deployment's team
82
+ reach: org # any team in the same organization
83
+ reach: external # agents outside the organization
84
+ ```
74
85
 
75
- ## 4. Messaging reachable team identities
86
+ "No communication" is not a level; it is the communication slot set to
87
+ `none`. `reach` governs whom an instance may address and who may address it;
88
+ the communication implementation enforces both sides.
76
89
 
77
- Team agents need to reach humans and each other. The messaging layer maps an
78
- instance name to a communication identity, then cleans that identity up when
79
- the instance retires.
90
+ **Proposed.** The type is exported to hooks and dispatched commands as
91
+ `OATS_SOUL_TYPE`; packages may ship types; a type may declare `reach`.
80
92
 
81
- The default integration is `oats-aweb`. It gives each instance an aweb identity
82
- and teaches agents to use `aw mail` and `aw chat`.
93
+ **Test.** Two souls of different types, spawned in one installation, receive
94
+ different capability sets and different knowledge scopes with no per-soul
95
+ configuration.
83
96
 
84
- Messaging is deliberately narrow. It is about communication only. Task
85
- coordination belongs to layer 5.
97
+ ## Capability manifest and lifecycle events
86
98
 
87
- ## 5. Tasks shared work state
99
+ **Shipped.** A capability is a set of scripts, skills, and docs with an
100
+ `oats.json` manifest declaring: `capability` (id), optional `layer`,
101
+ `skills`, `inject`, `commands`, `requires` (host commands and runtime
102
+ packages), `environment` (launch variables it may contribute, vendor-prefixed),
103
+ and `hooks`. Accepted events are `soul-scaffold`, `spawn`, and `retire`. Hooks
104
+ receive `OATS_EVENT`, `OATS_CAPABILITY`, `OATS_LAYER`, `OATS_INSTANCE`,
105
+ `OATS_HOME` (with `OATS_INSTANCE_HOME` as its alias), `OATS_AGENT`,
106
+ `OATS_SOUL`, `OATS_CONTEXT`, `OATS_WORKSPACE`, `OATS_ROOT`, `OATS_LEVEL`,
107
+ `OATS_SETTINGS`, `OATS_META`, and the team variables, and may return `meta`, `brief`, `warning`, runtime-specific
108
+ `launch` arguments, and (spawn only) `env`. Only a spawn hook may be
109
+ `required`. The full contract, including trust and rollback, is in
110
+ [capabilities](capabilities.md) and is not restated here.
88
111
 
89
- Work needs a queue and status that outlive any one instance: planned, in
90
- flight, blocked, done. OATS does not choose the tracker. It only requires that
91
- agents know where the shared work state lives and how to use it.
112
+ **Contract.** The event list is the API that makes capabilities composable
113
+ and changes rarely. An implementation of any slot below is a capability that
114
+ declares that slot as its `layer`; two active capabilities cannot fill one
115
+ slot for one soul. Packages talk to the kernel only through the structured
116
+ CLI boundary (`oats ... --json`, `OATS_CLI_BIN`), never by importing kernel
117
+ files; see [package-runtime-api](design/package-runtime-api.md).
92
118
 
93
- There is no shipped default task integration. One deployment can bind Jira,
94
- another Linear, another GitHub Issues. The LFX-style Jira integration is just
95
- skills plus an injection that points agents at those skills.
119
+ **Proposed.** A fourth event, `harvest`, run by `oats harvest` for every
120
+ active capability that declares it, with the same environment as `spawn`
121
+ plus the instance whose ephemeral state is to be promoted. The knowledge
122
+ implementation's harvest hook is how promotion is triggered without the
123
+ kernel knowing the knowledge format.
96
124
 
97
- ## Why the split matters
125
+ **Test.** Two capabilities filling the same slot in two installations; the
126
+ kernel's code has no branch that names either.
98
127
 
99
- Souls and instances are the stable core. Moving them out would leave nothing
100
- to specialize.
128
+ ## The knowledge contract
101
129
 
102
- Knowledge, messaging, and tasks vary by team. They should be easy to swap.
103
- One workspace can run OKF + aweb + Jira. Another can run a team wiki + Slack
104
- + Linear. A repo can disable messaging with `messaging: none`. The soul stays
105
- the same kind of object. Only its layer bindings change.
130
+ **Shipped.** The `knowledge` slot. The bundled implementation is `oats.okf`:
131
+ an OKF bundle under `soul/knowledge/`, per-instance `STATE.md`, `log.md`, and
132
+ `notes/`, the `okf` and `memory-harvest` skills, and `oats okf harvest`, which
133
+ spawns the capability-defined `memory-harvest` soul attached to the source
134
+ instance's work tree. `knowledge: none` is valid and yields no memory files
135
+ and no harvest.
106
136
 
107
- Layer exclusivity prevents two task systems or knowledge protocols from
108
- competing inside one soul context. Capability targeting still allows another
109
- soul to select a different provider. See [Integrations](integrations.md) and
110
- [Capability packages](capabilities.md).
137
+ **Contract.** Two sides.
138
+
139
+ *Read.* An instance can find and consult organizational knowledge,
140
+ index-first and selectively, and is told how by the implementation's injected
141
+ block and skill. Prior decisions, lessons, and playbooks in scope are binding
142
+ context; re-deriving what the soul already knows is a bug. **Proposed:** the
143
+ scope of what an instance may read is decided by its soul type, which needs
144
+ `OATS_SOUL_TYPE` (step 7) before an implementation can act on it.
145
+
146
+ *Write.* A permitted soul (a harvester type) can promote into the store. The
147
+ format is the implementation's. Delivery matches the soul's custody: a commit
148
+ on the instance's branch for repository-resident souls, a pull request to
149
+ the soul's home repository for workspace-mode souls, direct edits for local
150
+ souls.
151
+
152
+ *Custody, shipped.* Delivery custody is keyed by where the soul resides: a
153
+ commit on the instance's branch for repository-resident souls, a pull request
154
+ to the soul's home repository for workspace-mode souls, direct edits for local
155
+ souls. That is the only custody the kernel and `oats.okf` implement today.
156
+
157
+ *Custody scoping, proposed.* The requirement is that repository-specific
158
+ facts never move into a broader scope by default and that a cross-repository
159
+ soul never reads another repository's specifics. The design that meets it
160
+ belongs to the knowledge package, not the kernel. Custody layers (soul-shared,
161
+ workspace overlay, repository overlay) are one candidate; scoping by soul
162
+ type plus residency is another. Nothing here is settled or shipped.
163
+
164
+ *Promotion doctrine.* What the write side accepts is a decision, not a
165
+ format question. The line is decision versus description. Descriptions of
166
+ how the code fits together go stale and compete with the code; the write
167
+ side rejects them. Decisions, what was chosen, what was rejected, and why,
168
+ cannot be derived from code and are accepted, as are inspiration genealogy
169
+ ("took this from X, rejected Y because Z"), process lessons, and maintained,
170
+ timestamped, superseded-on-change slow state about an area. Slow state is
171
+ accepted only with its maintenance discipline: a named owner and an
172
+ update-on-change rule; a slow-state concept nobody maintains is
173
+ indistinguishable from residue and is rejected as such. Task residue
174
+ (pull-request numbers, half-done plans, point-in-time environment facts) dies
175
+ with the instance. One home per decision; split-brain comes from copies. The
176
+ homing rule: architecture facts that several roles need go in repository-
177
+ visible docs and souls point to them; craft decisions scoped to one role go
178
+ in that role's soul; product direction goes in the steward's bundle,
179
+ consulted and never copied. For non-coding specialists none of their
180
+ knowledge is re-derivable from a repository, so those souls are almost pure
181
+ knowledge. See [knowledge theory](knowledge-theory.md) for the derivation.
182
+
183
+ **Proposed.** The harvester's input widens from the agent's own notes to the
184
+ capture contract (below), so lessons reach the soul even when an agent wrote
185
+ no notes; the promotion doctrine is unchanged, only the input channel widens.
186
+
187
+ **Test.** A plain-Markdown or wiki-backed implementation beside `oats.okf`,
188
+ each with its own harvester; a soul's `AGENTS.md` unchanged between them.
189
+
190
+ ## The tasks contract
191
+
192
+ **Shipped.** The `tasks` slot. Bundled implementations are `oats.jira`
193
+ (the `jira-tasks` protocol via `acli`) and `oats.linear` (JSON-first
194
+ `oats linear` commands and the `linear-tasks` skill). There is no default;
195
+ `tasks: none` is valid.
196
+
197
+ **Contract.** Where shared work state lives and how an instance claims,
198
+ updates, blocks, hands off, and completes work, taught by the implementation's
199
+ injected block and skill. An instance is identified to the tracker in a way
200
+ that survives the instance (today a label, `agent-<instance-name>`). Task
201
+ state, status, and outcomes live in the tracker; conversation lives in the
202
+ communication slot; the two are not merged even when one tool offers both.
203
+
204
+ Verdicts and review outcomes are task records. That is how verification
205
+ enters the model without a component: a reviewer is a soul type, and what it
206
+ concludes is written where work state lives.
207
+
208
+ **Test.** Jira and Linear already satisfy it; a third (beads, GitHub Issues)
209
+ is the proof that the contract is not a description of either.
210
+
211
+ ## The communication contract
212
+
213
+ **Shipped.** The `messaging` slot. The bundled implementation is `oats.aweb`:
214
+ a team-scoped aweb identity minted per instance at spawn (alias = instance
215
+ name) by a required spawn hook and deleted at retire, the `aweb-messaging`,
216
+ `aweb-team-membership`, and `aweb-identity` skills, `oats aweb roster` and
217
+ `oats aweb setup`, and channel-plugin launch arguments so a session is woken
218
+ by incoming mail. `messaging: none` is valid.
219
+
220
+ **Contract.** How an instance becomes reachable and reaches others. The
221
+ implementation supplies:
222
+
223
+ - an address for the instance, discoverable by teammates, and the roster
224
+ that lists them across machines;
225
+ - durable asynchronous mail and synchronous chat, with reply and
226
+ acknowledgement state;
227
+ - a wake-up signal when work arrives, with the decision to resume or launch
228
+ left to the runtime owner;
229
+ - enforcement of the soul type's `reach`, outbound by what the address can
230
+ reach and inbound by who may deliver to it;
231
+ - a statement of whether the address can outlive the instance. For a durable
232
+ specialist the answer should be yes, realized however the implementation
233
+ chooses (for aweb: a soul-level identity served through per-instance
234
+ grants).
235
+
236
+ Communication is only communication. Task coordination lives in the tasks
237
+ slot.
238
+
239
+ *Fully local.* It must remain possible to run everything filesystem-based and
240
+ fully local, meaning with no dependency on a hosted service the operator
241
+ cannot replace. Communication needs a server; a self-hosted one on localhost
242
+ satisfies the constraint. What the implementation must hold on *its*
243
+ servers, and the traffic that must pass through them, is minimized. For aweb
244
+ today every delivery passes through an aweb server, hosted or self-hosted on
245
+ localhost with the reserved `local` namespace (`aweb-abhw` records the open
246
+ decision on a lighter local server). `reach: owner` maps to a contacts-only
247
+ inbound mode that aweb does not ship yet (`aweb-abhx`).
248
+
249
+ **Proposed.** The slot is renamed from `messaging` to `communication` in
250
+ documentation first; the config key stays `messaging` until a release
251
+ decides otherwise.
252
+
253
+ **Test.** aweb and a second implementation (a Slack bridge, an A2A gateway)
254
+ behind the same injected promises; a soul's `AGENTS.md` unchanged between
255
+ them.
256
+
257
+ ## The capture contract (proposed)
258
+
259
+ **Shipped, outside the slot model.** On machines where `oats setup` has run,
260
+ `packages/record` captures Claude Code, Pi, and Codex transcripts plus aw
261
+ client logs. It skips sources matched by the local record's ignore list. It
262
+ stores captured turns in an append-only, content-addressed record with a search
263
+ index (`oats setup`, `oats capture`, `oats recall`). It is not a capability and
264
+ no lifecycle hook knows about it.
265
+
266
+ **Contract.** The format of ephemeral state. Two kinds satisfy it: an agent's
267
+ own notes (its report of what mattered, today created by the knowledge
268
+ implementation) and a captured session (ground truth). The harvester may
269
+ consume either or both. Clothes, the optional spawn-time selection of past
270
+ conversation, are one consumer of the same contract and depend on nothing
271
+ else in this document. Capture never mediates the harness and fails visibly;
272
+ a silent capture gap is worse than none.
273
+
274
+ **Proposed.** `capture` becomes a slot; `packages/record` is wrapped as a
275
+ bundled, framework-trusted capability whose spawn hook records the
276
+ instance-to-session mapping; `oats setup`, `oats capture`, and `oats recall`
277
+ become kernel aliases resolving to the active capture implementation.
278
+ Whether capture is exclusive or additive is open.
279
+
280
+ **Test.** The record beside a notes-only implementation; the harvester reads
281
+ both.
282
+
283
+ ## The runtime provider contract (proposed)
284
+
285
+ **Shipped.** Two runtimes, `pi` and `claude`, selected by `soul.yaml` or
286
+ `--runtime`, launched in a local tmux window; the branching lives inside
287
+ `spawnInstance`. The worked example in the
288
+ [proposal](2026-09-03-architecture-proposal.md#worked-example-todays-pi-launch-as-bundle-and-handle)
289
+ names today's launch in the contract's terms.
290
+
291
+ **Contract.** OATS hands a provider a realization bundle and receives an
292
+ instance handle:
293
+
294
+ ```text
295
+ bundle
296
+ instructions the composed AGENTS.md
297
+ skills the exact materialized tree
298
+ environment, launch args what active capabilities contributed
299
+ task TASK.md
300
+ model preference resolved
301
+ realization artifacts per (soul, runtime); empty by default
302
+
303
+ handle
304
+ observe is it running; where the session transcript is
305
+ steer attach or send input, where supported
306
+ stop
307
+ ```
308
+
309
+ The provider decides how the bundle becomes a running agent. It knows
310
+ nothing of tmux; the **platform** (today tmux: session, window, working
311
+ directory) is a separate module with launch, alive, stop, and list. The
312
+ handle is recorded in `instance.json` with a kind; the existing `tmux` field
313
+ is kept beside it.
314
+
315
+ A provider declares which runtime packages the active capabilities require
316
+ of it and verifies them before launch; it never installs them. A provider
317
+ without a filesystem receives the bundle as a document rather than files;
318
+ how is open.
319
+
320
+ **Test.** Pi and Claude Code behind one interface with `spawnInstance` free of
321
+ runtime names, proven by the golden fixtures (step 1). A hosted provider is
322
+ the second real implementation and is not built until one asks.
323
+
324
+ ## The soul store contract (proposed)
325
+
326
+ **Shipped.** Souls live under `agents/` (committed) or `local-agents/`
327
+ (never committed) at a scope, and capability packages may ship souls under
328
+ `agents:` in their manifest. Three lookups find them; instance homes live in
329
+ the soul-owning repository's primary checkout.
330
+
331
+ **Contract.** A store lists souls, finds one by name, and says where its
332
+ instances live. The filesystem is the single implementation; a package and a
333
+ provider registry are the candidates that would prove the contract.
334
+ Separating the store from the work target is what removes the repository
335
+ from the architecture: today one path decides who the soul is, where its
336
+ knowledge lives, and what it works on.
337
+
338
+ **Test.** A soul found through a second store, instantiated with the same
339
+ bundle.
340
+
341
+ ## The work target contract
342
+
343
+ **Shipped.** Four modes decide what `<instance-home>/work` is and what
344
+ discipline the instance follows: `worktree` (an isolated branch), `checkout`
345
+ (the shared current branch), `attached` (another instance's tree), and
346
+ `workspace` (the whole team scope, read-only). A config may run a setup
347
+ script inside each fresh worktree. Retirement preserves ordinary work,
348
+ quarantines incomplete cleanup, and never removes a shared tree. The
349
+ generated instructions state the home/work boundary before the mode block.
350
+
351
+ **Contract.** The work target is a parameter of instantiation independent of
352
+ where the soul is stored. Each mode is a module that prepares the view,
353
+ states its discipline, and knows how to retire it safely, with the
354
+ retirement baseline and inspection alongside. The four modes stay exactly as
355
+ they are.
356
+
357
+ **Proposed.** A fifth target, `none`, for instances that operate on nothing
358
+ (a mail-only agent). It replaces no mode.
359
+
360
+ **Test.** An instance of one soul spawned with each target, the same soul
361
+ files throughout.
362
+
363
+ ## The package contract
364
+
365
+ **Shipped, and not touched by the migration.** Acquisition, exact version and
366
+ commit, payload and artifact integrity, dependency closure, executable trust,
367
+ and transactional restore; see [packages](packages.md),
368
+ [capabilities](capabilities.md), and the
369
+ [package-engine contract](design/package-engine-contract.md).
370
+
371
+ **Proposed.** A package may also ship soul types.
372
+
373
+ ## The replaceability test, summarized
374
+
375
+ | Contract | Implementations today | Second implementation |
376
+ | --- | --- | --- |
377
+ | Knowledge | `oats.okf` | plain Markdown or wiki |
378
+ | Tasks | `oats.jira`, `oats.linear` | beads, GitHub Issues |
379
+ | Communication | `oats.aweb` | Slack bridge, A2A gateway |
380
+ | Capture | `packages/record`, OKF notes | either alone |
381
+ | Runtime provider | Pi, Claude Code (entangled) | a hosted provider |
382
+ | Soul store | filesystem | package, provider registry |
383
+ | Work target | worktree, checkout, attached, workspace | `none` |
384
+
385
+ Where only one implementation exists, the contract is still a description of
386
+ that one; those rows are the work.