@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/docs/desktop-cli-api.md
CHANGED
|
@@ -37,7 +37,7 @@ canonical (`github.com/<org>/<repo>`, or `local/<abs-path>`). Examples use
|
|
|
37
37
|
"instance-git-remote","souls-declarations","lifecycle-plans","retire-retention","readiness","spawn-preview","instance-events",
|
|
38
38
|
"instance-events-2","schedule-history","schedule-read-2","spawn-preview-2","spawn-idempotency","spawn-idempotency-2","spawn-apply-2",
|
|
39
39
|
"workspace-v2","instance-modules","spawn-provider-payload","served-identity","packages-no-approval","spawn-name","settings-origins",
|
|
40
|
-
"team-model-
|
|
40
|
+
"team-model-3","settings-declared","capabilities-private","layers-from","harness","package-souls","triggers","automations","desktop-facts","launch-preference",
|
|
41
41
|
"preview-composed-from","observe-max-age","spawn-preview-max-age","capability-show","capture-file","workspace-identity"],
|
|
42
42
|
"automationsApi":1,"workspaceApi":2,"instanceGitApi":1,"spawnApplyApi":1,"soulsApi":2,"lifecycleApi":1,
|
|
43
43
|
"readinessApi":2,"spawnPreviewApi":2,"eventsApi":2,"scheduleHistoryApi":3,"scheduleApi":2,"operationsApi":2,
|
|
@@ -88,7 +88,7 @@ canonical (`github.com/<org>/<repo>`, or `local/<abs-path>`). Examples use
|
|
|
88
88
|
| `settings-declared` | `declares` on inspect capabilities and preview modules | |
|
|
89
89
|
| `capabilities-private` | `private` on `oats capabilities` rows | |
|
|
90
90
|
| `layers-from` | `layers.<slot>.from` in inspect | |
|
|
91
|
-
| `team-model-
|
|
91
|
+
| `team-model-3` | every team field; `oats teams`, `oats soul teams` (0.38.0; replaces `team-model-2`) | `teamsApi: 2`, `soulTeamsApi: 2` (payload only) |
|
|
92
92
|
| `harness` | the harness names ([Harness input spellings](#the-harness-rename-feature-harness-oats-0270)) | |
|
|
93
93
|
| `package-souls` | package soul rows, `qualifiedName`, `packages[].souls` | |
|
|
94
94
|
| `triggers` | `oats trigger …` | `triggerApi: 1` (payload only) |
|
|
@@ -253,9 +253,11 @@ oats capabilities show <name> … --max-age <seconds> --json (feature capabilit
|
|
|
253
253
|
commit can no longer be fetched. Each is observed live, as without the flag.
|
|
254
254
|
A live observation that fails is the usual error, never an older head.
|
|
255
255
|
- **Refusals:** every other command, a spawn apply (with or without
|
|
256
|
-
`--expect-decision`; the form named is `spawn`), every edit form (`teams add|remove|default
|
|
257
|
-
|
|
258
|
-
invocation refuse the flag before reading or writing anything
|
|
256
|
+
`--expect-decision`; the form named is `spawn`), every edit form (`teams add|remove|default`)
|
|
257
|
+
and any `--server`
|
|
258
|
+
invocation refuse the flag before reading or writing anything (the removed
|
|
259
|
+
`soul teams --add|--remove|--default|--clear-default` answer their own
|
|
260
|
+
`E_BAD_ARGS` first), with
|
|
259
261
|
`E_BAD_ARGS` "--max-age is not accepted by \`oats <form>\`: only the read
|
|
260
262
|
verbs reuse observations (status, workspace status, souls, capabilities,
|
|
261
263
|
capabilities show, inspect --soul|--home, spawn --preview, and the read
|
|
@@ -397,7 +399,8 @@ message}`.
|
|
|
397
399
|
A soul whose resolution is refused is an inspect error with the resolver's
|
|
398
400
|
code and details (`E_PACKAGE_MISSING`, `E_PACKAGE_INTEGRITY`,
|
|
399
401
|
`E_CAPABILITY_MISSING`, `E_LOCK_SCHEMA`, `E_REQUIREMENT_INACTIVE`,
|
|
400
|
-
`E_TEAM_UNKNOWN`, `
|
|
402
|
+
`E_TEAM_UNKNOWN`, and `E_WORKSPACE_SCHEMA` reason `local-teams-closed`);
|
|
403
|
+
readiness reports the same condition
|
|
401
404
|
as an item. Soul lookup errors are those of [spawn](#spawn-errors).
|
|
402
405
|
|
|
403
406
|
<a id="oats-readiness---home-----soul----dir----policy---json--readinessapi-2"></a>
|
|
@@ -595,6 +598,7 @@ A removed verb answers, before any namespace can claim it:
|
|
|
595
598
|
| `status --team` | `E_BAD_ARGS` | `oats status` in the deployment |
|
|
596
599
|
| `spawn --instance` | `E_BAD_ARGS` | `--purpose` or `--name` |
|
|
597
600
|
| `spawn --ephemeral`, `--instructions-file`, `--def-file` | `E_BAD_ARGS` | a soul in a member repository |
|
|
601
|
+
| `soul teams --add`, `--remove`, `--default`, `--clear-default` (0.38.0) | `E_BAD_ARGS` (`details: {flag, replacement}`) | `souls:` in `oats-workspace.yaml` |
|
|
598
602
|
| `session … --native-record` | `E_BAD_ARGS` | none |
|
|
599
603
|
|
|
600
604
|
`details.replacement` is the kernel's prose (shortened above): show it, do not
|
|
@@ -750,7 +754,7 @@ Read-only (it writes no lock):
|
|
|
750
754
|
- `declaredPackages`: the ids in `packages:` (standalone: the kernel's
|
|
751
755
|
default). `unsynced`: declared, not locked. `stale`: locked, no longer
|
|
752
756
|
declared. `external[]`: `{source, soul}`.
|
|
753
|
-
- `workspace.teams` (feature `team-model-
|
|
757
|
+
- `workspace.teams` (feature `team-model-3`): the shared teams `{label, team,
|
|
754
758
|
description}` by label; `[]` standalone.
|
|
755
759
|
- `problems`, `warnings`: as in sync.
|
|
756
760
|
- `automations` (feature `automations`): `{host, snapshot: {takenAt,
|
|
@@ -788,7 +792,7 @@ packages' capabilities and souls, sorted by name, then origin. Both carry
|
|
|
788
792
|
"version":"4.1.1","repoKey":"github.com/awebai/oats-okf","commit":"e1d604f7…","teams":null,"defaultTeam":null,"private":false,
|
|
789
793
|
"path":"oats-package/souls/knowledge-maintainer","work":"directory","description":"Reviews harvested knowledge.","harness":"pi","model":null,
|
|
790
794
|
"harnessFrom":"kernel-default","file":{"path":"oats-package/souls/knowledge-maintainer/soul.yaml","url":null},
|
|
791
|
-
"spawnable":false,"problem":{"code":"E_TEAM_UNKNOWN","message":"team \"reviewers\" is not declared (oats-local.yaml#/
|
|
795
|
+
"spawnable":false,"problem":{"code":"E_TEAM_UNKNOWN","message":"team \"reviewers\" is not declared (oats-local.yaml#/defaultTeam): …"}}],
|
|
792
796
|
"problems":[]}
|
|
793
797
|
```
|
|
794
798
|
|
|
@@ -804,13 +808,13 @@ are absent until `sync`.
|
|
|
804
808
|
commit, teams, defaultTeam, private (always false), path, work, description`,
|
|
805
809
|
plus the Desktop facts `harness, model, harnessFrom, file, spawnable,
|
|
806
810
|
problem`, and (feature `launch-preference`) `key` and `launch`.
|
|
807
|
-
- `key` is the soul key that `souls.
|
|
808
|
-
|
|
811
|
+
- `key` is the soul key that `souls.launch` uses, and that
|
|
812
|
+
`oats soul teams <key>` takes: `qualifiedName` for a package
|
|
809
813
|
soul, the bare `name` for a member or external soul. Two member souls that
|
|
810
814
|
share a bare name share one entry (spawning that name is
|
|
811
815
|
`E_SOUL_AMBIGUOUS`).
|
|
812
816
|
- `launch` is a [Launch](#the-launch-report-launch).
|
|
813
|
-
- `teams` and `defaultTeam` (feature `team-model-
|
|
817
|
+
- `teams` and `defaultTeam` (feature `team-model-3`) are a
|
|
814
818
|
[TeamRow](#the-team-row-teamrow) list and a
|
|
815
819
|
[DefaultTeam](#the-default-defaultteam); both `null` when the soul's teams
|
|
816
820
|
do not resolve (`problem` names the `E_TEAM_*` code).
|
|
@@ -1012,7 +1016,7 @@ them. Gate each field below on it.
|
|
|
1012
1016
|
v2 soul.yaml cannot). `spawnable`/`problem`: whether a spawn here would
|
|
1013
1017
|
refuse, resolved without spawning, writing or reaching past the sync cache;
|
|
1014
1018
|
`problem` is `{code, message}` or `null` (`E_SOUL_DISABLED`,
|
|
1015
|
-
`E_TEAM_UNKNOWN`, `
|
|
1019
|
+
`E_TEAM_UNKNOWN`, `E_WORKSPACE_SCHEMA` (local-teams-closed), `E_CAPABILITY_*`, `E_PACKAGE_*`,
|
|
1016
1020
|
`E_LOCK_SCHEMA`, `E_REMOTE_*`, …). `file`: `{path, url}` of soul.yaml.
|
|
1017
1021
|
- **Capabilities.** `layer` on every row, `null` outside the slots.
|
|
1018
1022
|
`description` or `null`. `skills`, `commands`, `hooks`: names, sorted
|
|
@@ -1039,61 +1043,91 @@ them. Gate each field below on it.
|
|
|
1039
1043
|
`…/tree/<commit>`); any other host gives `url: null` with `path` set.
|
|
1040
1044
|
`path` is repository-relative.
|
|
1041
1045
|
|
|
1046
|
+
<a id="team-model-3-feature-team-model-3-oats-0370-replaces-feature-team-model-2"></a>
|
|
1042
1047
|
<a id="team-model-v2-feature-team-model-2-oats-0300-replaces-feature-teams"></a>
|
|
1043
1048
|
## Teams
|
|
1044
1049
|
|
|
1045
|
-
Feature `team-model-
|
|
1046
|
-
[team model
|
|
1047
|
-
[workspaces.md](workspaces.md).
|
|
1048
|
-
|
|
1049
|
-
- **
|
|
1050
|
-
`teams.<label> = {description?, team?}
|
|
1051
|
-
provider id
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1050
|
+
Feature `team-model-3` (OATS 0.38.0; it replaces `team-model-2`): gate every
|
|
1051
|
+
team field and verb on it. Design: [team model 3](design/2026-10-02-team-model-3.md);
|
|
1052
|
+
operator guide: [workspaces.md](workspaces.md#teams).
|
|
1053
|
+
|
|
1054
|
+
- **The workspace file** (`oats-workspace.yaml`, committed) holds the shared
|
|
1055
|
+
teams `teams.<label> = {description?, team?}` (a shared team without `team`,
|
|
1056
|
+
the provider id, is **unmapped**), `defaultTeam: <label>` (the workspace's
|
|
1057
|
+
fallback default), `localTeams: true|false` (absent: false) and `souls:`
|
|
1058
|
+
(per pattern, `{default?, teams?: [labels] | "any"}`). Every label there is
|
|
1059
|
+
a shared label of that file; anything else is `E_WORKSPACE_SCHEMA` when the
|
|
1060
|
+
file is read.
|
|
1061
|
+
- **`oats-local.yaml`** may declare local teams `teams.<label> = {team,
|
|
1062
|
+
description?}` and `defaultTeam: <label>` only where the workspace says
|
|
1063
|
+
`localTeams: true`, or in the standalone view (no workspace file is read).
|
|
1064
|
+
Elsewhere they are refused: `E_WORKSPACE_SCHEMA` with details `{reason:
|
|
1065
|
+
"local-teams-closed", path: "oats-local.yaml", keys}`, the message naming
|
|
1066
|
+
both fixes. `souls.teams` and `souls.default` are removed keys
|
|
1067
|
+
(`E_WORKSPACE_SCHEMA`, reason `removed-key`): the refusal names each key
|
|
1068
|
+
found, and `details.replacement` is the `souls:` YAML to commit instead (a
|
|
1069
|
+
bare soul name written `<member>/<soul>` for the operator to qualify), also
|
|
1070
|
+
printed at the end of the message. Every command that reads the file
|
|
1071
|
+
refuses, an instance home's messaging commands, operations, `inspect --home`
|
|
1072
|
+
and `readiness --home` included: they never fall back to the home's
|
|
1073
|
+
recorded teams for it. A home's other capability commands read only the
|
|
1074
|
+
home's own record, as always.
|
|
1075
|
+
- **A soul's key** is its qualified name: `<package>/<soul>`, or
|
|
1076
|
+
`<member>/<soul>` with the member repository's name (as `souls.disabled`
|
|
1077
|
+
names it). A label matches `[a-z0-9][a-z0-9._-]*`.
|
|
1057
1078
|
- **Team ids.** A `team` value (in either file, and `oats teams add --team`)
|
|
1058
1079
|
matches `^[A-Za-z0-9][A-Za-z0-9._:@/+-]{0,255}$`: the kernel's safety rule
|
|
1059
1080
|
(never `-`-led, no whitespace or control characters, bounded). Otherwise
|
|
1060
1081
|
`E_WORKSPACE_SCHEMA` (a file) or `E_BAD_ARGS` (the verb). The messaging
|
|
1061
1082
|
provider validates its own id shape (oats.aweb: `<name>:<namespace>`).
|
|
1062
|
-
- **Resolution.** The
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
`
|
|
1067
|
-
`
|
|
1083
|
+
- **Resolution.** The `souls:` patterns for a soul are its key, then
|
|
1084
|
+
`<member|package>/*`, then `"*"`. The most specific one that exists gives
|
|
1085
|
+
the soul's teams outright (lists never merge); the most specific one that
|
|
1086
|
+
sets `default` gives its default. So `a/*: {default: security}` and
|
|
1087
|
+
`a/x: {teams: [docs]}` give `a/x` the default `security` and the teams
|
|
1088
|
+
`[docs]` only. The default is that `default`; else the local `defaultTeam`
|
|
1089
|
+
where local teams are allowed; else the workspace's `defaultTeam`; else
|
|
1090
|
+
none. A soul's teams are its default, its pattern's `teams` (`any`: every
|
|
1091
|
+
shared team) and, where local teams are allowed, every local team. A soul
|
|
1092
|
+
no pattern matches has its default only. A label in both files is a
|
|
1093
|
+
`team-label-collision` warning, and the shared definition wins. A local
|
|
1094
|
+
default no file declares is `E_TEAM_UNKNOWN`.
|
|
1068
1095
|
- **Removed keys** are `E_WORKSPACE_SCHEMA` with `reason: "removed-key"`:
|
|
1096
|
+
`oats-local.yaml` `souls.teams` and `souls.default` (0.38.0);
|
|
1069
1097
|
`messaging.byTeam`, `defaults.byTeam`, a soul.yaml `team`, an
|
|
1070
|
-
oats-membership.yaml `team`, and `byTeam` in any provider payload layer
|
|
1071
|
-
Other payload keys are opaque (a `team` setting passes through).
|
|
1098
|
+
oats-membership.yaml `team`, and `byTeam` in any provider payload layer
|
|
1099
|
+
(0.30). Other payload keys are opaque (a `team` setting passes through).
|
|
1072
1100
|
|
|
1073
1101
|
### The team row (`TeamRow`)
|
|
1074
1102
|
|
|
1075
|
-
Exactly `{label, team, default, from}`:
|
|
1103
|
+
Exactly `{label, team, default, from, via}`:
|
|
1076
1104
|
|
|
1077
1105
|
```json
|
|
1078
|
-
[{"label":"
|
|
1079
|
-
{"label":"
|
|
1080
|
-
{"label":"
|
|
1106
|
+
[{"label":"security","team":"security:acme.aweb.ai","default":true,"from":"shared","via":["default"]},
|
|
1107
|
+
{"label":"docs","team":null,"default":false,"from":"shared","via":["workspace"]},
|
|
1108
|
+
{"label":"mine","team":"mine:ana.aweb.ai","default":false,"from":"local","via":["local"]}]
|
|
1081
1109
|
```
|
|
1082
1110
|
|
|
1083
1111
|
`team` is `null` for an unmapped team. `default` is true on exactly the
|
|
1084
1112
|
soul's default row; the others are teams an instance may join (offered, never
|
|
1085
|
-
joined automatically). `from` is `"shared"` or
|
|
1086
|
-
|
|
1087
|
-
|
|
1113
|
+
joined automatically). `from` is where the label is defined: `"shared"` or
|
|
1114
|
+
`"local"`. `via` is why the soul may join it, an ordered non-empty subset of
|
|
1115
|
+
`"default"`, `"workspace"` (its `souls:` pattern) and `"local"` (a local team
|
|
1116
|
+
where local teams are allowed). The default row comes first, then the rest by
|
|
1117
|
+
label (codepoint order). Reports include unmapped rows; `OATS_TEAMS` and
|
|
1118
|
+
`instance.json.teams` carry mapped rows only. A home spawned before 0.38.0
|
|
1119
|
+
recorded rows without `via`, and they are reported as recorded.
|
|
1088
1120
|
|
|
1089
1121
|
### The default (`DefaultTeam`)
|
|
1090
1122
|
|
|
1091
1123
|
```json
|
|
1092
|
-
{"label":"
|
|
1124
|
+
{"label":"security","team":"security:acme.aweb.ai","from":"soul"}
|
|
1093
1125
|
```
|
|
1094
1126
|
|
|
1095
|
-
`from` is `"
|
|
1096
|
-
|
|
1127
|
+
`from` is `"soul"` (the soul's `souls:` default in the workspace file; before
|
|
1128
|
+
0.38.0 it meant `oats-local.yaml` `souls.default`), `"deployment"` (the local
|
|
1129
|
+
`defaultTeam`) or `"workspace"` (the workspace's `defaultTeam`). It is `null`
|
|
1130
|
+
only when no default is configured (with messaging active, that is
|
|
1097
1131
|
`E_TEAM_UNCONFIGURED`). An unmapped default is `{label, team: null, from}`,
|
|
1098
1132
|
the blocking problem `team-unmapped`.
|
|
1099
1133
|
|
|
@@ -1119,9 +1153,12 @@ its spawn-time default until respawned (readiness says so with
|
|
|
1119
1153
|
the teams in `OATS_DEFAULT_TEAM`, `OATS_DEFAULT_TEAM_ID`,
|
|
1120
1154
|
`OATS_DEFAULT_TEAM_FROM`, `OATS_TEAMS` and `OATS_TEAMS_SOURCE`:
|
|
1121
1155
|
[capabilities.md](capabilities.md#teams-in-the-provider-environment).
|
|
1122
|
-
`
|
|
1123
|
-
|
|
1156
|
+
`OATS_TEAMS` is exactly the soul's eligible mapped rows, so a provider that
|
|
1157
|
+
admits joins from it refuses any other team. `OATS_WORKSPACE_NAME` is the
|
|
1158
|
+
recorded workspace name (the discovered one for a soul subject), `""` when
|
|
1159
|
+
unknown.
|
|
1124
1160
|
|
|
1161
|
+
<a id="oats-teams"></a>
|
|
1125
1162
|
### `oats teams`
|
|
1126
1163
|
|
|
1127
1164
|
```text
|
|
@@ -1132,66 +1169,75 @@ oats teams default <label> --json
|
|
|
1132
1169
|
```
|
|
1133
1170
|
|
|
1134
1171
|
```json
|
|
1135
|
-
{"teamsApi":
|
|
1136
|
-
"teams":[{"label":"
|
|
1137
|
-
{"label":"
|
|
1138
|
-
"souls":{"
|
|
1139
|
-
"problems":[{"code":"team-unmapped","label":"
|
|
1140
|
-
"message":"shared team
|
|
1172
|
+
{"teamsApi":2,"deployment":"/w","localTeams":true,"defaultTeam":{"label":"mine","team":"mine:ana.aweb.ai","from":"deployment"},
|
|
1173
|
+
"teams":[{"label":"mine","team":"mine:ana.aweb.ai","description":null,"from":"local","default":true,"at":"oats-local.yaml#/teams/mine"},
|
|
1174
|
+
{"label":"docs","team":null,"description":null,"from":"shared","default":false,"at":"github.com/acme/agents:oats-workspace.yaml#/teams/docs"}],
|
|
1175
|
+
"souls":{"*":{"teams":["docs"]},"security-souls/*":{"default":"security","teams":["engineering"]}},
|
|
1176
|
+
"problems":[{"code":"team-unmapped","label":"docs","default":false,"severity":"warning","at":"github.com/acme/agents:oats-workspace.yaml#/teams/docs",
|
|
1177
|
+
"message":"shared team docs has no provider id yet","fix":"its owner runs `oats aweb setup`, then commits the id"}]}
|
|
1141
1178
|
```
|
|
1142
1179
|
|
|
1143
|
-
- `
|
|
1180
|
+
- `localTeams`: the workspace's answer (`true`/`false`), `null` in the
|
|
1181
|
+
standalone view. `defaultTeam` is the `DefaultTeam` a soul without a
|
|
1182
|
+
`souls:` default gets here (`from` `"deployment"` or `"workspace"`), or
|
|
1183
|
+
`null`.
|
|
1144
1184
|
- `teams[]`: every declared team by label, `{label, team, description, from,
|
|
1145
|
-
default, at}`; `at` is a pointer into
|
|
1146
|
-
`<workspace key>:oats-workspace.yaml#/teams/<label>`.
|
|
1147
|
-
shared definition.
|
|
1148
|
-
- `souls`:
|
|
1149
|
-
deployment's [team readiness items](#team-readiness-items).
|
|
1185
|
+
default, at}`; `default` marks that `defaultTeam`; `at` is a pointer into
|
|
1186
|
+
`oats-local.yaml` or `<workspace key>:oats-workspace.yaml#/teams/<label>`.
|
|
1187
|
+
A collision shows the shared definition.
|
|
1188
|
+
- `souls`: the workspace's `souls:` as committed (`{}` when none).
|
|
1189
|
+
`problems`: the deployment's [team readiness items](#team-readiness-items).
|
|
1190
|
+
The command discovers the workspace (every member's souls), for the
|
|
1191
|
+
`team-soul-unknown` check.
|
|
1150
1192
|
- The verbs never call a provider. They validate, rewrite `oats-local.yaml` in
|
|
1151
1193
|
place, and answer the document plus `changed: bool`.
|
|
1152
|
-
-
|
|
1153
|
-
|
|
1154
|
-
`
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1194
|
+
- **Where local teams are not allowed**, `add` and `default` are refused
|
|
1195
|
+
before anything is written: `E_WORKSPACE_SCHEMA {reason:
|
|
1196
|
+
"local-teams-closed", path, keys}` (`keys` what the verb writes). `remove`
|
|
1197
|
+
still runs there: taking local teams away is the last step of committing
|
|
1198
|
+
them in the workspace.
|
|
1199
|
+
- **`add`**: the first team added also becomes the local `defaultTeam`. A
|
|
1200
|
+
label already declared is `E_TEAM_EXISTS {label, from}`; a bad label or no
|
|
1201
|
+
`--team` is `E_BAD_ARGS`.
|
|
1202
|
+
- **`remove`**: a label the local `defaultTeam` names is `E_TEAM_IN_USE
|
|
1203
|
+
{label, usedBy: ["defaultTeam"]}`; a shared label is `E_TEAM_SHARED {label,
|
|
1204
|
+
at}` (a label in both files can be removed locally); unknown is
|
|
1205
|
+
`E_TEAM_UNKNOWN {label}`.
|
|
1159
1206
|
- **`default`**: any declared label, else `E_TEAM_UNKNOWN`.
|
|
1160
|
-
- A write that would introduce an unknown
|
|
1161
|
-
|
|
1207
|
+
- A write that would introduce an unknown reference is refused with that
|
|
1208
|
+
code; an invalid result is `E_WORKSPACE_SCHEMA`.
|
|
1209
|
+
- **Writes** edit `oats-local.yaml` in place and touch only the entries that
|
|
1210
|
+
change: comments and styles elsewhere, including inline comments on sibling
|
|
1211
|
+
entries, are kept. Each verb re-reads the file and judges its refusals on it
|
|
1212
|
+
as it is now, and writes only if the file did not change meanwhile (else it
|
|
1213
|
+
redoes the edit on the new content). A file that keeps changing is
|
|
1214
|
+
`E_LOCAL_CHANGED {path}`; nothing was written.
|
|
1162
1215
|
|
|
1216
|
+
<a id="oats-soul-teams"></a>
|
|
1163
1217
|
### `oats soul teams`
|
|
1164
1218
|
|
|
1165
1219
|
```text
|
|
1166
|
-
oats soul teams <soul>|'*' [--
|
|
1167
|
-
oats soul teams <soul>|'*' [--dir <d>] [--max-age <s>] --json (the read form only)
|
|
1220
|
+
oats soul teams <soul>|'*' [--dir <d>] [--max-age <s>] --json
|
|
1168
1221
|
```
|
|
1169
1222
|
|
|
1170
1223
|
```json
|
|
1171
|
-
{"soulTeamsApi":
|
|
1172
|
-
"
|
|
1173
|
-
|
|
1174
|
-
"
|
|
1224
|
+
{"soulTeamsApi":2,"soul":"incident-responder","key":"security-souls/incident-responder",
|
|
1225
|
+
"match":"security-souls/incident-responder","defaultMatch":"security-souls/*",
|
|
1226
|
+
"defaultTeam":{"label":"security","team":"security:acme.aweb.ai","from":"soul"},
|
|
1227
|
+
"teams":[{"label":"security","team":"security:acme.aweb.ai","default":true,"from":"shared","via":["default"]},
|
|
1228
|
+
{"label":"docs","team":null,"default":false,"from":"shared","via":["workspace"]},
|
|
1229
|
+
{"label":"engineering","team":"engineering:acme.aweb.ai","default":false,"from":"shared","via":["workspace"]}]}
|
|
1175
1230
|
```
|
|
1176
1231
|
|
|
1177
|
-
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
`'*'`, or both together: `E_BAD_ARGS`. Soul lookup: `E_SOUL_UNKNOWN`,
|
|
1187
|
-
`E_SOUL_AMBIGUOUS`.
|
|
1188
|
-
- **Writes** (`oats teams add|remove|default`, `oats soul teams`) edit
|
|
1189
|
-
`oats-local.yaml` in place and touch only the entries that change: comments
|
|
1190
|
-
and styles elsewhere, including inline comments on sibling entries and flow
|
|
1191
|
-
lists, are kept. Each verb re-reads the file and judges its refusals on it
|
|
1192
|
-
as it is now, and writes only if the file did not change meanwhile (else it
|
|
1193
|
-
redoes the edit on the new content). A file that keeps changing is
|
|
1194
|
-
`E_LOCAL_CHANGED {path}`; nothing was written.
|
|
1232
|
+
- Read only. `key` is the soul's key; `match` the `souls:` key its teams come
|
|
1233
|
+
from and `defaultMatch` the one its default comes from (`null`: none
|
|
1234
|
+
matches, or none sets a default). For `'*'`, `soul`, `key` and the only
|
|
1235
|
+
pattern tried are `"*"`. Soul lookup: `E_SOUL_UNKNOWN`, `E_SOUL_AMBIGUOUS`;
|
|
1236
|
+
the soul's teams: `E_WORKSPACE_SCHEMA` (local-teams-closed), `E_TEAM_UNKNOWN`.
|
|
1237
|
+
- The edit flags `--add`, `--remove`, `--default` and `--clear-default` were
|
|
1238
|
+
removed in 0.38.0: `E_BAD_ARGS` with details `{flag, replacement: "souls: in
|
|
1239
|
+
oats-workspace.yaml (a PR to the workspace file)"}`, before anything else
|
|
1240
|
+
is judged.
|
|
1195
1241
|
|
|
1196
1242
|
### The messaging provider's teams document
|
|
1197
1243
|
|
|
@@ -1218,8 +1264,9 @@ no `primary` and no `unmapped`: unmapped teams are kernel readiness items.
|
|
|
1218
1264
|
`oats teams` lists them under `problems[]` as `{code, severity: "failure" |
|
|
1219
1265
|
"warning", message, fix, …}`. `oats readiness` lists the soul's under
|
|
1220
1266
|
`checks.configured` with `subject` `"team <label>"` (or `"teams"`), `producer:
|
|
1221
|
-
"team model"`, `code`, `reason
|
|
1222
|
-
for a failure and `false` for a warning, plus the
|
|
1267
|
+
"team model"`, `code`, `reason` (the message), `remedy` (the fix), `status:
|
|
1268
|
+
"fail"`, `required: true` for a failure and `false` for a warning, plus the
|
|
1269
|
+
problem's own keys.
|
|
1223
1270
|
|
|
1224
1271
|
| Code | Severity | Keys | When |
|
|
1225
1272
|
|---|---|---|---|
|
|
@@ -1227,40 +1274,31 @@ for a failure and `false` for a warning, plus the problem's own keys.
|
|
|
1227
1274
|
| `team-unmapped` | failure if `default`, else warning | `label`, `default`, `at` | a shared team without `team` |
|
|
1228
1275
|
| `team-label-collision` | warning | `label`, `shared`, `local` (each `{team, description, at}`) | a label in both files |
|
|
1229
1276
|
| `default-team-changed` | warning | `recorded`, `current` | `--home` with live teams: the default changed since the spawn |
|
|
1230
|
-
| `E_TEAM_UNKNOWN` | failure | `label`, `at` | a
|
|
1231
|
-
| `
|
|
1232
|
-
| `team-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
`team-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
- `local-soul-teams`: `oats-local.yaml` has `souls.teams` and/or
|
|
1241
|
-
`souls.default` (`keys`: `["souls.teams", "souls.default"]` as found). They
|
|
1242
|
-
move to `souls:` in `oats-workspace.yaml`.
|
|
1243
|
-
- `local-teams-closed`: `oats-local.yaml` declares `teams` and/or
|
|
1244
|
-
`defaultTeam` (`keys`: `["teams", "defaultTeam"]` as found) and the
|
|
1245
|
-
workspace file does not say `localTeams: true`. The `fix` names both
|
|
1246
|
-
remedies: add `localTeams: true` to the workspace file, or commit the teams
|
|
1247
|
-
and `defaultTeam` there and remove them locally. Never raised in the
|
|
1248
|
-
standalone view, which has no workspace rules.
|
|
1277
|
+
| `E_TEAM_UNKNOWN` | failure | `label`, `at` | a local default no file declares |
|
|
1278
|
+
| `E_WORKSPACE_SCHEMA` | failure | `condition: "local-teams-closed"`, `path`, `keys` | `oats-local.yaml` declares `teams` / `defaultTeam` and the workspace does not allow local teams |
|
|
1279
|
+
| `team-soul-unknown` | warning | `key`, `at` | a `souls:` key that is neither `"*"` nor `<name>/*` nor a discovered soul's key (a typo guard) |
|
|
1280
|
+
|
|
1281
|
+
`E_TEAM_UNKNOWN` and local-teams-closed are also spawn, preview and inspect
|
|
1282
|
+
refusals (local-teams-closed as `E_WORKSPACE_SCHEMA` with details `{reason,
|
|
1283
|
+
path, keys}`). While local teams are closed, that one item is the soul's only
|
|
1284
|
+
team item. `team-soul-unknown` is reported where the souls are discovered
|
|
1285
|
+
(`oats teams`, readiness).
|
|
1249
1286
|
|
|
1250
1287
|
```json
|
|
1251
|
-
{"code":"
|
|
1252
|
-
"message":"oats-local.yaml declares teams, defaultTeam, but oats-workspace.yaml does not
|
|
1288
|
+
{"code":"E_WORKSPACE_SCHEMA","severity":"failure","condition":"local-teams-closed","path":"oats-local.yaml","keys":["teams","defaultTeam"],
|
|
1289
|
+
"message":"oats-local.yaml declares teams, defaultTeam, but oats-workspace.yaml does not allow local teams (localTeams: true): either (a) add `localTeams: true` to oats-workspace.yaml, or (b) commit the teams and defaultTeam in oats-workspace.yaml, then remove them from oats-local.yaml",
|
|
1253
1290
|
"fix":"either (a) add `localTeams: true` to oats-workspace.yaml, or (b) commit the teams and defaultTeam in oats-workspace.yaml, then remove them from oats-local.yaml"}
|
|
1254
1291
|
```
|
|
1255
1292
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1293
|
+
`oats doctor --json` lists local-teams-closed under `problems[]` (text: `!
|
|
1294
|
+
E_WORKSPACE_SCHEMA (local-teams-closed): …`). Doctor stays offline: it reads
|
|
1295
|
+
only the workspace file this machine's parsed cache holds; when there is
|
|
1296
|
+
none, it adds no problem and says so in `information[]`:
|
|
1297
|
+
`"local-teams-closed: whether oats-workspace.yaml allows oats-local.yaml
|
|
1298
|
+
teams/defaultTeam (localTeams: true) couldn't be checked: this deployment
|
|
1299
|
+
hasn't observed its workspace yet; run oats sync"`. A removed key in
|
|
1300
|
+
`oats-local.yaml` makes doctor answer that refusal, as for any unreadable
|
|
1301
|
+
local file.
|
|
1264
1302
|
|
|
1265
1303
|
<a id="soul-launch-preferences-feature-launch-preference-oats-0300"></a>
|
|
1266
1304
|
## Launch preferences
|
|
@@ -1613,7 +1651,7 @@ Feature `spawn-name`. `--name <slug>` is the exact name, with no prefix.
|
|
|
1613
1651
|
| `E_SOUL_AMBIGUOUS` | `{name, repos, qualified}` | several souls answer the bare name; use one of `qualified` |
|
|
1614
1652
|
| `E_SOUL_DISABLED` | `{name, qualifiedName, entry}` | listed in `souls.disabled` |
|
|
1615
1653
|
| `E_UNKNOWN_AGENT` | | the resolved soul is not under the deployment's agents root |
|
|
1616
|
-
| `E_TEAM_UNKNOWN`, `
|
|
1654
|
+
| `E_TEAM_UNKNOWN`, `E_WORKSPACE_SCHEMA` (local-teams-closed) | `{label, at}`, `{reason, path, keys}` | the soul's teams do not resolve |
|
|
1617
1655
|
| `E_NOT_A_MEMBER`, `E_MEMBERSHIP_UNCONFIRMED` | | the soul's repository is not a confirmed member |
|
|
1618
1656
|
| `E_CAPABILITY_MISSING`, `E_CAPABILITY_PRIVATE`, `E_CAPABILITY_INCOMPATIBLE`, `E_COMPATIBILITY` | | a capability cannot be resolved |
|
|
1619
1657
|
| `E_PACKAGE_MISSING`, `E_PACKAGE_INTEGRITY`, `E_LOCK_SCHEMA` | | the lock does not provide it (standalone: `{…, standalone: true, reason: "no-catalog", catalog}`) |
|
package/docs/first-team.md
CHANGED
|
@@ -102,17 +102,24 @@ that its session will stop at the folder-trust prompt, and so does
|
|
|
102
102
|
With a messaging capability in the soul's composition, every instance lives in
|
|
103
103
|
a team, and readiness fails with `E_TEAM_UNCONFIGURED` until there is a
|
|
104
104
|
default. Create the team with your messaging provider (its own docs say how;
|
|
105
|
-
for `oats.aweb`, see its skills), then
|
|
105
|
+
for `oats.aweb`, see its skills), then commit it in `oats-workspace.yaml` as a
|
|
106
|
+
**shared** team and the workspace's default:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
teams:
|
|
110
|
+
research: { team: "<provider team id>" }
|
|
111
|
+
defaultTeam: research
|
|
112
|
+
```
|
|
106
113
|
|
|
107
114
|
```bash
|
|
108
|
-
oats teams
|
|
109
|
-
oats teams # shared and local teams, and the default
|
|
115
|
+
oats teams # shared and local teams, the default, the workspace's souls:
|
|
110
116
|
```
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
Which other teams each soul may join is committed there too, in `souls:`
|
|
119
|
+
([workspaces.md](workspaces.md#teams)). A team only this deployment uses is a
|
|
120
|
+
**local** team (`oats teams add research --team <provider team id>`; the first
|
|
121
|
+
one becomes this deployment's default), which the workspace must allow with
|
|
122
|
+
`localTeams: true`. Without messaging, skip this step.
|
|
116
123
|
|
|
117
124
|
## 4. Look before you spawn
|
|
118
125
|
|
package/docs/integrations.md
CHANGED
|
@@ -126,28 +126,16 @@
|
|
|
126
126
|
"uniqueItems": true,
|
|
127
127
|
"items": { "type": "string", "pattern": "^(?:[a-z0-9][a-z0-9._-]*/)?[a-z0-9]+(?:-[a-z0-9]+)*$" }
|
|
128
128
|
},
|
|
129
|
-
"teams": {
|
|
130
|
-
"description": "Which teams each soul belongs to on this deployment (`oats soul teams` writes it): \"*\" applies to every soul; a soul's own entry (its bare name, or <package>/<soul> for a package soul) adds to it. Every soul is also in its default. Eligible, never auto-joined: an instance joins its default at spawn and the others on request.",
|
|
131
|
-
"type": "object",
|
|
132
|
-
"propertyNames": { "type": "string", "pattern": "^(?:\\*|(?:[a-z0-9][a-z0-9._-]*/)?[a-z0-9]+(?:-[a-z0-9]+)*)$" },
|
|
133
|
-
"additionalProperties": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/label" } }
|
|
134
|
-
},
|
|
135
129
|
"launch": {
|
|
136
130
|
"description": "Launch preferences on this machine (0.30; feature launch-preference), overriding the soul's own launch: \"*\" applies to every soul; a soul's own entry (its bare name, or <package>/<soul>) wins over it. A value is a launch configuration's name (in launch-configs of this file) or an inline { harness, model? }. Explicit spawn flags win over both. A changed preference affects no existing home until --reselect-launch or a respawn.",
|
|
137
131
|
"type": "object",
|
|
138
132
|
"propertyNames": { "type": "string", "pattern": "^(?:\\*|(?:[a-z0-9][a-z0-9._-]*/)?[a-z0-9]+(?:-[a-z0-9]+)*)$" },
|
|
139
133
|
"additionalProperties": { "oneOf": [ { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$" }, { "$ref": "#/$defs/launchPreference" } ] }
|
|
140
|
-
},
|
|
141
|
-
"default": {
|
|
142
|
-
"description": "A per-soul override of defaultTeam (`oats soul teams <soul> --default <label>`); it must be one of that soul's teams here (E_TEAM_NOT_ELIGIBLE).",
|
|
143
|
-
"type": "object",
|
|
144
|
-
"propertyNames": { "type": "string", "pattern": "^(?:[a-z0-9][a-z0-9._-]*/)?[a-z0-9]+(?:-[a-z0-9]+)*$" },
|
|
145
|
-
"additionalProperties": { "$ref": "#/$defs/label" }
|
|
146
134
|
}
|
|
147
135
|
}
|
|
148
136
|
},
|
|
149
137
|
"teams": {
|
|
150
|
-
"description": "LOCAL teams (`oats teams add` writes it): <label>: { team, description? }, the messaging provider's team id for a team only this deployment uses. Shared teams are committed in oats-workspace.yaml teams:; a label in both is team-label-collision (the shared one wins).",
|
|
138
|
+
"description": "LOCAL teams (`oats teams add` writes it): <label>: { team, description? }, the messaging provider's team id for a team only this deployment uses. Allowed only when oats-workspace.yaml says localTeams: true (or in the standalone view); otherwise E_WORKSPACE_SCHEMA reason local-teams-closed. Every soul may join every local team. Shared teams are committed in oats-workspace.yaml teams:; a label in both is team-label-collision (the shared one wins). souls.teams and souls.default were removed in 0.38.0: souls: in oats-workspace.yaml.",
|
|
151
139
|
"type": "object",
|
|
152
140
|
"propertyNames": { "$ref": "#/$defs/label" },
|
|
153
141
|
"additionalProperties": {
|
|
@@ -162,7 +150,7 @@
|
|
|
162
150
|
},
|
|
163
151
|
"defaultTeam": {
|
|
164
152
|
"$ref": "#/$defs/label",
|
|
165
|
-
"description": "
|
|
153
|
+
"description": "This deployment's default team (`oats teams default` writes it; the first `oats teams add` sets it): a label of teams here or in oats-workspace.yaml. Allowed only when oats-workspace.yaml says localTeams: true (or in the standalone view). A soul's souls: default in the workspace wins over it; it wins over the workspace's defaultTeam."
|
|
166
154
|
}
|
|
167
155
|
},
|
|
168
156
|
"$defs": {
|
|
@@ -25,21 +25,21 @@
|
|
|
25
25
|
"type": "object",
|
|
26
26
|
"propertyNames": { "$ref": "#/$defs/label" },
|
|
27
27
|
"additionalProperties": { "$ref": "#/$defs/team" },
|
|
28
|
-
"description": "SHARED teams: <label>: { description?, team? }. `team` is the messaging provider's team id, the same for everyone; without it the team is declared but not yet created (readiness team-unmapped).
|
|
28
|
+
"description": "SHARED teams: <label>: { description?, team? }. `team` is the messaging provider's team id, the same for everyone; without it the team is declared but not yet created (readiness team-unmapped). The default team and which teams each soul may join are defaultTeam and souls: below; a deployment's local teams live in its oats-local.yaml where localTeams allows them. A label never gates, restricts or partitions anything."
|
|
29
29
|
},
|
|
30
30
|
"defaultTeam": {
|
|
31
31
|
"$ref": "#/$defs/label",
|
|
32
|
-
"description": "
|
|
32
|
+
"description": "The workspace's fallback default team, a label of teams: in this file: a soul's souls: default wins over it, and so does a deployment's local defaultTeam where localTeams: true."
|
|
33
33
|
},
|
|
34
34
|
"localTeams": {
|
|
35
35
|
"type": "boolean",
|
|
36
|
-
"description": "
|
|
36
|
+
"description": "Whether deployments may declare their own teams and defaultTeam in oats-local.yaml (every soul may join a local team). Absent: false; then local teams and a local defaultTeam are refused (E_WORKSPACE_SCHEMA reason local-teams-closed)."
|
|
37
37
|
},
|
|
38
38
|
"souls": {
|
|
39
39
|
"type": "object",
|
|
40
40
|
"propertyNames": { "type": "string", "pattern": "^(?:\\*|[a-z0-9][a-z0-9._-]*/(?:\\*|[a-z0-9]+(?:-[a-z0-9]+)*))$" },
|
|
41
41
|
"additionalProperties": { "$ref": "#/$defs/soulTeams" },
|
|
42
|
-
"description": "
|
|
42
|
+
"description": "Per soul pattern (\"*\", <member|package>/* or <member|package>/<soul>), the soul's default team and the other teams it may join. The most specific key gives the soul's teams outright (lists never merge); the most specific key that sets a default gives its default. A soul no key matches has its default only. Every label is a label of teams: in this file."
|
|
43
43
|
},
|
|
44
44
|
"defaults": { "$ref": "#/$defs/defaults" },
|
|
45
45
|
"stores": {
|
package/docs/official-catalog.md
CHANGED
|
@@ -9,9 +9,9 @@ or workspace membership alone does not make a package official.
|
|
|
9
9
|
|
|
10
10
|
| package | release | capabilities | package souls |
|
|
11
11
|
|---|---|---|---|
|
|
12
|
-
| `oats.framework` | `oats-framework/v1.
|
|
12
|
+
| `oats.framework` | `oats-framework/v1.5.0` (this repository) | `oats.core`, `oats.setup`, `oats.knowledge-theory` | `knowledge-theory-expert` |
|
|
13
13
|
| `oats.okf` | `v4.1.1` | `oats.okf` (knowledge), `oats.okf-harvest`, `oats.okf-maintenance` | `knowledge-harvester`, `knowledge-maintainer` |
|
|
14
|
-
| `oats.aweb` | `v1.
|
|
14
|
+
| `oats.aweb` | `v1.19.0` | `oats.aweb` (messaging) | |
|
|
15
15
|
| `oats.engineering` | `v1.5.0` | `oats.engineering-expert`, `oats.developer`, `oats.code-review` | `code-reviewer` |
|
|
16
16
|
| `oats.authoring` | `v1.0.3` | `oats.authoring` | |
|
|
17
17
|
| `oats.jira` | `v1.0.1` | `oats.jira` (tasks) | |
|