@awebai/oats 0.24.13 → 0.25.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/bin/oats.mjs +994 -2837
- package/docs/capabilities.md +136 -323
- package/docs/configuration.md +68 -533
- package/docs/conventions.md +51 -24
- 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 +460 -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 +356 -5
- package/docs/desktop-succession.md +12 -6
- package/docs/desktop.md +9 -4
- package/docs/execution-targets.md +16 -4
- package/docs/first-team.md +107 -224
- package/docs/implementation.md +41 -11
- package/docs/integrations.md +50 -47
- package/docs/knowledge-capability-authoring.md +10 -4
- package/docs/knowledge-migration.md +21 -12
- package/docs/knowledge-reference/package-craft.md +11 -3
- package/docs/knowledge.md +60 -18
- package/docs/layers.md +3 -3
- package/docs/migration-from-oas.md +20 -9
- 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 +347 -0
- package/docs/release-notes/v0.25.0.md +99 -0
- package/docs/release-notes/v0.25.1.md +94 -0
- package/docs/schedules.md +12 -6
- 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 +436 -119
- package/lib/core.mjs +462 -61
- package/lib/instance-resolution.mjs +387 -0
- package/lib/materialize.mjs +580 -0
- package/lib/operator-dispatch.mjs +117 -0
- package/lib/packages.mjs +558 -1269
- package/lib/remote.mjs +718 -0
- package/lib/resolve.mjs +638 -0
- package/lib/schedule.mjs +90 -16
- package/lib/workspace.mjs +654 -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
|
@@ -25,10 +25,11 @@ knowledge layer. V2 uses external accepted bases and independent workers, not
|
|
|
25
25
|
The required v2 spawn hook refuses a legacy `soul/knowledge/`; it never silently
|
|
26
26
|
substitutes an empty bundle.
|
|
27
27
|
|
|
28
|
-
After publication,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
After publication, bump `packages.oats.okf` in the workspace file and run
|
|
29
|
+
`oats sync`: the new version resolves to a commit and its executables are
|
|
30
|
+
approved once. An existing lock never advances by itself. Package content is
|
|
31
|
+
read from the catalog **Git** repository, never from an npm mirror (npm drops
|
|
32
|
+
the source worker's canonical `CLAUDE.md` symlink).
|
|
32
33
|
|
|
33
34
|
## 2. Bind and provision external destinations
|
|
34
35
|
|
|
@@ -38,17 +39,25 @@ Choose stable base IDs, stable owner IDs, nonoverlapping node paths and durable
|
|
|
38
39
|
permissions. Confirm aliases and owners explicitly, rather than deriving them
|
|
39
40
|
from an instance branch or name.
|
|
40
41
|
|
|
41
|
-
Configure the absolute `bindings-file` for each source soul
|
|
42
|
-
|
|
43
|
-
`
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
and
|
|
42
|
+
Configure the absolute `bindings-file` **and** `state-dir` for each source soul
|
|
43
|
+
— the oats.okf 2.1.x binding requires both as normalized absolute host paths
|
|
44
|
+
(`setting state-dir is required (absolute host path)` is a refusal, not a
|
|
45
|
+
default). Remove obsolete v1 settings such as `record-window-turns` and
|
|
46
|
+
`record-window-bytes`; v2 accepts exactly `bindings-file`, `state-dir`,
|
|
47
|
+
`harvest-runtime` and `harvest-model`. Under the 0.25 workspace model these live
|
|
48
|
+
in `oats-local.yaml` `settings.oats.okf` ([configuration.md](configuration.md));
|
|
49
|
+
a rebuilt deployment gets a **fresh** `state-dir`
|
|
50
|
+
([rebuild-to-v2.md §7b](rebuild-to-v2.md#7b-okf-2-start-a-fresh-state-dir-do-not-re-point-the-old-one)).
|
|
51
|
+
Provision **empty owned nodes** using `oats okf init`. Accept Git initialization
|
|
52
|
+
through a reviewed PR before migration delivery; directory provisioning requires
|
|
53
|
+
explicit confirmation and a genuinely non-Git location.
|
|
47
54
|
|
|
48
55
|
## 3. Stage and deliver each legacy bundle
|
|
49
56
|
|
|
50
|
-
From the
|
|
51
|
-
inherited instance identity, selecting the source soul
|
|
57
|
+
From the deployment directory (the one holding `oats-local.yaml`) in an operator
|
|
58
|
+
shell without inherited instance identity, selecting the source soul with
|
|
59
|
+
`--soul` — the kernel resolves the command exactly as `oats spawn --soul <x>`
|
|
60
|
+
would ([knowledge.md](knowledge.md#inspection-and-operator-commands)):
|
|
52
61
|
|
|
53
62
|
```bash
|
|
54
63
|
oats okf migrate --legacy /absolute/soul/knowledge --base project --node expert --output /absolute/empty-migration-stage --soul domain-expert --json
|
|
@@ -104,11 +104,19 @@ not satisfy a skill's missing reference if it is outside the capability root.
|
|
|
104
104
|
|
|
105
105
|
## Acquisition, activation and trust
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
In a *test* workspace, pin the package by a direct ref and give it to a soul:
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
# test workspace's oats-workspace.yaml
|
|
111
|
+
packages:
|
|
112
|
+
example.knowledge-pkg: git:/abs/path/to/source-repo.git@v0.1.0 # a tag; branches are refused
|
|
113
|
+
defaults:
|
|
114
|
+
knowledge: { example.knowledge: { from: package } }
|
|
115
|
+
```
|
|
108
116
|
|
|
109
117
|
```bash
|
|
110
|
-
oats
|
|
111
|
-
oats
|
|
118
|
+
oats sync --dir /path/to/test-workspace # resolve, lock, approve once
|
|
119
|
+
oats spawn <soul> --preview --json # the module as it would be materialized
|
|
112
120
|
```
|
|
113
121
|
|
|
114
122
|
These are illustrative user operations, not instructions to change a live
|
package/docs/knowledge.md
CHANGED
|
@@ -51,23 +51,42 @@ artifact**: npm drops the source worker's `CLAUDE.md -> AGENTS.md` symlink.
|
|
|
51
51
|
Acquire the catalog Git payload; do not install a copied npm mirror as a local
|
|
52
52
|
package or repair missing aliases in installed artifacts.
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
Under the 0.25 workspace model OKF is a **package**: pin it once in the
|
|
55
|
+
workspace file, let `oats sync` lock and approve it, and let every soul that
|
|
56
|
+
fills the knowledge slot say (or inherit) `oats.okf: { from: package }`.
|
|
57
|
+
Operator-level `oats okf` commands run from the deployment directory with
|
|
58
|
+
`--soul <name>` (an explicit `--soul` does not override an invoking instance's
|
|
59
|
+
saved settings — use a clean shell). The pinned version resolves through the
|
|
60
|
+
official catalog:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
# oats-workspace.yaml
|
|
64
|
+
packages:
|
|
65
|
+
oats.okf: v2.1.3
|
|
66
|
+
defaults:
|
|
67
|
+
knowledge: { oats.okf: { from: package } }
|
|
68
|
+
|
|
69
|
+
# souls/domain-expert/soul.yaml
|
|
70
|
+
knowledge:
|
|
71
|
+
owns: domain-expert
|
|
72
|
+
|
|
73
|
+
# oats-local.yaml (this machine)
|
|
74
|
+
settings:
|
|
75
|
+
oats.okf:
|
|
76
|
+
bindings-file: /absolute/config/okf-bindings.json
|
|
77
|
+
state-dir: /absolute/state/okf
|
|
78
|
+
```
|
|
59
79
|
|
|
60
80
|
```bash
|
|
61
|
-
oats
|
|
62
|
-
oats
|
|
63
|
-
oats use oats.okf --soul domain-expert --settings bindings-file=/absolute/config/okf-bindings.json
|
|
64
|
-
oats doctor --soul domain-expert --json
|
|
81
|
+
oats sync # resolves v2.1.3 to a commit, asks executable approval once
|
|
82
|
+
oats spawn domain-expert --preview --json # the exact oats.okf module (package, version, commit)
|
|
65
83
|
```
|
|
66
84
|
|
|
67
|
-
|
|
68
|
-
`oats
|
|
69
|
-
|
|
70
|
-
|
|
85
|
+
Pinning activates nothing by itself: the soul's `knowledge:` payload and the
|
|
86
|
+
machine's `settings.oats.okf` must be bindable. The lock stays exact until the
|
|
87
|
+
workspace bumps `packages.oats.okf`; v1 operators must plan migration before
|
|
88
|
+
that bump. Executable changes come with a new version and a new approval. A
|
|
89
|
+
service worker need not itself fill the knowledge slot (`knowledge: none`).
|
|
71
90
|
|
|
72
91
|
### Bindings document
|
|
73
92
|
|
|
@@ -141,7 +160,9 @@ bindings, owner declarations, base metadata or indexes fail required spawn rathe
|
|
|
141
160
|
than silently bootstrapping empty knowledge.
|
|
142
161
|
|
|
143
162
|
Provisioning is an explicit operator action. Prepare node-map files (the
|
|
144
|
-
`nodes` object above, without its wrapper), then
|
|
163
|
+
`nodes` object above, without its wrapper), then run from the **deployment
|
|
164
|
+
directory** (the one holding `oats-local.yaml`), naming the soul whose
|
|
165
|
+
`knowledge:` payload and `settings.oats.okf` the command should run with:
|
|
145
166
|
|
|
146
167
|
```bash
|
|
147
168
|
# New directory base: refuses an existing destination.
|
|
@@ -150,6 +171,19 @@ oats okf init --base team --nodes /absolute/config/team-nodes.json --confirm --s
|
|
|
150
171
|
oats okf init --base project --nodes /absolute/config/project-nodes.json --output /absolute/new-bundle-stage --soul domain-expert --json
|
|
151
172
|
```
|
|
152
173
|
|
|
174
|
+
These run **before any instance exists**. Outside an instance home the kernel
|
|
175
|
+
resolves `oats okf … --soul <name>` exactly as `oats spawn <name>` would
|
|
176
|
+
(discover → resolve → the soul's `oats.okf` module at its locked, approved
|
|
177
|
+
commit), fetches that module into the deployment's module store
|
|
178
|
+
(`<deployment>/.oats/modules/oats.okf@<commit12>/`) and dispatches to that copy
|
|
179
|
+
with the soul's merged payload as `OATS_SETTINGS`; `--soul` is required
|
|
180
|
+
(`E_BAD_ARGS` names it) unless the namespace's capability is a workspace
|
|
181
|
+
default. It never runs "the newest instance's copy" and never an unapproved
|
|
182
|
+
cache read (`E_PACKAGE_UNAPPROVED` until `oats sync` approves the version).
|
|
183
|
+
*0.25.0 still answers `E_CAPABILITY_INACTIVE` here (the operator-level dispatch
|
|
184
|
+
lands in 0.25.1); the interim is to run the module binary directly with
|
|
185
|
+
`OATS_SETTINGS` and `OATS_CLI_BIN` set, as the tarball smoke does.*
|
|
186
|
+
|
|
153
187
|
Put the Git proposal at the configured root in an operator-owned checkout and
|
|
154
188
|
review/merge it through a PR before spawning working sources. Existing ownership
|
|
155
189
|
changes require an explicit reviewed operator change, not harvest. The standalone
|
|
@@ -173,7 +207,7 @@ Snapshots are immutable by protocol, not live mounts. For current accepted text:
|
|
|
173
207
|
# From the source home:
|
|
174
208
|
oats okf read --base project --path expert/index.md --json
|
|
175
209
|
oats okf refresh --json
|
|
176
|
-
# From the deployment
|
|
210
|
+
# From the deployment directory (oats-local.yaml), even after source retirement — --soul selects the resolution:
|
|
177
211
|
oats okf read --source /absolute/state/sources/UUID/source.json --base project --path expert/index.md --soul domain-expert --json
|
|
178
212
|
oats okf refresh --source /absolute/state/sources/UUID/source.json --soul domain-expert --json
|
|
179
213
|
```
|
|
@@ -273,9 +307,17 @@ spawn and command exit alone are not successful learning.
|
|
|
273
307
|
|
|
274
308
|
## Inspection and operator commands
|
|
275
309
|
|
|
276
|
-
Run home-local commands from that source home
|
|
277
|
-
|
|
278
|
-
|
|
310
|
+
Run home-local commands from that source home: inside an instance the
|
|
311
|
+
dispatcher resolves `okf` from the home's materialized module
|
|
312
|
+
(`instance.json.modules` → `<home>/.oats/modules/oats.okf/`). For cross-source
|
|
313
|
+
or retired-source commands, run from the **deployment directory** (the one
|
|
314
|
+
holding `oats-local.yaml`) in a clean operator shell without another instance's
|
|
315
|
+
`OATS_*`/`PI_*` identity, and select the source soul with `--soul <name>`: the
|
|
316
|
+
kernel resolves that soul as a spawn would and dispatches to the deployment's
|
|
317
|
+
copy of its `oats.okf` module with the soul's merged payload (see
|
|
318
|
+
[Acquire, bind and provision explicitly](#acquire-bind-and-provision-explicitly)).
|
|
319
|
+
No `oats-config.yaml` chain is consulted; a namespace no module of the soul
|
|
320
|
+
provides is `E_UNKNOWN_COMMAND`.
|
|
279
321
|
|
|
280
322
|
```bash
|
|
281
323
|
# Read-only; no capture, refresh, scheduling or worker launch:
|
package/docs/layers.md
CHANGED
|
@@ -34,8 +34,8 @@ Classic `kind`/`type`/`repo` declarations and config-targeted agent types are a
|
|
|
34
34
|
|
|
35
35
|
## Workspace, repository and adoption contracts
|
|
36
36
|
|
|
37
|
-
- `oats-workspace.yaml` declares
|
|
38
|
-
- `oats.yaml`
|
|
37
|
+
- `oats-workspace.yaml` (v2) declares members, the pinned `packages:`, team labels, defaults per slot and per team, stores, the messaging payload and pinned `external:` souls.
|
|
38
|
+
- `oats-membership.yaml` is a repository's half of the handshake: the workspace backlink plus an optional default team label. Everything under `souls/` and `capabilities/` is discoverable by convention (`private: true` opts out); there are no export lists.
|
|
39
39
|
- Membership requires compatible observations on both sides; folder adjacency or a copied declaration is not admission.
|
|
40
40
|
- External source import does not adopt the publisher's workspace. A framework repository may host its own development workspace without imposing it on consumers.
|
|
41
41
|
- Operator choices and workspace defaults must respect source requirements. Git read access is not write permission, executable approval or messaging enrollment.
|
|
@@ -96,7 +96,7 @@ The work target is independent of source publication and knowledge placement. Pr
|
|
|
96
96
|
|
|
97
97
|
## Kernel briefings versus operational capabilities
|
|
98
98
|
|
|
99
|
-
The kernel owns only what describes the layout it creates: the `instance-boundary` briefing (home versus `work/`), the selected work-mode briefing and config-declared injections. Knowing how to *operate* OATS (status, spawn, retire, soul discovery) and how to *configure* it (workspaces, packages,
|
|
99
|
+
The kernel owns only what describes the layout it creates: the `instance-boundary` briefing (home versus `work/`), the selected work-mode briefing and config-declared injections. Knowing how to *operate* OATS (status, spawn, retire, soul discovery) and how to *configure* it (workspaces, packages, approval) is capability content — the official capabilities `oats.core` (a workspace default via `defaults.capabilities`, removable per soul with `off`) and `oats.setup` (held by an onboarding expert), both provided by the `oats.framework` package; see [souls and instances](souls-and-instances.md#oats-operational-knowledge-is-a-capability).
|
|
100
100
|
|
|
101
101
|
## Capture and knowledge are separate
|
|
102
102
|
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Migrating from OAS to OATS
|
|
2
2
|
|
|
3
|
+
> **0.25 status — this is a 0.22–0.24 procedure.** `oats migrate` and
|
|
4
|
+
> `oats trust` are **removed verbs** in the 0.25 kernel (`E_UNKNOWN_COMMAND`
|
|
5
|
+
> naming the replacement), and 0.25 reads none of the files this page
|
|
6
|
+
> converts to (`oats-config.yaml`, `oats-lock.json` v2, the `installed/` tier).
|
|
7
|
+
> An OAS deployment reaches 0.25 in two steps: run this page's commands with a
|
|
8
|
+
> **0.24.x** kernel (`npm install -g @awebai/oats@0.24`), then rebuild for the
|
|
9
|
+
> workspace model with [rebuild-to-v2.md](rebuild-to-v2.md) — which is a rewrite
|
|
10
|
+
> of three shared files, not a conversion, so an operator comfortable with the
|
|
11
|
+
> v2 declarations may skip straight to it and let the old files go.
|
|
12
|
+
|
|
3
13
|
OATS is the successor to OAS. **OATS 0.22.0 was published on 2026-09-03**:
|
|
4
14
|
the kernel, Pi adapter, and Desktop assets are available. The published
|
|
5
15
|
kernel acquired the official OKF, aweb, authoring, and development packages
|
|
@@ -17,15 +27,15 @@ while its knowledge and messaging configuration remains unmigrated.
|
|
|
17
27
|
> before activation/spawn. The v2 integration is [prepared](release-notes/v0.23.1.md),
|
|
18
28
|
> not a claim that those dependencies or any deployment have already changed.
|
|
19
29
|
|
|
20
|
-
## Upgrade one scope
|
|
30
|
+
## Upgrade one scope (0.24.x kernel)
|
|
21
31
|
|
|
22
32
|
Finish or preserve active work before changing a daily-use deployment.
|
|
23
|
-
Install OATS alongside the old CLI
|
|
24
|
-
scope you intend to convert:
|
|
33
|
+
Install OATS **0.24.x** alongside the old CLI (the 0.25 line has no `oats
|
|
34
|
+
migrate`), then inspect the plan for the exact scope you intend to convert:
|
|
25
35
|
|
|
26
36
|
```bash
|
|
27
|
-
npm install -g @awebai/oats@
|
|
28
|
-
pi install npm:@awebai/oats-pi@
|
|
37
|
+
npm install -g @awebai/oats@0.24
|
|
38
|
+
pi install npm:@awebai/oats-pi@0.24
|
|
29
39
|
oats migrate --from-oas --dry-run --dir /path/to/scope
|
|
30
40
|
```
|
|
31
41
|
|
|
@@ -39,10 +49,11 @@ oats doctor /path/to/scope
|
|
|
39
49
|
```
|
|
40
50
|
|
|
41
51
|
Run the exact `oats trust <capability> --dir <scope>` commands printed by
|
|
42
|
-
migration for the executable capabilities you approve.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
migration for the executable capabilities you approve (0.24: per-artifact
|
|
53
|
+
trust; under 0.25 approval is per package version through `oats sync`). Trust
|
|
54
|
+
does not transfer automatically. Verify the team ID and messaging membership
|
|
55
|
+
with `oats aweb setup --dir /path/to/scope`, then exercise a real task,
|
|
56
|
+
harvest, and retirement as described in [Run your first team](first-team.md).
|
|
46
57
|
|
|
47
58
|
For a multi-repository deployment, start with one scope. The explicit
|
|
48
59
|
`--recursive --dir /path/to/workspace` form converts every discovered OAS
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://oats.dev/schemas/local-v2.json",
|
|
4
|
+
"title": "Deployment-local overrides v2 (oats-local.yaml)",
|
|
5
|
+
"description": "The operator's side of a workspace: which workspace this machine realizes, where member clones live when not at the taught convention, host-owned capability settings (absolute paths belong HERE, never in the workspace file), and souls disabled on this machine. Never shared through Git.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "workspace"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "const": 2 },
|
|
11
|
+
"workspace": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"minLength": 1,
|
|
14
|
+
"pattern": "^(?:git@[^@\\s]+|[^@\\s]+)$",
|
|
15
|
+
"description": "Repo ref of the workspace host; observed over the remote, need not be cloned."
|
|
16
|
+
},
|
|
17
|
+
"standalone": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1,
|
|
20
|
+
"pattern": "^(?:git@[^@\\s]+|[^@\\s]+)$",
|
|
21
|
+
"description": "Repo ref to realize in the STANDALONE view (decision 10): its own souls and from: here capabilities plus oats.core (decision 25), no workspace lookup. Use when the repo's workspace cannot be read; `workspace:` still names the repo you point the kernel at."
|
|
22
|
+
},
|
|
23
|
+
"clones": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"propertyNames": { "type": "string", "pattern": "^[^\\s@/][^\\s@]*/[^\\s@]+$" },
|
|
26
|
+
"additionalProperties": { "type": "string", "minLength": 1 },
|
|
27
|
+
"description": "<repo key>: <path on this machine> for member clones outside the convention."
|
|
28
|
+
},
|
|
29
|
+
"settings": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"propertyNames": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
32
|
+
"additionalProperties": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"propertyNames": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_.-]*$" }
|
|
35
|
+
},
|
|
36
|
+
"description": "<capability>: { <key>: <value> } host-owned values the manifests ask for."
|
|
37
|
+
},
|
|
38
|
+
"souls": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"properties": {
|
|
42
|
+
"disabled": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"uniqueItems": true,
|
|
45
|
+
"items": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://oats.dev/schemas/membership-v2.json",
|
|
4
|
+
"title": "Repository membership backlink v2 (oats-membership.yaml)",
|
|
5
|
+
"description": "The repo's half of the reciprocal handshake: it names the workspace it belongs to, plus an optional default team label for the repo's items. Nothing else. A backlink is consent, not admission — the workspace must list the repo too.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "workspace"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "const": 2 },
|
|
11
|
+
"workspace": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"minLength": 1,
|
|
14
|
+
"pattern": "^(?:git@[^@\\s]+|[^@\\s]+)$",
|
|
15
|
+
"description": "Repo ref of the workspace host, without revision."
|
|
16
|
+
},
|
|
17
|
+
"team": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"pattern": "^[a-z0-9][a-z0-9._-]*$",
|
|
20
|
+
"description": "Default team label for souls and capabilities in this repo that carry no `team:` of their own."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,68 +1,153 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
3
|
-
"$id": "https://oats.dev/schemas/workspace-
|
|
4
|
-
"title": "
|
|
5
|
-
"description": "Data shape only;
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://oats.dev/schemas/workspace-v2.json",
|
|
4
|
+
"title": "Workspace declaration v2 (oats-workspace.yaml)",
|
|
5
|
+
"description": "Data shape only. Members carry NO revision (a member is always its latest state); `external` sources REQUIRE a full 40-hex commit; absolute filesystem paths are refused anywhere in this file (host paths belong in oats-local.yaml). Reciprocal membership is observed over Git remotes, not declared here.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["schemaVersion", "name"],
|
|
8
8
|
"additionalProperties": false,
|
|
9
9
|
"properties": {
|
|
10
|
-
"schemaVersion": { "const":
|
|
11
|
-
"name": { "
|
|
12
|
-
"members": {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
10
|
+
"schemaVersion": { "const": 2 },
|
|
11
|
+
"name": { "$ref": "#/$defs/slug" },
|
|
12
|
+
"members": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"uniqueItems": true,
|
|
15
|
+
"items": { "$ref": "#/$defs/memberRef" },
|
|
16
|
+
"description": "Repo refs without revision. Each becomes a member only when its oats-membership.yaml names this workspace back."
|
|
17
|
+
},
|
|
18
|
+
"packages": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"propertyNames": { "$ref": "#/$defs/packageId" },
|
|
21
|
+
"additionalProperties": { "$ref": "#/$defs/packageVersion" },
|
|
22
|
+
"description": "The ONLY versioned things: <package-id>: <version | git ref with @revision>."
|
|
17
23
|
},
|
|
18
24
|
"teams": {
|
|
19
|
-
"type": "object",
|
|
20
|
-
"
|
|
21
|
-
"additionalProperties": {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
"type": "object",
|
|
26
|
+
"propertyNames": { "$ref": "#/$defs/label" },
|
|
27
|
+
"additionalProperties": { "$ref": "#/$defs/team" },
|
|
28
|
+
"description": "Org team labels. A label never gates, restricts or partitions anything."
|
|
29
|
+
},
|
|
30
|
+
"defaults": { "$ref": "#/$defs/defaults" },
|
|
31
|
+
"stores": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"propertyNames": { "$ref": "#/$defs/slug" },
|
|
34
|
+
"additionalProperties": { "$ref": "#/$defs/memberRef" },
|
|
35
|
+
"description": "Knowledge stores, declared once: <name>: <repo ref>."
|
|
25
36
|
},
|
|
26
|
-
"
|
|
27
|
-
"type": "
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
"messaging": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"description": "Opaque provider payload consumed by the messaging-slot capability. May carry byTeam: { <team label>: <payload> } — the kernel merges base ⊕ byTeam[soul.team] and strips byTeam before the provider sees it (decision 23).",
|
|
40
|
+
"properties": {
|
|
41
|
+
"byTeam": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"propertyNames": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
|
|
44
|
+
"additionalProperties": { "type": "object" }
|
|
45
|
+
}
|
|
30
46
|
}
|
|
31
47
|
},
|
|
32
|
-
"
|
|
48
|
+
"external": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": { "$ref": "#/$defs/external" },
|
|
51
|
+
"description": "Souls adopted by reference from repos that are NOT members; pinned to a full commit."
|
|
52
|
+
}
|
|
33
53
|
},
|
|
34
54
|
"$defs": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"type": "
|
|
41
|
-
"
|
|
55
|
+
"slug": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
|
|
56
|
+
"label": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
57
|
+
"capabilityName": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
58
|
+
"packageId": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
59
|
+
"packageVersion": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"minLength": 1,
|
|
62
|
+
"pattern": "^(?:v?\\d+(?:\\.\\d+)*(?:[-+][0-9A-Za-z.-]+)?|git:(?:git@[^@\\s/:]+:)?[^@\\s]+@(?:[0-9a-f]{40}|(?!-)(?!.*(?:\\.\\.|@\\{|\\^|~|:|\\?|\\*|\\[|\\\\|\\.lock$|\\.$|/$|^/))[!-?A-~]+))$",
|
|
63
|
+
"description": "Exactly two forms: a bare version (v2.1.3) resolved through the catalog, or git:<repo>@<ref> (a direct package ref). lib/packages.mjs#classifyPackageValue is the full grammar."
|
|
64
|
+
},
|
|
65
|
+
"memberRef": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1,
|
|
68
|
+
"pattern": "^(?:git@[^@\\s]+|[^@\\s]+)$",
|
|
69
|
+
"description": "A repo ref (git:<host>/<path>, https://…, git@host:path.git, file:///…) with NO @revision."
|
|
70
|
+
},
|
|
71
|
+
"pinnedRef": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"pattern": "^(?:git@[^@\\s]+|[^@\\s]+)@[0-9a-f]{40}$",
|
|
74
|
+
"description": "<repo ref>@<full 40-hex commit OID>."
|
|
75
|
+
},
|
|
76
|
+
"repoKey": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"pattern": "^[^\\s@/][^\\s@]*/[^\\s@]+$",
|
|
79
|
+
"description": "Canonical repo identity <host>/<path> (or local/<abs-path> for file remotes), as produced by parseRepoRef(...).key."
|
|
42
80
|
},
|
|
43
|
-
"
|
|
44
|
-
"
|
|
81
|
+
"fromLocation": {
|
|
82
|
+
"anyOf": [
|
|
83
|
+
{ "const": "package" },
|
|
84
|
+
{ "const": "here" },
|
|
85
|
+
{ "$ref": "#/$defs/repoKey" }
|
|
86
|
+
],
|
|
87
|
+
"description": "WHERE a capability comes from — a location, never a version."
|
|
88
|
+
},
|
|
89
|
+
"capabilityRef": {
|
|
90
|
+
"type": "object",
|
|
91
|
+
"required": ["from"],
|
|
92
|
+
"additionalProperties": false,
|
|
93
|
+
"properties": { "from": { "$ref": "#/$defs/fromLocation" } }
|
|
94
|
+
},
|
|
95
|
+
"capabilityChoice": { "anyOf": [{ "$ref": "#/$defs/capabilityRef" }, { "const": "off" }] },
|
|
96
|
+
"capabilityMap": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"propertyNames": { "$ref": "#/$defs/capabilityName" },
|
|
99
|
+
"additionalProperties": { "$ref": "#/$defs/capabilityChoice" }
|
|
100
|
+
},
|
|
101
|
+
"slotDefault": {
|
|
102
|
+
"anyOf": [
|
|
103
|
+
{ "const": "none" },
|
|
104
|
+
{
|
|
105
|
+
"type": "object",
|
|
106
|
+
"maxProperties": 1,
|
|
107
|
+
"propertyNames": { "$ref": "#/$defs/capabilityName" },
|
|
108
|
+
"additionalProperties": { "$ref": "#/$defs/capabilityRef" }
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"description": "At most one capability fills a slot; `none` leaves it empty."
|
|
112
|
+
},
|
|
113
|
+
"team": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"additionalProperties": false,
|
|
116
|
+
"properties": { "description": { "type": "string" } }
|
|
117
|
+
},
|
|
118
|
+
"defaults": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"additionalProperties": false,
|
|
45
121
|
"properties": {
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"type": "object",
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"knowledge": { "$ref": "https://oats.dev/schemas/soul-v1.json#/$defs/defaultProvider" },
|
|
58
|
-
"messaging": { "$ref": "https://oats.dev/schemas/soul-v1.json#/$defs/defaultProvider" },
|
|
59
|
-
"tasks": { "$ref": "https://oats.dev/schemas/soul-v1.json#/$defs/defaultProvider" }
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
"bindings": { "type": "object" }
|
|
122
|
+
"capabilities": { "$ref": "#/$defs/capabilityMap" },
|
|
123
|
+
"knowledge": { "$ref": "#/$defs/slotDefault" },
|
|
124
|
+
"messaging": { "$ref": "#/$defs/slotDefault" },
|
|
125
|
+
"tasks": { "$ref": "#/$defs/slotDefault" },
|
|
126
|
+
"byTeam": {
|
|
127
|
+
"type": "object",
|
|
128
|
+
"propertyNames": { "$ref": "#/$defs/label" },
|
|
129
|
+
"additionalProperties": {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"additionalProperties": false,
|
|
132
|
+
"properties": { "capabilities": { "$ref": "#/$defs/capabilityMap" } }
|
|
63
133
|
}
|
|
64
134
|
}
|
|
65
135
|
}
|
|
136
|
+
},
|
|
137
|
+
"external": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"required": ["source", "soul"],
|
|
140
|
+
"additionalProperties": false,
|
|
141
|
+
"properties": {
|
|
142
|
+
"source": { "$ref": "#/$defs/pinnedRef" },
|
|
143
|
+
"soul": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"minLength": 1,
|
|
146
|
+
"pattern": "^(?![A-Za-z]:)(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))[^/\\\\\u0000]+(?:/[^/\\\\\u0000]+)*$",
|
|
147
|
+
"description": "Repository-relative directory holding the soul's soul.yaml."
|
|
148
|
+
},
|
|
149
|
+
"team": { "$ref": "#/$defs/label" }
|
|
150
|
+
}
|
|
66
151
|
}
|
|
67
152
|
}
|
|
68
153
|
}
|
|
@@ -10,14 +10,17 @@ or workspace membership alone does not make a package official.
|
|
|
10
10
|
- Browse the catalog for the kernel/source version you use. Each package entry
|
|
11
11
|
identifies its repository, release ref and payload root; capability aliases
|
|
12
12
|
can point to the package that supplies them.
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
- A workspace pins an official package by **bare version** in its
|
|
14
|
+
`packages:` map (`oats.okf: v2.1.3`); `oats sync` resolves it through the
|
|
15
|
+
catalog to an exact commit, locks it and asks for executable approval once
|
|
16
|
+
per version. A package outside the catalog is written `git:<repo>@<ref>`.
|
|
17
|
+
Pinning does not enroll a team or adopt the publisher's workspace. See
|
|
18
|
+
[packages](packages.md).
|
|
17
19
|
- The Desktop marketplace view/search is **planned for the parity phase**, not
|
|
18
20
|
shipped by this policy or by OATS 0.24. There is no new marketplace CLI verb.
|
|
19
|
-
- **Discoverable ≠
|
|
20
|
-
|
|
21
|
+
- **Discoverable ≠ pinned ≠ approved.** A catalog listing grants nothing; a
|
|
22
|
+
`packages:` pin selects a version; the lock's per-version approval is what
|
|
23
|
+
lets its executables run. Nothing is installed.
|
|
21
24
|
Official status never grants trust, credentials or permission to run code.
|
|
22
25
|
- Listing also does not prove that every harness, provider combination or
|
|
23
26
|
deployment profile is supported. Check the package's declared compatibility,
|