@awebai/oats 0.22.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/LICENSE +21 -0
- package/README.md +380 -0
- package/bin/oats.mjs +3294 -0
- package/capabilities/oats-authoring/oats.json +12 -0
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +297 -0
- package/capabilities/oats-aweb/injects/aweb.md +55 -0
- package/capabilities/oats-aweb/oats.json +47 -0
- package/capabilities/oats-aweb/package.json +20 -0
- package/capabilities/oats-jira/bin/oats-jira.mjs +40 -0
- package/capabilities/oats-jira/injects/jira.md +10 -0
- package/capabilities/oats-jira/oats.json +22 -0
- package/capabilities/oats-jira/package.json +25 -0
- package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +176 -0
- package/capabilities/oats-linear/README.md +234 -0
- package/capabilities/oats-linear/bin/oats-linear-hook.mjs +32 -0
- package/capabilities/oats-linear/bin/oats-linear.mjs +344 -0
- package/capabilities/oats-linear/injects/linear.md +8 -0
- package/capabilities/oats-linear/oats.json +24 -0
- package/capabilities/oats-linear/package.json +29 -0
- package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +217 -0
- package/capabilities/oats-linear/test/oats-linear.test.mjs +168 -0
- package/capabilities/oats-okf/agents/memory-harvest.md +25 -0
- package/capabilities/oats-okf/bin/oats-okf.mjs +283 -0
- package/capabilities/oats-okf/injects/okf.md +62 -0
- package/capabilities/oats-okf/oats.json +20 -0
- package/capabilities/oats-okf/package.json +22 -0
- package/capabilities/oats-okf/skills/memory-harvest/SKILL.md +100 -0
- package/capabilities/oats-okf/skills/okf/SKILL.md +107 -0
- package/capabilities/oats-okf/skills/okf/scripts/okf-validate.mjs +123 -0
- package/capabilities/oats-review/agents/reviewer/AGENTS.md +53 -0
- package/capabilities/oats-review/agents/reviewer/soul.yaml +6 -0
- package/capabilities/oats-review/injects/review.md +68 -0
- package/capabilities/oats-review/oats.json +10 -0
- package/capabilities/oats-review/skills/code-review/SKILL.md +44 -0
- package/capabilities/oats-review/skills/security-review/SKILL.md +59 -0
- package/docs/capabilities.md +505 -0
- package/docs/capability-manifest.schema.json +223 -0
- package/docs/configuration.md +482 -0
- package/docs/conventions.md +73 -0
- package/docs/design/desktop-ux-plan.md +362 -0
- package/docs/design/package-engine-contract.md +813 -0
- package/docs/design/package-runtime-api.md +414 -0
- package/docs/desktop-cli-api.md +89 -0
- package/docs/desktop-succession.md +51 -0
- package/docs/desktop.md +187 -0
- package/docs/implementation.md +282 -0
- package/docs/integrations.md +123 -0
- package/docs/knowledge-theory.md +97 -0
- package/docs/knowledge.md +139 -0
- package/docs/layers.md +110 -0
- package/docs/migration-from-oas.md +122 -0
- package/docs/oats-config.schema.json +140 -0
- package/docs/oats-lock.schema.json +175 -0
- package/docs/oats-package.schema.json +129 -0
- package/docs/packages.md +442 -0
- package/docs/release-lane.md +132 -0
- package/docs/release-notes/v0.18.2.md +79 -0
- package/docs/release-notes/v0.18.3.md +63 -0
- package/docs/release-notes/v0.18.4.md +65 -0
- package/docs/release-notes/v0.18.5.md +66 -0
- package/docs/release-notes/v0.18.6.md +87 -0
- package/docs/release-notes/v0.19.0.md +186 -0
- package/docs/release-notes/v0.19.1.md +24 -0
- package/docs/release-notes/v0.19.2.md +32 -0
- package/docs/release-notes/v0.19.3.md +16 -0
- package/docs/release-notes/v0.19.4.md +12 -0
- package/docs/release-notes/v0.20.0.md +89 -0
- package/docs/release-notes/v0.22.0.md +180 -0
- package/docs/souls-and-instances.md +344 -0
- package/injects/framework-workspace.md +7 -0
- package/injects/instance-boundary.md +43 -0
- package/injects/local-soul.md +19 -0
- package/injects/oats.md +11 -0
- package/injects/work-attached.md +16 -0
- package/injects/work-checkout.md +12 -0
- package/injects/work-workspace.md +22 -0
- package/injects/work-worktree.md +13 -0
- package/lib/core.mjs +6792 -0
- package/lib/packages.mjs +1375 -0
- package/lib/tmux-config.mjs +35 -0
- package/package-catalog.json +44 -0
- package/package.json +55 -0
- package/packages/record/README.md +151 -0
- package/packages/record/bin/capture.mjs +256 -0
- package/packages/record/bin/recall.mjs +102 -0
- package/packages/record/bin/setup.mjs +281 -0
- package/packages/record/bin/turn-record.mjs +47 -0
- package/packages/record/docs/turn-record-sot.md +350 -0
- package/packages/record/lib/canonical.mjs +151 -0
- package/packages/record/lib/capture-aw.mjs +179 -0
- package/packages/record/lib/capture-cc.mjs +322 -0
- package/packages/record/lib/formats.mjs +296 -0
- package/packages/record/lib/ignore.mjs +155 -0
- package/packages/record/lib/index-db.mjs +524 -0
- package/packages/record/lib/project-aweb.mjs +251 -0
- package/packages/record/lib/segments.mjs +186 -0
- package/packages/record/lib/store.mjs +447 -0
- package/packages/record/lib/tags.mjs +114 -0
- package/packages/record/package.json +45 -0
- package/packages/record/test/vectors/README.md +34 -0
- package/packages/record/test/vectors/aweb-projection-v1.json +231 -0
- package/packages/record/test/vectors/journal-merge-v1.json +261 -0
- package/packages/record/test/vectors/turn-id-v1.json +152 -0
- package/packages/record/test/vectors/validate.mjs +391 -0
- package/skills/integration-authoring/SKILL.md +76 -0
- package/skills/oats/SKILL.md +151 -0
- package/skills/oats-config/SKILL.md +162 -0
- package/skills/oats-getting-started/SKILL.md +159 -0
- package/skills/oats-packages/SKILL.md +180 -0
- package/skills/oats-support/SKILL.md +79 -0
- package/skills/skill-craft/SKILL.md +109 -0
- package/skills/soul-craft/SKILL.md +109 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
# Capability packages
|
|
2
|
+
|
|
3
|
+
A **capability package** is OATS's reusable distribution unit. It can contribute
|
|
4
|
+
skills, instance instructions, requirements, namespaced commands, and approved
|
|
5
|
+
lifecycle hooks. Configuration—not the package—decides which souls receive it.
|
|
6
|
+
|
|
7
|
+
An **integration** is a capability package that implements one exclusive
|
|
8
|
+
fundamental layer: `knowledge`, `messaging`, or `tasks`. General capabilities
|
|
9
|
+
claim no layer and compose additively.
|
|
10
|
+
|
|
11
|
+
## Mental model
|
|
12
|
+
|
|
13
|
+
This is OATS's first public capability-package contract. The unpublished,
|
|
14
|
+
pre-release integration prototype has no compatibility promise: its manifest,
|
|
15
|
+
config, discovery, and command aliases are intentionally not accepted.
|
|
16
|
+
|
|
17
|
+
The contract is:
|
|
18
|
+
|
|
19
|
+
1. **Acquire** a package. External artifacts are pinned in `oats-lock.json`.
|
|
20
|
+
2. **Activate** it for global scope, a config-owned soul group, or one soul.
|
|
21
|
+
3. **Spawn** a soul. OATS resolves the target, creates the exact
|
|
22
|
+
`.agents/skills/`, and generates that instance's `AGENTS.md` without
|
|
23
|
+
changing the canonical soul.
|
|
24
|
+
|
|
25
|
+
Acquired does not mean active. `oats init` activates only the explicit defaults
|
|
26
|
+
it writes; it never enables every package merely because it is available.
|
|
27
|
+
|
|
28
|
+
## Manifest
|
|
29
|
+
|
|
30
|
+
A self-contained package has an `oats.json`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"capability": "example.team-chat",
|
|
35
|
+
"command": "team-chat",
|
|
36
|
+
"version": "1.2.3",
|
|
37
|
+
"compatibility": { "oats": ">=0.6.2" },
|
|
38
|
+
"description": "Messaging through Team Chat.",
|
|
39
|
+
"layer": "messaging",
|
|
40
|
+
"requires": [
|
|
41
|
+
{ "command": "team-chat", "why": "send and receive messages" },
|
|
42
|
+
{
|
|
43
|
+
"runtime": "pi",
|
|
44
|
+
"package": "npm:team-chat-pi",
|
|
45
|
+
"why": "real-time push events in pi sessions"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"skills": ["skills"],
|
|
49
|
+
"inject": "injects/team-chat.md",
|
|
50
|
+
"commands": { "auth": "bin/team-chat.mjs auth" },
|
|
51
|
+
"environment": ["EXAMPLE_IDENTITY_HOME"],
|
|
52
|
+
"hooks": {
|
|
53
|
+
"spawn": "bin/team-chat-hook.mjs spawn",
|
|
54
|
+
"retire": "bin/team-chat-hook.mjs retire"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `capability` is a namespaced ID. Duplicate IDs are errors. A capability that
|
|
60
|
+
declares launch environment must use a lowercase dotted vendor prefix such
|
|
61
|
+
as `aweb.identity`, because that prefix owns the corresponding `AWEB_*`
|
|
62
|
+
namespace.
|
|
63
|
+
- `command` is an optional, unique CLI namespace. The example exposes
|
|
64
|
+
`oats team-chat auth`.
|
|
65
|
+
- `layer` is optional and may name exactly one fundamental layer. Two active
|
|
66
|
+
packages cannot implement the same layer for one soul.
|
|
67
|
+
- `skills` entries can be skill directories or roots containing skills.
|
|
68
|
+
- `inject` is optional instance instruction Markdown.
|
|
69
|
+
- Only `soul-scaffold`, `spawn`, and `retire` hooks are accepted. A hook is a
|
|
70
|
+
command string, or `{ command, required }`. `required: true` is valid **only
|
|
71
|
+
on `spawn`**: the hook's failure then fails the spawn and rolls it back,
|
|
72
|
+
instead of producing an instance whose capability never configured itself —
|
|
73
|
+
an aweb identity that could not be minted leaves an agent believing it can be
|
|
74
|
+
woken by mail. Every other hook stays best-effort and only warns, so advisory
|
|
75
|
+
work never becomes a spawn blocker. `retire` and `soul-scaffold` cannot be
|
|
76
|
+
required: they run outside a spawn transaction, so there is no moment to
|
|
77
|
+
enforce them.
|
|
78
|
+
- A capability declaring a **required** spawn hook should declare a `retire` hook
|
|
79
|
+
too. Without one, OATS has no way to undo what the spawn hook did and no way to
|
|
80
|
+
know whether it did anything, so a failure quarantines the home rather than
|
|
81
|
+
rolling it back — the operator cleans up by hand and removes it with `--force`.
|
|
82
|
+
- A required hook must also be **able** to run: if its capability's executable
|
|
83
|
+
surface is not trusted, the spawn fails with the `oats trust` remedy rather
|
|
84
|
+
than starting without the setup. Advisory executable hooks stay
|
|
85
|
+
disabled-with-warning.
|
|
86
|
+
- When a required hook fails and its compensation cannot finish, the instance
|
|
87
|
+
home is **retained**, not deleted — it holds the credentials and metadata a
|
|
88
|
+
retry needs, and removing it would turn a transient cleanup failure into
|
|
89
|
+
permanent external residue. It is marked `.oats-rollback-incomplete.json`, so
|
|
90
|
+
`oats status` reports it as retained state rather than a live instance, and
|
|
91
|
+
`oats retire <instance>` retries the cleanup — re-running the retire hooks and
|
|
92
|
+
the rollback-owned Git steps, and verifying both. A retry that still cannot
|
|
93
|
+
finish keeps the home again, names what is outstanding, and exits nonzero.
|
|
94
|
+
- The **escape hatch is `oats retire <instance> --force`**, for a home OATS cannot
|
|
95
|
+
identify at all: no `instance.json` and no **usable** cleanup descriptor. Usable
|
|
96
|
+
means it satisfies the versioned cleanup contract the rollback writes, checked
|
|
97
|
+
to the depth the retry consumes it: `version`, a context `repo`, a recognised
|
|
98
|
+
`work` mode (plus a `branch` for `worktree` — an unknown mode would skip the
|
|
99
|
+
rollback-owned Git cleanup and call it done), a real non-empty capability set,
|
|
100
|
+
and the record of what still owes cleanup — retire hooks by capability id, plus
|
|
101
|
+
the rollback-owned Git steps (`worktree`, `branch`) where the mode has them. That
|
|
102
|
+
record can never be empty: a quarantine exists because something is outstanding,
|
|
103
|
+
and one claiming otherwise would give the retry nothing to prove. A marker failing any of
|
|
104
|
+
that is no more retryable than a missing one, and is treated as missing so the
|
|
105
|
+
escape hatch works.
|
|
106
|
+
- A retry clears the quarantine only by **proving the outstanding work happened**:
|
|
107
|
+
every retire hook the marker records as owing cleanup must have run and reported
|
|
108
|
+
success, and every Git step it records must be re-run and verified. A retry that resolves no
|
|
109
|
+
capabilities — a hand-edited descriptor, or config drift since the spawn — is an
|
|
110
|
+
incomplete cleanup, not a clean one, and the home stays.
|
|
111
|
+
- Because some cleanups can never succeed (a capability offering no way to undo its
|
|
112
|
+
own setup, a permanently unreachable remote), **`--force` also overrides
|
|
113
|
+
retention**: the home is removed, and everything still outstanding is printed as
|
|
114
|
+
state the operator now owns. Nothing is ever permanently unremovable through OATS,
|
|
115
|
+
and nothing is silently dropped. Without `--force` that state fails closed with
|
|
116
|
+
`E_UNIDENTIFIED_INSTANCE_HOME` rather than deleting whatever credentials the
|
|
117
|
+
directory still holds; `--force` removes it and leaves any external state for
|
|
118
|
+
the operator to clean up by hand.
|
|
119
|
+
- `requires` declares what must exist before the capability works. Two kinds:
|
|
120
|
+
- a **host command** (`command`), satisfied by a binary on `PATH`;
|
|
121
|
+
- a **runtime package** (`runtime` + `package`, optionally `marketplace`),
|
|
122
|
+
satisfied by that runtime's own package manager — `npm:@scope/name` for pi,
|
|
123
|
+
`plugin@marketplace` for Claude Code. It is raised only for deployments that use the named
|
|
124
|
+
runtime — a Claude-only deployment is never asked to install a pi package —
|
|
125
|
+
and is verified in the runtime's package list, never on `PATH`. A version
|
|
126
|
+
selector is allowed and ignored for identity, so `@latest` and a pinned
|
|
127
|
+
version are one requirement.
|
|
128
|
+
A runtime package is **verified at spawn, never installed there**: installing
|
|
129
|
+
would mutate the operator's runtime configuration without asking, in the
|
|
130
|
+
middle of a spawn. A missing, uninstalled or disabled package fails the spawn
|
|
131
|
+
with the consent command that fixes it.
|
|
132
|
+
- OATS never installs a requirement silently. `oats install` prompts per
|
|
133
|
+
requirement with the exact argv, source and scope; automation passes
|
|
134
|
+
`--accept-requirement <name>` (the name is the command, or
|
|
135
|
+
`<runtime>:<package>`), and `--no-requirements` skips the gate. When a plan
|
|
136
|
+
has several steps — registering a Claude marketplace before installing from
|
|
137
|
+
it — every step is shown, because agreeing to a plugin also means agreeing to
|
|
138
|
+
the source it comes from. Declining
|
|
139
|
+
leaves an actionable `oats doctor` warning. Consent to install is separate
|
|
140
|
+
from capability trust.
|
|
141
|
+
- `environment` lists the exact launch variables executable trust approves;
|
|
142
|
+
spawn hook output must be a subset and use the capability vendor prefix.
|
|
143
|
+
- Target names never appear in a package manifest.
|
|
144
|
+
|
|
145
|
+
`capability` is the only manifest identity field. The machine-readable
|
|
146
|
+
contract is [`capability-manifest.schema.json`](capability-manifest.schema.json).
|
|
147
|
+
|
|
148
|
+
## Config and targets
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
agent-types:
|
|
152
|
+
developers:
|
|
153
|
+
description: Agents that build the service (souls declare `type: developers`)
|
|
154
|
+
reviewers:
|
|
155
|
+
description: Agents that review changes
|
|
156
|
+
|
|
157
|
+
capabilities:
|
|
158
|
+
layers:
|
|
159
|
+
knowledge:
|
|
160
|
+
capability: oats.okf
|
|
161
|
+
from: installed
|
|
162
|
+
# injection-override: .agents/injections/capabilities/oats.okf.md
|
|
163
|
+
messaging: none
|
|
164
|
+
tasks: none
|
|
165
|
+
|
|
166
|
+
additive:
|
|
167
|
+
example.code-review:
|
|
168
|
+
from: installed
|
|
169
|
+
agent-types:
|
|
170
|
+
developers:
|
|
171
|
+
enabled: true
|
|
172
|
+
settings:
|
|
173
|
+
depth: normal
|
|
174
|
+
souls:
|
|
175
|
+
security-reviewer:
|
|
176
|
+
enabled: true
|
|
177
|
+
settings:
|
|
178
|
+
depth: exhaustive
|
|
179
|
+
|
|
180
|
+
example.deploy:
|
|
181
|
+
from: installed
|
|
182
|
+
global: true
|
|
183
|
+
agent-types:
|
|
184
|
+
reviewers: false # explicit exclusion
|
|
185
|
+
souls:
|
|
186
|
+
release-reviewer: true # more-specific re-enable
|
|
187
|
+
|
|
188
|
+
skill-overrides:
|
|
189
|
+
review: example.code-review
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`global` means all souls governed by the config level declaring it—not every
|
|
193
|
+
soul on the machine regardless of scope. Laptop, workspace, and repository
|
|
194
|
+
configs each govern souls beneath that level.
|
|
195
|
+
|
|
196
|
+
Composition is additive across matching global, agent-type, and soul
|
|
197
|
+
bindings. Settings use `soul > agent-type > global`, then closer config scope.
|
|
198
|
+
Conflicting values at equal specificity and scope are errors.
|
|
199
|
+
`enabled: false` follows the same precedence. Agent types are declared by
|
|
200
|
+
name in config; each soul opts in via `type:` in its soul.yaml. Tags and
|
|
201
|
+
selectors are not implemented, and bindings do not target individual
|
|
202
|
+
instances.
|
|
203
|
+
|
|
204
|
+
`capabilities` is the only activation map: fundamental integrations live
|
|
205
|
+
under `capabilities.layers.<layer>` (an entry or an explicit `none` that
|
|
206
|
+
suppresses an inherited integration), everything else under
|
|
207
|
+
`capabilities.additive`.
|
|
208
|
+
|
|
209
|
+
## Exact runtime composition
|
|
210
|
+
|
|
211
|
+
Every spawned instance receives:
|
|
212
|
+
|
|
213
|
+
- canonical soul skills;
|
|
214
|
+
- the kernel `oats` skill; and
|
|
215
|
+
- skills from capabilities active for that soul.
|
|
216
|
+
|
|
217
|
+
OATS copies only those skill trees into real directories under
|
|
218
|
+
`<instance>/.agents/skills/` and records the names and source capability in
|
|
219
|
+
`instance.json`. `.claude/skills` points to
|
|
220
|
+
the same canonical directory. Pi launches with this directory as an explicit
|
|
221
|
+
skill path; ambient skills (user-level, pi packages, the work tree) coexist
|
|
222
|
+
with the OATS-composed set rather than being excluded — `instance.json`
|
|
223
|
+
records exactly what OATS composed, not everything the harness may discover.
|
|
224
|
+
`oats-getting-started` is the pi adapter's one ambient contribution before a workspace exists.
|
|
225
|
+
|
|
226
|
+
Duplicate skill names fail spawn unless `skill-overrides` explicitly names the
|
|
227
|
+
winning source. Pi and Claude therefore receive the same OATS-managed set rather
|
|
228
|
+
than relying on different ancestor-discovery rules.
|
|
229
|
+
|
|
230
|
+
For pi, exact isolation needs the capability-aware versions of both
|
|
231
|
+
`@awebai/oats` and `@awebai/oats-pi`. The kernel disables normal skill
|
|
232
|
+
discovery at launch. The changed adapter contributes only the instance-local
|
|
233
|
+
set instead of the older workspace and package roots. Install matching package
|
|
234
|
+
versions and upgrade them together.
|
|
235
|
+
|
|
236
|
+
The instance's `AGENTS.md` is a generated regular file containing:
|
|
237
|
+
|
|
238
|
+
1. the canonical soul `AGENTS.md`;
|
|
239
|
+
2. the kernel and work-mode blocks;
|
|
240
|
+
3. active capability blocks in deterministic order; and
|
|
241
|
+
4. unconditional config instruction blocks.
|
|
242
|
+
|
|
243
|
+
Its `CLAUDE.md` symlinks to `AGENTS.md`. The committed soul remains unchanged.
|
|
244
|
+
Edit the canonical soul, injection source, or config, then spawn a new
|
|
245
|
+
instance; do not edit generated blocks as source-of-truth changes.
|
|
246
|
+
|
|
247
|
+
Inspect a final composition:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
oats doctor /path/to/repo --soul api-expert
|
|
251
|
+
oats doctor /path/to/repo --soul api-expert --json
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Doctor reports active/acquired packages, target provenance, settings, skills,
|
|
255
|
+
hooks, trust, instruction sources, and final composed text. It cannot infer
|
|
256
|
+
semantic contradictions between two prose injections; review the output.
|
|
257
|
+
|
|
258
|
+
## Distribution packages
|
|
259
|
+
|
|
260
|
+
A **distribution package** is the install/update/review unit above
|
|
261
|
+
capabilities: a directory with an `oats-package.json` manifest that explicitly
|
|
262
|
+
enumerates one or more capabilities and optional reference config templates
|
|
263
|
+
(schema:
|
|
264
|
+
`docs/oats-package.schema.json`; contract:
|
|
265
|
+
`docs/design/package-engine-contract.md`). A capability remains the
|
|
266
|
+
targeting/activation unit — every capability a package exports stays
|
|
267
|
+
independently addressable by ID with `from: installed`.
|
|
268
|
+
|
|
269
|
+
A Git repository *contains* that directory; `#<path>` selects which one, and
|
|
270
|
+
only the selected subtree is installed and hashed. Omitting it selects
|
|
271
|
+
`oats-package/` (the convention for every official example and scaffold); `#.`
|
|
272
|
+
selects the repository root. Local paths are always exact directories.
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
oats install git:github.com/org/repo@v1.0.0 --dir /path/to/scope # git shorthand → oats-package/
|
|
276
|
+
oats install git:github.com/org/repo@v1.0.0#dist/oats # a custom contained root
|
|
277
|
+
oats install https://host/org/repo.git@v1.0.0#. # raw git URL, repository root
|
|
278
|
+
oats install ../my-package # local path (exact directory)
|
|
279
|
+
oats install oats.okf # official catalog id
|
|
280
|
+
oats install # bare: exact restore of this chain's locks
|
|
281
|
+
oats list # installed packages, exported capabilities, scopes
|
|
282
|
+
oats update <package> # transactional re-resolve + diff + trust reset
|
|
283
|
+
oats remove <package> # refuses while config/dependents reference it
|
|
284
|
+
oats migrate [--dry-run] # map v1 capability locks to package locks
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Installing a package materializes each capability into the owning scope's
|
|
288
|
+
`.agents/capabilities/installed/<id>/` (gitignored, like the capability store).
|
|
289
|
+
There is no persistent package store. `oats-lock.json` uses `lockfileVersion: 2`
|
|
290
|
+
with two maps: `packages` (exact source, commit, selected path, payload
|
|
291
|
+
integrity, and dependencies) and `capabilities` (each artifact's version,
|
|
292
|
+
provider package, path, integrity, and trust) — schema
|
|
293
|
+
`docs/oats-lock.schema.json`. Dependencies are pinned (official selector,
|
|
294
|
+
tag/commit, or local path — no semver solver). Cycles and two sources claiming
|
|
295
|
+
one package identity at a scope are errors with provenance. Acquisition
|
|
296
|
+
**activates nothing** and adopts no config template; an unpinned git source
|
|
297
|
+
resolves once and never advances on restore.
|
|
298
|
+
|
|
299
|
+
Trust binds to each materialized capability artifact at its exact integrity.
|
|
300
|
+
`oats trust <capability>` approves only that capability's commands, hooks, and
|
|
301
|
+
declared launch environment.
|
|
302
|
+
`oats trust <package> --all-capabilities` is the explicit bulk path and prints
|
|
303
|
+
the full executable surface first. Any artifact integrity change (including
|
|
304
|
+
`oats update`) resets that capability's trust.
|
|
305
|
+
Skill/instruction/config-only capabilities need lock integrity but no
|
|
306
|
+
executable approval, and official-catalog identity grants **no** executable
|
|
307
|
+
trust. A capability may carry a checked-in `package-lock.json` for JS runtime
|
|
308
|
+
dependencies; OATS materializes it with `npm ci --ignore-scripts` only — npm
|
|
309
|
+
lifecycle scripts never run at acquisition, and capability code/hook paths
|
|
310
|
+
must resolve inside the materialized capability root.
|
|
311
|
+
|
|
312
|
+
`oats migrate` converts a scope's v1 marketplace/git/path capability locks to
|
|
313
|
+
the revised v2 lock, preserving `from: installed` activation. It is
|
|
314
|
+
all-or-nothing per scope: a scope converts only when every entry maps to a
|
|
315
|
+
package. If any entry is held, manual, or retained, the whole scope stays
|
|
316
|
+
byte-identical v1 and keeps working. There is no residue container, and
|
|
317
|
+
executable approvals are never carried over.
|
|
318
|
+
|
|
319
|
+
All package operations are agent-callable: every command above supports
|
|
320
|
+
`--json` (one stdout envelope; failures carry the contract's stable error
|
|
321
|
+
codes) and noninteractive operation. Agents never hand-edit `oats-lock.json`
|
|
322
|
+
or the stores — the kernel-owned **oats-packages** skill (composed into every
|
|
323
|
+
instance) teaches the full lifecycle.
|
|
324
|
+
|
|
325
|
+
## Acquisition, lock, restore, and trust (single capabilities)
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
oats install oats.jira --dir /path/to/repo # official catalog id; approve executable surfaces with `oats trust`
|
|
329
|
+
oats install https://example.invalid/team-chat.git --dir /path/to/repo
|
|
330
|
+
oats install ../team-chat --dir /path/to/repo
|
|
331
|
+
oats install # bare: restore locked-but-missing artifacts
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Every acquired artifact lands in the owning scope's
|
|
335
|
+
`.agents/capabilities/installed/`, beside the `oats-config.yaml` and
|
|
336
|
+
`oats-lock.json` that govern it. Install maintains a one-line
|
|
337
|
+
`.agents/capabilities/.gitignore` so acquired artifacts stay uncommitted, like
|
|
338
|
+
`node_modules`. A fresh clone with a committed config and lock runs bare
|
|
339
|
+
`oats install` to reacquire everything; each restored artifact must hash to the
|
|
340
|
+
locked integrity or the restore fails and removes the fetched copy.
|
|
341
|
+
|
|
342
|
+
Installation acquires and locks; it does **not** activate. `oats-lock.json`
|
|
343
|
+
records:
|
|
344
|
+
|
|
345
|
+
- source;
|
|
346
|
+
- exact package version and git commit when available; and
|
|
347
|
+
- SHA-256 integrity of the artifact.
|
|
348
|
+
|
|
349
|
+
OATS never pulls an existing package silently. Changed integrity blocks use
|
|
350
|
+
until the package is deliberately reacquired. For external packages containing
|
|
351
|
+
commands, hooks, or launch-environment authority, approve that exact locked
|
|
352
|
+
artifact:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
oats trust example.team-chat --dir /path/to/repo
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Changing integrity invalidates approval. Skill/instruction-only packages still
|
|
359
|
+
require a valid lock but do not require executable approval. Manifest paths in
|
|
360
|
+
external packages must remain inside the locked artifact (including after
|
|
361
|
+
symlink resolution), so approved hooks and commands cannot execute unhashed
|
|
362
|
+
files. The trust boundary is structural: anything under `installed/` must have
|
|
363
|
+
a matching lock entry, so an installed artifact cannot masquerade as scope-owned
|
|
364
|
+
by dropping its lock. A committed lock's approval survives restore when the
|
|
365
|
+
restored artifact hashes to the locked integrity.
|
|
366
|
+
|
|
367
|
+
One narrow exception exists for the kernel's own marketplace, kept only until
|
|
368
|
+
official packages replace legacy `marketplace:` installs. A capability whose
|
|
369
|
+
lock source is `marketplace:<id>@<version>` may declare resources that live
|
|
370
|
+
outside its installed copy — `oats.authoring` selects framework skills with
|
|
371
|
+
`../../skills/<name>` — and those declarations are resolved against the
|
|
372
|
+
capability's directory in the kernel marketplace
|
|
373
|
+
(`<kernel>/capabilities/<slug>`), located by capability id rather than by the
|
|
374
|
+
lock selector's spelling. If that declared path names an npm dependency hoisted
|
|
375
|
+
by npm, OATS also checks the equivalent path from the kernel root; this is the
|
|
376
|
+
published `oats.aweb` layout (`node_modules/@awebai/pi/skills/...`). The shipped source must still have the same
|
|
377
|
+
capability identity, while its version may advance with an explicitly installed
|
|
378
|
+
kernel upgrade: framework-hoisted resources belong to that trusted kernel, and
|
|
379
|
+
this preserves valid older v1 installs until official-package migration. The
|
|
380
|
+
installed copy and its lock must still agree on version and integrity. If they
|
|
381
|
+
do not, recovery is to delete the installed copy the error names and then run
|
|
382
|
+
`oats install <id> --dir <scope>`, which re-acquires and rewrites the lock entry;
|
|
383
|
+
run with the copy still in place, that command reports `Already acquired` and
|
|
384
|
+
changes nothing, and legacy v1 capability entries are not removable with
|
|
385
|
+
`oats remove`, which services packages. Such a tree may leave the
|
|
386
|
+
installed copy but never the kernel package: `..` segments and symlinks that
|
|
387
|
+
resolve outside it are rejected exactly like any other escape. Capabilities
|
|
388
|
+
exported by packages, authored at a scope, or referenced by path never receive
|
|
389
|
+
this resolution — they stay inside their own artifact.
|
|
390
|
+
|
|
391
|
+
Bundled framework packages are trusted. Packages you author at a scope live in
|
|
392
|
+
`.agents/capabilities/owned/` and are config-owned trusted — trusting the
|
|
393
|
+
scope trusts them; review them like other repository instructions and code.
|
|
394
|
+
In a git-managed scope they are committed; at a non-git scope (the laptop
|
|
395
|
+
level, a plain workspace root) they are ordinary files whose durability is the
|
|
396
|
+
scope's own — they have no lock and are not restorable by `oats install`, so
|
|
397
|
+
back them up with whatever backs up that scope. Capabilities directly
|
|
398
|
+
under `.agents/capabilities/` are rejected — move them into `installed/` or
|
|
399
|
+
`owned/`.
|
|
400
|
+
|
|
401
|
+
## Activation and exclusions
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
oats use oats.okf --global --dir /path/to/repo
|
|
405
|
+
oats use example.code-review --type developers --dir /path/to/repo
|
|
406
|
+
oats use example.deploy --type reviewers --disable --dir /path/to/repo
|
|
407
|
+
oats use example.deploy --soul release-reviewer --dir /path/to/repo
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
`--global` is the default. Choose only one target. An integration's manifest
|
|
411
|
+
declares its layer, so activation does not repeat it. Disable an inherited
|
|
412
|
+
fundamental layer with `oats use none --layer <layer>`.
|
|
413
|
+
|
|
414
|
+
## Capability-defined agents
|
|
415
|
+
|
|
416
|
+
A manifest may declare `agents: ["agents/<name>"]` — package-relative soul
|
|
417
|
+
directories (`soul.yaml` + `AGENTS.md` directly inside). Wherever the
|
|
418
|
+
capability is **declared** in the config chain, `oats spawn <name>` resolves
|
|
419
|
+
these like local souls: the canonical soul stays read-only inside the package
|
|
420
|
+
(a fresh identity every spawn — by design for service agents like reviewers),
|
|
421
|
+
while instances home under the scope's `local-agents/`. Capability agents
|
|
422
|
+
carry their own `model:`/`runtime:` defaults in soul.yaml.
|
|
423
|
+
|
|
424
|
+
## Commands and hooks
|
|
425
|
+
|
|
426
|
+
Operational commands resolve only when their package is active in the current
|
|
427
|
+
instance or soul context. Package-management commands (`install`, `trust`,
|
|
428
|
+
`use`, `doctor`) remain available globally.
|
|
429
|
+
|
|
430
|
+
Hooks receive `OATS_EVENT`, `OATS_CAPABILITY`, `OATS_LAYER`, `OATS_INSTANCE`,
|
|
431
|
+
`OATS_HOME`, `OATS_AGENT`, `OATS_SOUL`, `OATS_CONTEXT`, `OATS_WORKSPACE`,
|
|
432
|
+
`OATS_ROOT`, `OATS_LEVEL`, `OATS_SETTINGS`, and `OATS_META`. A final JSON line may
|
|
433
|
+
return `meta`, `brief`, `warning`, or runtime-specific `launch` arguments. A
|
|
434
|
+
**spawn hook only** may also return an `env` object for the launched process;
|
|
435
|
+
returning `env` from retire or soul-scaffold is an explicit contract error.
|
|
436
|
+
|
|
437
|
+
Hook environment values are strings, at most 8192 UTF-8 bytes, with no NUL or
|
|
438
|
+
newlines. Names use the portable environment grammar and must belong to an
|
|
439
|
+
unambiguous vendor namespace. Only a dotted capability ID participates: its
|
|
440
|
+
component before the first `.` must be lowercase alphanumeric. Thus `aweb.*`
|
|
441
|
+
may contribute only `AWEB_*`; `aweb@evil` and `aweb/evil` are not vendor forms
|
|
442
|
+
for this contract. Hyphenated vendors are also excluded because translating a
|
|
443
|
+
hyphen to `_` would let `aweb-evil.*` collide with names already inside
|
|
444
|
+
`aweb.*`'s `AWEB_*` namespace.
|
|
445
|
+
|
|
446
|
+
A hook may return only names in its manifest's exact `environment` declaration.
|
|
447
|
+
For acquired packages that declaration is part of the integrity-locked artifact.
|
|
448
|
+
Third-party install previews the future request, and `oats trust` prints the
|
|
449
|
+
exact request before persisting executable authority. Marketplace automatic
|
|
450
|
+
trust likewise prints it before writing the trusted lock. Undeclared output is
|
|
451
|
+
fatal. Config-owned packages receive the same exact-subset enforcement under
|
|
452
|
+
their existing config-owned trust. This positive authority is the contract
|
|
453
|
+
boundary — adding a new launch variable requires a visible manifest/trust
|
|
454
|
+
change.
|
|
455
|
+
|
|
456
|
+
`OATS_*`, `PI_AGENT_*`, kernel launch variables, and known shell/bootstrap/loader
|
|
457
|
+
names are also rejected as defense in depth. The denylist includes current Node,
|
|
458
|
+
JVM, .NET, Python, Perl, Ruby, Lua, PHP, ELF, and dyld surfaces, but is explicitly
|
|
459
|
+
not the authority boundary: runtime bootstrap names are open-ended, so the
|
|
460
|
+
manifest declaration and trust review enforce what an artifact may contribute.
|
|
461
|
+
Two capabilities claiming the same name is an error even when their values
|
|
462
|
+
match.
|
|
463
|
+
|
|
464
|
+
Environment names are sorted before shell-quoted command construction, and a
|
|
465
|
+
contributed value deliberately overrides an ambient value of the same name.
|
|
466
|
+
Invalid or colliding contributions abort before `instance.json` and session
|
|
467
|
+
launch. OATS enters the same rollback transaction as a required spawn-hook
|
|
468
|
+
failure: declared retire compensation runs in reverse, worktree-mode Git state
|
|
469
|
+
is removed and verified, and the home is deleted only after cleanup completes.
|
|
470
|
+
A failed compensation, unverifiable topology removal, or reported spawn state
|
|
471
|
+
without a retire hook uses the standard retryable quarantine instead. Ordinary
|
|
472
|
+
advisory hook execution failure itself contributes no environment.
|
|
473
|
+
|
|
474
|
+
The environment prefix applies to the initial Pi or Claude process. `--no-launch`
|
|
475
|
+
validates command preparation but has no runtime consumer. The fallback shell
|
|
476
|
+
after that process exits does not inherit command-scoped assignments, and OATS
|
|
477
|
+
has no restart command or replay policy yet. The generated command is persisted
|
|
478
|
+
as before; hooks must contribute locators, selectors, or broker endpoints—not
|
|
479
|
+
bearer tokens or private key material. An instance-lifetime local principal may
|
|
480
|
+
be selected by a home locator. A replaceable execution serving a durable global
|
|
481
|
+
identity must instead use a custody/action broker or equivalent narrow adapter;
|
|
482
|
+
this mechanism must never copy or expose that global identity's root keys to the
|
|
483
|
+
worker process. Session-scoped execution credentials need a separate lifecycle
|
|
484
|
+
and must not be encoded into this persisted spawn command.
|
|
485
|
+
|
|
486
|
+
Spawn/scaffold order is outer scope to inner scope, then capability ID;
|
|
487
|
+
retirement reverses successful spawn order. Scaffold hooks cannot modify or
|
|
488
|
+
delete canonical or another package's files. OATS records ownership, restores
|
|
489
|
+
the pre-hook snapshot, and raises a conflict instead of accepting destructive
|
|
490
|
+
or last-writer-wins behavior.
|
|
491
|
+
|
|
492
|
+
## Bundled packages
|
|
493
|
+
|
|
494
|
+
| Capability | Kind | Provides |
|
|
495
|
+
|---|---|---|
|
|
496
|
+
| `oats.okf` | knowledge integration | OKF bundles, instance memory, harvest skills and command |
|
|
497
|
+
| `oats.aweb` | messaging integration | aweb identity lifecycle and messaging skills |
|
|
498
|
+
| `oats.jira` | tasks integration | Jira task protocol via `acli` |
|
|
499
|
+
| `oats.linear` | tasks integration | Linear GraphQL task commands and workflow |
|
|
500
|
+
| `oats.authoring` | additive | capability, skill, and soul authoring guidance |
|
|
501
|
+
|
|
502
|
+
The source packages live under `capabilities/`. Acquired packages live under
|
|
503
|
+
`<level>/.agents/capabilities/installed/` (gitignored, restorable); packages
|
|
504
|
+
authored at a scope live under `<level>/.agents/capabilities/owned/`
|
|
505
|
+
(committed where the scope is a git repo). Within one scope `owned/` overrides `installed/` on ID collision.
|