@awebai/oats 0.25.9 → 0.26.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/README.md +8 -6
- package/bin/oats.mjs +576 -1714
- package/capabilities/oats-authoring/oats-package.json +2 -2
- package/capabilities/oats-authoring/oats.json +2 -2
- package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +46 -25
- package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +13 -6
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +279 -93
- package/capabilities/oats-aweb/injects/aweb.md +7 -2
- package/capabilities/oats-aweb/lib/binding-wire.mjs +89 -13
- package/capabilities/oats-aweb/lib/captured-native.mjs +1 -1
- package/capabilities/oats-aweb/lib/grant-custody.mjs +38 -0
- package/capabilities/oats-aweb/oats.json +8 -4
- package/capabilities/oats-jira/bin/oats-jira.mjs +4 -4
- package/capabilities/oats-jira/oats.json +2 -2
- package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +6 -3
- package/capabilities/oats-linear/bin/oats-linear-hook.mjs +6 -4
- package/capabilities/oats-linear/oats.json +2 -2
- package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +6 -0
- package/capabilities/oats-review/oats.json +3 -2
- package/docs/capabilities.md +218 -47
- package/docs/capability-manifest.schema.json +13 -4
- package/docs/configuration.md +17 -5
- package/docs/conventions.md +16 -26
- package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +1 -1
- package/docs/design/2026-09-13-knowledge-and-memory-direction.md +3 -3
- package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +2 -2
- package/docs/design/2026-09-15-portable-souls-handoff.md +2 -2
- package/docs/design/2026-09-15-portable-souls-implementation.md +1 -1
- package/docs/design/2026-09-20-redesign-program-board.md +2 -2
- package/docs/design/2026-09-23-workspace-module-contracts.md +1 -1
- package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +1 -1
- package/docs/design/2026-09-24-desktop-phase-f-boundary.md +34 -1
- package/docs/design/2026-09-24-phase-d-plan.md +57 -0
- package/docs/design/2026-09-25-teams-contract.md +226 -0
- package/docs/design/README.md +3 -3
- package/docs/design/launch-configurations.md +20 -16
- package/docs/design/operations-contract.md +27 -10
- package/docs/desktop-cli-api.md +537 -261
- package/docs/desktop-instance-start.md +1 -1
- package/docs/desktop.md +7 -13
- package/docs/execution-targets.md +16 -18
- package/docs/first-team.md +14 -17
- package/docs/implementation.md +28 -59
- package/docs/integrations.md +64 -33
- package/docs/knowledge-capability-authoring.md +1 -1
- package/docs/knowledge-reference/package-craft.md +10 -8
- package/docs/knowledge-theory.md +1 -1
- package/docs/knowledge.md +10 -11
- package/docs/layers.md +16 -17
- package/docs/oats-local.schema.json +29 -1
- package/docs/oats-membership.schema.json +5 -3
- package/docs/oats-package.schema.json +2 -2
- package/docs/oats-workspace.schema.json +1 -1
- package/docs/{official-marketplace.md → official-catalog.md} +15 -16
- package/docs/packages.md +75 -52
- package/docs/release-notes/v0.22.0.md +1 -1
- package/docs/release-notes/v0.23.1.md +1 -1
- package/docs/release-notes/v0.26.0.md +670 -0
- package/docs/schedules.md +48 -126
- package/docs/soul.schema.json +11 -4
- package/docs/souls-and-instances.md +56 -43
- package/docs/workspaces.md +80 -58
- package/injects/instance-boundary.md +1 -1
- package/injects/work-attached.md +1 -1
- package/injects/work-workspace.md +2 -2
- package/lib/{portable-files.mjs → bounded-read.mjs} +6 -6
- package/lib/{portable-values.mjs → canonical-json.mjs} +3 -12
- package/lib/capability-contract.mjs +110 -0
- package/lib/config-data.mjs +2 -2
- package/lib/core.mjs +700 -4824
- package/lib/digest.mjs +12 -0
- package/lib/instance-inspect.mjs +396 -0
- package/lib/instance-lifecycle.mjs +3 -4
- package/lib/instance-resolution.mjs +212 -26
- package/lib/instruction-composition.mjs +0 -20
- package/lib/materialize.mjs +6 -4
- package/lib/operator-dispatch.mjs +33 -13
- package/lib/packages.mjs +25 -190
- package/lib/provider-binding.mjs +4 -2
- package/lib/provider-reasons.mjs +3 -68
- package/lib/resolve.mjs +204 -68
- package/lib/schedule.mjs +97 -272
- package/lib/servers.mjs +13 -13
- package/lib/{portable-shape.mjs → shape.mjs} +4 -3
- package/lib/tree-copy.mjs +44 -0
- package/lib/workspace.mjs +125 -20
- package/package-catalog.json +6 -6
- package/package.json +1 -1
- package/skills/integration-authoring/SKILL.md +48 -40
- package/skills/oats-getting-started/SKILL.md +105 -110
- package/skills/oats-support/SKILL.md +2 -2
- package/skills/soul-craft/SKILL.md +13 -6
- package/bin/oats-pi-sdk-host.mjs +0 -17
- package/docs/2026-09-03-architecture-proposal.md +0 -642
- package/docs/artifact-approvals.schema.json +0 -7
- package/docs/captured-invocation-context.schema.json +0 -7
- package/docs/captured-resolution.schema.json +0 -7
- package/docs/design/package-engine-contract.md +0 -813
- package/docs/design/package-runtime-api.md +0 -588
- package/docs/desktop-succession.md +0 -57
- package/docs/execution-capsule.schema.json +0 -108
- package/docs/first-team-demo.md +0 -92
- package/docs/knowledge-migration.md +0 -147
- package/docs/migration-from-oas.md +0 -103
- package/docs/oats-config.schema.json +0 -172
- package/docs/oats-lock-v3.schema.json +0 -7
- package/docs/oats-lock.schema.json +0 -175
- package/docs/operating-team-migration.md +0 -470
- package/docs/portable.schema.json +0 -2512
- package/docs/provider-check-input.schema.json +0 -7
- package/docs/rebuild-to-v2.md +0 -511
- package/docs/workspace-adoption.md +0 -74
- package/injects/framework-workspace.md +0 -7
- package/injects/local-soul.md +0 -19
- package/injects/oats-portable.md +0 -20
- package/injects/oats.md +0 -11
- package/injects/portable-instance-boundary.md +0 -39
- package/injects/portable-work-directory.md +0 -29
- package/lib/artifact-approvals.mjs +0 -120
- package/lib/artifact-tree.mjs +0 -141
- package/lib/capability-artifacts.mjs +0 -179
- package/lib/capability-execution.mjs +0 -15
- package/lib/capability-inputs.mjs +0 -39
- package/lib/capability-provenance.mjs +0 -231
- package/lib/captured-action-shape.mjs +0 -21
- package/lib/captured-admission-shape.mjs +0 -20
- package/lib/captured-binding-file.mjs +0 -36
- package/lib/captured-dispatch.mjs +0 -66
- package/lib/captured-instance-index.mjs +0 -277
- package/lib/captured-invocation-context.mjs +0 -130
- package/lib/captured-launch-request.mjs +0 -66
- package/lib/captured-operation-process.mjs +0 -15
- package/lib/captured-pi-custody.mjs +0 -29
- package/lib/captured-pi-host.mjs +0 -167
- package/lib/captured-pi-outcome.mjs +0 -172
- package/lib/captured-resolutions.mjs +0 -275
- package/lib/captured-scaffold.mjs +0 -87
- package/lib/captured-selector.mjs +0 -28
- package/lib/captured-session-backend.mjs +0 -52
- package/lib/captured-source-receipt-file.mjs +0 -72
- package/lib/helper-injection-policy.mjs +0 -104
- package/lib/legacy-lock-codec.mjs +0 -106
- package/lib/manifest-settings.mjs +0 -84
- package/lib/package-closure.mjs +0 -48
- package/lib/package-materialization.mjs +0 -83
- package/lib/pi-sdk-host.mjs +0 -229
- package/lib/portable-artifacts.mjs +0 -115
- package/lib/portable-choices.mjs +0 -82
- package/lib/portable-composition.mjs +0 -136
- package/lib/portable-digest.mjs +0 -105
- package/lib/portable-identity.mjs +0 -40
- package/lib/portable-lock.mjs +0 -117
- package/lib/portable-onboarding-request.mjs +0 -49
- package/lib/portable-onboarding.mjs +0 -256
- package/lib/portable-package-preparation.mjs +0 -188
- package/lib/portable-policy.mjs +0 -44
- package/lib/portable-soul.mjs +0 -42
- package/lib/portable-state.mjs +0 -80
- package/lib/prepare-composition.mjs +0 -170
- package/lib/prepared-bindings.mjs +0 -92
- package/lib/prepared-resources.mjs +0 -127
- package/lib/provider-binding-broker.mjs +0 -65
- package/lib/provider-binding-wire.mjs +0 -116
- package/lib/readiness.mjs +0 -225
- package/lib/repository-observation.mjs +0 -226
- package/lib/resolution-shape.mjs +0 -393
- package/lib/schedule-capsule.mjs +0 -206
- package/lib/soul-constraints.mjs +0 -40
- package/lib/source-projection.mjs +0 -84
- package/lib/source-spec.mjs +0 -189
- package/lib/workspace-definition.mjs +0 -126
- package/lib/workspace-discovery.mjs +0 -146
- package/skills/oats/SKILL.md +0 -162
- package/skills/oats-config/SKILL.md +0 -164
- package/skills/oats-packages/SKILL.md +0 -184
- package/skills/oats-portable/SKILL.md +0 -115
- package/skills/oats-portable-artifacts/SKILL.md +0 -63
|
@@ -25,7 +25,7 @@ Legend: ✅ on main/published · 🔄 in flight (PR/branch) · 🟡 preserved, n
|
|
|
25
25
|
- Open: strict-Pi "enriched profile" remains unqualified (documented, not hidden).
|
|
26
26
|
|
|
27
27
|
## S2 — Workspace adoption of the OATS repos
|
|
28
|
-
- ✅ **PR23 merged f6d5a89b**: `oats-workspace.yaml` (7 members, `imports: []`), `oats.yaml` (exports souls/oats-expert, oats-package, capabilities/oats-authoring), transitional `souls/oats-expert/` edition,
|
|
28
|
+
- ✅ **PR23 merged f6d5a89b**: `oats-workspace.yaml` (7 members, `imports: []`), `oats.yaml` (exports souls/oats-expert, oats-package, capabilities/oats-authoring), transitional `souls/oats-expert/` edition, the workspace adoption guide (removed in 0.26.0), layout tests.
|
|
29
29
|
- ✅ **PR24 merged da38e5a9**: deletion of `skills/oats-portable-setup` + `oats inspect --request` read-only seam (ACCEPTED as the public inspection route); full gate 1621/0.
|
|
30
30
|
- ✅ Member `oats.yaml` merged to main: oats-okf #3 (fec78a20), oats-aweb #1 (069ea2f6), oats-authoring #1 (54183a6a), oats-jira #1 (2f855daf).
|
|
31
31
|
- ✅ oats-dev#1 (main 6e164ee3) and oats-linear#1 (main a2121e48) merged after Juan granted write access — M's exact commits 0434f4ef / 8c183c37.
|
|
@@ -117,7 +117,7 @@ Fresh directory and deployment, `@awebai/oats@0.24.4`, policy sources v2.1.2 / v
|
|
|
117
117
|
|
|
118
118
|
## S5 — Official marketplace
|
|
119
119
|
- ✅ Mechanism exists (`package-catalog.json`, `officialPackageCatalog()`); decision names it the official list.
|
|
120
|
-
- ✅ **D4 merged PR26 (786490ae)**: `docs/official-
|
|
120
|
+
- ✅ **D4 merged PR26 (786490ae)**: the official list policy (now `docs/official-catalog.md`), `package-catalog.json` policy pointer (inert to the reader), README/packages/capabilities links, D3 sketch in adoption guide. ⬜ entries for `oats.core`/`oats.setup` at D1 release. Desktop view → S8.
|
|
121
121
|
|
|
122
122
|
## S6 — Five expert souls in the oats repo
|
|
123
123
|
- ✅ **PR30 merged (40a579dc)** + maintainer follow-up **caa341f3**: all five declare `oats.core: {source: repo:oats-package}`, oats.okf@v2.1.1; `oats.yaml` exports all five; `oats-workspace.yaml` imports all five at caa341f3 (375b9f42). Live inspection against published main resolves them.
|
|
@@ -462,7 +462,7 @@ stays advertised because the verb still serves classic homes
|
|
|
462
462
|
### 0.25.2 operator-rebuild round (2026-09-24) — appended, not edited in place
|
|
463
463
|
|
|
464
464
|
Source: an operator's first rebuild of a real two-team deployment on 0.25.0,
|
|
465
|
-
following
|
|
465
|
+
following the 0.25 rebuild guide literally (removed in 0.26.0). **The guide is a contract the
|
|
466
466
|
kernel must honour**: where the guide claimed behaviour the kernel lacked, the
|
|
467
467
|
kernel changes; where the guide described keys no provider consumes, the guide
|
|
468
468
|
changes. Findings R1–R10; kernel side in 0.25.2 (`docs/release-notes/v0.25.2.md`).
|
|
@@ -29,7 +29,7 @@ Each is one PR (or two small ones), reviewed by me, on `main`, as canonical code
|
|
|
29
29
|
| **W8** | **Delete v1** | Remove `portable-*`, `source-spec`, `capability-provenance` (v1 parts), `prepared-resources`, migration stores/evidence, the installed tier in `packages.mjs`, classic config activation, their tests and docs; `core.mjs` loses everything that only served v1 | lead | L (mostly deletion) |
|
|
30
30
|
| **W9** | **Framework repos as the first workspace (decisions 18–21)** | `oats-workspace.yaml` v2 in `oats` (drop the six imports; `packages:` pins oats.framework/okf/aweb/jira/linear/authoring/dev **as packages**; `teams:` global/engineering; `defaults`); `oats-membership.yaml` in ALL seven repos; the six soul editions rewritten (`oats.okf: {from: package}` etc. even though the repos are members); **a new expert soul in every package repo** — `okf-expert`, `aweb-expert`, `jira-expert`, `linear-expert`, `authoring-expert`, `dev-expert` (v2 `souls/<name>/`, team global, knows and evolves that capability); `package-catalog.json` kept as the official marketplace (bare-version `packages:` entries resolve through it) | lead (member-repo PRs to their owners; the expert souls' AGENTS.md drafted by me, reviewed by the package owner) | L |
|
|
31
31
|
| **W9b** | **`oats.core` and `oats.setup` rewritten for the new architecture (human, 2026-09-23)** | The two official capabilities' skills and injects are rewritten to teach the *new* model, not patched: **`oats.core`** (`oats-operate`, `oats-souls`, the "you run on OATS" inject) — how an agent works inside an instance under this architecture: its home layout (`.oats/modules/`, `.agents/skills/`, `instance.json` modules/providers), the verbs it will actually use (`status`, `spawn --preview/--provider`, `retire`, `session`, `instance events`, `capabilities`, `souls`, `workspace status`), what a workspace/member/package/team is *from the agent's seat*, drift ("member moved since"), how to find and read other souls. **`oats.setup`** (`oats-config`/`oats-packages` → renamed to what they now are: `oats-workspace`, `oats-packages`, `oats-onboarding`) — the whole architecture and its best practices: workspace ↔ repo handshake and why, `oats-workspace.yaml` / `oats-membership.yaml` / `soul.yaml` v2 / `oats-local.yaml` field by field, teams as labels, member-tier vs package-tier and the non-collapse rule, `packages:` + lock v3 + per-version approval, the official catalog vs `git:` refs, `sync`/`package add`, the deployment directory (the operator's; no naming convention) and clone-then-spawn, private items, external souls, the standalone case, provider payload homes (soul/machine/spawn), what is deliberately NOT versioned and why. Every skill is validated against the shipped CLI (`oats <verb> --help` snapshot test) so they cannot drift from the commands. | lead (swarm + review) | M |
|
|
32
|
-
| **W10** | **Docs** |
|
|
32
|
+
| **W10** | **Docs** | **the rebuild guide (removed in 0.26.0; ships with the schemas; states that 0.24.x keeps spawning 0.24.x deployments)**; `docs/workspaces.md` rewritten around v2; `souls-and-instances.md`, `packages.md`, `configuration.md` (mostly deleted), `first-team.md` → the operator's deployment directory; DTO doc § Workspace v2; release notes | lead | M |
|
|
33
33
|
| **W11** | **Onboarding skill** | `oats-setup-expert` / `oats.setup`: ASK for the deployment directory (an existing folder with the operator's clones is the usual case — no named convention, decision 9), `oats sync`, clone-then-spawn; **the hosting rule for mixed public/private organisations (decision 26): ask up front whether any member is private; if so the workspace file is hosted in a private repo that is NOT a public member (a dedicated private `workspace` repo is the honest shape), public contributors get the standalone case with `oats.core` by default (decision 25); `oats onboard` prints the same rule in its next-steps**; the `oats-operate` skill updated for the new verbs | lead | S |
|
|
34
34
|
| **W12** | **Desktop follow-through** | New kernel DTOs (from W7) consumed the usual way — engineer reads the merged head, files pins, wires: Capabilities/Souls origin + team columns; "installed" removed as a state; spawn preview shows modules (from/commit/hash) + team; Workspaces surface shows membership status | Desktop engineer, after W7 | M |
|
|
35
35
|
|
|
@@ -119,6 +119,38 @@ action (`oats retire`) and `--force` behind a confirm.
|
|
|
119
119
|
**F5 — Redesign frames** (the original Phase 3 deliverable, excl. 05/06),
|
|
120
120
|
implemented on top of F1–F4 rather than on the 0.24 model.
|
|
121
121
|
|
|
122
|
+
**F7 — Side panels redesigned, teams everywhere (human, 2026-09-25). This
|
|
123
|
+
supersedes the frames and the text above wherever they differ.** One Desktop PR:
|
|
124
|
+
- **Side panels** in the spawn modal's design language (frame 01a):
|
|
125
|
+
- an identity header and compact cards;
|
|
126
|
+
- only useful facts (no "Not reported" rows), and empty sections hidden;
|
|
127
|
+
- relative dates, and shortened paths with Copy;
|
|
128
|
+
- errors as one plain sentence, with the code behind Details;
|
|
129
|
+
- discoverable cross-links between an instance and its soul.
|
|
130
|
+
- **Terminal-side context panel tabs, in order:** Instance · Soul · Git & GitHub.
|
|
131
|
+
- **Teams, per surface** (teams contract `docs/design/2026-09-25-teams-contract.md`):
|
|
132
|
+
- **Soul** (Workspace inspector): the soul's labels, primary marked, each
|
|
133
|
+
joinable or "not mapped by this workspace". Read-only, from
|
|
134
|
+
`inspect --soul` `teams`.
|
|
135
|
+
- **Instance** (Workspace inspector and the terminal-side Instance tab): the
|
|
136
|
+
live panel (#178). Personal is always on; joined teams have Leave, and
|
|
137
|
+
joinable ones have Join.
|
|
138
|
+
- **Spawn modal, main form** (not Developer settings), a Teams row:
|
|
139
|
+
- "Personal team — always", fixed;
|
|
140
|
+
- each joinable label as an unchecked checkbox, sent as
|
|
141
|
+
`--provider <messaging> join=<a,b>`;
|
|
142
|
+
- unmapped labels greyed with the reason;
|
|
143
|
+
- the line "By default it's only in your personal team. Tick the teams it
|
|
144
|
+
should also join."
|
|
145
|
+
|
|
146
|
+
The row is shown iff the preview carries `teams` AND the messaging
|
|
147
|
+
module's preview row lists `join` in `declares` (feature
|
|
148
|
+
`settings-declared`; the Desktop gates on declared facts, never on
|
|
149
|
+
versions).
|
|
150
|
+
- **Second human redirect (QA, same day):** unmapped labels are not shown
|
|
151
|
+
anywhere (no greyed rows, no "not mapped" text), and Teams in the spawn
|
|
152
|
+
modal is one row styled like Relationship.
|
|
153
|
+
|
|
122
154
|
**F6 — Version and doctor surface.** `oats version --json` and `oats doctor
|
|
123
155
|
--json` in an About/Health pane; `ACCEPT_RANGE` and the three pins move to
|
|
124
156
|
`>=0.25.6`; a kernel below the floor is refused with the upgrade command shown.
|
|
@@ -131,7 +163,8 @@ spawns children (its call; the lead reviews each PR).
|
|
|
131
163
|
Read, in this order, in the checked-out main:
|
|
132
164
|
1. `docs/workspaces.md` — the v2 model end to end (deployment vs workspace,
|
|
133
165
|
members, packages, payloads, `byTeam`, hosting).
|
|
134
|
-
2.
|
|
166
|
+
2. the 0.25 rebuild guide (removed in 0.26.0; `docs/configuration.md` and
|
|
167
|
+
`oats onboard` now) — how an operator builds a deployment (this is the
|
|
135
168
|
flow F2 wraps).
|
|
136
169
|
3. `docs/desktop-cli-api.md` — every JSON surface, with examples; note
|
|
137
170
|
`features[]`, `decision.effective.providers`, `instances[].identity`.
|
|
@@ -167,6 +167,51 @@ Kernel (lead): pass the soul's team label and the workspace identity so the
|
|
|
167
167
|
provider derives the personal team deterministically; an unmapped team means
|
|
168
168
|
"personal". The onboarding skill's manual invite-then-join step is the 1.12.0
|
|
169
169
|
path and is rewritten when the provider ships R1/R2.
|
|
170
|
+
**Teams, re-stated as THE priority (human, 2026-09-25; amends R1/R2):**
|
|
171
|
+
"As long as we don't have this working seamlessly, people won't understand
|
|
172
|
+
things." The two most important messaging behaviours, above every other
|
|
173
|
+
messaging item:
|
|
174
|
+
- **(R1) A personal team by default.** A user's agents in a workspace get
|
|
175
|
+
that person's personal team for the workspace with no setup step. This is
|
|
176
|
+
the default whenever the workspace maps nothing else.
|
|
177
|
+
- **Defaults and joining (human, later the same day; refines R1/R2′):**
|
|
178
|
+
- By default an instance is in the person's personal team ONLY, even when
|
|
179
|
+
its soul names teams.
|
|
180
|
+
- Joining a wider team is explicit: a spawn choice, or at any point of the
|
|
181
|
+
instance's life one simple command, run by the human, another agent, or
|
|
182
|
+
the instance when told to. It covers only the soul's labels the workspace
|
|
183
|
+
maps.
|
|
184
|
+
- The Desktop offers these controls.
|
|
185
|
+
- Personal teams are per WORKSPACE: one personal team spanning several
|
|
186
|
+
workspaces is wrong, and aweb's per-workspace get-or-create (abjj) is
|
|
187
|
+
urgent. Nobody uses OATS in production yet, which is what keeps this a
|
|
188
|
+
fix and not a migration.
|
|
189
|
+
- Contract: `docs/design/2026-09-25-teams-contract.md`.
|
|
190
|
+
- **(R2′) Wider teams, at spawn AND during an instance's life.** When a soul
|
|
191
|
+
belongs to one or more wider teams, its instance is also included in each
|
|
192
|
+
team the soul specifies, both at spawn and at any later point of its life,
|
|
193
|
+
not only at spawn. The teams are exactly those the workspace defines
|
|
194
|
+
(`messaging.byTeam` / the workspace's team labels); no team outside the
|
|
195
|
+
workspace's definition, and none silently missing. R2′ supersedes R2's
|
|
196
|
+
"is spawned … joins": joining is a lifetime operation, and a soul may name
|
|
197
|
+
several teams.
|
|
198
|
+
Both are oats.aweb's (Antares) with aweb primitives. **The kernel's share is
|
|
199
|
+
the lead's:**
|
|
200
|
+
- today `soul.team` is ONE label (docs/soul.schema.json), and the messaging
|
|
201
|
+
payload merges `byTeam[soul.team]` for that one label. "Team/teams" needs a
|
|
202
|
+
soul to name several team labels, and the payload to carry each mapped
|
|
203
|
+
team's entry (not one merged view), so the provider can join all of them;
|
|
204
|
+
- the workspace identity and the person's identity reach the provider, so
|
|
205
|
+
the personal team derives deterministically;
|
|
206
|
+
- a lifecycle entry point for "join now" during an instance's life (for
|
|
207
|
+
example, a provider operation or hook run against a live home when the
|
|
208
|
+
workspace's teams or the soul's team labels change at a new commit).
|
|
209
|
+
The contract shape is decided with Antares and recorded as a Decision before
|
|
210
|
+
code. **Human, same day:** the primitives must be seamlessly integrated into
|
|
211
|
+
the aweb messaging capability (acceptance is the oats.aweb experience: no
|
|
212
|
+
manual `aw team …` anywhere we ship, and live instances follow the
|
|
213
|
+
workspace's teams), and kernel changes are in scope, so the provider is not
|
|
214
|
+
bent around today's kernel.
|
|
170
215
|
**Naming (lead, 2026-09-24):** the `oats-` prefix on all six —
|
|
171
216
|
it matches the repository names and the roster's `oats-kernel-`/`oats-desktop-`/
|
|
172
217
|
`oats-operator-expert`, and it keeps instance aliases from colliding with the
|
|
@@ -211,6 +256,18 @@ the harvester delivers to that node as a PR the owning expert reviews.
|
|
|
211
256
|
- **Legacy souls** (`agents/*` and their knowledge bundles) are NOT part of D4:
|
|
212
257
|
they go when the live instances linking them retire (human rule).
|
|
213
258
|
|
|
259
|
+
**Human direction 2026-09-25: runtime → harness** ("throughout the app and cli and everywhere"). It ships in 0.26.0 as one kernel PR after (e):
|
|
260
|
+
- every kernel-owned name is renamed with no alias (`--harness`, `launch-configs.<n>.harness`, `instance.json.harness`, JSON fields, feature `harness`);
|
|
261
|
+
- two released-contract aliases stay: the provider env sets both `OATS_HARNESS` and `OATS_RUNTIME`, and manifests may say `requires[].runtime` or `requires[].harness`;
|
|
262
|
+
- the Desktop switches on the `harness` feature.
|
|
263
|
+
|
|
264
|
+
**Human direction 2026-09-25 (~17:20Z), amending the above: release 0.26.0 WITHOUT the harness rename; harness ships as a separate, later release.**
|
|
265
|
+
- 0.26.0 ships main as it stands once the in-flight PRs land: (e), K, the teamsOf check, `layers.<layer>.from`, and Desktop F7. It keeps the `runtime` names everywhere.
|
|
266
|
+
- The harness rename (the kernel PR, with the alias addendum: env `OATS_RUNTIME`, stdin `launch.runtime`, manifest `agents[].runtime`/`requires[].runtime`, `spawn --runtime`) ships in the **next minor, 0.27.0**. It is a breaking CLI/JSON change (`--runtime` refused on session/launch-config, `version.runtimes` dropped, launch-configs field renamed), so it isn't a patch. It ships together with the Desktop's switch on feature `harness`, and the Desktop's accepted kernel range widens to include 0.27.
|
|
267
|
+
- Neither the kernel harness PR nor the Desktop switch merges to main before the v0.26.0 tag.
|
|
268
|
+
|
|
269
|
+
Also: "core capabilities" is the human vocabulary for the knowledge/messaging/tasks capabilities in prose; wire names are unchanged.
|
|
270
|
+
|
|
214
271
|
### D5 — Catalog update and 0.26.0
|
|
215
272
|
|
|
216
273
|
Catalog pins for the new package versions; **widen Desktop `ACCEPT_RANGE` and
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Teams contract: several team labels per soul, per-team messaging, live reconciliation
|
|
2
|
+
|
|
3
|
+
Status: AGREED 2026-09-25 by both co-leads (provider verbs confirmed in e205c93a). First drafted by the lead (kernel lane), with the messaging
|
|
4
|
+
co-lead's provider plan. It serves the human priority of 2026-09-25, recorded
|
|
5
|
+
in `2026-09-24-phase-d-plan.md` under "Teams, re-stated as THE priority".
|
|
6
|
+
This document is the kernel half; the provider half (oats.aweb) is the
|
|
7
|
+
messaging lane's. Co-lead review (9a18a381): agreed, with three additions,
|
|
8
|
+
folded in below.
|
|
9
|
+
|
|
10
|
+
## The model (human, 2026-09-25)
|
|
11
|
+
|
|
12
|
+
- **Default: the personal team only.** Every instance is in its person's
|
|
13
|
+
personal team for THIS workspace. A soul's `team` labels do NOT put it
|
|
14
|
+
in those teams by default.
|
|
15
|
+
- **Joining is explicit.** A wider team is joined by an explicit action:
|
|
16
|
+
- at spawn, a spawn choice;
|
|
17
|
+
- or at any point of the instance's life, one simple command, run by the
|
|
18
|
+
human, by another agent, or by the instance itself when told to.
|
|
19
|
+
- **Only what the soul and workspace allow.** The teams an instance MAY join
|
|
20
|
+
are exactly its soul's labels that the workspace maps. Nothing else is
|
|
21
|
+
offered or accepted.
|
|
22
|
+
- **Leaving** is the same kind of command. When the workspace removes a
|
|
23
|
+
mapping or the soul drops a label, the joined membership for it is left.
|
|
24
|
+
- **The Desktop has controls for it:** at spawn (which eligible teams to
|
|
25
|
+
join) and on a live instance (join/leave, and the joined vs eligible
|
|
26
|
+
teams).
|
|
27
|
+
- **Personal teams are per WORKSPACE.** One personal team spanning several
|
|
28
|
+
workspaces is wrong. Until aweb ships the per-workspace get-or-create, the
|
|
29
|
+
person's single default team is an explicitly temporary stand-in.
|
|
30
|
+
|
|
31
|
+
## Problem
|
|
32
|
+
|
|
33
|
+
- A v2 soul names ONE team label (`soul.yaml` `team`, else the repository's
|
|
34
|
+
default from `oats-membership.yaml`).
|
|
35
|
+
- The resolver merges `workspace.messaging ⊕ byTeam[<that label>]` into one
|
|
36
|
+
messaging payload, and applies `defaults.byTeam[<that label>].capabilities`
|
|
37
|
+
to the soul's composition.
|
|
38
|
+
- An instance can therefore be placed in one team only, and only at spawn.
|
|
39
|
+
- The human's bar: a person's agents are in their personal team by default,
|
|
40
|
+
AND in every wider team their soul belongs to, at spawn and during the
|
|
41
|
+
instance's life, and those teams are exactly the ones the workspace defines.
|
|
42
|
+
|
|
43
|
+
## Decision
|
|
44
|
+
|
|
45
|
+
1. **Several labels.**
|
|
46
|
+
- `soul.yaml` `team` accepts a label or a non-empty list of distinct
|
|
47
|
+
labels: `team: dev` or `team: [dev, reviewers]`.
|
|
48
|
+
- `oats-membership.yaml`'s repository default takes the same shape.
|
|
49
|
+
- The FIRST label is the **primary**. A single string is a one-element
|
|
50
|
+
list, so existing souls don't change.
|
|
51
|
+
2. **Composition (`defaults.byTeam[*].capabilities`).**
|
|
52
|
+
- Applied for every label, in soul order, after `defaults.capabilities`
|
|
53
|
+
and before the soul's own `capabilities`. The soul's own entries still
|
|
54
|
+
win.
|
|
55
|
+
- Two labels that give the same capability different entries is
|
|
56
|
+
`E_TEAM_CONFLICT`, naming both labels. There's no silent
|
|
57
|
+
last-writer-wins. Identical entries from two labels are not a
|
|
58
|
+
conflict.
|
|
59
|
+
3. **Messaging payload.**
|
|
60
|
+
- **Amended (K, co-lead ruling on the 1.14.0 review):** the messaging
|
|
61
|
+
provider's merged settings are `base ⊕ soul ⊕ host ⊕ spawn`, and **no
|
|
62
|
+
`byTeam[<label>]` is merged into them**, the primary's included. Each
|
|
63
|
+
label's `base ⊕ byTeam[label]` lives only in its `teams` entry (below).
|
|
64
|
+
So `settings.team` / `OATS_TEAM_ID` mean "the personal team, if the
|
|
65
|
+
host, soul or spawn set one"; empty means the provider's own default
|
|
66
|
+
(for oats.aweb, the root's active team). Reason: the instance is
|
|
67
|
+
personal-by-default (the human's model), and the primary label is just
|
|
68
|
+
the first eligible team. Merging its payload made the provider mint the
|
|
69
|
+
primary identity into the mapped team, and it couldn't tell a host-set
|
|
70
|
+
personal team from the workspace's mapped one.
|
|
71
|
+
- New and kernel-owned: `teams`, an ordered list of
|
|
72
|
+
`{ label, mapped: boolean, payload }`.
|
|
73
|
+
- `payload` is `base ⊕ byTeam[label]` when the workspace maps the label.
|
|
74
|
+
- It's `base` alone, with `mapped: false`, when the label isn't mapped.
|
|
75
|
+
- Each entry also carries the resolved team id as `team` (null when the
|
|
76
|
+
label isn't mapped), so a provider never digs it out of `payload`.
|
|
77
|
+
"Personal" is the provider's to resolve; the kernel says nothing about
|
|
78
|
+
it.
|
|
79
|
+
- These are the **eligible** teams. Joining them is explicit (see "The
|
|
80
|
+
model"), not automatic.
|
|
81
|
+
- It's delivered beside the settings, in the environment (`OATS_TEAMS` JSON),
|
|
82
|
+
never inside the provider's own settings object, so it can't collide
|
|
83
|
+
with a provider key or its manifest's settings validation.
|
|
84
|
+
- `teams` is present when the soul has a label; a soul with no label gets
|
|
85
|
+
`[]`, meaning "personal only".
|
|
86
|
+
4. **Environment.**
|
|
87
|
+
- `OATS_TEAM_LABEL` / `OATS_TEAM_ID` stay the primary's.
|
|
88
|
+
- New: `OATS_TEAM_LABELS` (all labels, comma-joined, in order) and
|
|
89
|
+
`OATS_TEAMS` (the JSON above).
|
|
90
|
+
- New: `OATS_TEAMS_SOURCE`, which is `live` or `recorded` (decision 6). It's empty
|
|
91
|
+
when `OATS_TEAMS` is empty (unknown).
|
|
92
|
+
- **The environment is the only channel.** No stdin wire gains keys: the
|
|
93
|
+
binding check's request stays exactly the released wire, because released
|
|
94
|
+
providers (oats.aweb 1.13.1) key it strictly and refuse unknown keys with
|
|
95
|
+
`invalid-binding`. A provider check reads the teams from the same env
|
|
96
|
+
variables its hooks get. (Correction after #179, co-lead finding.)
|
|
97
|
+
- Workspace identity is unchanged: `OATS_WORKSPACE_KEY` / `OATS_WORKSPACE_NAME`.
|
|
98
|
+
- The person's identity stays the provider's (its messaging root from host
|
|
99
|
+
settings); the kernel passes the deployment, as today.
|
|
100
|
+
5. **Discovery.**
|
|
101
|
+
- A label the workspace doesn't map is a discovery **warning**
|
|
102
|
+
(`unmapped-team-label`), not an error, so the provider can fall back to
|
|
103
|
+
the personal team and say so.
|
|
104
|
+
- There's one warning per unmapped label, naming its souls
|
|
105
|
+
(`{ code, label, souls, paths, message }`), not one per soul and label.
|
|
106
|
+
A workspace with no `messaging.byTeam` must not print a line per soul.
|
|
107
|
+
- A label that isn't in the workspace's `teams:` list at all stays the
|
|
108
|
+
error it is today.
|
|
109
|
+
6. **Live resolution for a home.**
|
|
110
|
+
- A home's teams are **live messaging state, not frozen composition**. The
|
|
111
|
+
modules and skills an instance got at spawn don't change under it; which
|
|
112
|
+
teams it belongs to follows the workspace.
|
|
113
|
+
- For home-context provider operations and the launch hook, the kernel
|
|
114
|
+
computes `teams` from the soul's labels at the soul commit the
|
|
115
|
+
deployment currently resolves (the lock), and the workspace's current
|
|
116
|
+
`messaging`.
|
|
117
|
+
- That lets the provider offer a team the workspace added as eligible,
|
|
118
|
+
and leave one it removed, without a respawn.
|
|
119
|
+
- The recorded spawn-time `teams` stays in `instance.json.teams` as
|
|
120
|
+
evidence: beside `providers`, never inside that capability-keyed map.
|
|
121
|
+
- **Live or recorded.** When the workspace can't be read now (the host is
|
|
122
|
+
offline, or the soul is no longer listed), the kernel falls back to the
|
|
123
|
+
recorded set and says so: `OATS_TEAMS_SOURCE=recorded`, or
|
|
124
|
+
`teamsSource: "recorded"` in inspect.
|
|
125
|
+
- **A provider leaves a joined team only on a `live` answer.** On
|
|
126
|
+
`recorded` or unknown it keeps every membership and may warn
|
|
127
|
+
(`teams-unverified`).
|
|
128
|
+
- Reason: a team mapped after spawn and joined live is absent from the
|
|
129
|
+
record, and an offline host must never cost an instance a membership.
|
|
130
|
+
- **Cost.** Live teams are computed only where they're consumed:
|
|
131
|
+
- session start/restart;
|
|
132
|
+
- the messaging module's own home-context commands and operations;
|
|
133
|
+
- `inspect` / `readiness --home`.
|
|
134
|
+
|
|
135
|
+
The live read covers the workspace host and the soul's repo, not a full
|
|
136
|
+
workspace discovery. Every other in-home capability command uses the
|
|
137
|
+
record and costs what it did before.
|
|
138
|
+
- **0.26.0 limitation:** a scheduled wake's start uses the spawn-time teams.
|
|
139
|
+
The scheduler is synchronous; only operator starts are live.
|
|
140
|
+
- **Retire** works from the provider's own recorded membership list,
|
|
141
|
+
never from the live eligible set. A mapping removed after the spawn
|
|
142
|
+
still has its membership revoked at retire.
|
|
143
|
+
7. **Explicit join, spawn choice, Desktop.**
|
|
144
|
+
- The join/leave/list verbs are the provider's (oats.aweb 1.14.0), run
|
|
145
|
+
inside a home or with `--home <abs>`, all idempotent, all with `--json`:
|
|
146
|
+
- `oats aweb teams` answers
|
|
147
|
+
`{ personal: {team}, primary, eligible: [{label, team, joined}], joined: [{label, team, since, identityHome, receive}], unmapped: [label], at }`, where `receive` is `native` or `poll`;
|
|
148
|
+
- `oats aweb join <label>[,<label>]` and
|
|
149
|
+
`oats aweb leave <label>[,<label>]` answer the same document. The
|
|
150
|
+
personal team can't be left (`E_TEAM_PERSONAL`).
|
|
151
|
+
- The same verbs are declared as home-context operations
|
|
152
|
+
`messaging:teams|join|leave`, so the Desktop uses `oats operation run`
|
|
153
|
+
and needs no new kernel surface.
|
|
154
|
+
All three are `kind: action` (the default): a `view` must answer
|
|
155
|
+
`{documents:[…]}` (markdown/text for reading), and the teams document
|
|
156
|
+
is structured JSON. `messaging:teams` is read-only by its own
|
|
157
|
+
contract, which its description says. Join and leave declare one
|
|
158
|
+
required arg, `labels` (flag `--labels`, comma-separated).
|
|
159
|
+
- Identity model: one local identity per joined team, under the home as
|
|
160
|
+
`.aweb-identity-<label>`. The personal-team identity is the primary one,
|
|
161
|
+
wired to the harness. There are no global identities by default.
|
|
162
|
+
- **Sending and receiving as a joined team (oats.aweb 1.14.0):**
|
|
163
|
+
- Sending is complete: `aw --identity-home <identityHome> mail|chat …`,
|
|
164
|
+
the one form the aweb inject teaches.
|
|
165
|
+
- Receiving is by POLL: the channel plugin, the pi extension and a wake
|
|
166
|
+
registration each listen on one identity home. The inject says to
|
|
167
|
+
check a joined team's inbox at task boundaries, and readiness and
|
|
168
|
+
`receive: poll` say so.
|
|
169
|
+
- Native receive for joined teams needs one of two aweb primitives:
|
|
170
|
+
wake/channel on several identity homes per instance home, or global
|
|
171
|
+
instance identities with address release (one identity, many teams,
|
|
172
|
+
one channel). This is a named gap against the "seamless" bar,
|
|
173
|
+
tracked as an aweb ask.
|
|
174
|
+
- Each is idempotent, and refuses a label the instance isn't eligible for
|
|
175
|
+
(`E_TEAM_NOT_ELIGIBLE`, naming the eligible labels).
|
|
176
|
+
- **Declared setting keys (added after #179):** the spawn preview's
|
|
177
|
+
`modules[]` rows and `inspect`'s `capabilities[]` rows carry
|
|
178
|
+
`declares: [<setting key>…]` (names only; feature `settings-declared`).
|
|
179
|
+
That's how a Desktop sees that the messaging manifest declares
|
|
180
|
+
`settings.join` without reading manifests.
|
|
181
|
+
- `inspect --soul` on a soul whose labels conflict (`E_TEAM_CONFLICT`)
|
|
182
|
+
refuses. The error details name the capability and both labels; no
|
|
183
|
+
`teams` is answered, because the soul can't be spawned until the
|
|
184
|
+
workspace resolves it.
|
|
185
|
+
- At spawn, the kernel carries the operator's choice to the provider as a
|
|
186
|
+
spawn provider setting (`--provider <messaging> join=<label>[,<label>]`).
|
|
187
|
+
That needs no new kernel flag, and the spawn preview shows it.
|
|
188
|
+
- The launch hook re-checks joined memberships against the live eligible
|
|
189
|
+
set: it leaves what's no longer eligible (only when
|
|
190
|
+
`OATS_TEAMS_SOURCE=live`, decision 6) and never joins on its own.
|
|
191
|
+
- **The kernel puts `teams` (eligible, the OATS_TEAMS entries) in the
|
|
192
|
+
spawn preview and in `inspect --home`**, so a Desktop can offer the
|
|
193
|
+
choice before anything is minted. The Desktop reads that, plus joined memberships from the provider's inspect or
|
|
194
|
+
operation, and drives the same verbs.
|
|
195
|
+
- Later kernel item: `oats sync` reports the souls whose labels or
|
|
196
|
+
mappings changed since the previous lock.
|
|
197
|
+
|
|
198
|
+
## Compatibility
|
|
199
|
+
|
|
200
|
+
- A single-label soul sees byte-identical **composition** (modules, skills,
|
|
201
|
+
injects). Its messaging **payload** changes: the mapped label's `byTeam`
|
|
202
|
+
entry is no longer merged into the provider's settings; it's only in
|
|
203
|
+
`OATS_TEAMS` (amendment K). With 0.26.0 + oats.aweb 1.13.1, the primary
|
|
204
|
+
identity therefore mints into the personal (root-active) team, as the
|
|
205
|
+
human's model wants.
|
|
206
|
+
- oats.aweb 1.13.1 ignores `OATS_TEAMS` and keeps working, because no stdin
|
|
207
|
+
wire changes (its binding decoder refuses unknown request keys).
|
|
208
|
+
- oats.aweb 1.14.0 reads them.
|
|
209
|
+
- The schema change goes into 0.26.0, the release that already breaks the
|
|
210
|
+
file formats.
|
|
211
|
+
|
|
212
|
+
## Tests
|
|
213
|
+
|
|
214
|
+
- Several labels compose in order; a conflict → `E_TEAM_CONFLICT`. A
|
|
215
|
+
capability the soul names itself is exempt, since the soul's entry wins over
|
|
216
|
+
every label.
|
|
217
|
+
- A mapped primary's `byTeam` payload is absent from the provider's merged
|
|
218
|
+
settings and present in `OATS_TEAMS[0].payload` (amendment K).
|
|
219
|
+
- `OATS_TEAMS` shape: mapped and unmapped labels, and no label → `[]`.
|
|
220
|
+
- Home-context `teams` follows a new workspace commit (a mapping added and
|
|
221
|
+
removed) while the home's modules stay frozen.
|
|
222
|
+
- Discovery warns once per unmapped label.
|
|
223
|
+
- A home whose workspace can't be read gets the record with
|
|
224
|
+
`OATS_TEAMS_SOURCE=recorded`; a non-messaging in-home command runs no live
|
|
225
|
+
team read.
|
|
226
|
+
- `teams` entries carry `team`; identical cross-label entries don't conflict.
|
package/docs/design/README.md
CHANGED
|
@@ -7,12 +7,12 @@ Dated design documents record how decisions were reached and what each implement
|
|
|
7
7
|
- **[Workspace module contracts (2026-09-23)](2026-09-23-workspace-module-contracts.md) — NORMATIVE for implementation**: `lib/remote.mjs`, `lib/workspace.mjs`, `lib/resolve.mjs`, `lib/packages.mjs` (lock v3), `lib/materialize.mjs`, the CLI verbs and DTOs, the error codes, the Northwind fixture.
|
|
8
8
|
- [Simplified workspace model — worked example (2026-09-23)](2026-09-23-simplified-workspace-model.md) — ACCEPTED: one workspace per org, membership = trust, `from:` as location, nothing installed, full per-instance copy, teams as labels, harnesses start normally. The Decision concept is `agents/oats-expert/soul/knowledge/decisions/workspace-model-v2.md`.
|
|
9
9
|
- [Implementation plan (2026-09-23)](2026-09-23-workspace-v2-implementation-plan.md) — phases A/B/C, what each deletes.
|
|
10
|
-
- Operator-facing: [
|
|
10
|
+
- Operator-facing: [workspace model](../workspaces.md), [Desktop CLI API — workspace model](../desktop-cli-api.md#workspace-model-workspaceapi-2).
|
|
11
11
|
- Open threads (tracked here until closed): the `workspace` work mode still derives its `./work` boundary from the classic `team:` scope; the readiness `enrolled` producer still reads the 0.24 `oats.yaml` backlink; launch configurations / yolo / work-mode setup are still read from a classic config chain.
|
|
12
12
|
|
|
13
13
|
## Superseded by the workspace model
|
|
14
14
|
|
|
15
|
-
Everything below this line that describes per-soul `source:` provenance, `oats.yaml` exports/imports, the installed-capability tier (`.agents/capabilities/installed/`), `oats-config.yaml` scopes, `oats init`/`use`/`install`/`restore`/`trust`/`migrate`, lock v1/v2 or ambient-skill exclusion at launch is **history**. In particular
|
|
15
|
+
Everything below this line that describes per-soul `source:` provenance, `oats.yaml` exports/imports, the installed-capability tier (`.agents/capabilities/installed/`), `oats-config.yaml` scopes, `oats init`/`use`/`install`/`restore`/`trust`/`migrate`, lock v1/v2 or ambient-skill exclusion at launch is **history**. In particular `package-engine-contract.md` and `package-runtime-api.md` (both deleted in 0.26) described the removed acquisition/materialization engine; the package tier is now [packages.md](../packages.md) + module contract §4. Capability **manifests**, hooks, the operations contract, provider binding wire/codecs and the knowledge/messaging capability contracts are unchanged.
|
|
16
16
|
|
|
17
17
|
## Earlier plan (0.24)
|
|
18
18
|
|
|
@@ -38,7 +38,7 @@ Everything below this line that describes per-soul `source:` provenance, `oats.y
|
|
|
38
38
|
|
|
39
39
|
## Capabilities and providers
|
|
40
40
|
|
|
41
|
-
-
|
|
41
|
+
- Package engine contract (`package-engine-contract.md`, removed in 0.26) · package-runtime API (`package-runtime-api.md`, removed in 0.26) — **superseded** (installed tier removed; see [packages](../packages.md)) · [operations contract](operations-contract.md) · [launch configurations](launch-configurations.md).
|
|
42
42
|
- [Provider binding wire v1](2026-09-16-provider-binding-wire.md) · [provider binding codecs](2026-09-16-provider-binding-codecs.md) · [capability helper/input contract](2026-09-17-capability-helper-input-contract.md).
|
|
43
43
|
- [Knowledge capability contract](2026-09-16-knowledge-capability-contract.md) · [messaging capability contract](2026-09-16-messaging-capability-contract.md).
|
|
44
44
|
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# Launch configurations and launch recipes
|
|
2
2
|
|
|
3
|
-
A **launch configuration** is a named way to start a harness, declared
|
|
4
|
-
|
|
5
|
-
docs/configuration.md
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
A **launch configuration** is a named way to start a harness, declared by
|
|
4
|
+
the host under `launch-configs:` in the deployment's `oats-local.yaml` (see
|
|
5
|
+
docs/configuration.md; 0.26.0, lead decision 2 — earlier kernels read it
|
|
6
|
+
from a scope's `oats-config.yaml`): runtime, an executable, literal
|
|
7
|
+
arguments, environment (literals or `{fromEnv}` references), model, yolo.
|
|
8
|
+
It is independent of any soul, and a spawn, start or restart selects one by
|
|
9
|
+
name (`--launch-config`, or the Desktop's per-launch choice). A launch
|
|
10
|
+
configuration is a spawn-time host choice, never a soul field: `launch-config:`
|
|
11
|
+
is not a field of a workspace-model soul.yaml (docs/soul.schema.json; discovery
|
|
12
|
+
refuses it), so a v2 soul cannot name one, not even as a default. (A classic
|
|
13
|
+
0.25 soul.yaml could name a preferred entry; 0.26.0 reads no such field.)
|
|
10
14
|
|
|
11
15
|
A **launch recipe** is what a start is made of, recorded in the instance's
|
|
12
16
|
`instance.json` under `launch` beside the rendered `command`:
|
|
@@ -15,9 +19,9 @@ A **launch recipe** is what a start is made of, recorded in the instance's
|
|
|
15
19
|
{
|
|
16
20
|
"version": 1,
|
|
17
21
|
"runtime": "claude",
|
|
18
|
-
"launchConfig": "personal", "launchConfigSource": "/
|
|
19
|
-
"executable": "/
|
|
20
|
-
"executableDeclared": "./tools/claude-wrapper.sh", "executableResolvedFrom": "relative to /
|
|
22
|
+
"launchConfig": "personal", "launchConfigSource": "/deployment",
|
|
23
|
+
"executable": "/deployment/tools/claude-wrapper.sh",
|
|
24
|
+
"executableDeclared": "./tools/claude-wrapper.sh", "executableResolvedFrom": "relative to /deployment",
|
|
21
25
|
"args": ["--settings", "/abs/settings.json"],
|
|
22
26
|
"env": { "KEY": { "fromEnv": "SRC" }, "LIT": "plain" },
|
|
23
27
|
"model": "claude-opus-5", "yolo": true,
|
|
@@ -55,16 +59,16 @@ shows them: `list` and `preview` redact every environment value.
|
|
|
55
59
|
that disagrees with the configuration's runtime is refused
|
|
56
60
|
(`E_LAUNCH_CONFIG_MISMATCH`) before anything happens; the same runtime may
|
|
57
61
|
be repeated; `--model` and `--yolo` override the configuration's fields.
|
|
58
|
-
- Without `--launch-config`: a spawn
|
|
59
|
-
|
|
62
|
+
- Without `--launch-config`: a spawn uses no configuration (the runtime's
|
|
63
|
+
defaults; a soul names none); an existing home keeps its recorded configuration, except that
|
|
60
64
|
`--runtime` alone deliberately leaves it behind and renders the new
|
|
61
65
|
runtime's defaults (no old executable or args are carried).
|
|
62
66
|
- Model: explicit, else the configuration's, else on an existing home the
|
|
63
67
|
recorded model when the runtime is unchanged, else the runtime's native
|
|
64
|
-
default; a spawn without either
|
|
65
|
-
|
|
68
|
+
default; a spawn without either uses the runtime's native default (a
|
|
69
|
+
workspace-model soul declares no model). A model never crosses runtimes.
|
|
66
70
|
- Executable: the configuration's (bare name on PATH; a path resolved against
|
|
67
|
-
the
|
|
71
|
+
the deployment directory when relative) or the runtime's default (claude through
|
|
68
72
|
`oats-claude-config`). It must be a regular executable file; it is never
|
|
69
73
|
run to probe it. Capability runtime-package requirements are checked with
|
|
70
74
|
the runtime's default binary, as at spawn.
|
|
@@ -87,7 +91,7 @@ re-run by a start or restart.
|
|
|
87
91
|
Read-only; nothing is locked or started. `--home ABS` describes an existing
|
|
88
92
|
home under a selection (`selection.source`: `frozen` when nothing was
|
|
89
93
|
selected, `config` when re-resolved, `frozen-command` for a home that
|
|
90
|
-
predates recipes,
|
|
94
|
+
predates recipes, where a selection answers `E_LAUNCH_LEGACY`: re-spawn it);
|
|
91
95
|
`--soul NAME [--dir SCOPE] [--agents-root ABS]` describes a new instance.
|
|
92
96
|
Answer: `{context, selected, selection:{source, launchConfig, runtime,
|
|
93
97
|
model, yolo}, runtime, model, modelSource, yolo, launchConfig,
|
|
@@ -97,15 +97,16 @@ are listed. `use none --layer l` is a level statement and takes no soul or
|
|
|
97
97
|
type. A layer bound to another capability at a level is never overwritten
|
|
98
98
|
(`E_LAYER_BOUND` with the exact remedy).
|
|
99
99
|
|
|
100
|
+
*(0.24/0.25 only — `oats soul set` was removed in 0.26.0: a soul is edited in its member repository, then `oats sync`. Kept for history.)*
|
|
100
101
|
`oats soul set <name> [--dir] [--agents-root] [--runtime] [--model |
|
|
101
102
|
--no-model] [--yolo | --no-yolo] [--backend] [--description |
|
|
102
|
-
--no-description] [--instructions-file <path>] --json`
|
|
103
|
-
`soul.yaml` lines and
|
|
104
|
-
(`E_SOUL_READONLY`). The receipt
|
|
103
|
+
--no-description] [--instructions-file <path>] --json` edited only the given
|
|
104
|
+
`soul.yaml` lines and replaced `AGENTS.md`; packaged souls were refused
|
|
105
|
+
(`E_SOUL_READONLY`). The receipt carried before/after and sha256s.
|
|
105
106
|
|
|
106
107
|
## Remote
|
|
107
108
|
|
|
108
|
-
`inspect
|
|
109
|
+
`inspect` and `operation` route with `--server <id>` through
|
|
109
110
|
the saved route. The gate is the destination's `features` list containing
|
|
110
111
|
`operations` and its `operationsApi: 1` (`E_REMOTE_INCOMPATIBLE` before
|
|
111
112
|
anything is sent): `features` describes what a kernel can do locally, which
|
|
@@ -113,12 +114,28 @@ is what runs on the host. The probe's `remote` list describes what a CLI
|
|
|
113
114
|
can ROUTE to a server and is what a GUI checks on the local CLI before
|
|
114
115
|
offering remote actions; it is not a gate on the destination. An explicit `--dir` is the exact member context and
|
|
115
116
|
travels as is; `--home` is its own context; otherwise the registered
|
|
116
|
-
workspace is the scope.
|
|
117
|
-
(`--instructions-stdin` on the host), never as a local path.
|
|
117
|
+
workspace is the scope.
|
|
118
118
|
|
|
119
119
|
## Replaceability
|
|
120
120
|
|
|
121
|
-
`test/
|
|
122
|
-
|
|
123
|
-
provider
|
|
124
|
-
|
|
121
|
+
`test/operation.test.mjs` runs the real CLI on the Northwind fixture and
|
|
122
|
+
replaces the provider in a spawned home's module copy (what `operation run
|
|
123
|
+
--home` executes) with a recording provider of its own: the runner is generic
|
|
124
|
+
and assumes nothing about the official provider's operations.
|
|
125
|
+
|
|
126
|
+
## Workspace model (0.26.0)
|
|
127
|
+
|
|
128
|
+
On a workspace deployment, and for a home whose `instance.json` records
|
|
129
|
+
`modules`, `oats inspect`, `oats readiness` and `oats operation run` read the
|
|
130
|
+
workspace model's own records instead of the config chain:
|
|
131
|
+
- the subject is `--home` (instance.json plus its module copies) or `--soul`
|
|
132
|
+
(the soul resolved as its spawn would be), never a scope;
|
|
133
|
+
- `operationsApi` is 2 (also on the run result), and each soul row carries
|
|
134
|
+
`soulsApi: 2`;
|
|
135
|
+
- there is no trust gate (`E_CAPABILITY_BLOCKED` is gone);
|
|
136
|
+
- no `scope`, `chain`, `activation`, `snapshot` or `currentConfig` block.
|
|
137
|
+
|
|
138
|
+
The payloads are specified in
|
|
139
|
+
[desktop-cli-api.md](../desktop-cli-api.md#inspect-readiness-and-operation-run-on-the-workspace-model-operationsapi-2-soulsapi-2-readinessapi-2-oats-0260).
|
|
140
|
+
The sections above describe the classic path, which is removed with the classic
|
|
141
|
+
config chain.
|