@awebai/oats 0.37.0 → 0.38.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 +71 -65
- package/docs/capabilities.md +11 -7
- package/docs/configuration.md +10 -20
- package/docs/design/2026-09-27-team-model-v2.md +1 -1
- package/docs/design/2026-10-02-team-model-3.md +146 -0
- package/docs/design/README.md +5 -1
- package/docs/desktop-cli-api.md +159 -121
- package/docs/first-team.md +14 -7
- package/docs/integrations.md +1 -1
- package/docs/oats-local.schema.json +2 -14
- package/docs/oats-workspace.schema.json +4 -4
- package/docs/official-catalog.md +2 -2
- package/docs/packages.md +10 -9
- package/docs/release-notes/v0.38.0.md +128 -0
- package/docs/souls-and-instances.md +4 -3
- package/docs/workspaces.md +122 -77
- package/lib/instance-inspect.mjs +18 -15
- package/lib/instance-resolution.mjs +9 -6
- package/lib/resolve.mjs +5 -4
- package/lib/teams-verbs.mjs +44 -70
- package/lib/teams.mjs +151 -112
- package/lib/workspace.mjs +15 -5
- package/package-catalog.json +2 -2
- package/package.json +1 -1
- package/skills/oats-getting-started/SKILL.md +20 -9
package/lib/workspace.mjs
CHANGED
|
@@ -18,7 +18,8 @@ import { oatsError } from "./errors.mjs";
|
|
|
18
18
|
import * as defaultRemote from "./remote.mjs";
|
|
19
19
|
import { bindRemote, classifyPackageValue, lockedPackageRef } from "./packages.mjs";
|
|
20
20
|
import { manifestContractProblems } from "./capability-contract.mjs";
|
|
21
|
-
import
|
|
21
|
+
import YAML from "yaml";
|
|
22
|
+
import { BY_TEAM_REMOVED, TEAM_MEMBERSHIP_MOVED, soulsReplacement } from "./teams.mjs";
|
|
22
23
|
|
|
23
24
|
/* ───────────────────────────── errors ─────────────────────────────────── */
|
|
24
25
|
|
|
@@ -261,7 +262,7 @@ function sharedLabelProblems(value, problems) {
|
|
|
261
262
|
}
|
|
262
263
|
export function validateMembership(value) { return withRemovedKeys(validateAgainst(schemaFor("membership"), value), value, REMOVED_KEYS.membership); }
|
|
263
264
|
|
|
264
|
-
/** Keys 0.30
|
|
265
|
+
/** Keys 0.30 (team model v2) and 0.38.0 (team model 3) removed: each is a schema problem naming its replacement, in place of
|
|
265
266
|
* the schema's generic "unexpected property". `at(value)` → the JSON pointers where it appears. */
|
|
266
267
|
const REMOVED_KEYS = {
|
|
267
268
|
workspace: [
|
|
@@ -270,6 +271,11 @@ const REMOVED_KEYS = {
|
|
|
270
271
|
],
|
|
271
272
|
membership: [{ at: (v) => (isObject(v) && Object.hasOwn(v, "team") ? ["/team"] : []), message: TEAM_MEMBERSHIP_MOVED }],
|
|
272
273
|
soul: [{ at: (v) => (isObject(v) && Object.hasOwn(v, "team") ? ["/team"] : []), message: TEAM_MEMBERSHIP_MOVED }],
|
|
274
|
+
// 0.38.0 (team model 3): a soul's teams and default are committed in the workspace's souls:.
|
|
275
|
+
local: [
|
|
276
|
+
{ at: (v) => (isObject(v?.souls) && Object.hasOwn(v.souls, "teams") ? ["/souls/teams"] : []), message: "souls.teams was removed in 0.38.0 (team model 3): which teams a soul may join is souls: in oats-workspace.yaml" },
|
|
277
|
+
{ at: (v) => (isObject(v?.souls) && Object.hasOwn(v.souls, "default") ? ["/souls/default"] : []), message: "souls.default was removed in 0.38.0 (team model 3): a soul's default team is souls: in oats-workspace.yaml (default:)" },
|
|
278
|
+
],
|
|
273
279
|
};
|
|
274
280
|
function withRemovedKeys(problems, value, removed) {
|
|
275
281
|
const found = removed.flatMap((r) => r.at(value).map((path) => ({ path, reason: "removed-key", message: r.message })));
|
|
@@ -316,7 +322,7 @@ function fromProblems(remote, capabilities, path, problems, { here }) {
|
|
|
316
322
|
}
|
|
317
323
|
/** Schema + domain problems for an oats-local.yaml value: settings[<cap>] may not carry the removed `byTeam` key. */
|
|
318
324
|
export function validateLocal(value) {
|
|
319
|
-
const problems = validateAgainst(schemaFor("local"), value);
|
|
325
|
+
const problems = withRemovedKeys(validateAgainst(schemaFor("local"), value), value, REMOVED_KEYS.local);
|
|
320
326
|
if (isObject(value) && isObject(value.settings)) for (const [cap, payload] of Object.entries(value.settings)) reservedKeyProblems(payload, `/settings/${pointerKey(cap)}`, problems);
|
|
321
327
|
// runtime → harness (0.27.0, lead call 6): `runtime`, the pre-0.27 name, is still read; both,
|
|
322
328
|
// disagreeing, are refused.
|
|
@@ -361,8 +367,12 @@ function schemaError(kind, origin, problems, value) {
|
|
|
361
367
|
const where = origin.repoKey ? `${origin.repoKey}@${(origin.commit || "").slice(0, 12)}:${origin.path}` : origin.path;
|
|
362
368
|
// A single-cause refusal (reserved-key, …) surfaces its reason on details for callers that branch on it.
|
|
363
369
|
const reasons = new Set(problems.map((p) => p.reason).filter(Boolean));
|
|
364
|
-
|
|
365
|
-
|
|
370
|
+
// Team model 3: the refused souls.teams / souls.default come with the souls: that replaces them.
|
|
371
|
+
const moved = kind === "local" && problems.some((p) => p.reason === "removed-key" && /^\/souls\/(teams|default)$/.test(p.path)) ? soulsReplacement(value) : null;
|
|
372
|
+
const replacement = moved ? YAML.stringify(moved, { lineWidth: 0 }) : null;
|
|
373
|
+
return fail("E_WORKSPACE_SCHEMA", `${FILE_KINDS[kind].file} at ${where} is invalid${schemaHint(kind, value)}: ${problems.map((p) => `${p.path || "/"}: ${p.message}`).join("; ")}`
|
|
374
|
+
+ (replacement ? `; commit this in oats-workspace.yaml (<member> is the soul's member repository name, as souls.disabled names it), then remove souls.teams and souls.default from oats-local.yaml:\n${replacement}` : ""), {
|
|
375
|
+
path: origin.path, repoKey: origin.repoKey, commit: origin.commit, problems, ...(reasons.size === 1 ? { reason: [...reasons][0] } : {}), ...(replacement ? { replacement } : {}),
|
|
366
376
|
});
|
|
367
377
|
}
|
|
368
378
|
|
package/package-catalog.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"oats.aweb": {
|
|
10
10
|
"url": "https://github.com/awebai/oats-aweb.git",
|
|
11
|
-
"ref": "v1.
|
|
11
|
+
"ref": "v1.19.0",
|
|
12
12
|
"path": "oats-package"
|
|
13
13
|
},
|
|
14
14
|
"oats.jira": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"oats.framework": {
|
|
35
35
|
"url": "https://github.com/awebai/oats.git",
|
|
36
|
-
"ref": "oats-framework/v1.
|
|
36
|
+
"ref": "oats-framework/v1.5.0",
|
|
37
37
|
"path": "oats-package"
|
|
38
38
|
}
|
|
39
39
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awebai/oats",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "OATS (Open Agent Team Specification) — durable souls, disposable instances, targetable capability packages, and the runtime-neutral oats CLI/kernel.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -60,7 +60,7 @@ members:
|
|
|
60
60
|
- git:github.com/acme/agents # the host is a member too
|
|
61
61
|
- git:github.com/acme/platform
|
|
62
62
|
packages:
|
|
63
|
-
oats.framework: v1.
|
|
63
|
+
oats.framework: v1.5.0 # bare versions resolve through the official catalog
|
|
64
64
|
oats.okf: v4.1.1
|
|
65
65
|
defaults:
|
|
66
66
|
capabilities: { oats.core: { from: package } }
|
|
@@ -135,18 +135,29 @@ membership.
|
|
|
135
135
|
## 6. Give the deployment a team (with messaging)
|
|
136
136
|
|
|
137
137
|
If a messaging capability fills the messaging slot, every instance lives in a
|
|
138
|
-
team, and readiness fails with `E_TEAM_UNCONFIGURED` until
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
team, and readiness fails with `E_TEAM_UNCONFIGURED` until there is a default
|
|
139
|
+
team. Create the team with the messaging provider (its own skills say how),
|
|
140
|
+
then commit it in `oats-workspace.yaml` with its provider id, and make it the
|
|
141
|
+
default:
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
teams:
|
|
145
|
+
research: { team: <provider team id> }
|
|
146
|
+
defaultTeam: research
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Push, then sync and check:
|
|
141
150
|
|
|
142
151
|
```bash
|
|
143
|
-
oats
|
|
144
|
-
oats teams
|
|
152
|
+
oats sync --dir <dir>
|
|
153
|
+
oats teams --dir <dir>
|
|
145
154
|
```
|
|
146
155
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
The teams an instance may join, and its default, are the organisation's
|
|
157
|
+
decision, committed in this file: by default a soul joins its default team
|
|
158
|
+
only, and `souls:` entries open other teams to a soul. A deployment declares
|
|
159
|
+
teams of its own (`oats teams add`) only when the workspace says
|
|
160
|
+
`localTeams: true` (`/oats-teams`, in `oats.setup`).
|
|
150
161
|
|
|
151
162
|
## 7. Spawn the first soul
|
|
152
163
|
|