@awebai/oats 0.24.0 → 0.24.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.
- package/README.md +224 -394
- package/bin/oats.mjs +29 -1
- package/capabilities/oats-okf/lib/captured-worker.mjs +12 -4
- package/capabilities/oats-okf/oats.json +1 -1
- package/docs/capabilities.md +4 -0
- package/docs/design/2026-09-20-redesign-program-board.md +70 -0
- package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +287 -0
- package/docs/design/2026-09-20-workspace-onboarding-public.md +124 -0
- package/docs/design/README.md +42 -0
- package/docs/first-team.md +1 -1
- package/docs/knowledge-theory.md +353 -111
- package/docs/knowledge.md +10 -1
- package/docs/layers.md +89 -354
- package/docs/official-marketplace.md +79 -0
- package/docs/packages.md +4 -0
- package/docs/release-notes/v0.24.1.md +17 -0
- package/docs/souls-and-instances.md +20 -7
- package/docs/workspace-adoption.md +285 -0
- package/docs/workspaces.md +154 -0
- package/injects/oats-portable.md +4 -5
- package/lib/core.mjs +43 -4
- package/lib/portable-onboarding.mjs +19 -0
- package/lib/prepared-resources.mjs +1 -1
- package/package-catalog.json +2 -1
- package/package.json +1 -1
- package/skills/oats-config/SKILL.md +4 -5
- package/skills/oats-portable/SKILL.md +1 -2
- package/skills/oats-portable-artifacts/SKILL.md +2 -2
- package/skills/oats-portable-setup/SKILL.md +0 -69
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# Adopt the OATS development workspace
|
|
2
|
+
|
|
3
|
+
OATS hosts the shared `oats-workspace.yaml`. Its separate `oats.yaml` advertises
|
|
4
|
+
source-complete exports and declares its own reciprocal membership. `oats-dev`
|
|
5
|
+
remains a development-capability repository, including `oats.review`; membership
|
|
6
|
+
neither activates that package nor replaces its existing configuration templates.
|
|
7
|
+
|
|
8
|
+
This is phase 1: a shared repository graph and a transitional portable edition of
|
|
9
|
+
**the existing oats-expert**. It is not the five-role rebuild, the curated knowledge
|
|
10
|
+
cutover, a shared live runtime, a private-team enrollment or Desktop feature parity.
|
|
11
|
+
The [phase plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) and
|
|
12
|
+
[knowledge model](knowledge-theory.md) retain those separate boundaries.
|
|
13
|
+
|
|
14
|
+
## Shared versus local
|
|
15
|
+
|
|
16
|
+
| Git-shared declaration | Operator-local input or evidence |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Workspace membership candidates and reviewed source import pins | Local source access and qualified repository observations |
|
|
19
|
+
| A repository's backlink and real package/soul export paths | Working checkout mappings and the explicitly chosen work target |
|
|
20
|
+
| Intrinsic capability requirements and logical knowledge interests | Provider settings, explicit store binding, private human/team choices |
|
|
21
|
+
| Complete immutable instructions and skill resources | Native harness/model/auth, backend endpoint, home and durable state |
|
|
22
|
+
| A reviewed source revision | Exact executable approval, current readiness and deployment acceptance |
|
|
23
|
+
|
|
24
|
+
No machine paths, credentials, private team identifiers, accepted-store locator or
|
|
25
|
+
owner registry belongs in the public workspace. The uninitialized phase-2 knowledge
|
|
26
|
+
repository is not advertised as a ready knowledge export. Preserve the parked
|
|
27
|
+
roster/curation and every old home, lock, source, pending job, history and worktree.
|
|
28
|
+
|
|
29
|
+
## Planned onboarding: OATS Soul Setup (D3)
|
|
30
|
+
|
|
31
|
+
**Not shipped in OATS 0.24.** The planned onboarding flow creates and instantiates
|
|
32
|
+
`oats-setup-expert`, declaring both `oats.core` and `oats.setup` from the
|
|
33
|
+
[official marketplace](official-marketplace.md). Their package releases and this
|
|
34
|
+
onboarding flow are future work, not existing catalog entries or a new command
|
|
35
|
+
introduced by this guide.
|
|
36
|
+
|
|
37
|
+
- The setup expert will help the operator adopt repositories, select capabilities
|
|
38
|
+
and carry out the normal prepare/approve/scaffold/start steps. It bypasses no
|
|
39
|
+
executable approval, provider readiness, identity or permission boundary.
|
|
40
|
+
- Every soul created by that flow will declare `requires.capabilities.oats.core`
|
|
41
|
+
and its source explicitly. The operator can remove or replace that dependency
|
|
42
|
+
by editing the authored definition, not a captured record; the kernel will not
|
|
43
|
+
silently reinsert an absent one.
|
|
44
|
+
- The CLI/Desktop entry point remains separately implemented and reviewed. Do not
|
|
45
|
+
invent a workspace init/adopt command, create a setup soul from this sketch, or
|
|
46
|
+
treat a planned package as installed. Existing instances and retained resources
|
|
47
|
+
are not rewritten by the plan.
|
|
48
|
+
|
|
49
|
+
## What this first source commit establishes
|
|
50
|
+
|
|
51
|
+
- `oats-workspace.yaml` explicitly admits `oats` and the six intended capability
|
|
52
|
+
repositories: `oats-dev`, `oats-okf`, `oats-aweb`, `oats-authoring`, `oats-jira`
|
|
53
|
+
and `oats-linear`. It activates no additional capability; tasks default to none.
|
|
54
|
+
- `oats.yaml` advertises `souls/oats-expert` and the actual framework package roots
|
|
55
|
+
`oats-package` and `capabilities/oats-authoring`, not the npm root as a fictitious
|
|
56
|
+
OATS distribution. Its workspace backlink names the same framework repository.
|
|
57
|
+
- `souls/oats-expert/` is parallel to, not a replacement for, the live `agents/`
|
|
58
|
+
source. It contains canonical instructions, `CLAUDE.md -> AGENTS.md`, and the
|
|
59
|
+
existing reviewed PR/release procedure closure. No durable KB is copied into it.
|
|
60
|
+
- The role preserves its knowledge owner, owned node and four cross-read interests.
|
|
61
|
+
Store `oats` requires the explicit `stores.oats` binding; no publisher writer,
|
|
62
|
+
production store or grants are supplied. An acceptance fixture is parent-owned
|
|
63
|
+
and cannot be counted as production knowledge adoption.
|
|
64
|
+
- Knowledge **oats.okf@2.1.1** and messaging **oats.aweb@1.10.3** are explicit hard
|
|
65
|
+
requirements, not optional defaults. They are published starting revisions,
|
|
66
|
+
**not proof that their combined bindings/runtime profile is ready**. The provider
|
|
67
|
+
owner supplies that evidence and any subsequently reviewed compatible revision.
|
|
68
|
+
Do not replace either requirement with none or erase a read edge to launch.
|
|
69
|
+
|
|
70
|
+
At these starting pins, the provider boundary is concrete:
|
|
71
|
+
|
|
72
|
+
- Published OKF2.1.0 already supports `inherit: stores.oats`, normalized to
|
|
73
|
+
`/bindings/knowledge/stores/oats`. The explicit `destination: oats` preserves
|
|
74
|
+
routing; omitting it would instead require `write.default`. No new schema,
|
|
75
|
+
owner or production locator is needed for this declaration.
|
|
76
|
+
- Released aweb1.10.3 (`24efa6f9`) has **no mandatory portable binding interface**,
|
|
77
|
+
so it currently blocks this pilot's portable preparation. Candidate
|
|
78
|
+
[aweb PR2](https://github.com/awebai/oats-aweb/pull/2), `165b20e7`, adds codecs;
|
|
79
|
+
it is not a reviewed/published successor or native lifecycle qualification.
|
|
80
|
+
Human/native-principal, private-context, admin/grant and admitted-lifecycle
|
|
81
|
+
requirements remain provider/integration-owner work.
|
|
82
|
+
- Published OKF2.1.0's captured worker profile retains its strict Pi,
|
|
83
|
+
explicit-model and sole-OKF limitation. Candidate
|
|
84
|
+
[OKF PR4](https://github.com/awebai/oats-okf/pull/4), `7cff887c`, preserves retained
|
|
85
|
+
Claude/Codex/null-model intent and the approved helper capability closure;
|
|
86
|
+
review is pending, not published2.1.0 behavior. Pi plus messaging is still
|
|
87
|
+
unqualified. Do not silently switch runtimes, force a model, or drop capabilities.
|
|
88
|
+
|
|
89
|
+
These are explicit readiness holds, not reasons to weaken the source. Parent must
|
|
90
|
+
select reviewed compatible provider revisions and update the source pin deliberately
|
|
91
|
+
before claiming an operational pilot; metadata-only repository indexes change none
|
|
92
|
+
of these runtime facts.
|
|
93
|
+
|
|
94
|
+
The workspace intentionally starts with **`imports: []`**. A source cannot pin a
|
|
95
|
+
future commit containing itself. This first commit is publishable source metadata,
|
|
96
|
+
not an already usable/adopted pilot graph or a phase-1 exit verdict.
|
|
97
|
+
|
|
98
|
+
## Publish in this order
|
|
99
|
+
|
|
100
|
+
1. Review and publish this source/export commit to the framework repository. Save
|
|
101
|
+
the **actual reviewed immutable source commit** containing the complete soul.
|
|
102
|
+
Do not put an invented SHA, a mutable branch or an unreviewed local candidate
|
|
103
|
+
in the workspace import and describe it as the accepted source.
|
|
104
|
+
2. In each of the six repositories, review a root `oats.yaml` against its actual
|
|
105
|
+
source head and actual `oats-package/oats-package.json`. The declaration is:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
schemaVersion: 1
|
|
109
|
+
workspace:
|
|
110
|
+
source: git:github.com/awebai/oats
|
|
111
|
+
exports:
|
|
112
|
+
packages:
|
|
113
|
+
- path: oats-package
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Preserve payloads, versions, old tags and legacy templates. This does not
|
|
117
|
+
activate oats.dev, messaging or either optional task integration.
|
|
118
|
+
3. In a subsequent reviewed framework commit, replace the empty imports list with
|
|
119
|
+
an import of the source commit from step 1:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
imports:
|
|
123
|
+
- source: git:github.com/awebai/oats
|
|
124
|
+
soul: souls/oats-expert
|
|
125
|
+
revision: <actual-reviewed-published-source-commit>
|
|
126
|
+
alias: oats-expert
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The placeholder is explanatory text, never a value to commit. Update the
|
|
130
|
+
staged-import test with that real publication evidence at this step. Do not
|
|
131
|
+
change the stable export path or owner merely because the workspace advances.
|
|
132
|
+
4. Qualify reciprocal admission at the now-published observations. A missing
|
|
133
|
+
backlink, a fork's copied file or a stale workspace observation is not membership.
|
|
134
|
+
Cross-repository indexes may land separately; until both sides exist, report the
|
|
135
|
+
specific unqualified member rather than claim the whole graph is ready.
|
|
136
|
+
|
|
137
|
+
Membership selectors and backlinks omit `revision` deliberately: the repository
|
|
138
|
+
adapter observes the hosting provider's actual default branch, not a guessed
|
|
139
|
+
`main`. Within one preparation, observations are frozen. In particular, the
|
|
140
|
+
framework's self-member and workspace backlink must resolve to the **same commit**.
|
|
141
|
+
A separately pinned older workspace with backlinks resolving to a later head is
|
|
142
|
+
correctly stale; choose a fresh coherent observation, never rewrite an old retained
|
|
143
|
+
record. Imports have their own immutable source revision and need not track each
|
|
144
|
+
new workspace metadata commit.
|
|
145
|
+
|
|
146
|
+
Importing the exported soul directly does **not** follow the publisher's workspace
|
|
147
|
+
as adopter policy. A different workspace, or an explicitly standalone operator,
|
|
148
|
+
may consume it without membership in the OATS development workspace.
|
|
149
|
+
|
|
150
|
+
## Inspect source metadata before preparation
|
|
151
|
+
|
|
152
|
+
The public source inspector is implemented in **PR24, commit
|
|
153
|
+
`bc598c484fd097fc5707fd4a33b7877ca00e5da3`**. Use this section only after the
|
|
154
|
+
integration owner supplies a reviewed CLI containing that implementation. It is
|
|
155
|
+
**not a command supported by the original 0.24.0 release**: that older inspect
|
|
156
|
+
route can ignore the request flag and consult ambient classic configuration.
|
|
157
|
+
Do not infer availability from the version floor of a capability.
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
oats inspect --request /absolute/inspection.json --json
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
After the real workspace import from publication step 3 exists, the authored
|
|
164
|
+
inspection input may use the same repository for workspace, member and source:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"deployment": "/operator/deployments/oats-pilot",
|
|
169
|
+
"workTarget": "/operator/projects/oats",
|
|
170
|
+
"source": "oats-expert",
|
|
171
|
+
"origin": {
|
|
172
|
+
"kind": "operator",
|
|
173
|
+
"document": {"kind": "operator", "id": "workspace-adoption"},
|
|
174
|
+
"pointer": "/source"
|
|
175
|
+
},
|
|
176
|
+
"workspace": {
|
|
177
|
+
"source": "git:github.com/awebai/oats",
|
|
178
|
+
"origin": {
|
|
179
|
+
"kind": "operator",
|
|
180
|
+
"document": {"kind": "operator", "id": "workspace-adoption"},
|
|
181
|
+
"pointer": "/workspace"
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"member": {
|
|
185
|
+
"source": "git:github.com/awebai/oats",
|
|
186
|
+
"origin": {
|
|
187
|
+
"kind": "operator",
|
|
188
|
+
"document": {"kind": "operator", "id": "workspace-adoption"},
|
|
189
|
+
"pointer": "/member"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The paths are operator-selected examples, not host defaults or new grants.
|
|
196
|
+
Independent adoption uses the full source/soul/revision/alias reference and an
|
|
197
|
+
explicit standalone context instead of workspace/member. Do not mix this inspect
|
|
198
|
+
mode with current-context flags or captured deployment/resolution selectors.
|
|
199
|
+
|
|
200
|
+
The result is **non-authorizing metadata**, not provider readiness: even `ok:true`
|
|
201
|
+
may carry `needs-configuration` or `separate-deployment-required`. A
|
|
202
|
+
`ready-for-preparation` observation still has no approval or enrollment effect.
|
|
203
|
+
Provider payloads and opaque adoption values are deliberately omitted. Preserve
|
|
204
|
+
the original authored inputs; neither the result nor its inspection request is a
|
|
205
|
+
preparation request or an issued mutation witness. In particular, `workTarget`
|
|
206
|
+
and inspection catalog wrappers are not accepted preparation fields.
|
|
207
|
+
|
|
208
|
+
The inspector owns transient repository scratch but writes no deployment state.
|
|
209
|
+
Missing paths need explicit operator provisioning and reinspection, not automatic
|
|
210
|
+
repair. Observing a project work target does not change the separate captured H/work
|
|
211
|
+
placement. Existing retained inspect remains the later exact-record inspection.
|
|
212
|
+
|
|
213
|
+
## Prepare a fresh local pilot only after the profile is qualified
|
|
214
|
+
|
|
215
|
+
Use the selected installed compatible CLI. Do not turn this source check into a
|
|
216
|
+
global install, a daemon start or a model/GUI test on another operator's machine.
|
|
217
|
+
Keep native HOME/profile/auth and explicit permission choices; no credential copy
|
|
218
|
+
or empty profile. Knowledge, messaging and tasks have distinct authority contracts.
|
|
219
|
+
|
|
220
|
+
Before preparing, the integration lead must supply:
|
|
221
|
+
|
|
222
|
+
- The published workspace/source observations and an explicit fresh physical
|
|
223
|
+
deployment/home placement. Do not copy old locks, retained records or identities.
|
|
224
|
+
- An operator-owned nonsecret request with `workspace` (its source and origin),
|
|
225
|
+
`source: "oats-expert"` after the real import is published, and `mode: "directory"`.
|
|
226
|
+
Standalone callers instead give the complete `{source,soul,revision,alias}`
|
|
227
|
+
reference and an explicit standalone context; they do not inherit this workspace.
|
|
228
|
+
- Explicit provider-specific settings and bindings. OKF preparation needs selected
|
|
229
|
+
absolute `bindings-file` and `state-dir`, `harvest-runtime`, and the `stores.oats`
|
|
230
|
+
binding; an omitted `harvest-model` preserves native-default intent. The parent-owned
|
|
231
|
+
acceptance fixture must supply an accepted node registry supporting the preserved
|
|
232
|
+
owner **and all four read nodes**. This is not accepted production KB publication;
|
|
233
|
+
Git destinations remain PR-only.
|
|
234
|
+
- Actual messaging human/context inputs and the pilot's explicit **`delivery: session`**
|
|
235
|
+
setting (aweb's default is channel). Supply it in the complete supported
|
|
236
|
+
`operator.policy.messaging` selection: capability, matching selected source and
|
|
237
|
+
`settings: {delivery: session}`. Retain host requirements, session `ifInstalled`
|
|
238
|
+
minimums and any selected authoring requirements. Selecting session delivery neither
|
|
239
|
+
adds the missing1.10.3 binding adapter nor supplies captured wake/input authority.
|
|
240
|
+
- A qualified primary/helper runtime/model/resource profile. Capture the intended
|
|
241
|
+
helper selection in `helperLaunches["oats.okf:memory-harvest"]`, not the legacy
|
|
242
|
+
`souls.memory-harvest` configuration. Do not replace retained intent to fit an easier
|
|
243
|
+
runtime profile. An old default-OKF-only learning gate does not qualify a combined
|
|
244
|
+
aweb profile. If provider or kernel support is missing, stop at that typed result;
|
|
245
|
+
do not bypass it with a legacy route, a dropped capability or a fabricated identity.
|
|
246
|
+
|
|
247
|
+
The existing public routes are stepwise (D/R/H are returned or explicitly approved
|
|
248
|
+
values, not names inferred from cwd):
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
oats prepare --request /absolute/operator-preparation.json --json
|
|
252
|
+
# Review returned exact artifacts/problems; approve only explicitly authorized code.
|
|
253
|
+
oats trust <capability-id> --deployment "$D" --artifact-set "$ARTIFACT_SET" --json
|
|
254
|
+
oats prepare --request /absolute/operator-preparation.json --json
|
|
255
|
+
oats inspect --deployment "$D" --resolution "$R" --composition --json
|
|
256
|
+
oats spawn oats-expert --deployment "$D" --resolution "$R" --home "$H" --no-launch --json
|
|
257
|
+
oats session start --deployment "$D" --resolution "$R" --home "$H" \
|
|
258
|
+
--request /absolute/approved-native-request.json --json
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Do not mix other preparation flags into request-file mode. A needs-configuration or
|
|
262
|
+
approval result is not a ready instance. A scaffold materializes resources and may
|
|
263
|
+
run approved hooks; it is not a message exchange or model session. Actual dispatch,
|
|
264
|
+
continuation, native capture, messaging and learning require the integration owner's
|
|
265
|
+
qualified profile and receipts. Captured wake/input and public captured retirement
|
|
266
|
+
remain unsupported; a stopped-home observation is not delivery or retirement authority.
|
|
267
|
+
A session-delivered messaging profile therefore cannot pass on start-only evidence.
|
|
268
|
+
Do not route it through legacy input/retire or remove the messaging requirement.
|
|
269
|
+
Consult the current installed public help and the provider's supported commands;
|
|
270
|
+
this guide introduces no new CLI grammar. The source inspector above is a separate
|
|
271
|
+
implementation dependency, not a change to the existing prepare request contract.
|
|
272
|
+
|
|
273
|
+
## Local checks and limits
|
|
274
|
+
|
|
275
|
+
`node --test test/workspace-repository-layout.test.mjs` checks the actual declarations
|
|
276
|
+
against the shipped codecs/schemas, required providers and owner/read mapping, and
|
|
277
|
+
contained source resources. An isolated native-Git fixture exercises source-before-
|
|
278
|
+
import publication, host-default observations, reciprocal/self admission, refusal of
|
|
279
|
+
missing/stale backlinks, and independent public source projection. Fixture member
|
|
280
|
+
indexes are not evidence that the six real repositories are already published.
|
|
281
|
+
|
|
282
|
+
Source and metadata checks do not enroll users, initialize the phase-2 store, register
|
|
283
|
+
production writers or qualify private messaging. Parent alone coordinates publication,
|
|
284
|
+
local operator approval and actual adoption. Full Desktop parity follows usable
|
|
285
|
+
infrastructure adoption, not merely seven YAML files passing validation.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Workspaces, repositories and portable souls
|
|
2
|
+
|
|
3
|
+
A **workspace definition** describes a shared agent setup in Git. A **local deployment** is one operator's realization of it. A **portable soul** declares its role, requirements and software sources independently of either operator's directory layout.
|
|
4
|
+
|
|
5
|
+
This is the current OATS architecture. Start here for the model, then use [first-team onboarding](first-team.md) and the version-scoped [configuration](configuration.md) and [packages](packages.md) guides for operations. The [0.24 release notes](release-notes/v0.24.0.md) distinguish shipped foundations from unqualified profiles; an accepted architecture is not proof that every capability is ready.
|
|
6
|
+
|
|
7
|
+
## Four independent things
|
|
8
|
+
|
|
9
|
+
| Thing | What it decides | What it does not imply |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Workspace | Intended repository membership, shared defaults, source imports and provider declarations | Installed software, executable approval, messaging enrollment or a shared live session |
|
|
12
|
+
| Source repository | The soul/package/store definitions it actually exports | Membership of every consumer in the publisher's workspace |
|
|
13
|
+
| Local deployment | Local mappings, retained artifacts/resolutions, operator inputs and execution state | Permission to change source requirements or copy another operator's credentials |
|
|
14
|
+
| Work target | Where an instance is assigned to work | Where its soul must be published, where knowledge must live or which team it joins |
|
|
15
|
+
|
|
16
|
+
A workspace needs no OATS account, registry or OATS-operated control plane. Git hosting, messaging and model providers retain their own access and authentication requirements.
|
|
17
|
+
|
|
18
|
+
## The three declaration files
|
|
19
|
+
|
|
20
|
+
### `oats-workspace.yaml` — the shared workspace
|
|
21
|
+
|
|
22
|
+
The workspace names intended members and may provide defaults, knowledge-store declarations, team aliases, catalogs and external soul imports. Omitted lists admit or activate nothing.
|
|
23
|
+
|
|
24
|
+
A workspace is a role, not a requirement for a separate repository. It can live in a dedicated repository or beside project code. For OATS development, the selected home is the `oats` framework repository; `oats-dev` remains a development-capability repository.
|
|
25
|
+
|
|
26
|
+
This schematic example uses placeholder sources, not a runnable published team:
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
schemaVersion: 1
|
|
30
|
+
name: example-development
|
|
31
|
+
members:
|
|
32
|
+
- source: git:github.com/example/service
|
|
33
|
+
imports:
|
|
34
|
+
- source: git:github.com/example/experts
|
|
35
|
+
soul: souls/domain-expert
|
|
36
|
+
revision: reviewed-source-ref
|
|
37
|
+
alias: domain-expert
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Use actual reviewed source revisions when preparing work. When a repository reference omits its optional revision, discovery observes the hosting provider's intended default branch; it must not guess `main` or silently reuse unrelated local branch state.
|
|
41
|
+
|
|
42
|
+
### `oats.yaml` — a repository's advertised exports
|
|
43
|
+
|
|
44
|
+
A repository advertises the souls, package roots and provider-owned knowledge declarations it actually supplies. A member also points back to its workspace:
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
schemaVersion: 1
|
|
48
|
+
workspace:
|
|
49
|
+
source: git:github.com/example/workspace
|
|
50
|
+
exports:
|
|
51
|
+
souls:
|
|
52
|
+
- path: souls/domain-expert
|
|
53
|
+
definition: souls/domain-expert/soul.yaml
|
|
54
|
+
packages:
|
|
55
|
+
- path: oats-package
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Only include exports that exist at the selected revision. A repository need not export every kind. A package export identifies a real directory containing `oats-package.json`; it is not an arbitrary npm package directory.
|
|
59
|
+
|
|
60
|
+
`oats-workspace.yaml` and `oats.yaml` may coexist. If the workspace host also participates as a member, it is explicitly admitted and has a matching backlink just like another member.
|
|
61
|
+
|
|
62
|
+
### `soul.yaml` — a source-complete specialist
|
|
63
|
+
|
|
64
|
+
A portable soul is an authored definition, not a dependency on whatever happens to be installed on its publisher's machine. It contains canonical `AGENTS.md`, a relative `CLAUDE.md` alias, its reviewed skill/resource closure and a versioned declaration.
|
|
65
|
+
|
|
66
|
+
For example, this declaration excerpt requires a particular knowledge capability **and names where it comes from**:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
schemaVersion: 1
|
|
70
|
+
name: domain-expert
|
|
71
|
+
requires:
|
|
72
|
+
knowledge:
|
|
73
|
+
capability: oats.okf
|
|
74
|
+
source: git:github.com/awebai/oats-okf@v2.1.1#oats-package
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This illustrates software selection, not complete OKF provisioning: the chosen capability also needs its own valid knowledge declaration, bindings and accepted base.
|
|
78
|
+
|
|
79
|
+
- `requires` expresses hard requirements. A fundamental provider can be required by presence or as a concrete capability/source selection.
|
|
80
|
+
- `defaults` supplies choices that remain rebindable within those requirements.
|
|
81
|
+
- Additive capabilities are named under `requires.capabilities` or `defaults.capabilities`; each concrete selection has a `source`, with optional provider-owned settings.
|
|
82
|
+
- `git:` selects versioned software from a repository/package root. `repo:` refers to a contained path in the declaring source repository, not the caller's working directory. `path:` is an explicitly authorised local development choice, not a remotely portable ambient fallback.
|
|
83
|
+
- Capability IDs alone do not establish software origin. An old `from: installed` config entry is not a substitute for a portable source declaration.
|
|
84
|
+
- A source may contain authored knowledge snapshots or resources, but retained artifacts are not writable knowledge stores. Learning locations and procedures belong to the selected capability.
|
|
85
|
+
|
|
86
|
+
See the [soul schema](soul.schema.json) and [declaration contract](design/2026-09-15-portable-declarations.md). Classic fields such as `kind`, `type` and a machine-local `repo` are not portable declaration fields; do not relabel an old file without validating it.
|
|
87
|
+
|
|
88
|
+
## Membership and adoption are different
|
|
89
|
+
|
|
90
|
+
**Repository membership is reciprocal:** the workspace admits the repository and the repository's `oats.yaml` points back to that workspace. Both observations must have compatible identity, access context and revision evidence. A copied backlink, neighbouring folder or URL is not admission.
|
|
91
|
+
|
|
92
|
+
**Source adoption is by reference:** an import identifies `source`, exported `soul` path, `revision` and a local `alias`. It may carry supported adoption choices. Importing does not create an adopter-maintained copy of the soul or automatically follow the publisher's workspace backlink.
|
|
93
|
+
|
|
94
|
+
A team can therefore use a public expert without joining its publisher's organization. One source can serve several workspaces or an explicit standalone context, with different legitimate work targets and knowledge bindings.
|
|
95
|
+
|
|
96
|
+
Publish source/export revisions before pinning imports to them. Do not use invented future SHAs or require two repositories to contain each other's not-yet-created commit IDs.
|
|
97
|
+
|
|
98
|
+
## How requirements and defaults meet
|
|
99
|
+
|
|
100
|
+
The kernel uses one resolver:
|
|
101
|
+
|
|
102
|
+
- Workspace defaults establish shared fallback choices.
|
|
103
|
+
- The soul's own defaults can specialise them.
|
|
104
|
+
- Explicit adoption/operator choices select supported alternatives or supply missing inputs.
|
|
105
|
+
- Hard source requirements remain constraints; a conflicting override is an error, not a reason to discard the requirement.
|
|
106
|
+
|
|
107
|
+
Provider-owned declarations remain opaque to the kernel until the selected provider interprets them through its contract. There is no portable repository-level capability policy tier silently inherited from the publisher, and no mandatory agent-type hierarchy replacing a soul's own requirements.
|
|
108
|
+
|
|
109
|
+
Repository briefing/worktree setup remains work-target behavior with its own supported authority. Merely placing a repository `AGENTS.md` nearby does not guarantee it is composed into every harness's instructions.
|
|
110
|
+
|
|
111
|
+
## From a definition to a running instance
|
|
112
|
+
|
|
113
|
+
1. Select an explicit workspace or standalone context, source reference, deployment location and work target.
|
|
114
|
+
2. Observe actual source identities/revisions and check requested reciprocal membership.
|
|
115
|
+
3. Resolve requirements, defaults and operator inputs; retain the selected source and software closure.
|
|
116
|
+
4. Review and approve exact executable artifacts before provider code runs.
|
|
117
|
+
5. Obtain honest provider readiness and a retained resolution; missing configuration or unsupported behavior remains visible.
|
|
118
|
+
6. Scaffold and start through the supported captured lifecycle. Preserve the exact source/resources and evidence needed for continuation.
|
|
119
|
+
|
|
120
|
+
An existing instance does not silently adopt a new upstream commit, changed workspace default or different curriculum. Updates prepare new choices deliberately; required knowledge refresh and native credential rotation are separate from rewriting its retained software.
|
|
121
|
+
|
|
122
|
+
A successful lookup is not execution, an accepted dispatch is not completed work, and a declared knowledge destination is not accepted learning.
|
|
123
|
+
|
|
124
|
+
## What each operator shares or keeps local
|
|
125
|
+
|
|
126
|
+
Share reviewed definitions, relevant nonsecret configuration/provenance, published source references and accepted knowledge through their chosen Git repositories. Keep credentials, private runtime evidence, instance homes and machine-specific realization local. A messaging roster does not replicate any of these.
|
|
127
|
+
|
|
128
|
+
An adopted package config template is an editable local snapshot, not live inheritance from the package. Updating the kernel or package does not rewrite it, migrate a knowledge base or update a running instance's loaded instructions.
|
|
129
|
+
|
|
130
|
+
## Compatibility and current readiness
|
|
131
|
+
|
|
132
|
+
Classic `oats-config.yaml` scopes, `oats init`, `oats use`, local `agents/` lookup and lock-v2 package restore still have their own supported contracts. They are not renamed portable workspace commands. See [configuration](configuration.md) and [packages](packages.md) for that compatibility surface; do not apply classic lifecycle commands blindly to captured instances.
|
|
133
|
+
|
|
134
|
+
At the documented0.24 baseline, workspace/declaration/retained-execution foundations are shipped. The released `oats.aweb`1.10.3 package lacks the captured provider-binding interface, so its legacy messaging success does not qualify a new captured profile requiring it. Capability adaptation is implementation work, not a YAML setting that can honestly turn readiness green. Follow current [release scope](release-notes/v0.24.0.md) and the provider's actual version/readiness rather than removing requirements.
|
|
135
|
+
|
|
136
|
+
The project's [adoption plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) puts workspace/source adoption first, centralised knowledge and five experts second, and full Desktop parity afterward.
|
|
137
|
+
|
|
138
|
+
## How a soul knows OATS (accepted direction, not yet shipped)
|
|
139
|
+
|
|
140
|
+
An agent's knowledge of OATS itself — how to check status, spawn and retire, find other souls — is ordinary capability content, not kernel magic:
|
|
141
|
+
|
|
142
|
+
- **`oats.core`** carries day-to-day operation (skills `oats-operate`, `oats-souls`, the "you run on OATS" briefing). Every soul gets it **by default at creation, written explicitly into its definition**; you can remove or replace it.
|
|
143
|
+
- **`oats.setup`** carries deployment/workspace configuration and package knowledge ("OATS Soul Setup"). Onboarding a workspace creates and starts an **`oats-setup-expert`** soul with both, which then adopts repositories and creates the team's other souls.
|
|
144
|
+
- The **official marketplace** is the reviewed package list in the `oats` repository; a package becomes official through an approved PR to that list, and official packages are discoverable from the CLI and Desktop. Discoverable is not installed; installed is not approved.
|
|
145
|
+
|
|
146
|
+
At the0.24 baseline these skills still ship inside the kernel. Work packages D1–D4 of the [adoption plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) track the move.
|
|
147
|
+
|
|
148
|
+
## Related references
|
|
149
|
+
|
|
150
|
+
- [Souls and instances](souls-and-instances.md)
|
|
151
|
+
- [Capability contracts](layers.md) and [capability authoring/distribution](capabilities.md)
|
|
152
|
+
- [Knowledge model](knowledge-theory.md) and [version-scoped operations](knowledge.md)
|
|
153
|
+
- [Workspace schema](oats-workspace.schema.json) and [repository export schema](oats-member.schema.json)
|
|
154
|
+
- [Design/contract navigation](design/README.md)
|
package/injects/oats-portable.md
CHANGED
|
@@ -7,11 +7,10 @@ settings, provider bindings, and executable resources come from that exact
|
|
|
7
7
|
configuration cascade, package lock, similarly named capability, or source path.
|
|
8
8
|
|
|
9
9
|
Load **oats-portable** before invoking or reasoning about captured OATS commands.
|
|
10
|
-
Load **oats-portable-
|
|
11
|
-
source/workspace/deployment/work/team choices. Load **oats-portable-artifacts**
|
|
12
|
-
for exact retained inspection and approval. Do not load the legacy **oats**,
|
|
10
|
+
Load **oats-portable-artifacts** for exact retained inspection and approval. Do not load the legacy **oats**,
|
|
13
11
|
**oats-config**, or **oats-packages** procedures to fill a captured input.
|
|
14
12
|
|
|
15
|
-
Captured start/restart
|
|
16
|
-
|
|
13
|
+
Captured start/restart use exact retained launch inputs and supported native
|
|
14
|
+
endpoints. Captured wake/retire, unqualified runtime contributions and non-directory
|
|
15
|
+
work remain held. If a command is unsupported or retained authority is missing,
|
|
17
16
|
stop and report it; never remove selectors or fall back to ambient configuration.
|
package/lib/core.mjs
CHANGED
|
@@ -61,6 +61,7 @@ import { validateCapturedLaunchRequest } from "./captured-launch-request.mjs";
|
|
|
61
61
|
import { validateCapabilityInputDeclarations } from "./capability-inputs.mjs";
|
|
62
62
|
import { validateCapturedSessionBackend, validateCapturedSessionTarget, assertCapturedSessionPlacement } from "./captured-session-backend.mjs";
|
|
63
63
|
import { createRepositoryTransaction } from "./repository-observation.mjs";
|
|
64
|
+
import { inspectPortableOnboarding as inspectOnboarding, describePortableOnboarding } from "./portable-onboarding.mjs";
|
|
64
65
|
import { readLock3 } from "./portable-lock.mjs";
|
|
65
66
|
import { portableScope, portableStateDirectory } from "./portable-state.mjs";
|
|
66
67
|
import { objectAt } from "./portable-shape.mjs";
|
|
@@ -1194,6 +1195,31 @@ export function approveAvailableCapability(deployment, artifactSet, capability,
|
|
|
1194
1195
|
return approveAvailableArtifact(deployment, artifactSet, capability, origin, loadRetainedManifest);
|
|
1195
1196
|
}
|
|
1196
1197
|
|
|
1198
|
+
/** Public read-only source/workspace inspection through the existing facade.
|
|
1199
|
+
* Owns only transient repository scratch, never deployment state, provisioning,
|
|
1200
|
+
* provider code, approvals or a serialized mutation witness. */
|
|
1201
|
+
export function inspectPortableOnboarding(input, { repositoryOptions = {} } = {}) {
|
|
1202
|
+
canonicalJson(input);
|
|
1203
|
+
const directory = mkdtempSync(join(realpathSync(tmpdir()), "oats-source-inspection-")), owned = lstatSync(directory);
|
|
1204
|
+
let repositories, primary;
|
|
1205
|
+
try {
|
|
1206
|
+
repositories = createRepositoryTransaction({ ...repositoryOptions, directory, accessContextKey: repositoryOptions.accessContextKey ?? "native" });
|
|
1207
|
+
return describePortableOnboarding(inspectOnboarding(input, { repositories }));
|
|
1208
|
+
} catch (error) { primary = error; throw error; }
|
|
1209
|
+
finally {
|
|
1210
|
+
try {
|
|
1211
|
+
repositories?.close();
|
|
1212
|
+
const current = lstatSync(directory);
|
|
1213
|
+
if (!current.isDirectory() || current.dev !== owned.dev || current.ino !== owned.ino) throw oatsError("source-incomplete", "inspection scratch ownership changed");
|
|
1214
|
+
removeOwnedStaging(directory);
|
|
1215
|
+
} catch (cleanup) {
|
|
1216
|
+
if (!primary) throw cleanup;
|
|
1217
|
+
const error = new AggregateError([primary, cleanup], "inspection and owned scratch cleanup failed", { cause: primary });
|
|
1218
|
+
error.code = primary.code; error.stagingPath = directory; throw error;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1197
1223
|
/** Explicit new-work preparation, with one frozen repository transaction.
|
|
1198
1224
|
* This first adapter captures command/curriculum profiles; provider-owned
|
|
1199
1225
|
* binding or distinct helper policy gaps return needs-configuration, never
|
|
@@ -7121,9 +7147,11 @@ function runtimeAuthorityOf(baseline) {
|
|
|
7121
7147
|
return { launched: true, tmux: { session: tmux.session, window: tmux.window, socket: resolve(tmux.socket) } };
|
|
7122
7148
|
}
|
|
7123
7149
|
|
|
7124
|
-
/** Session control uses the
|
|
7150
|
+
/** Session control uses the independent endpoint receipt and, for captured
|
|
7151
|
+
* homes, its original incarnation's existing home/work custody. */
|
|
7125
7152
|
function instanceSessionTarget(home) {
|
|
7126
7153
|
if (typeof home !== "string" || !isAbsolute(home)) throw oatsError("E_BAD_ARGS", "session needs an absolute instance home");
|
|
7154
|
+
const requestedHome = home;
|
|
7127
7155
|
home = realPathOrNearest(home);
|
|
7128
7156
|
let baseline, meta;
|
|
7129
7157
|
try {
|
|
@@ -7132,18 +7160,29 @@ function instanceSessionTarget(home) {
|
|
|
7132
7160
|
} catch (e) { throw oatsError("E_RUNTIME_ENDPOINT_UNKNOWN", `cannot read session receipt for ${home}: ${e.message}`); }
|
|
7133
7161
|
const authority = baseline.version === RETIRE_BASELINE_VERSION && baseline.home === home && runtimeAuthorityOf(baseline);
|
|
7134
7162
|
if (!authority) throw oatsError("E_RUNTIME_ENDPOINT_UNKNOWN", `independent session receipt is missing or invalid for ${home}`);
|
|
7163
|
+
let io;
|
|
7164
|
+
if ([baseline, meta].some(value => ["executionBinding", "incarnationId", "captured"].some(key => Object.hasOwn(value, key)))) {
|
|
7165
|
+
// The independent receipt remains the anchor even if mutable home markers
|
|
7166
|
+
// are removed. Missing/invalid captured evidence never falls back to legacy.
|
|
7167
|
+
validateExecutionBinding(baseline.executionBinding);
|
|
7168
|
+
const { row } = readCapturedInstanceAuthority(baseline.executionBinding.deployment, requestedHome);
|
|
7169
|
+
if (row.incarnationId !== baseline.incarnationId || canonicalJson(row.executionBinding) !== canonicalJson(baseline.executionBinding)) {
|
|
7170
|
+
throw oatsError("E_RUNTIME_AUTHORITY_MISMATCH", "captured incarnation disagrees with independent session receipt");
|
|
7171
|
+
}
|
|
7172
|
+
io = { exec: (...args) => { assertCapturedInstanceCustody(row); return execFileSync(...args); } };
|
|
7173
|
+
}
|
|
7135
7174
|
const endpointAgrees = authority.sessionTarget
|
|
7136
7175
|
? !meta.tmux && ["backend", "binary", "socket", "workspaceId", "paneId", "terminalId", "protocol"].every((key) => meta.sessionTarget?.[key] === authority.sessionTarget[key])
|
|
7137
7176
|
: !meta.sessionTarget && meta.tmux?.session === authority.tmux?.session && meta.tmux?.window === authority.tmux?.window && resolve(meta.tmux?.socket || ".") === authority.tmux?.socket;
|
|
7138
7177
|
if (meta.launched !== authority.launched || (authority.launched && !endpointAgrees)) throw oatsError("E_RUNTIME_AUTHORITY_MISMATCH", "instance metadata disagrees with independent session receipt");
|
|
7139
|
-
return { home, target: authority.launched ? authority.sessionTarget || { backend: "tmux", ...authority.tmux } : undefined };
|
|
7178
|
+
return { home, target: authority.launched ? authority.sessionTarget || { backend: "tmux", ...authority.tmux } : undefined, io };
|
|
7140
7179
|
}
|
|
7141
7180
|
|
|
7142
7181
|
export function inspectInstanceSession(home) {
|
|
7143
7182
|
if (typeof home === "string" && isAbsolute(home) && !existsSync(home)) return { home: realPathOrNearest(home), backend: null, present: false, state: "stopped" };
|
|
7144
7183
|
const s = instanceSessionTarget(home);
|
|
7145
7184
|
if (!s.target) return { home: s.home, backend: null, present: false, state: "not-launched" };
|
|
7146
|
-
try { return { home: s.home, ...inspectSessionTarget(s.target) }; }
|
|
7185
|
+
try { return { home: s.home, ...inspectSessionTarget(s.target, s.io) }; }
|
|
7147
7186
|
catch (e) { throw oatsError("E_SESSION_UNAVAILABLE", `cannot inspect session: ${e.message}`); }
|
|
7148
7187
|
}
|
|
7149
7188
|
|
|
@@ -7157,7 +7196,7 @@ export function inputInstanceSession(home, text) {
|
|
|
7157
7196
|
if (typeof text !== "string" || !text.trim() || text.includes("\0") || Buffer.byteLength(text) > 256 * 1024) throw oatsError("E_BAD_ARGS", "session input must be nonempty text without NUL, at most 256 KiB");
|
|
7158
7197
|
const s = instanceSessionTarget(home);
|
|
7159
7198
|
if (!s.target) throw oatsError("E_SESSION_NOT_RUNNING", "instance was not launched");
|
|
7160
|
-
try { return { home: s.home, ...inputSessionTarget(s.target, text) }; }
|
|
7199
|
+
try { return { home: s.home, ...inputSessionTarget(s.target, text, s.io) }; }
|
|
7161
7200
|
catch (e) { throw oatsError("E_SESSION_INPUT_FAILED", `cannot submit session input: ${e.message}`); }
|
|
7162
7201
|
}
|
|
7163
7202
|
|
|
@@ -189,6 +189,25 @@ export function inspectPortableOnboarding(input, { repositories } = {}) {
|
|
|
189
189
|
return result;
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
/** Metadata-only public view, NOT a serialized fresh-inspection witness or a
|
|
193
|
+
* preparation request. Provider payloads/adoption values have not gone through
|
|
194
|
+
* their owner's nonsecret classification and must not leak through inspection. */
|
|
195
|
+
export function describePortableOnboarding(inspection) {
|
|
196
|
+
if (!issued.has(inspection)) throw oatsError("invalid-declaration", "inspection summary requires an issued onboarding view");
|
|
197
|
+
const reference = value => ({ source: value.source, soul: value.soul, revision: value.revision, alias: value.alias,
|
|
198
|
+
adoptionPresent: Object.hasOwn(value, "adoption") });
|
|
199
|
+
const { reference: selected, exports, ...source } = inspection.source;
|
|
200
|
+
return freezeJson({ ...inspection,
|
|
201
|
+
source: { ...source, adoptionPresent: Object.hasOwn(selected, "adoption"), exports: {
|
|
202
|
+
souls: (exports.souls ?? []).map(({ path, definition, description }) => ({ path, definition, ...(description === undefined ? {} : { description }) })),
|
|
203
|
+
packages: (exports.packages ?? []).map(({ path, description }) => ({ path, ...(description === undefined ? {} : { description }) })),
|
|
204
|
+
knowledge: (exports.knowledge ?? []).map(({ contract, version }) => ({ contract, version, payloadOmitted: true })),
|
|
205
|
+
} },
|
|
206
|
+
workspace: inspection.workspace ? { ...inspection.workspace, imports: inspection.workspace.imports.map(reference) } : null,
|
|
207
|
+
omitted: { providerPayloads: true, adoptionValues: true },
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
192
211
|
/** Ephemeral local root custody, not a new persistent authority/schema. Ordinary
|
|
193
212
|
* project content changes are allowed; replacing the inspected directories or
|
|
194
213
|
* provisioning a previously absent deployment requires a fresh inspection. */
|
|
@@ -23,7 +23,7 @@ export function completePreparedResources({ seed, plan, manifests, mode, deploym
|
|
|
23
23
|
}
|
|
24
24
|
if (problems.length) return { record: null, problems };
|
|
25
25
|
const snapshot = join(directory, "kernel-resources"); mkdirSync(snapshot); mkdirSync(join(snapshot, "injects"));
|
|
26
|
-
const kernelSkills = ["oats-portable", "oats-portable-
|
|
26
|
+
const kernelSkills = ["oats-portable", "oats-portable-artifacts"];
|
|
27
27
|
const workInjection = (workMode) => workMode === "directory" ? "portable-work-directory.md" : `work-${workMode}.md`;
|
|
28
28
|
const injectionFiles = ["oats-portable.md", "portable-instance-boundary.md", ...kernel.workModes.map(workInjection)];
|
|
29
29
|
// Only known kernel resources, never a sweep of the checkout/node_modules,
|
package/package-catalog.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awebai/oats",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"description": "OATS (Open Agent Team Specification) — durable souls, disposable instances, targetable capability packages, and the runtime-neutral oats CLI/kernel.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -4,17 +4,16 @@ description: >-
|
|
|
4
4
|
Use only for configuring a legacy uncaptured OATS deployment with the current
|
|
5
5
|
oats-config.yaml cascade, including legacy activation, agent types, targeting,
|
|
6
6
|
overrides, and templates. Triggers: "legacy oats-config", "uncaptured config",
|
|
7
|
-
"oats use", or "agent type".
|
|
8
|
-
|
|
7
|
+
"oats use", or "agent type". This legacy policy is not a portable preparation
|
|
8
|
+
authority and never fills a captured record.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Configuring legacy uncaptured OATS
|
|
12
12
|
|
|
13
13
|
> **Legacy-only procedure.** The cascading scopes, agent-type targeting and
|
|
14
14
|
> closest-team rules below are compatibility behavior for uncaptured instances.
|
|
15
|
-
> They are not portable composition authorities.
|
|
16
|
-
>
|
|
17
|
-
> fallback during captured preparation or dispatch.
|
|
15
|
+
> They are not portable composition authorities. Never consult this cascade as
|
|
16
|
+
> a fallback during captured preparation or dispatch.
|
|
18
17
|
|
|
19
18
|
Config lives in `oats-config.yaml` at laptop (`~`), workspace, and repository
|
|
20
19
|
levels; resolution walks from a soul's repository outward, closest scope wins.
|
|
@@ -112,5 +112,4 @@ still refuse. Do not strip selectors or call legacy forms as a workaround. A sca
|
|
|
112
112
|
may contain external hook effects; preserve it and escalate rather than deleting
|
|
113
113
|
it. A scaffold marked `spawned-launch-pending` is not a running instance.
|
|
114
114
|
|
|
115
|
-
Use **oats-portable-
|
|
116
|
-
**oats-portable-artifacts** for exact approval and retained A/B diagnostics.
|
|
115
|
+
Use **oats-portable-artifacts** for exact approval and retained A/B diagnostics.
|