@awebai/oats 0.24.12 → 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.
- package/bin/oats.mjs +936 -2822
- package/docs/capabilities.md +136 -323
- package/docs/configuration.md +68 -533
- package/docs/design/2026-09-16-fresh-operator-walkthrough.md +19 -14
- package/docs/design/2026-09-16-portable-migration-evidence.md +2 -0
- package/docs/design/2026-09-16-portable-onboarding.md +4 -2
- package/docs/design/2026-09-20-redesign-program-board.md +1 -1
- package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +2 -0
- package/docs/design/2026-09-23-simplified-workspace-model.md +711 -0
- package/docs/design/2026-09-23-workspace-module-contracts.md +309 -0
- package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +65 -0
- package/docs/design/README.md +20 -8
- package/docs/design/operations-contract.md +1 -0
- package/docs/design/package-engine-contract.md +1 -1
- package/docs/design/package-runtime-api.md +1 -1
- package/docs/desktop-cli-api.md +386 -6
- package/docs/desktop-succession.md +3 -4
- package/docs/first-team.md +107 -224
- package/docs/implementation.md +6 -4
- package/docs/integrations.md +45 -44
- package/docs/knowledge-capability-authoring.md +10 -4
- package/docs/knowledge-migration.md +5 -4
- package/docs/knowledge-reference/package-craft.md +11 -3
- package/docs/knowledge.md +24 -8
- package/docs/layers.md +3 -3
- package/docs/oats-local.schema.json +50 -0
- package/docs/oats-membership.schema.json +23 -0
- package/docs/oats-workspace.schema.json +133 -48
- package/docs/official-marketplace.md +9 -6
- package/docs/packages.md +229 -440
- package/docs/rebuild-to-v2.md +233 -0
- package/docs/release-notes/v0.24.13.md +51 -0
- package/docs/release-notes/v0.25.0.md +99 -0
- package/docs/soul.schema.json +41 -68
- package/docs/souls-and-instances.md +175 -108
- package/docs/workspace-adoption.md +70 -345
- package/docs/workspaces.md +429 -119
- package/lib/core.mjs +419 -55
- package/lib/instance-resolution.mjs +312 -0
- package/lib/materialize.mjs +580 -0
- package/lib/packages.mjs +501 -1273
- package/lib/remote.mjs +639 -0
- package/lib/resolve.mjs +576 -0
- package/lib/schedule.mjs +194 -34
- package/lib/workspace.mjs +635 -0
- package/package.json +1 -1
- package/lib/portable-migration-artifacts.mjs +0 -135
- package/lib/portable-migration-evidence.mjs +0 -305
- package/lib/portable-migration-store.mjs +0 -199
- package/lib/portable-migration.mjs +0 -104
- package/lib/portable-onboarding-acceptance.mjs +0 -66
- package/lib/setup-expert-source.mjs +0 -100
package/docs/configuration.md
CHANGED
|
@@ -1,557 +1,92 @@
|
|
|
1
|
-
# Configuration
|
|
1
|
+
# Configuration — `oats-local.yaml`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
A deployment has **one** per-machine file: `oats-local.yaml`. It says which
|
|
4
|
+
workspace this machine realizes and holds the few facts that are true of this
|
|
5
|
+
host only. Everything shared — members, packages and their versions, teams,
|
|
6
|
+
defaults, stores, the messaging policy — lives in the workspace repo's
|
|
7
|
+
`oats-workspace.yaml`; everything about a soul lives in its `soul.yaml`
|
|
8
|
+
([workspaces.md](workspaces.md)).
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
`
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
**`oats-config.yaml` no longer exists.** Its `capabilities.layers` /
|
|
11
|
+
`additive` / `from:` / `global` / `agent-types` blocks are gone — activation is
|
|
12
|
+
derived from workspace defaults plus each soul's `capabilities:` — and its
|
|
13
|
+
`souls:` blocks are gone — per-instance provider content moved to
|
|
14
|
+
`oats spawn … --provider`. There is no `oats init`, no `oats use`, no config
|
|
15
|
+
scope chain, no adopted config templates. A 0.24.x deployment is rebuilt, not
|
|
16
|
+
converted: [rebuild-to-v2.md](rebuild-to-v2.md).
|
|
14
17
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
Resolution walks from the soul's repository upward:
|
|
18
|
-
|
|
19
|
-
1. repository;
|
|
20
|
-
2. containing workspace(s); and
|
|
21
|
-
3. laptop/home.
|
|
22
|
-
|
|
23
|
-
A `global` binding applies to all souls governed by the level that declares
|
|
24
|
-
it. It does not escape that scope. This lets a laptop set defaults, a workspace
|
|
25
|
-
add shared team capabilities, and one repository make a narrower choice.
|
|
26
|
-
|
|
27
|
-
```text
|
|
28
|
-
~/oats-config.yaml
|
|
29
|
-
~/workspace/oats-config.yaml
|
|
30
|
-
~/workspace/service/oats-config.yaml
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Use `oats doctor <context> --soul <name>` to inspect the result.
|
|
34
|
-
|
|
35
|
-
## Schema
|
|
18
|
+
## The file
|
|
36
19
|
|
|
37
20
|
```yaml
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# ── Team — the deployment boundary. The closest scope declaring team: wins;
|
|
41
|
-
# every repo under it resolves the same team (identity, discovery, messaging).
|
|
42
|
-
team:
|
|
43
|
-
name: example-engineering
|
|
44
|
-
# id: example-engineering:example.com # explicit provider team id (e.g. aweb <name>:<namespace>)
|
|
45
|
-
|
|
46
|
-
# ── Agent types (families) ── declared here by name; each soul opts in via
|
|
47
|
-
# `type: <name>` in its soul.yaml. Capability entries can target them.
|
|
48
|
-
agent-types:
|
|
49
|
-
developers:
|
|
50
|
-
description: Agents that build and maintain the service
|
|
51
|
-
reviewers:
|
|
52
|
-
description: Agents that review changes
|
|
53
|
-
|
|
54
|
-
capabilities:
|
|
55
|
-
# Fundamental layers — exclusive slots; a capability entry or an explicit none.
|
|
56
|
-
layers:
|
|
57
|
-
knowledge:
|
|
58
|
-
capability: oats.okf
|
|
59
|
-
from: installed
|
|
60
|
-
settings:
|
|
61
|
-
bindings-file: /absolute/config/okf-bindings.json
|
|
62
|
-
harvest-runtime: pi
|
|
63
|
-
# harvest-model: provider/model # optional; default is runtime-selected
|
|
64
|
-
# injection-override: .agents/injections/capabilities/oats.okf.md
|
|
65
|
-
messaging: none
|
|
66
|
-
tasks:
|
|
67
|
-
capability: oats.linear
|
|
68
|
-
from: installed
|
|
69
|
-
agent-types:
|
|
70
|
-
developers:
|
|
71
|
-
enabled: true
|
|
72
|
-
settings: {team: ENG}
|
|
73
|
-
# injection-override: .agents/injections/capabilities/oats.linear.md
|
|
74
|
-
|
|
75
|
-
# Additive capabilities — non-exclusive; target global, agent-types, or souls.
|
|
76
|
-
additive:
|
|
77
|
-
example.review:
|
|
78
|
-
from: installed
|
|
79
|
-
agent-types:
|
|
80
|
-
developers:
|
|
81
|
-
enabled: true
|
|
82
|
-
settings:
|
|
83
|
-
depth: normal
|
|
84
|
-
souls:
|
|
85
|
-
security-reviewer:
|
|
86
|
-
enabled: true
|
|
87
|
-
settings:
|
|
88
|
-
depth: exhaustive
|
|
89
|
-
# injection-override: .agents/injections/capabilities/example.review.md
|
|
90
|
-
|
|
91
|
-
skill-overrides:
|
|
92
|
-
review: example.review
|
|
93
|
-
|
|
94
|
-
# ── Work modes — optional per-mode env bootstrap (briefings are packaged, not overridable).
|
|
95
|
-
work-modes:
|
|
96
|
-
worktree:
|
|
97
|
-
# Runs inside each NEW worktree right after `git worktree add` — env setup
|
|
98
|
-
# scripts (installs, .env copying, direnv/mise). Relative to this config's dir.
|
|
99
|
-
setup: scripts/setup-worktree.sh
|
|
100
|
-
|
|
101
|
-
# ── OATS defaults — the framework's baseline instruction block.
|
|
102
|
-
oats:
|
|
103
|
-
# injection-override: .agents/injections/oats-defaults/oats.md
|
|
104
|
-
|
|
105
|
-
# Extra unconditional instruction blocks for every instance at this scope.
|
|
106
|
-
agents-md-injection:
|
|
107
|
-
repository: injects/repository.md
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### `team`
|
|
111
|
-
|
|
112
|
-
`team:` declares the deployment boundary — typically at the workspace scope.
|
|
113
|
-
The closest scope declaring it wins, so every repo under `~/lfx` resolves the
|
|
114
|
-
same team. `name:` is required; `id:` optionally pins the provider team id
|
|
115
|
-
(for aweb, the canonical `<name>:<namespace>` form). Three things hang off
|
|
116
|
-
it:
|
|
117
|
-
|
|
118
|
-
- **Identity**: instances record their team in `instance.json` and their
|
|
119
|
-
TASK.md briefing; hooks receive `OATS_TEAM_NAME`/`OATS_TEAM_ID`/`OATS_TEAM_SCOPE`.
|
|
120
|
-
- **Discovery**: `oats status --team` lists agents across every `agents/`
|
|
121
|
-
root in the team scope (the scope's own plus each member repo's), so an
|
|
122
|
-
agent in one repo can see teammates defined at the workspace level or in
|
|
123
|
-
sibling repos. There is no explicit member list — every repo under the
|
|
124
|
-
team scope is a member by construction.
|
|
125
|
-
- **Cross-repo spawn/retire**: `oats spawn <soul>` and `oats retire <instance>`
|
|
126
|
-
resolve across the team scope's repos when the name isn't found locally
|
|
127
|
-
(unique match wins; ambiguity errors with guidance to pass `--dir`). The
|
|
128
|
-
instance homes with the soul's own repo, works in that repo, and resolves
|
|
129
|
-
that repo's config chain — spawning from elsewhere changes nothing about
|
|
130
|
-
the instance itself.
|
|
131
|
-
- **Messaging**: the aweb integration joins spawned instances into the
|
|
132
|
-
resolved team (id wins over name; a bare name is resolved against the aweb
|
|
133
|
-
root's memberships), with the instance name as the discoverable alias.
|
|
134
|
-
Because every instance joins with its own name, the aweb team roster is
|
|
135
|
-
also the **cross-machine directory**: `oats aweb roster` lists team members
|
|
136
|
-
wherever they run, complementing the local `oats status --team`.
|
|
137
|
-
|
|
138
|
-
### `agent-types`
|
|
139
|
-
|
|
140
|
-
Agent types are agent families. Config declares type names (optionally with a
|
|
141
|
-
description); membership is **not** listed in config — each soul opts in with
|
|
142
|
-
an optional single `type: <name>` in its `soul.yaml` (`oats create --type <t>`
|
|
143
|
-
sets it; `oats type add <name>` declares it in config). A type is identity: what kind of agent a soul is travels with the
|
|
144
|
-
soul, while config decides what each type gets. Tags, dynamic selectors, and
|
|
145
|
-
instance names are not supported.
|
|
146
|
-
|
|
147
|
-
### `capabilities.layers`
|
|
148
|
-
|
|
149
|
-
The three fundamental layers — `knowledge`, `messaging`, `tasks` — are
|
|
150
|
-
exclusive slots with an explicit home. Each slot holds either a capability
|
|
151
|
-
entry (`capability: <id>` plus optional `from`, targets, `settings`,
|
|
152
|
-
`injection-override`) or the explicit string `none`, which suppresses an integration
|
|
153
|
-
inherited from an outer scope. A slot absent from a config inherits from
|
|
154
|
-
outer scopes; `oats init` writes all three so the resolution is visible.
|
|
21
|
+
schemaVersion: 2
|
|
22
|
+
workspace: git:github.com/acme/agents # REQUIRED — the workspace host, observed over the remote
|
|
155
23
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
`additive`. A layer entry with no explicit targets is globally enabled at
|
|
159
|
-
that scope.
|
|
24
|
+
clones: # optional — member clones outside the <name>-workspace/ convention
|
|
25
|
+
github.com/acme/platform: /Users/ana/src/acme-platform
|
|
160
26
|
|
|
161
|
-
|
|
27
|
+
settings: # optional — host-owned values per capability
|
|
28
|
+
oats.okf:
|
|
29
|
+
bindings-file: /Users/ana/.oats/okf-bindings.json
|
|
30
|
+
state-dir: /Users/ana/.oats/okf
|
|
31
|
+
oats.aweb:
|
|
32
|
+
delivery: channel
|
|
162
33
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
inactive. A target value can be `true`, `false`, or an object containing
|
|
166
|
-
`enabled` and `settings`.
|
|
167
|
-
|
|
168
|
-
For a soul, matching global, agent-type, and soul bindings compose. Setting
|
|
169
|
-
precedence is:
|
|
170
|
-
|
|
171
|
-
1. soul;
|
|
172
|
-
2. matching agent-type;
|
|
173
|
-
3. global;
|
|
174
|
-
4. at equal target specificity, closer config scope.
|
|
175
|
-
|
|
176
|
-
Conflicting values at equal specificity and the same scope are errors. OATS
|
|
177
|
-
never uses YAML order as an implicit winner. `enabled: false` uses the same
|
|
178
|
-
precedence, allowing global enable → type exclusion → soul re-enable.
|
|
179
|
-
|
|
180
|
-
### `from` (provenance)
|
|
181
|
-
|
|
182
|
-
`from:` documents where the artifact must come from, and resolution enforces
|
|
183
|
-
it: `installed` (acquired into `.agents/capabilities/installed/`,
|
|
184
|
-
lock-governed — from the official marketplace by id, a git URL, or a local
|
|
185
|
-
path), `owned` (authored at this scope under `.agents/capabilities/owned/`),
|
|
186
|
-
or `path:<dir>` (development declaration pointing at a manifest directory).
|
|
187
|
-
A mismatch between `from:` and the discovered artifact origin is an error.
|
|
188
|
-
`from: bundled` was removed. Official capabilities are acquired like any other
|
|
189
|
-
package, and acquisition never grants executable trust — approve executable
|
|
190
|
-
surfaces explicitly with `oats trust <capability>`.
|
|
191
|
-
|
|
192
|
-
### `injection-override`
|
|
193
|
-
|
|
194
|
-
Every injectable item — each capability entry, each work mode, and the `oats:`
|
|
195
|
-
kernel block — accepts an `injection-override:` key: a config-relative path replaces
|
|
196
|
-
the packaged instruction file, `none` suppresses it, and `default` restores
|
|
197
|
-
it. The closest scope declaring the key wins. Scaffolded configs carry these
|
|
198
|
-
as commented-out lines pointing at the conventional locations:
|
|
199
|
-
|
|
200
|
-
```text
|
|
201
|
-
.agents/injections/capabilities/<capability-id>.md
|
|
202
|
-
.agents/injections/oats-defaults/oats.md
|
|
34
|
+
souls: # optional — souls this machine does not run
|
|
35
|
+
disabled: [data-analyst]
|
|
203
36
|
```
|
|
204
37
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
file then deliberately stops tracking package updates. Overrides are not
|
|
208
|
-
allowed on `from: owned`/`path:` entries: the scope owns the package source,
|
|
209
|
-
so its `injects/` file is edited directly.
|
|
210
|
-
|
|
211
|
-
### `skill-overrides`
|
|
212
|
-
|
|
213
|
-
Spawn fails when two sources contribute the same skill directory name. An
|
|
214
|
-
explicit override maps that name to the winning source (`soul`, `kernel`, a
|
|
215
|
-
capability ID, or a config source shown by doctor). Overrides are deliberate;
|
|
216
|
-
OATS never keeps whichever filesystem entry happened to be discovered first.
|
|
217
|
-
|
|
218
|
-
### Instruction sources
|
|
219
|
-
|
|
220
|
-
`agents-md-injection` adds unconditional config-owned instruction files (it
|
|
221
|
-
adds content; it does not override packaged defaults — that is `injection-override:`).
|
|
222
|
-
Capability packages can ship an `inject`; work modes have their own source.
|
|
38
|
+
Schema: [`oats-local.schema.json`](oats-local.schema.json). Unknown keys are
|
|
39
|
+
refused (`E_WORKSPACE_SCHEMA`).
|
|
223
40
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
41
|
+
| key | meaning |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `workspace` | Repo ref of the workspace host (`git:host/org/repo`, `https://…`, `git@host:…`, `file:///…`, `/abs/bare.git`). Read with your own Git credentials; the repo need not be cloned. |
|
|
44
|
+
| `clones` | `<canonical repo key>: <absolute path>` — where a member's clone lives when it is not at `<deployment>/<repo-name>/`. Only a soul's **work target** needs a clone. |
|
|
45
|
+
| `settings.<cap>.<key>` | Host-owned provider values the capability's manifest asks for — absolute paths, state roots, delivery modes. The workspace file **refuses** absolute paths; this is where they go. Merged into the capability's provider payload after the soul's own payload and before any `--provider` flag (see [three homes](workspaces.md#provider-payloads-have-three-homes)). |
|
|
46
|
+
| `souls.disabled` | Soul names not run on this machine; reported by `oats sync` ("disabled here"). |
|
|
228
47
|
|
|
229
|
-
|
|
48
|
+
## Where it sits and how it is found
|
|
230
49
|
|
|
231
|
-
|
|
50
|
+
Every `oats` command that needs the workspace (`sync`, `workspace status`,
|
|
51
|
+
`capabilities`, `souls`, `spawn`, `status` drift) walks **up** from the current
|
|
52
|
+
directory (or `--dir`) to the nearest `oats-local.yaml`; its directory is the
|
|
53
|
+
deployment. Not found → `E_LOCAL_MISSING`. Beside it:
|
|
232
54
|
|
|
233
|
-
- `worktree`: dedicated branch/worktree;
|
|
234
|
-
- `checkout`: shared current checkout;
|
|
235
|
-
- `attached`: another instance's work tree;
|
|
236
|
-
- `workspace`: the whole team scope — cross-repo coordinators that read all
|
|
237
|
-
member repos but never edit them (their soul's knowledge updates arrive as
|
|
238
|
-
PRs to the soul's home repo).
|
|
239
|
-
|
|
240
|
-
Work-mode briefings are packaged with the kernel and are not overridable;
|
|
241
|
-
the only work-mode configuration is `setup:` — an env-bootstrap command that
|
|
242
|
-
runs inside each fresh worktree after creation (a lot of teams prefer a
|
|
243
|
-
script that sets up the environment: installs, .env copying, direnv/mise).
|
|
244
|
-
Its failure warns without hiding the instance.
|
|
245
|
-
|
|
246
|
-
### `launch-configs`
|
|
247
|
-
|
|
248
|
-
A named way to start a harness, independent of any soul: which runtime, an
|
|
249
|
-
executable (a wrapper, another binary), literal arguments, environment, a
|
|
250
|
-
model and yolo. Souls keep their own defaults; a launch configuration is
|
|
251
|
-
selected by name at spawn or when an existing instance is started or
|
|
252
|
-
restarted, so the same home can move between configurations without
|
|
253
|
-
being replaced.
|
|
254
|
-
|
|
255
|
-
```yaml
|
|
256
|
-
launch-configs:
|
|
257
|
-
personal:
|
|
258
|
-
runtime: claude
|
|
259
|
-
executable: ./bin/claude-personal # relative: against THIS scope's directory
|
|
260
|
-
args:
|
|
261
|
-
- "--settings"
|
|
262
|
-
- "/Users/me/.claude-personal/settings.json" # a native config file is an ordinary
|
|
263
|
-
# argument the harness reads from the
|
|
264
|
-
# INSTANCE HOME it starts in: absolute
|
|
265
|
-
env:
|
|
266
|
-
ANTHROPIC_API_KEY:
|
|
267
|
-
fromEnv: PERSONAL_ANTHROPIC_KEY # resolved on the execution host at start
|
|
268
|
-
CLAUDE_CONFIG_DIR: "/Users/me/.claude-personal"
|
|
269
|
-
model: claude-opus-5
|
|
270
|
-
yolo: true
|
|
271
|
-
fast:
|
|
272
|
-
runtime: codex
|
|
273
|
-
model: gpt-5.5
|
|
274
55
|
```
|
|
275
|
-
|
|
276
|
-
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
It must exist and be executable; it is never run just to probe it.
|
|
281
|
-
- `args` and literal `env` values are passed byte-exact: spaces, quotes and
|
|
282
|
-
shell metacharacters are literal, never interpreted. A path among them is
|
|
283
|
-
read by the harness from the instance home it starts in, not from the
|
|
284
|
-
declaring scope: write native configuration paths absolute.
|
|
285
|
-
- `env` values are either literals (non-secret by contract, but no answer ever
|
|
286
|
-
shows them: `oats launch-config list` and `preview` redact them) or
|
|
287
|
-
`{fromEnv: NAME}` references, which is the way to hand a secret to a
|
|
288
|
-
harness. Only the reference is recorded in an instance's launch recipe and
|
|
289
|
-
receipts; the value is read from the execution host's environment at start
|
|
290
|
-
time, and a missing reference refuses the start before anything stops.
|
|
291
|
-
- `model` and `yolo` override the soul's defaults when the configuration is
|
|
292
|
-
selected; explicit `--model`/`--yolo` flags override the configuration.
|
|
293
|
-
|
|
294
|
-
The CLI authors the block:
|
|
295
|
-
|
|
296
|
-
```sh
|
|
297
|
-
oats launch-config list [--dir <scope> | --home <abs> | --soul <name>] --json
|
|
298
|
-
oats launch-config set personal --file personal.json [--keep-env] --dir <scope>
|
|
299
|
-
oats launch-config remove personal --dir <scope>
|
|
56
|
+
~/acme-workspace/
|
|
57
|
+
├── oats-local.yaml
|
|
58
|
+
├── oats-lock.json # written by `oats sync` (lock v3; docs/packages.md)
|
|
59
|
+
├── agents/ # instance homes + fetched member-soul sources
|
|
60
|
+
└── <member clones>/ # only where someone works IN a repo
|
|
300
61
|
```
|
|
301
62
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
or the inherited one being overridden) into the complete new entry, once: an
|
|
306
|
-
editor that saw only redacted values omits `env` from its definition. It is a
|
|
307
|
-
copy at save time, not inheritance; the new entry shadows whole. `list --home`
|
|
308
|
-
reads the home's recorded context; `list --soul` reads the soul's own member
|
|
309
|
-
scope.
|
|
310
|
-
|
|
311
|
-
## Acquisition and lockfile
|
|
312
|
-
|
|
313
|
-
External acquisition writes `oats-lock.json` beside the declaring config in
|
|
314
|
-
`lockfileVersion: 2`. It records two levels — a `packages` map (source, exact
|
|
315
|
-
commit, selected path, payload integrity, dependencies) and a `capabilities`
|
|
316
|
-
map (each materialized capability's version, provider package, path, artifact
|
|
317
|
-
integrity, and executable trust):
|
|
318
|
-
|
|
319
|
-
```json
|
|
320
|
-
{
|
|
321
|
-
"lockfileVersion": 2,
|
|
322
|
-
"packages": {
|
|
323
|
-
"example.engineering": {
|
|
324
|
-
"source": "git:https://example.invalid/engineering.git@v1.4.2",
|
|
325
|
-
"version": "1.4.2",
|
|
326
|
-
"commit": "0123456789abcdef0123456789abcdef01234567",
|
|
327
|
-
"path": "oats-package",
|
|
328
|
-
"integrity": "sha256-…",
|
|
329
|
-
"dependencies": []
|
|
330
|
-
}
|
|
331
|
-
},
|
|
332
|
-
"capabilities": {
|
|
333
|
-
"example.review": {
|
|
334
|
-
"version": "1.4.2",
|
|
335
|
-
"package": "example.engineering",
|
|
336
|
-
"path": "capabilities/example-review",
|
|
337
|
-
"integrity": "sha256-…",
|
|
338
|
-
"trusted": false
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
No command silently updates this record. Changed capability integrity blocks the
|
|
345
|
-
artifact and resets its trust. `oats trust <id>` approves commands, hooks, and
|
|
346
|
-
launch-environment authority only for the exact locked artifact integrity, and
|
|
347
|
-
official identity never grants it.
|
|
348
|
-
Declarative skill/instruction capabilities need a valid lock but no executable
|
|
349
|
-
approval. Capabilities authored under a scope's `.agents/capabilities/owned/`
|
|
350
|
-
follow their reviewed source provenance. Materialized artifacts live in
|
|
351
|
-
`.agents/capabilities/installed/<id>/` beside their lock, stay gitignored, and
|
|
352
|
-
are re-materialized by bare `oats install` with integrity verification.
|
|
353
|
-
|
|
354
|
-
Legacy `lockfileVersion: 1` locks (per-capability marketplace installs) remain
|
|
355
|
-
readable and usable. `oats migrate` converts a scope to the revised v2 lock
|
|
356
|
-
**all-or-nothing**: if any entry cannot map to a package yet, the whole scope
|
|
357
|
-
stays byte-identical v1 and keeps working, and a successful run converts the
|
|
358
|
-
entire scope at once. There is no residue container — a converted lock never
|
|
359
|
-
carries leftover v1 entries. The earlier transitional v2 shape — capability
|
|
360
|
-
lists on package rows, a persistent `.agents/packages/installed/` store — is
|
|
361
|
-
rejected as an invalid lock and recreated by a fresh acquisition, never
|
|
362
|
-
migrated. See `docs/capabilities.md` (“Distribution packages”), the schemas
|
|
363
|
-
`docs/oats-package.schema.json` / `docs/oats-lock.schema.json`, and
|
|
364
|
-
`docs/design/package-engine-contract.md`.
|
|
365
|
-
|
|
366
|
-
## CLI
|
|
367
|
-
|
|
368
|
-
```bash
|
|
369
|
-
oats init [--raw] [--template <name|path|git-url>] [--knowledge <id|none>] [--messaging <id|none>] [--tasks <id|none>]
|
|
370
|
-
oats install [<id|git-url|path>] [--dir <dir>] # acquire; bare form restores; inactive by default
|
|
371
|
-
oats trust <capability> [--dir <dir>]
|
|
372
|
-
oats use <capability> [--global|--type <t>|--soul <s>] [--disable] [--settings k=v [k2=v2 ...]]
|
|
373
|
-
oats use none --layer <layer>
|
|
374
|
-
oats type add <name> [--description <d>] # declare an agent type
|
|
375
|
-
oats type list
|
|
376
|
-
oats inject eject <capability|oats> # materialize an injection override
|
|
377
|
-
oats create <name> --type <agent-type> ...
|
|
378
|
-
oats doctor [context] --soul <name> [--json]
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
`oats init` writes only explicitly selected defaults, acquiring marketplace
|
|
382
|
-
layer capabilities into this scope's installed/ store as needed; it does not
|
|
383
|
-
activate every acquired package. `oats use`
|
|
384
|
-
places a layer-declaring capability under `capabilities.layers.<layer>` and
|
|
385
|
-
everything else under `capabilities.additive`, regenerating the conventional
|
|
386
|
-
injection comments; custom comments inside the `capabilities:` block are not
|
|
387
|
-
preserved.
|
|
388
|
-
|
|
389
|
-
`oats use` activates **into a config file**, so it needs one at this scope or an
|
|
390
|
-
outer one. In a scope with no `oats-config.yaml` anywhere in its chain, a
|
|
391
|
-
capability already present in that scope's own `installed/` or `owned/` store
|
|
392
|
-
fails with `E_NO_CONFIG` naming the initialization to run first — exactly
|
|
393
|
-
`oats init --raw --dir <scope>`, which is offline, deterministic and writes only
|
|
394
|
-
the minimal config — and then the same `oats use` command again. It never
|
|
395
|
-
reports the capability as unacquired, and it writes nothing: authoring a
|
|
396
|
-
scope's first config is `oats init`'s job.
|
|
397
|
-
|
|
398
|
-
### Templates
|
|
399
|
-
|
|
400
|
-
`oats init --template <name|path|git-url>` seeds the new config from a template
|
|
401
|
-
config file: a local path, a git URL whose default branch carries an
|
|
402
|
-
`oats-config.yaml`, or a name resolved through a `templates:` map declared in an
|
|
403
|
-
outer scope (typically the laptop config):
|
|
404
|
-
|
|
405
|
-
```yaml
|
|
406
|
-
# ~/oats-config.yaml
|
|
407
|
-
templates:
|
|
408
|
-
personal: ~/templates/personal-oats-config.yaml
|
|
409
|
-
team: https://example.invalid/oats-templates.git
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
A template seed is copied once. `init` copies the content, records provenance in
|
|
413
|
-
a leading `# template:` comment, rewrites `name:`, strips the `templates:` map,
|
|
414
|
-
and runs a restore so declared external capabilities are present. Later template
|
|
415
|
-
edits never propagate silently.
|
|
416
|
-
|
|
417
|
-
### Package config templates
|
|
418
|
-
|
|
419
|
-
When the config and its capability providers travel together, prefer
|
|
420
|
-
`oats init --package <source> [--config <name>]`. It validates a reference config
|
|
421
|
-
template shipped by a distribution package and writes it as your local
|
|
422
|
-
`oats-config.yaml`, recording the exact template as a commit-safe adopted base
|
|
423
|
-
with package, template, and commit provenance. `oats config diff` and
|
|
424
|
-
`oats config sync` compare against that base later. Installing the package alone
|
|
425
|
-
adopts no template. See [Distribution packages](packages.md).
|
|
426
|
-
|
|
427
|
-
## Fundamental-layer disable
|
|
428
|
-
|
|
429
|
-
An inner scope can suppress an inherited integration without selecting a
|
|
430
|
-
replacement:
|
|
431
|
-
|
|
432
|
-
```yaml
|
|
433
|
-
capabilities:
|
|
434
|
-
layers:
|
|
435
|
-
tasks: none
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
`oats use none --layer tasks` writes this. Pre-v0.9 spellings (`groups:`,
|
|
439
|
-
top-level `layers:`, flat `capabilities.<id>` maps, `source:`,
|
|
440
|
-
`agents-md-injection` on capability entries) are rejected with pointed
|
|
441
|
-
migration errors. Key names are matched as own properties only, so a key
|
|
442
|
-
spelled `constructor` or `toString` is reported as an unsupported key, never as
|
|
443
|
-
a renamed one. `__proto__` is refused outright by every YAML reader — the
|
|
444
|
-
kernel's and the desktop app's own read-only reader — and by the commands that
|
|
445
|
-
WRITE config keys (`oats use --settings`, `--soul`, `--type`), all with
|
|
446
|
-
`unsafe-config-key`: assigning it rewrites the parsed mapping's prototype
|
|
447
|
-
instead of becoming data, which would hide the entry from every key validator.
|
|
448
|
-
The kernel fails closed and reports the offending file; the desktop reader
|
|
449
|
-
degrades that document to "not visible", per its read-only contract.
|
|
450
|
-
|
|
451
|
-
Text that cannot be written as ONE YAML scalar on one line is refused. The
|
|
452
|
-
policed inputs are exactly: `oats use --settings` keys and values, `oats use
|
|
453
|
-
--soul` and `--type` names, `oats type add --description`, and the scaffolded
|
|
454
|
-
`name:` value that `oats init` (in every form) and the first `oats use` / `oats
|
|
455
|
-
type add` at a fresh scope take from the target directory's basename — a
|
|
456
|
-
basename is filesystem input, so one carrying a newline would otherwise write
|
|
457
|
-
arbitrary top-level blocks into the config.
|
|
458
|
-
|
|
459
|
-
Refused: a control character (a newline in a `--settings` value used to inject
|
|
460
|
-
whole extra capability entries into the file) or one of the three line breaks
|
|
461
|
-
outside that range (U+0085, U+2028, U+2029 — U+2028/U+2029 made the reader drop
|
|
462
|
-
the written line entirely, so the command reported success for a setting that
|
|
463
|
-
was not there afterwards); leading or trailing whitespace a read would strip; a
|
|
464
|
-
leading YAML structure indicator (`#`, `|`, `>`, `&`, `*`, `!`, `%`, `@`,
|
|
465
|
-
`` ` ``, `,`, a quote, a flow bracket, or `- `/`? `/`: `); for a VALUE, an
|
|
466
|
-
embedded `" #"` (which opens a trailing comment, so the rest would be dropped
|
|
467
|
-
on read) and an empty value (`key:` with nothing after it reads back as an
|
|
468
|
-
empty map, not an empty string); and — for keys and `--soul`/`--type` names —
|
|
469
|
-
the `:` and `#` that end a key token. Those fail with `unsafe-config-value`
|
|
470
|
-
(values, the scaffolded name included) or `unsafe-config-key` (keys and names),
|
|
471
|
-
and nothing is written.
|
|
472
|
-
|
|
473
|
-
The guarantee is a round trip through the OATS reader, not conformance to an
|
|
474
|
-
external YAML parser: ordinary values are untouched because those characters
|
|
475
|
-
are structural only in first position, so `expr=2 > 1`, `tag=v1.0#build`,
|
|
476
|
-
`list=a,b` and even `mode=a: b` come back exactly as they were written.
|
|
477
|
-
|
|
478
|
-
## Worked examples
|
|
479
|
-
|
|
480
|
-
### All souls use OKF; only developers use Linear
|
|
481
|
-
|
|
482
|
-
For OKF v2, every working soul needs an explicit `okf.json` owner declaration
|
|
483
|
-
and provisioned external nodes. A `bindings-file` alone is not initialization.
|
|
484
|
-
See [knowledge setup](knowledge.md#acquire-bind-and-provision-explicitly) and
|
|
485
|
-
[v1 migration](knowledge-migration.md); target only ready souls if the rest of
|
|
486
|
-
the scope is not yet configured. These examples describe the prepared v2 path.
|
|
487
|
-
|
|
488
|
-
```yaml
|
|
489
|
-
agent-types:
|
|
490
|
-
developers:
|
|
491
|
-
description: Souls with type: developers in their soul.yaml
|
|
492
|
-
capabilities:
|
|
493
|
-
layers:
|
|
494
|
-
knowledge:
|
|
495
|
-
capability: oats.okf
|
|
496
|
-
from: installed
|
|
497
|
-
settings:
|
|
498
|
-
bindings-file: /absolute/config/okf-bindings.json
|
|
499
|
-
tasks:
|
|
500
|
-
capability: oats.linear
|
|
501
|
-
from: installed
|
|
502
|
-
agent-types:
|
|
503
|
-
developers:
|
|
504
|
-
enabled: true
|
|
505
|
-
settings: {team: ENG, project: Product}
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
### Laptop default with repository exclusion
|
|
509
|
-
|
|
510
|
-
Laptop:
|
|
511
|
-
|
|
512
|
-
```yaml
|
|
513
|
-
capabilities:
|
|
514
|
-
layers:
|
|
515
|
-
messaging:
|
|
516
|
-
capability: oats.aweb
|
|
517
|
-
from: installed
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
Solo repository:
|
|
521
|
-
|
|
522
|
-
```yaml
|
|
523
|
-
capabilities:
|
|
524
|
-
layers:
|
|
525
|
-
messaging: none
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
### One marketplace capability for one soul
|
|
529
|
-
|
|
530
|
-
```yaml
|
|
531
|
-
capabilities:
|
|
532
|
-
additive:
|
|
533
|
-
vendor.security-review:
|
|
534
|
-
from: installed
|
|
535
|
-
souls:
|
|
536
|
-
security-reviewer: true
|
|
537
|
-
```
|
|
63
|
+
Never commit `oats-local.yaml` to a shared repo: it names one machine's paths.
|
|
64
|
+
Two operators of the same workspace share the declarations through Git and
|
|
65
|
+
nothing else.
|
|
538
66
|
|
|
539
|
-
|
|
540
|
-
does not download, update, or approve code.
|
|
67
|
+
## What is NOT in it
|
|
541
68
|
|
|
542
|
-
|
|
69
|
+
- **Which capabilities a soul gets** — the soul's `capabilities:` plus the
|
|
70
|
+
workspace `defaults` (and `defaults.byTeam`). There is no per-deployment
|
|
71
|
+
activation or targeting.
|
|
72
|
+
- **Versions** — `packages:` in the workspace file; exact commits in
|
|
73
|
+
`oats-lock.json`.
|
|
74
|
+
- **Trust** — membership for members; per-version approval in the lock for
|
|
75
|
+
packages. No per-operator trust list.
|
|
76
|
+
- **Per-instance provider facts** (a retained messaging seat, a one-off state
|
|
77
|
+
root) — `oats spawn <soul> --provider <cap> key=value`, recorded in
|
|
78
|
+
`instance.json.providers`.
|
|
79
|
+
- **Team labels, stores, messaging policy** — the workspace file.
|
|
543
80
|
|
|
544
|
-
|
|
545
|
-
`~/.tmux.conf` or XDG tmux config so agent windows scroll normally with a mouse
|
|
546
|
-
or trackpad. It never changes terminal keyboard mappings. Agent-led and
|
|
547
|
-
scripted setup should pass the user's answer explicitly:
|
|
81
|
+
## Inspecting the effective configuration
|
|
548
82
|
|
|
549
83
|
```bash
|
|
550
|
-
oats
|
|
551
|
-
oats
|
|
552
|
-
oats
|
|
84
|
+
oats workspace status # membership table, locked packages, approval state, external souls
|
|
85
|
+
oats sync # confirm, resolve, approve, report the diff
|
|
86
|
+
oats capabilities | oats souls # everything a soul may name, with origin and team
|
|
87
|
+
oats spawn <soul> --preview # the exact modules (from/commit/changedSince), team, resolution revision
|
|
88
|
+
oats doctor # this deployment's oats-local.yaml and lock, plus kernel diagnostics
|
|
553
89
|
```
|
|
554
90
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
activation.
|
|
91
|
+
Environment knobs the kernel honours: `OATS_REMOTE_CACHE` (relocates the
|
|
92
|
+
invisible fetch cache), `OATS_PACKAGE_CATALOG` (an alternative catalog file).
|