@awebai/oats 0.29.4 → 0.30.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 +12 -6
- package/bin/oats.mjs +194 -50
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +538 -204
- package/capabilities/oats-aweb/injects/aweb.md +1 -1
- package/capabilities/oats-aweb/lib/binding-wire.mjs +31 -22
- package/capabilities/oats-aweb/oats.json +5 -12
- package/capabilities/oats-aweb/skills/VENDORED.md +4 -4
- package/capabilities/oats-aweb/skills/aweb-team-membership/SKILL.md +1 -1
- package/capabilities/oats-aweb/skills/oats-aweb/SKILL.md +83 -13
- package/capabilities/oats-code-review/injects/reviewer.md +26 -0
- package/capabilities/oats-code-review/oats.json +16 -0
- package/capabilities/oats-code-review/skills/adversarial-review/SKILL.md +66 -0
- package/capabilities/oats-code-review/skills/review-dev-docs/SKILL.md +30 -0
- package/capabilities/oats-code-review/skills/security-review/SKILL.md +56 -0
- package/capabilities/oats-code-review/skills/simplification-review/SKILL.md +34 -0
- package/capabilities/oats-developer/injects/developer.md +38 -0
- package/capabilities/oats-developer/oats.json +17 -0
- package/capabilities/oats-developer/skills/execution-strategy/SKILL.md +43 -0
- package/capabilities/oats-developer/skills/maintain-dev-docs/SKILL.md +47 -0
- package/capabilities/oats-developer/skills/run-the-review-loop/SKILL.md +65 -0
- package/capabilities/oats-developer/skills/understand-the-spec/SKILL.md +37 -0
- package/capabilities/oats-developer/skills/worktrees/SKILL.md +36 -0
- package/capabilities/oats-engineering-expert/injects/expert.md +37 -0
- package/capabilities/oats-engineering-expert/oats.json +17 -0
- package/capabilities/oats-engineering-expert/skills/coordinate-developers/SKILL.md +37 -0
- package/capabilities/oats-engineering-expert/skills/coordinate-experts/SKILL.md +52 -0
- package/capabilities/oats-engineering-expert/skills/land-your-prs/SKILL.md +50 -0
- package/capabilities/oats-engineering-expert/skills/plan-and-spec/SKILL.md +53 -0
- package/capabilities/oats-engineering-expert/skills/verify-developer-work/SKILL.md +49 -0
- package/capabilities/oats-okf/bin/oats-okf.mjs +8 -4
- package/capabilities/oats-okf/lib/binding-wire.mjs +47 -15
- package/capabilities/oats-okf/lib/inspection.mjs +26 -7
- package/capabilities/oats-okf/lib/sources.mjs +16 -2
- package/capabilities/oats-okf/lib/worker.mjs +5 -16
- package/capabilities/oats-okf/oats.json +6 -3
- package/capabilities/oats-okf-harvest/bin/okf-harvest.mjs +2 -2
- package/capabilities/oats-okf-harvest/oats.json +3 -3
- package/capabilities/oats-okf-harvest/skills/knowledge-harvest/SKILL.md +6 -6
- package/capabilities/oats-okf-maintenance/bin/okf-maintenance.mjs +2 -2
- package/capabilities/oats-okf-maintenance/injects/maintainer.md +1 -1
- package/capabilities/oats-okf-maintenance/oats.json +2 -2
- package/capabilities/oats-okf-maintenance/skills/knowledge-review/SKILL.md +1 -1
- package/capabilities/oats-okf-maintenance/skills/okf-trigger-setup/SKILL.md +11 -23
- package/capabilities/oats-workspace-experts/injects/oats-experts.md +26 -0
- package/capabilities/oats-workspace-experts/oats.json +9 -0
- package/docs/capabilities.md +160 -171
- package/docs/capability-manifest.schema.json +6 -11
- package/docs/configuration.md +213 -64
- package/docs/design/2026-09-16-knowledge-capability-contract.md +36 -50
- package/docs/design/2026-09-23-workspace-module-contracts.md +377 -544
- package/docs/design/2026-09-26-okf-knowledge-operations.md +132 -357
- package/docs/design/2026-09-27-team-model-v2.md +97 -117
- package/docs/design/2026-09-28-automations-trust.md +38 -0
- package/docs/design/2026-09-28-soul-launch-preference.md +63 -0
- package/docs/design/HISTORY.md +65 -0
- package/docs/design/README.md +23 -54
- package/docs/desktop-cli-api.md +1787 -1777
- package/docs/desktop.md +30 -91
- package/docs/execution-targets.md +146 -292
- package/docs/first-team.md +31 -17
- package/docs/implementation.md +76 -288
- package/docs/integrations.md +118 -320
- package/docs/knowledge-capability-authoring.md +25 -52
- package/docs/knowledge-reference/acceptance.md +3 -3
- package/docs/knowledge-reference/adoption.md +1 -1
- package/docs/knowledge-reference/harvester.md +2 -2
- package/docs/knowledge-reference/package-craft.md +3 -3
- package/docs/knowledge-reference/provider-mapping.md +3 -6
- package/docs/knowledge-reference/reader-capture.md +3 -3
- package/docs/knowledge-theory.md +62 -166
- package/docs/knowledge.md +225 -404
- package/docs/layers.md +42 -97
- package/docs/oats-local.schema.json +58 -5
- package/docs/oats-membership.schema.json +1 -8
- package/docs/oats-package.schema.json +5 -5
- package/docs/oats-workspace.schema.json +8 -22
- package/docs/official-catalog.md +25 -28
- package/docs/packages.md +45 -63
- package/docs/plans/0.30-close-out.md +61 -0
- package/docs/release-lane.md +77 -0
- package/docs/release-notes/oats-framework-v1.1.3.md +10 -8
- package/docs/release-notes/v0.19.0.md +48 -147
- package/docs/release-notes/v0.19.1.md +2 -3
- package/docs/release-notes/v0.19.3.md +2 -15
- package/docs/release-notes/v0.20.0.md +0 -15
- package/docs/release-notes/v0.22.0.md +71 -138
- package/docs/release-notes/v0.22.1.md +42 -90
- package/docs/release-notes/v0.22.10.md +1 -1
- package/docs/release-notes/v0.22.11.md +1 -47
- package/docs/release-notes/v0.22.12.md +4 -13
- package/docs/release-notes/v0.22.13.md +1 -42
- package/docs/release-notes/v0.22.14.md +3 -11
- package/docs/release-notes/v0.22.15.md +1 -46
- package/docs/release-notes/v0.22.16.md +6 -8
- package/docs/release-notes/v0.22.18.md +1 -99
- package/docs/release-notes/v0.22.19.md +3 -14
- package/docs/release-notes/v0.22.2.md +6 -15
- package/docs/release-notes/v0.22.3.md +0 -1
- package/docs/release-notes/v0.22.4.md +1 -14
- package/docs/release-notes/v0.22.5.md +2 -12
- package/docs/release-notes/v0.22.6.md +0 -3
- package/docs/release-notes/v0.23.0.md +9 -25
- package/docs/release-notes/v0.23.1.md +9 -25
- package/docs/release-notes/v0.23.2.md +2 -4
- package/docs/release-notes/v0.24.0.md +56 -97
- package/docs/release-notes/v0.24.1.md +7 -11
- package/docs/release-notes/v0.24.10.md +34 -45
- package/docs/release-notes/v0.24.11.md +12 -20
- package/docs/release-notes/v0.24.12.md +35 -48
- package/docs/release-notes/v0.24.13.md +34 -41
- package/docs/release-notes/v0.24.2.md +9 -13
- package/docs/release-notes/v0.24.3.md +7 -11
- package/docs/release-notes/v0.24.4.md +6 -6
- package/docs/release-notes/v0.24.5.md +6 -10
- package/docs/release-notes/v0.24.6.md +2 -5
- package/docs/release-notes/v0.24.7.md +46 -75
- package/docs/release-notes/v0.24.8.md +58 -96
- package/docs/release-notes/v0.24.9.md +38 -54
- package/docs/release-notes/v0.25.0.md +59 -76
- package/docs/release-notes/v0.25.1.md +57 -81
- package/docs/release-notes/v0.25.2.md +51 -70
- package/docs/release-notes/v0.25.3.md +11 -13
- package/docs/release-notes/v0.25.4.md +9 -13
- package/docs/release-notes/v0.25.5.md +3 -5
- package/docs/release-notes/v0.25.6.md +20 -29
- package/docs/release-notes/v0.25.7.md +5 -7
- package/docs/release-notes/v0.25.8.md +26 -39
- package/docs/release-notes/v0.26.0.md +175 -646
- package/docs/release-notes/v0.27.0.md +4 -5
- package/docs/release-notes/v0.27.1.md +4 -6
- package/docs/release-notes/v0.27.2.md +1 -1
- package/docs/release-notes/v0.28.0.md +57 -124
- package/docs/release-notes/v0.29.0.md +89 -208
- package/docs/release-notes/v0.29.1.md +1 -1
- package/docs/release-notes/v0.29.2.md +3 -4
- package/docs/release-notes/v0.30.0.md +205 -0
- package/docs/schedules.md +280 -363
- package/docs/servers.md +99 -117
- package/docs/soul.schema.json +2 -9
- package/docs/souls-and-instances.md +145 -158
- package/docs/workspaces.md +132 -215
- package/lib/automations.mjs +21 -6
- package/lib/core.mjs +226 -74
- package/lib/instance-events.mjs +1 -1
- package/lib/instance-inspect.mjs +109 -34
- package/lib/instance-lifecycle.mjs +14 -1
- package/lib/instance-resolution.mjs +26 -27
- package/lib/launch-preference.mjs +87 -0
- package/lib/materialize.mjs +3 -3
- package/lib/resolve.mjs +29 -87
- package/lib/schedule.mjs +1 -1
- package/lib/teams-verbs.mjs +195 -0
- package/lib/teams.mjs +190 -0
- package/lib/triggers.mjs +2 -2
- package/lib/workspace.mjs +54 -147
- package/package-catalog.json +9 -15
- package/package.json +1 -1
- package/skills/oats-getting-started/SKILL.md +25 -13
- package/capabilities/oats-review/injects/review.md +0 -69
- package/capabilities/oats-review/oats.json +0 -10
- package/capabilities/oats-review/skills/code-review/SKILL.md +0 -44
- package/capabilities/oats-review/skills/security-review/SKILL.md +0 -59
- package/docs/conventions.md +0 -90
- package/docs/design/2026-09-07-architecture-reassessment.md +0 -131
- package/docs/design/2026-09-07-desktop-souls-capabilities.md +0 -50
- package/docs/design/2026-09-07-mobile-agent-management-proposal.md +0 -228
- package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +0 -558
- package/docs/design/2026-09-13-knowledge-and-memory-direction.md +0 -744
- package/docs/design/2026-09-13-knowledge-implementation.md +0 -127
- package/docs/design/2026-09-13-knowledge-location-contract.md +0 -340
- package/docs/design/2026-09-14-artifact-retention-contract.md +0 -190
- package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +0 -708
- package/docs/design/2026-09-14-portable-souls-contract-amendments.md +0 -85
- package/docs/design/2026-09-14-portable-souls-explainer.md +0 -750
- package/docs/design/2026-09-15-captured-dispatch.md +0 -127
- package/docs/design/2026-09-15-captured-resolution-records.md +0 -143
- package/docs/design/2026-09-15-package-preparation.md +0 -100
- package/docs/design/2026-09-15-portable-data-contract.md +0 -121
- package/docs/design/2026-09-15-portable-declarations.md +0 -189
- package/docs/design/2026-09-15-portable-souls-handoff.md +0 -150
- package/docs/design/2026-09-15-portable-souls-implementation.md +0 -417
- package/docs/design/2026-09-15-selection-lock-and-approval.md +0 -122
- package/docs/design/2026-09-15-source-observation.md +0 -119
- package/docs/design/2026-09-16-captured-admission.md +0 -77
- package/docs/design/2026-09-16-captured-helper-dispatch.md +0 -105
- package/docs/design/2026-09-16-captured-launch-inputs.md +0 -42
- package/docs/design/2026-09-16-command-profile-preparation.md +0 -86
- package/docs/design/2026-09-16-fresh-install-first-rollout.md +0 -47
- package/docs/design/2026-09-16-fresh-operator-walkthrough.md +0 -282
- package/docs/design/2026-09-16-messaging-capability-contract.md +0 -59
- package/docs/design/2026-09-16-portable-migration-evidence.md +0 -158
- package/docs/design/2026-09-16-portable-onboarding.md +0 -179
- package/docs/design/2026-09-16-prepare-request-transport.md +0 -26
- package/docs/design/2026-09-16-provider-binding-codecs.md +0 -98
- package/docs/design/2026-09-16-provider-binding-wire.md +0 -274
- package/docs/design/2026-09-17-capability-helper-input-contract.md +0 -95
- package/docs/design/2026-09-17-captured-backend-parity.md +0 -53
- package/docs/design/2026-09-17-captured-native-start.md +0 -58
- package/docs/design/2026-09-17-portable-boundary-hookup.md +0 -19
- package/docs/design/2026-09-17-portable-boundary-resources.md +0 -52
- package/docs/design/2026-09-17-public-captured-start.md +0 -108
- package/docs/design/2026-09-17-public-prepare-request.md +0 -90
- package/docs/design/2026-09-18-captured-pi-host.md +0 -205
- package/docs/design/2026-09-18-first-cut-release-checklist.md +0 -131
- package/docs/design/2026-09-18-herdr-protocol-compatibility.md +0 -60
- package/docs/design/2026-09-20-redesign-program-board.md +0 -142
- package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +0 -289
- package/docs/design/2026-09-20-workspace-onboarding-public.md +0 -207
- package/docs/design/2026-09-22-desktop-parity-seams.md +0 -58
- package/docs/design/2026-09-23-simplified-workspace-model.md +0 -711
- package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +0 -65
- package/docs/design/2026-09-24-desktop-phase-f-boundary.md +0 -242
- package/docs/design/2026-09-24-phase-d-plan.md +0 -305
- package/docs/design/2026-09-25-teams-contract.md +0 -258
- package/docs/design/2026-09-26-desktop-design-brief-architecture.md +0 -241
- package/docs/design/desktop-ux-plan.md +0 -362
- package/docs/design/launch-configurations.md +0 -168
- package/docs/design/okf-mirror-provenance.md +0 -105
- package/docs/design/operations-contract.md +0 -141
- package/docs/oats-member.schema.json +0 -38
- package/skills/integration-authoring/SKILL.md +0 -84
- package/skills/oats-support/SKILL.md +0 -79
- package/skills/skill-craft/SKILL.md +0 -109
- package/skills/soul-craft/SKILL.md +0 -116
|
@@ -1,711 +0,0 @@
|
|
|
1
|
-
# A simpler multi-repo model for OATS — brainstorm with a worked example
|
|
2
|
-
|
|
3
|
-
**Status:** **ACCEPTED DIRECTION** — every question closed with the human on 2026-09-23; nothing implemented yet. This document is the worked example; the normative record is the Decision concept `agents/oats-expert/soul/knowledge/decisions/workspace-model-v2.md` and the adoption plan. Implementation is a clean v2 (no migration), planned separately. **Decided so far (human, 2026-09-23):** (1) reciprocal membership stays a hard gate; (2) workspace-tier trust = membership, nothing more; (3) everything in a member is discoverable by default — a soul or capability that wants to stay internal says `private: true` in its own definition; (4) the repo's half of the handshake is a one-line **`oats-membership.yaml`** (replaces `oats.yaml`); (5) **no migration path** — a clean break to v2; (6) a soul names each capability **with where it comes from** (`from: <member repo>` or `from: package`) — a location, never a version; resolution is a handshake check + lookup, not a search; (7) **full per-instance materialization** — every capability (skills, injects, scripts, hooks) is copied into the instance at spawn; a running instance never changes under itself; (8) **nothing is "installed"** — a package is just a second kind of source, fetched at the pinned version and copied in like a member's capability; the lock records exact commit/integrity and the one-time executable approval per version; (9) **discovery and resolution work against Git remotes, never local clones** — the only thing that needs a clone is a soul's work target; the local layout is the operator's — onboarding asks for the directory, no named convention; (10) the handshake is *observed* with the operator's own read access to both halves — no access to the workspace repo means no membership from that seat, by design; (11) **members carry no revision** — a member is always its latest state; a team that wants frozen capabilities publishes them as a package and pins that; (12) **one workspace per org, teams are labels** — `team:` on a soul/capability (or a repo default in `oats-membership.yaml`) organises and can supply additive defaults, but never gates, restricts or partitions anything; (13) **harnesses start normally and resolve skills from their own default places** — OATS contributes materialized capability skills into the instance's `.agents/skills/` and stops excluding machine-level or repo-level skills. **All questions closed; ready to be written up as a Decision.**
|
|
4
|
-
**Date:** 2026-09-23
|
|
5
|
-
**Author:** oats-expert, from a conversation with the human about the weight of the current declaration files.
|
|
6
|
-
|
|
7
|
-
The current model (`docs/workspaces.md`) is functional but heavy: provenance is declared *per soul per capability*, three files each know about versions, membership needs a reciprocal handshake, and the workspace file must import every soul it wants from its own member repos. This document proposes a lighter model and walks it through an imaginary company end to end.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## 1. The one idea
|
|
12
|
-
|
|
13
|
-
**Every capability an instance runs is copied whole into that instance at spawn. A capability comes from one of two kinds of source, and only one kind is versioned.**
|
|
14
|
-
|
|
15
|
-
| Source kind | Comes from | Versioned? | Trust decision | Fetched |
|
|
16
|
-
|---|---|---|---|---|
|
|
17
|
-
| **Member repo** | A repo that has completed the membership handshake | **No** — the member's *latest state* | **Membership is the trust.** Same model as a repo's `.agents/skills/`: you run what is on the branch because you trust who can push to it | At spawn, latest, copied in |
|
|
18
|
-
| **Package** | A published package (official catalog or a git ref) | **Yes** — the version pinned in the workspace's `packages:`; `oats-lock.json` records the exact commit + integrity | Per version: executables approved once, recorded in the lock, inherited by every instance materializing that version | At spawn, at the locked version, copied in |
|
|
19
|
-
|
|
20
|
-
Nothing is *installed* in a deployment. There is no installed-capability directory, no activation step, no "is it installed?" question: a package is a place to fetch from with a version attached, a member is a place to fetch from without one. A fetch cache may exist as invisible plumbing.
|
|
21
|
-
|
|
22
|
-
A soul names each capability **with where it comes from** — `from: <member repo>` or `from: package`. That is a **location, never a version**: the soul says *which repo* or *which kind*, the workspace's `packages:` says which version, and materialization *records* the exact state (commit, content hash) in the instance. Resolution is then a handshake check plus a lookup — no search across members, no name-collision rules.
|
|
23
|
-
|
|
24
|
-
That removes: per-soul `source:` lines, the `git:` / `repo:` / `path:` grammar from soul files, `from: installed | owned` in deployment config, the version triplication across soul → catalog → lock, and the whole notion of an installed-package tier with `oats install` / `oats use` activation.
|
|
25
|
-
|
|
26
|
-
**One relation is kept as a hard gate: reciprocal membership.** A repo is a member of a workspace only when the workspace lists the repo **and** the repo's `oats-membership.yaml` lists the workspace. One file per side of the handshake: `oats-workspace.yaml` says "these are my members", `oats-membership.yaml` says "this is my workspace". This is decided (human, 2026-09-23). It is the consent that makes "trust per member" honest: a workspace cannot pull in a repo's souls or run its capabilities' executables just by naming it, and a repo cannot inject itself into a workspace just by claiming it.
|
|
27
|
-
|
|
28
|
-
**And membership is the whole trust decision (decided, human, 2026-09-23).** Member capabilities are trusted exactly the way teams already trust skills committed to their own repos: the repo's access control — who can push to it — is the boundary, and the latest state of the branch is what runs. There is no second approval layer for members. Packages keep a one-time executable approval **per version** because they come from **outside** that boundary; the approval lives in the lock next to the commit it approved.
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 2. The imaginary company: Northwind
|
|
33
|
-
|
|
34
|
-
Northwind builds a shipping platform. Northwind has an **engineering** team and a **marketing** team, and a few things that belong to everyone (**global**). They share **one workspace** — marketers use engineering capabilities and vice versa; teams are labels for organising, not walls. Their agent setup spans **six of their own repos** plus **one public repo** they borrow an expert from, and **four packages**.
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
github.com/northwind/agents ← hosts the workspace file; org-wide souls + capabilities (team: global)
|
|
38
|
-
github.com/northwind/platform ← the product; exports souls that work IN this repo (team: engineering)
|
|
39
|
-
github.com/northwind/data ← analytics; exports a soul + a data-access capability (team: engineering)
|
|
40
|
-
github.com/northwind/marketing ← campaigns; exports souls + brand/metrics capabilities (team: marketing)
|
|
41
|
-
github.com/northwind/knowledge ← the shared OKF knowledge base (a store, not a member)
|
|
42
|
-
github.com/northwind/nw-tools ← MEMBER *and* PACKAGE PUBLISHER: publishes package `nw.tools` (versioned, pinned,
|
|
43
|
-
approved) AND exports the member soul `tools-expert` who knows that package (team: engineering)
|
|
44
|
-
|
|
45
|
-
github.com/oss-collective/experts ← PUBLIC; Northwind borrows one soul, pinned (not a member)
|
|
46
|
-
|
|
47
|
-
packages (versioned; fetched at spawn, never "installed"):
|
|
48
|
-
oats.framework v1.1.3 → oats.core, oats.setup (official catalog)
|
|
49
|
-
oats.okf v2.1.3 → knowledge layer (official catalog)
|
|
50
|
-
oats.aweb v1.11.2 → messaging layer (official catalog)
|
|
51
|
-
oats.jira v1.0.0 → tasks layer (official catalog)
|
|
52
|
-
nw.tools v0.4.0 → nw-lint, nw-deploy (Northwind's OWN package, from a member repo — written as git:…@v0.4.0)
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Two operators realize this workspace on their machines: **Ana** (macOS, works mostly on `platform`) and **Bo** (Linux, works on `data`). They share the declarations through Git and share nothing else.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## 3. Repo by repo
|
|
60
|
-
|
|
61
|
-
### 3.1 `northwind/agents` — the workspace host
|
|
62
|
-
|
|
63
|
-
> **Who may read the host** (team review, decision 26). Everyone who can read
|
|
64
|
-
> `oats-workspace.yaml` sees the member list. Northwind is all-private, so a
|
|
65
|
-
> member (`agents`) hosting it is fine. A mixed organisation — a public
|
|
66
|
-
> `awebai/aweb` and a private `awebai/ac`, say — hosts the file in a private
|
|
67
|
-
> repo that is **not** a public member (`awebai/workspace`): a public host
|
|
68
|
-
> would publish the private repo's name, and hosting inside the private
|
|
69
|
-
> member hides the workspace from public contributors. Those contributors get
|
|
70
|
-
> the public member's souls through the standalone case (§6): `from: here`
|
|
71
|
-
> capabilities plus `oats.core` (decision 25). Two teams with two messaging
|
|
72
|
-
> identities stay in the one workspace via `messaging.byTeam.<label>`
|
|
73
|
-
> (decision 23); a store names a repo, the root inside it is the provider's
|
|
74
|
-
> (`root`, decision 24).
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
agents/
|
|
78
|
-
├── oats-workspace.yaml ← THE shared declaration (only one in the whole company)
|
|
79
|
-
├── oats-membership.yaml ← the backlink (+ optional default team label: global)
|
|
80
|
-
├── souls/
|
|
81
|
-
│ ├── release-manager/
|
|
82
|
-
│ │ ├── soul.yaml
|
|
83
|
-
│ │ ├── AGENTS.md
|
|
84
|
-
│ │ ├── CLAUDE.md → AGENTS.md
|
|
85
|
-
│ │ └── skills/release-checklist/SKILL.md
|
|
86
|
-
│ └── support-triager/
|
|
87
|
-
│ └── …
|
|
88
|
-
└── capabilities/
|
|
89
|
-
├── nw-release-tooling/ ← a WORKSPACE-tier capability (unversioned, latest state)
|
|
90
|
-
│ ├── oats.json
|
|
91
|
-
│ ├── skills/cut-release/SKILL.md
|
|
92
|
-
│ ├── injects/release-policy.md
|
|
93
|
-
│ └── bin/nw-release.mjs
|
|
94
|
-
└── nw-house-style/
|
|
95
|
-
├── oats.json
|
|
96
|
-
└── injects/house-style.md
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
#### `oats-workspace.yaml`
|
|
100
|
-
|
|
101
|
-
```yaml
|
|
102
|
-
schemaVersion: 2
|
|
103
|
-
name: northwind
|
|
104
|
-
|
|
105
|
-
# Member repos. Membership is RECIPROCAL: a repo listed here is a member only if
|
|
106
|
-
# its own oats-membership.yaml lists this workspace back (§3.2). A member has NO
|
|
107
|
-
# revision — it is always its latest state. Want something frozen? Publish it as
|
|
108
|
-
# a package and pin it under `packages:`. Everything a member exports
|
|
109
|
-
# (souls, capabilities) is then discoverable here. Trusting a member = trusting
|
|
110
|
-
# its capabilities' executables.
|
|
111
|
-
members:
|
|
112
|
-
- git:github.com/northwind/agents # this repo is a member too — it backlinks like any other
|
|
113
|
-
- git:github.com/northwind/platform
|
|
114
|
-
- git:github.com/northwind/data
|
|
115
|
-
- git:github.com/northwind/marketing
|
|
116
|
-
- git:github.com/northwind/nw-tools # a member that ALSO publishes a package (below)
|
|
117
|
-
|
|
118
|
-
# The ONLY versioned things. Chosen once for the whole team; the lock records the
|
|
119
|
-
# exact commit + integrity each version resolves to, and the one-time executable
|
|
120
|
-
# approval for that version. Nothing is installed: instances fetch these at spawn.
|
|
121
|
-
packages:
|
|
122
|
-
oats.framework: v1.1.3 # bare version → resolves through the official catalog
|
|
123
|
-
oats.okf: v2.1.3
|
|
124
|
-
oats.aweb: v1.11.2
|
|
125
|
-
oats.jira: v1.0.0
|
|
126
|
-
nw.tools: git:github.com/northwind/nw-tools@v0.4.0 # not in the catalog → written as a git ref; STILL a package:
|
|
127
|
-
# versioned, locked, approved — membership does not change that
|
|
128
|
-
|
|
129
|
-
# Org teams — LABELS, declared once so they cannot drift into typos. A team never
|
|
130
|
-
# gates, restricts or partitions anything; it organises (grouping, filtering,
|
|
131
|
-
# ownership signal) and may supply additive defaults below.
|
|
132
|
-
teams:
|
|
133
|
-
global: { description: Org-wide souls and house capabilities }
|
|
134
|
-
engineering: { description: "Platform, data and release automation" }
|
|
135
|
-
marketing: { description: "Campaigns, content and positioning" }
|
|
136
|
-
|
|
137
|
-
# What every soul gets unless it says otherwise.
|
|
138
|
-
defaults:
|
|
139
|
-
capabilities:
|
|
140
|
-
oats.core: { from: package }
|
|
141
|
-
nw-house-style: { from: northwind/agents }
|
|
142
|
-
knowledge: { oats.okf: { from: package } } # slot default — a soul may name another or `none`
|
|
143
|
-
messaging: { oats.aweb: { from: package } }
|
|
144
|
-
tasks: { oats.jira: { from: package } }
|
|
145
|
-
byTeam: # additive, per team label; same semantics, `off` removes
|
|
146
|
-
engineering:
|
|
147
|
-
capabilities: { nw-release-tooling: { from: northwind/agents } }
|
|
148
|
-
marketing:
|
|
149
|
-
capabilities: { nw-brand-voice: { from: northwind/marketing } }
|
|
150
|
-
|
|
151
|
-
# Knowledge stores, declared ONCE (today each soul repeats `stores.x.inherit`).
|
|
152
|
-
stores:
|
|
153
|
-
org: git:github.com/northwind/knowledge
|
|
154
|
-
|
|
155
|
-
# Messaging policy — a PROVIDER payload consumed by oats.aweb, kept under the slot
|
|
156
|
-
# it belongs to so "team" means one thing in this file. Enrolls nobody by itself.
|
|
157
|
-
messaging:
|
|
158
|
-
private: per-human
|
|
159
|
-
channels: [northwind-eng, northwind-mkt]
|
|
160
|
-
|
|
161
|
-
# By-reference adoption of souls from repos that are NOT members. A stranger's
|
|
162
|
-
# repo cannot be "latest state", so these stay pinned.
|
|
163
|
-
external:
|
|
164
|
-
- source: git:github.com/oss-collective/experts@9c4e1f2a9c4e1f2a9c4e1f2a9c4e1f2a9c4e1f2a
|
|
165
|
-
soul: souls/security-reviewer
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Note what is **absent** compared to today: no `imports:` for the company's own souls (they are discovered), no per-soul revisions. The backlink is **still required** — it is the other half of the handshake — but it is now its own one-line file, `oats-membership.yaml`.
|
|
169
|
-
|
|
170
|
-
#### `souls/release-manager/soul.yaml`
|
|
171
|
-
|
|
172
|
-
```yaml
|
|
173
|
-
schemaVersion: 2
|
|
174
|
-
name: release-manager
|
|
175
|
-
description: Cuts, verifies and announces platform releases.
|
|
176
|
-
work: worktree
|
|
177
|
-
team: engineering # a label: overrides this repo's default (global)
|
|
178
|
-
|
|
179
|
-
# Each capability says where it lives. `from` is a LOCATION (a member repo, or
|
|
180
|
-
# `package` = one of the workspace's pinned packages) — never a version.
|
|
181
|
-
# oats.core + nw-house-style arrive from workspace defaults; nw-release-tooling
|
|
182
|
-
# from the engineering team default — named here anyway for readability.
|
|
183
|
-
capabilities:
|
|
184
|
-
nw-release-tooling: { from: here } # `here` = the repo this soul.yaml lives in
|
|
185
|
-
|
|
186
|
-
# Provider payloads stay opaque to the kernel — same as today, just shorter:
|
|
187
|
-
knowledge:
|
|
188
|
-
owns: release-manager # store defaults to the workspace's `org`
|
|
189
|
-
reads: [platform-engineer, data-analyst]
|
|
190
|
-
messaging:
|
|
191
|
-
channels: [northwind-eng]
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
#### `souls/support-triager/soul.yaml` — opting out of a default
|
|
195
|
-
|
|
196
|
-
```yaml
|
|
197
|
-
schemaVersion: 2
|
|
198
|
-
name: support-triager
|
|
199
|
-
description: Triages inbound support issues into Jira.
|
|
200
|
-
work: directory
|
|
201
|
-
# no `team:` → this repo's default from oats-membership.yaml (global)
|
|
202
|
-
|
|
203
|
-
capabilities:
|
|
204
|
-
nw-house-style: off # removes a workspace default
|
|
205
|
-
tasks: { oats.jira: { from: package } } # explicit, same as the default; harmless
|
|
206
|
-
knowledge: none # opts out of the knowledge slot entirely
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
#### `capabilities/nw-release-tooling/oats.json` — unchanged shape
|
|
210
|
-
|
|
211
|
-
The capability manifest is the one file that does **not** need to change. It already says everything the kernel needs:
|
|
212
|
-
|
|
213
|
-
```json
|
|
214
|
-
{
|
|
215
|
-
"capability": "nw-release-tooling",
|
|
216
|
-
"team": "engineering",
|
|
217
|
-
"version": "0.0.0-workspace",
|
|
218
|
-
"description": "Northwind release checklist, changelog and tag automation.",
|
|
219
|
-
"compatibility": { "oats": ">=0.24.0" },
|
|
220
|
-
"requires": ["oats.core"],
|
|
221
|
-
"skills": ["skills/cut-release"],
|
|
222
|
-
"inject": "injects/release-policy.md",
|
|
223
|
-
"commands": { "cut": "bin/nw-release.mjs cut", "verify": "bin/nw-release.mjs verify" }
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
`version` is informational for workspace-tier capabilities — what identifies a materialized copy is the **content hash**, recorded at spawn (see §5).
|
|
228
|
-
|
|
229
|
-
### 3.2 `northwind/platform` — the product repo, exporting souls that work in it
|
|
230
|
-
|
|
231
|
-
```
|
|
232
|
-
platform/
|
|
233
|
-
├── src/ … ← the actual product
|
|
234
|
-
├── oats-membership.yaml ← REQUIRED: the handshake (+ default team: engineering)
|
|
235
|
-
└── souls/
|
|
236
|
-
├── platform-engineer/soul.yaml
|
|
237
|
-
└── platform-reviewer/soul.yaml
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
**Convention replaces declaration for exports; the handshake stays.** `oats-membership.yaml` is **required** in every member and carries one mandatory line — the backlink — plus, optionally, a default `team:` label for the items in the repo. (It replaces today's `oats.yaml`; the export lists that file carried are gone, see below.) Because `platform` backlinks and the workspace lists it, every `souls/*/soul.yaml` and `capabilities/*/oats.json` in it is a workspace soul/capability, **discoverable by default**:
|
|
241
|
-
|
|
242
|
-
```yaml
|
|
243
|
-
# oats-membership.yaml — REQUIRED in every member repo
|
|
244
|
-
schemaVersion: 2
|
|
245
|
-
workspace: git:github.com/northwind/agents # the handshake: "I am a member of northwind"
|
|
246
|
-
team: engineering # optional: default team label for items in this repo
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Both halves are observed at spawn/sync with compatible identity and access context; a copied backlink in a fork, or a neighbouring folder with the right name, is not admission — same rule as today.
|
|
250
|
-
|
|
251
|
-
**Something that wants to stay internal says so itself.** There is no export list anywhere; the decision lives next to the thing it is about, so it survives a move between repos and never drifts from an index:
|
|
252
|
-
|
|
253
|
-
```yaml
|
|
254
|
-
# souls/platform-reviewer/soul.yaml — internal to this repo
|
|
255
|
-
schemaVersion: 2
|
|
256
|
-
name: platform-reviewer
|
|
257
|
-
private: true # not discoverable in the workspace; usable only from this repo
|
|
258
|
-
…
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
```json
|
|
262
|
-
// capabilities/nw-experimental-linter/oats.json — half-finished, not for the team yet
|
|
263
|
-
{ "capability": "nw-experimental-linter", "private": true, "…": "…" }
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
A private soul can still be spawned when the spawner stands in its own repo (it is not hidden from its owners); a private capability can be named only by souls of the same repo. `oats capabilities` shows private items to their own repo with a `private` badge and to nobody else.
|
|
267
|
-
|
|
268
|
-
```yaml
|
|
269
|
-
# northwind/agents/oats-membership.yaml — the host repo backlinks to itself
|
|
270
|
-
schemaVersion: 2
|
|
271
|
-
workspace: git:github.com/northwind/agents
|
|
272
|
-
team: global # optional: default team label for items in this repo
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
#### `souls/platform-engineer/soul.yaml`
|
|
276
|
-
|
|
277
|
-
```yaml
|
|
278
|
-
schemaVersion: 2
|
|
279
|
-
name: platform-engineer
|
|
280
|
-
description: Implements platform features on a branch and opens PRs.
|
|
281
|
-
work: worktree
|
|
282
|
-
capabilities: {} # only the workspace defaults
|
|
283
|
-
knowledge:
|
|
284
|
-
owns: platform-engineer
|
|
285
|
-
reads: [release-manager]
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
The soul's **work target** is whatever repo the spawner points it at (by default, the repo the soul lives in). Where a soul is *published* and where it *works* remain independent, exactly as today.
|
|
289
|
-
|
|
290
|
-
### 3.3 `northwind/data` — a repo that exports a soul AND a capability
|
|
291
|
-
|
|
292
|
-
```
|
|
293
|
-
data/
|
|
294
|
-
├── warehouse/ …
|
|
295
|
-
├── oats-membership.yaml ← { workspace, team: engineering }
|
|
296
|
-
├── souls/data-analyst/soul.yaml
|
|
297
|
-
└── capabilities/nw-warehouse-access/
|
|
298
|
-
├── oats.json
|
|
299
|
-
├── skills/query-warehouse/SKILL.md
|
|
300
|
-
└── bin/nw-wh.mjs ← an executable; trusted because `data` is a trusted member
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
```yaml
|
|
304
|
-
# souls/data-analyst/soul.yaml
|
|
305
|
-
schemaVersion: 2
|
|
306
|
-
name: data-analyst
|
|
307
|
-
description: Answers questions against the warehouse with attributable evidence.
|
|
308
|
-
work: directory
|
|
309
|
-
capabilities:
|
|
310
|
-
nw-warehouse-access: { from: here } # `here` = the repo this soul.yaml lives in
|
|
311
|
-
knowledge:
|
|
312
|
-
owns: data-analyst
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
`nw-warehouse-access` is now **discoverable across the whole workspace**: `release-manager` in `northwind/agents` could add `nw-warehouse-access: { from: northwind/data }`, and `oats capabilities` / the Desktop Capabilities view list it with origin `workspace (northwind/data)`. Reading any `soul.yaml` tells you where each of its capabilities lives without running anything.
|
|
316
|
-
|
|
317
|
-
### 3.4 `northwind/marketing` — the second team, same workspace
|
|
318
|
-
|
|
319
|
-
```
|
|
320
|
-
marketing/
|
|
321
|
-
├── campaigns/ …
|
|
322
|
-
├── oats-membership.yaml ← { workspace, team: marketing }
|
|
323
|
-
├── souls/
|
|
324
|
-
│ ├── campaign-writer/soul.yaml
|
|
325
|
-
│ └── positioning-analyst/soul.yaml
|
|
326
|
-
└── capabilities/
|
|
327
|
-
├── nw-brand-voice/ ← injects/brand-voice.md + skills/tone-check
|
|
328
|
-
└── nw-campaign-metrics/ ← bin/nw-cm.mjs (queries the ads APIs)
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
```yaml
|
|
332
|
-
# souls/campaign-writer/soul.yaml
|
|
333
|
-
schemaVersion: 2
|
|
334
|
-
name: campaign-writer
|
|
335
|
-
description: Drafts launch campaigns from what engineering is actually shipping.
|
|
336
|
-
work: directory
|
|
337
|
-
# team: marketing — inherited from this repo's oats-membership.yaml
|
|
338
|
-
capabilities:
|
|
339
|
-
nw-campaign-metrics: { from: here }
|
|
340
|
-
nw-release-tooling: { from: northwind/agents } # a marketer using an ENGINEERING capability — nothing stops it
|
|
341
|
-
knowledge:
|
|
342
|
-
owns: campaign-writer
|
|
343
|
-
reads: [release-manager, platform-engineer] # marketers learning what is shipping
|
|
344
|
-
messaging:
|
|
345
|
-
channels: [northwind-mkt]
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
```json
|
|
349
|
-
// capabilities/nw-brand-voice/oats.json
|
|
350
|
-
{ "capability": "nw-brand-voice", "team": "marketing", "inject": "injects/brand-voice.md", "skills": ["skills/tone-check"], "…": "…" }
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
Because `nw-brand-voice` is a marketing team default (`defaults.byTeam.marketing`), every marketing soul carries the brand voice without naming it; `release-manager` (engineering) could still add `nw-brand-voice: { from: northwind/marketing }` for its release announcements. **Nothing about trust, handshake, packages or the store is different for this team** — it is one more member repo with a label.
|
|
354
|
-
|
|
355
|
-
### 3.5 `northwind/nw-tools` — a member that also publishes a package (decisions 19–20)
|
|
356
|
-
|
|
357
|
-
```
|
|
358
|
-
nw-tools/
|
|
359
|
-
├── oats-membership.yaml ← { workspace, team: engineering } — it IS a member
|
|
360
|
-
├── souls/tools-expert/soul.yaml ← the MEMBER soul: knows and evolves the nw.tools package
|
|
361
|
-
├── capabilities/nw-tools-dev/ ← member-tier: latest state, for people working ON nw-tools
|
|
362
|
-
└── oats-package/ ← PACKAGE-tier: versioned, tagged v0.4.0, pinned in packages:, approved
|
|
363
|
-
├── oats-package.json ← { package: "nw.tools", version: "0.4.0", capabilities: [...] }
|
|
364
|
-
└── capabilities/
|
|
365
|
-
├── nw-lint/oats.json
|
|
366
|
-
└── nw-deploy/oats.json ← has bin/ → executables approved once per version
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
Two roles, two tiers, one repo — and they do not collapse into each other:
|
|
370
|
-
|
|
371
|
-
- `souls/*` and `capabilities/*` are **member-tier**: discoverable at latest state because `nw-tools` completed the handshake. `nw-tools-dev` is what `tools-expert` uses while working on the package itself.
|
|
372
|
-
- `oats-package/*` is **package-tier**: it is consumed only through `packages:` (`nw.tools: git:…@v0.4.0`), locked to a commit, integrity-checked, executables approved per version. `release-manager` says `nw-deploy: { from: package }` — never `from: northwind/nw-tools` — even though that repo is a member. Membership does not turn a package into a latest-state capability.
|
|
373
|
-
|
|
374
|
-
```yaml
|
|
375
|
-
# souls/tools-expert/soul.yaml — the package's own expert, an ordinary member soul
|
|
376
|
-
schemaVersion: 2
|
|
377
|
-
name: tools-expert
|
|
378
|
-
description: Knows the nw.tools package — its manifests, executables, release tags and consumers; evolves it through PRs.
|
|
379
|
-
work: worktree
|
|
380
|
-
capabilities:
|
|
381
|
-
nw-tools-dev: { from: here } # member-tier, latest
|
|
382
|
-
nw-lint: { from: package } # eats its own published food, at the pinned version
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
This is exactly the shape the OATS workspace itself takes: `oats-okf`, `oats-aweb`, `oats-jira`, `oats-linear`, `oats-authoring`, `oats-dev` are members that publish packages **and** each carries its expert soul (`okf-expert`, `aweb-expert`, …); the framework's souls say `oats.okf: { from: package }`. The **official catalog** (`package-catalog.json` in the `oats` repo) stays as the reviewed marketplace: a bare-version entry like `oats.okf: v2.1.3` resolves through it; a package outside it is written as `git:<repo>@<ref>`.
|
|
386
|
-
|
|
387
|
-
### 3.6 `northwind/knowledge` — a store, not a member
|
|
388
|
-
|
|
389
|
-
Contains the OKF base. It appears in the workspace under `stores:`, not `members:` — it exports no souls or capabilities. Publication to it stays PR-only, as today.
|
|
390
|
-
|
|
391
|
-
### 3.7 `oss-collective/experts` — the borrowed public soul
|
|
392
|
-
|
|
393
|
-
```
|
|
394
|
-
experts/
|
|
395
|
-
└── souls/security-reviewer/
|
|
396
|
-
├── soul.yaml
|
|
397
|
-
├── AGENTS.md
|
|
398
|
-
└── skills/threat-model/SKILL.md
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
```yaml
|
|
402
|
-
# souls/security-reviewer/soul.yaml (written by oss-collective, not Northwind)
|
|
403
|
-
schemaVersion: 2
|
|
404
|
-
name: security-reviewer
|
|
405
|
-
description: Reviews changes for security regressions.
|
|
406
|
-
work: worktree
|
|
407
|
-
capabilities: {}
|
|
408
|
-
compatibility: # optional FLOORS — constraints, not sources
|
|
409
|
-
oats.okf: ">=2.1"
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
Northwind adopts it through `external:` with a pinned revision. There is deliberately **no handshake** here: oss-collective has not consented to be in Northwind's workspace and Northwind is not asking — it borrows one soul by reference. That is exactly why `external` souls get no workspace-tier capabilities of their own repo and stay pinned. It is a **source-complete** soul: its skills travel with it. Its knowledge slot is filled by Northwind's default (`oats.okf`), and Northwind decides at spawn whether it gets a node in the team store. Northwind never joins oss-collective’s workspace and never reads its `oats-membership.yaml`.
|
|
413
|
-
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
## 4. The deployment side — any layout, one convention
|
|
417
|
-
|
|
418
|
-
**Nothing below is shared, and none of it is required to look a particular way.** Discovery and resolution work against **Git remotes**: the kernel fetches `oats-workspace.yaml`, each member's `oats-membership.yaml`, every `souls/*/soul.yaml` and `capabilities/*/oats.json`, and every package, **by URL** — shallow fetch or host contents API, at latest or at the locked commit. A capability is copied into an instance straight from the remote. The repo that defines a capability never needs to be cloned; neither does the repo that hosts the workspace.
|
|
419
|
-
|
|
420
|
-
**The only thing that needs a local clone is a soul's work target** — a soul with `work: worktree | checkout | directory` works *in* a repo, so that repo must be on disk. Spawning a soul whose repo is not yet cloned is therefore a *guided clone into the conventional place, then spawn*: a job for the onboarding skill (`oats-setup-expert`), not the kernel.
|
|
421
|
-
|
|
422
|
-
**The deployment directory is the operator's choice** (decision 9): an existing folder that already holds the member clones is the usual case; onboarding asks for it (`oats onboard <dir>`) and adds the three entries the kernel needs. Shown here as Ana's `~/northwind/`, with the member clones inside it:
|
|
423
|
-
|
|
424
|
-
```
|
|
425
|
-
~/northwind/ ← the directory Ana chose (any name, any place)
|
|
426
|
-
├── oats-local.yaml ← which workspace this machine realizes + host paths + disabled souls
|
|
427
|
-
├── oats-lock.json ← exact commit + integrity + per-version approval per package
|
|
428
|
-
├── agents/ ← instance homes, each self-contained
|
|
429
|
-
├── agents-repo/ ← clone of github.com/northwind/agents (only if someone works IN it)
|
|
430
|
-
├── platform/ ← clone of github.com/northwind/platform
|
|
431
|
-
└── data/ ← clone of github.com/northwind/data
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
The kernel never depends on this shape. It finds clones through `oats-local.yaml` (or by matching a clone's remote URL to a member), and an operator who prefers `~/src/nw-platform` simply points at it.
|
|
435
|
-
|
|
436
|
-
### Ana (macOS)
|
|
437
|
-
|
|
438
|
-
```
|
|
439
|
-
~/northwind-oats/
|
|
440
|
-
├── oats-local.yaml ← this machine's overrides (host paths, disabled souls)
|
|
441
|
-
├── oats-lock.json ← exact commit + integrity + approval per package version
|
|
442
|
-
└── agents/
|
|
443
|
-
└── <soul>/instances/<instance>/ ← instance homes; each carries its own full copy of its capabilities
|
|
444
|
-
(a fetch cache, if any, lives under the OS cache dir and is not part of the model)
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
```yaml
|
|
448
|
-
# oats-local.yaml — replaces the role of today's oats-config.yaml
|
|
449
|
-
schemaVersion: 2
|
|
450
|
-
workspace: git:github.com/northwind/agents # observed over the remote; this repo need not be cloned
|
|
451
|
-
|
|
452
|
-
clones: # optional: where member clones live, if not the convention
|
|
453
|
-
northwind/platform: ~/src/nw-platform
|
|
454
|
-
|
|
455
|
-
settings: # host-owned values the manifests ask for
|
|
456
|
-
oats.okf:
|
|
457
|
-
bindings-file: /Users/ana/.oats/okf-bindings.json
|
|
458
|
-
state-dir: /Users/ana/.oats/okf
|
|
459
|
-
oats.aweb:
|
|
460
|
-
delivery: channel
|
|
461
|
-
|
|
462
|
-
souls:
|
|
463
|
-
disabled: [data-analyst] # Ana doesn't run analytics agents
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
### Bo (Linux)
|
|
467
|
-
|
|
468
|
-
```yaml
|
|
469
|
-
schemaVersion: 2
|
|
470
|
-
workspace: git:github.com/northwind/agents
|
|
471
|
-
settings:
|
|
472
|
-
oats.okf:
|
|
473
|
-
bindings-file: /home/bo/.oats/okf-bindings.json
|
|
474
|
-
state-dir: /home/bo/.oats/okf
|
|
475
|
-
souls:
|
|
476
|
-
disabled: [release-manager, support-triager]
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
There is no per-operator trust list: Bo is in the workspace, so Bo runs the workspace's capabilities — the same way cloning `northwind/data` already means running whatever skills its `.agents/skills/` carries. Package executables are approved once per version, in the lock.
|
|
480
|
-
|
|
481
|
-
### `oats-lock.json` — today's lock plus the per-version approval
|
|
482
|
-
|
|
483
|
-
```json
|
|
484
|
-
{
|
|
485
|
-
"lockfileVersion": 3,
|
|
486
|
-
"packages": {
|
|
487
|
-
"oats.okf": {
|
|
488
|
-
"source": "catalog:oats.okf", "path": "oats-package", "version": "2.1.3",
|
|
489
|
-
"commit": "aafdd3ef0c2b…", "integrity": "sha256-…", "dependencies": [],
|
|
490
|
-
"approved": { "executables": "sha256-…", "at": "2026-09-23T09:02:11Z" }
|
|
491
|
-
},
|
|
492
|
-
"oats.aweb": { "…": "…" },
|
|
493
|
-
"oats.jira": { "…": "…" },
|
|
494
|
-
"oats.framework": { "…": "…" }
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
Ana's and Bo's locks are **identical** if they synced the same workspace commit — the lock is the one place exact commits, integrity and the per-version executable approval belong. A package version is approved once; every instance that materializes it inherits the approval. A moved tag (same version, different commit) fails integrity and asks again.
|
|
500
|
-
|
|
501
|
-
### Everything that disappeared from deployment config
|
|
502
|
-
|
|
503
|
-
Today's `capabilities.layers.messaging.{capability, from, global, souls, settings}` and `capabilities.additive.<x>.{from, global, souls}` blocks are gone. Activation and targeting are **derived**: workspace `defaults` + each soul's `capabilities` + slot names. The deployment only *overrides* (host paths, disabled souls).
|
|
504
|
-
|
|
505
|
-
---
|
|
506
|
-
|
|
507
|
-
### Provider payloads have three homes (team review, decided)
|
|
508
|
-
|
|
509
|
-
| What it is | Where | Example |
|
|
510
|
-
|---|---|---|
|
|
511
|
-
| True of every instance of the soul | `soul.yaml` → `messaging:` / `knowledge:` | `messaging: { channels: [northwind-eng] }`, `knowledge: { owns: release-manager }` |
|
|
512
|
-
| A fact about this machine | `oats-local.yaml` → `settings.<capability>.<key>` (absolute paths refused in the workspace file) | `settings.oats.okf.state-dir: /Users/ana/.oats/okf` |
|
|
513
|
-
| A fact about **this spawn** | `oats spawn … --provider <cap> key=value` → `instance.json` `providers.<cap>` (the Desktop's confirmed apply carries the same map) | `--provider oats.aweb identity.source=/abs/path/to/retained/.aw` — one instance takes the retained seat; other instances of the soul mint fresh |
|
|
514
|
-
|
|
515
|
-
The provider's `binding` contract (`normalize → bind → check`) runs over the merged payload exactly as today; the provider still enforces its own rules (e.g. a state root outside the work tree).
|
|
516
|
-
|
|
517
|
-
## 5. Materialization — a full copy inside the instance (decided)
|
|
518
|
-
|
|
519
|
-
At spawn, every capability a soul resolves to is **copied in full** — skills, injects, scripts, hooks — into the instance home. Nothing is symlinked; nothing is shared between instances; there is no deployment-level modules directory.
|
|
520
|
-
|
|
521
|
-
```
|
|
522
|
-
~/northwind-oats/agents/release-manager/instances/release-manager-v3/
|
|
523
|
-
├── .oats/modules/
|
|
524
|
-
│ ├── nw-release-tooling/ ← full copy: skills/, injects/, bin/
|
|
525
|
-
│ ├── nw-house-style/
|
|
526
|
-
│ └── oats.core/ ← from a package: fetched at the locked version, copied the same way
|
|
527
|
-
├── AGENTS.md ← composed from the soul's AGENTS.md + every module's inject
|
|
528
|
-
├── instance.json
|
|
529
|
-
└── work/ …
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
```json
|
|
533
|
-
// instance.json — provenance is RECORDED here, not declared in the soul
|
|
534
|
-
{
|
|
535
|
-
"instance": "release-manager-v3",
|
|
536
|
-
"soul": "release-manager",
|
|
537
|
-
"createdAt": "2026-09-23T10:12:44.118Z",
|
|
538
|
-
"modules": {
|
|
539
|
-
"nw-release-tooling": { "from": "northwind/agents", "commit": "3f2a9c1e…", "hash": "sha256-…" },
|
|
540
|
-
"nw-house-style": { "from": "northwind/agents", "commit": "3f2a9c1e…", "hash": "sha256-…" },
|
|
541
|
-
"oats.core": { "from": "package", "package": "oats.framework", "version": "1.1.3", "commit": "…" }
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
What this buys, and why it was chosen over "shared latest with per-instance skills only":
|
|
547
|
-
|
|
548
|
-
- **A running instance never changes under itself.** Its hooks and scripts are the ones it started with; a member repo moving, or `packages:` being bumped, affects only *new* spawns.
|
|
549
|
-
- **"What an instance runs is what it was spawned with" stays provable** — the retirement baseline, the confirmed-apply contract (`decision` binds effective launch facts) and the Desktop's reported facts all rely on it.
|
|
550
|
-
- **How far behind a running instance is** is visible: `instance.json` records the commit; the spawn preview says "changed since release-manager-v2".
|
|
551
|
-
- **No shared state to reason about.** No cache invalidation, no "which instances still reference hash b71e…", no directory anyone has to know about. If fetch cost ever matters, a cache is an invisible implementation detail.
|
|
552
|
-
|
|
553
|
-
Cost: disk, a few MB per instance. Accepted.
|
|
554
|
-
|
|
555
|
-
**Drift is shown, not prevented** (team review): `oats status` and the Desktop roster show per instance `modules: nw-release-tooling from northwind/agents @ 3f2a9c1e` and, when the member has moved, `member moved since (now @ 9b0c…)` or `capability no longer present`. The preview already says "changed since release-manager-v2".
|
|
556
|
-
|
|
557
|
-
### The harness starts normally (decided)
|
|
558
|
-
|
|
559
|
-
OATS is a **skill contributor, not a skill sandbox**. Today the harness is launched with ambient skill discovery suppressed and only the capability-injected skills visible. That defended against content we have just decided to trust (decision 2: a repo's committed `.agents/skills/` is exactly as trusted as its committed capabilities). So:
|
|
560
|
-
|
|
561
|
-
- The harness (Pi, Claude, Codex) is started **the way it starts anywhere**, with cwd = the instance home and its own discovery intact — Pi's `~/.pi/agent/skills` and `.agents/skills` up the tree, Claude's `.claude/`, Codex's equivalent.
|
|
562
|
-
- Materialized capability skills are placed **where the harness already looks**: `<instance>/.agents/skills/<capability>/<skill>/SKILL.md` (copied from the capability's `skills/`). Precedence is the harness's own nearest-wins rule — no special profile, no exclusion list, no injected skill index.
|
|
563
|
-
- An agent therefore sees, in this order of proximity: its capability skills (instance home), the repo's own `.agents/skills/` once it works in `work/`, and whatever the operator keeps at machine level. **All three are intended.**
|
|
564
|
-
- What OATS still composes is **instructions** (`AGENTS.md` from the soul + every capability's inject) and the **model/provider settings** the deployment pins (e.g. a Pi profile). Neither touches skill discovery.
|
|
565
|
-
- **Duplicate names** (team review): two *composed* capability skills with the same name are still a spawn error naming both (`skill-overrides` picks one). A composed skill and an ambient repo/machine skill with the same name is **not** an error — the harness's precedence decides; the preview lists composed names so a clash is visible.
|
|
566
|
-
|
|
567
|
-
```
|
|
568
|
-
~/northwind/agents/release-manager/instances/release-manager-v3/
|
|
569
|
-
├── AGENTS.md ← canonical, composed: soul AGENTS.md + capability injects
|
|
570
|
-
├── CLAUDE.md → AGENTS.md ← relative symlink (unchanged from today)
|
|
571
|
-
├── .agents/skills/ ← canonical; where Pi (and Codex) look
|
|
572
|
-
│ ├── nw-release-tooling/cut-release/SKILL.md
|
|
573
|
-
│ ├── nw-house-style/…
|
|
574
|
-
│ └── oats-core/oats-operate/SKILL.md
|
|
575
|
-
├── .claude/skills → ../.agents/skills ← relative symlink alias for Claude (unchanged from today)
|
|
576
|
-
├── .oats/modules/ ← the full capability copies (bin/, injects/, manifests)
|
|
577
|
-
│ ├── nw-release-tooling/
|
|
578
|
-
│ └── …
|
|
579
|
-
├── instance.json
|
|
580
|
-
└── work/ ← the worktree; its own .agents/ or .claude/ resolve as the harness sees fit
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
The canonical-plus-alias construction (`AGENTS.md` ⇐ `CLAUDE.md`, `.agents/skills` ⇐ `.claude/skills`) is kept exactly as the kernel builds it today. It covers **our contributed skills** only; repo-level or machine-level skills are the harness's own business — neither aliased nor excluded by OATS.
|
|
584
|
-
|
|
585
|
-
### What a spawn preview shows
|
|
586
|
-
|
|
587
|
-
```
|
|
588
|
-
release-manager-v3 ← soul release-manager · team engineering (northwind/agents @ 3f2a9c1e)
|
|
589
|
-
modules
|
|
590
|
-
nw-release-tooling workspace northwind/agents @ 3f2a9c1e (changed since release-manager-v2)
|
|
591
|
-
nw-house-style workspace northwind/agents @ 3f2a9c1e
|
|
592
|
-
oats.core package oats.framework v1.1.3
|
|
593
|
-
slots
|
|
594
|
-
knowledge oats.okf v2.1.3 → store org (owns release-manager)
|
|
595
|
-
messaging oats.aweb v1.11.2 → private + channels [northwind-eng]
|
|
596
|
-
team engineering
|
|
597
|
-
tasks oats.jira v1.0.0
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
The Desktop's existing spawn preview/apply contract (`decision.revision`, `--expect-decision`, idempotency) carries this as facts; nothing about that contract changes.
|
|
601
|
-
|
|
602
|
-
---
|
|
603
|
-
|
|
604
|
-
## 6. Resolution, spelled out
|
|
605
|
-
|
|
606
|
-
```
|
|
607
|
-
membership (before anything else; OBSERVED over the remotes with the operator's own Git access):
|
|
608
|
-
member = listed in oats-workspace.yaml AND its oats-membership.yaml names this workspace
|
|
609
|
-
both halves must be READ in the same access context (this operator's credentials for that host)
|
|
610
|
-
a repo failing either half → not a member (E_MEMBERSHIP_UNCONFIRMED names the missing half)
|
|
611
|
-
a half that cannot be READ → not confirmed (E_MEMBERSHIP_UNCONFIRMED: cannot read <url>) — never a half-success
|
|
612
|
-
|
|
613
|
-
standalone (a repo you can read whose workspace you cannot):
|
|
614
|
-
its souls exist and can be spawned; their `from: here` capabilities resolve
|
|
615
|
-
`from: <other member>` and `from: package` are unresolvable (the version list lives in the workspace file)
|
|
616
|
-
workspace defaults do not apply — you cannot see them
|
|
617
|
-
|
|
618
|
-
for each (name, from) in workspace.defaults.capabilities ⊕ soul.capabilities (soul wins; `off` removes):
|
|
619
|
-
from: package
|
|
620
|
-
→ some entry in the workspace's `packages:` provides `name` else E_PACKAGE_MISSING
|
|
621
|
-
→ fetch that package at the locked commit; verify integrity else E_PACKAGE_INTEGRITY
|
|
622
|
-
→ its executables must be approved for that version (lock) else E_PACKAGE_UNAPPROVED (asks once)
|
|
623
|
-
→ copy the capability into the instance; record package/version/commit
|
|
624
|
-
from: <repo> (or `here` = the soul's own repo)
|
|
625
|
-
→ <repo> must be a confirmed member else E_NOT_A_MEMBER
|
|
626
|
-
→ <repo> must contain capabilities/<name>/oats.json else E_CAPABILITY_MISSING
|
|
627
|
-
→ it must not be `private: true` unless <repo> is the soul's own repo else E_CAPABILITY_PRIVATE
|
|
628
|
-
→ materialize from the member's current state; record repo/commit/hash
|
|
629
|
-
|
|
630
|
-
team label:
|
|
631
|
-
item's own `team:` → its repo's default in oats-membership.yaml → none ("unassigned")
|
|
632
|
-
a name not in the workspace's `teams:` → E_TEAM_UNKNOWN (labels cannot drift into typos)
|
|
633
|
-
defaults.byTeam.<team>.capabilities are added for a soul with that label, before the soul's own (soul wins; `off` removes)
|
|
634
|
-
a label never gates, restricts, changes trust or partitions the store
|
|
635
|
-
|
|
636
|
-
launch:
|
|
637
|
-
cwd = instance home; harness started with its default skill discovery — nothing excluded
|
|
638
|
-
capability skills copied to <instance>/.agents/skills/<capability>/…; injects composed into AGENTS.md
|
|
639
|
-
machine-level and repo-level skills resolve exactly as they would without OATS
|
|
640
|
-
|
|
641
|
-
slots (knowledge / messaging / tasks):
|
|
642
|
-
a resolved capability whose manifest has `layer: X` fills slot X
|
|
643
|
-
soul says `X: none` → slot empty; soul names nothing → workspace default fills it
|
|
644
|
-
two capabilities with the same `layer` on one soul → E_SLOT_CONFLICT
|
|
645
|
-
```
|
|
646
|
-
|
|
647
|
-
No search, no ambiguity: `from` makes every reference a direct lookup. Two members may even export the same bare name — each soul says which one it meant. Discovery (`oats capabilities`, the Desktop view) still lists every non-private capability of every member with its origin, so choosing a `from` is a lookup in a list, not guesswork.
|
|
648
|
-
|
|
649
|
-
## 7. A day in the life
|
|
650
|
-
|
|
651
|
-
**Monday.** Bo lands a change to `northwind/data/capabilities/nw-warehouse-access/bin/nw-wh.mjs` on the default branch.
|
|
652
|
-
|
|
653
|
-
- `data-analyst-7`, already running on Bo's machine, keeps its **own full copy**. Nothing moves under it.
|
|
654
|
-
- Ana runs `oats sync`: fetches members, reports `nw-warehouse-access: 88d1c2… → 4a0f31… (northwind/data @ e91b…)`. Ana doesn't run data souls, so nothing else happens.
|
|
655
|
-
- Bo spawns `data-analyst-8`: preview shows the new hash and "changed since data-analyst-7"; apply materializes the new state. `instance.json` records the commit.
|
|
656
|
-
|
|
657
|
-
**Tuesday.** The team decides to move to `oats.okf` v2.2.0. One line changes in `oats-workspace.yaml` (`packages.oats.okf: v2.2.0`). The next `oats sync` on each machine resolves the new version to a commit, **asks for executable approval once**, and writes both to the lock. Nothing is installed; the next spawn of any soul with `oats.okf` fetches and copies v2.2.0. Running instances are untouched until re-spawned.
|
|
658
|
-
|
|
659
|
-
**Wednesday (a).** Someone adds `git:github.com/northwind/billing` to `members:` before the billing team has added their `oats-membership.yaml`. `oats sync` reports `billing: E_MEMBERSHIP_UNCONFIRMED (no backlink)`; billing's souls stay invisible until they consent. Nothing half-joins.
|
|
660
|
-
|
|
661
|
-
**Thursday.** A contractor, Cy, has read access to `northwind/platform` but not to the private `northwind/agents`. Cy can spawn `platform-engineer` standalone (it has no capabilities of its own). Spawning `release-manager` — not visible, it lives in `agents`. Naming `nw-house-style` — `E_MEMBERSHIP_UNCONFIRMED: cannot read git:github.com/northwind/agents`. That is the workspace's access control working: reading the workspace repo *is* being in the workspace. Northwind can make `agents` readable (it holds declarations, no secrets) or grant Cy access.
|
|
662
|
-
|
|
663
|
-
**Wednesday (b).** `oss-collective/experts` publishes an improved `security-reviewer`. Nothing happens until someone bumps the pinned revision in `external:` — a stranger's repo is never "latest".
|
|
664
|
-
|
|
665
|
-
---
|
|
666
|
-
|
|
667
|
-
## 8. `oats sync` — one command for the common path
|
|
668
|
-
|
|
669
|
-
```
|
|
670
|
-
$ oats sync
|
|
671
|
-
workspace northwind (github.com/northwind/agents @ 3f2a9c1e)
|
|
672
|
-
members agents ✓↔ platform ✓↔ (@ 77c0…) data ✓↔ (@ e91b…, changed) marketing ✓↔ billing ✗ (no backlink)
|
|
673
|
-
packages oats.framework 1.1.3 ✓ oats.okf 2.1.3 ✓ (approved) oats.aweb 1.11.2 ✓ oats.jira 1.0.0 ✓ (approval needed → y)
|
|
674
|
-
changed nw-warehouse-access 88d1c2… → 4a0f31… (1 running instance still on the old state; new spawns get this)
|
|
675
|
-
souls 9 discovered (7 members, 1 external, 1 disabled here) · 1 private (platform-reviewer, platform only)
|
|
676
|
-
teams global 2 souls · engineering 4 souls, 3 capabilities · marketing 2 souls, 2 capabilities
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
`sync` is what a person types: it confirms membership, resolves `packages:` versions to commits, verifies integrity, asks for any missing per-version approval, and reports what changed. `install`, `restore`, `init` and `use` go away — there is nothing to install or activate; `oats package add <id> <version>` edits `packages:` and syncs.
|
|
680
|
-
|
|
681
|
-
---
|
|
682
|
-
|
|
683
|
-
## 9. What this gives up — decisions for the human
|
|
684
|
-
|
|
685
|
-
| # | Today | Proposed | Who should decide |
|
|
686
|
-
|---|---|---|---|
|
|
687
|
-
| 1 | **Per-artifact executable approval** for every capability | **Members: membership IS the trust (decided).** Same as trusting a repo's committed skills. **Packages:** once per version, recorded in the lock, inherited by every instance | Decided |
|
|
688
|
-
| 2 | **Reproducible resolution** by construction | Members are *auditable* (commit + hash recorded in every instance), not reproducible-by-construction. **No `@revision` on members (decided)** — frozen capabilities are what packages are for | Decided |
|
|
689
|
-
| 3 | **Reciprocal backlink** as a membership gate | **Kept as a hard gate (decided).** The repo's half becomes a one-line `oats-membership.yaml` (replaces `oats.yaml`) | Decided: keep |
|
|
690
|
-
| 4 | **Per-soul software pins** (`source: git:…@v2.1.2#…` per capability) | A soul says **where** (`from: <member>` / `from: package`), never **which version** (**decided**). Optional `compatibility` floors | Decided |
|
|
691
|
-
| 5 | `imports:` for member souls; `exports:` lists in the old `oats.yaml` | Gone; discovery by convention, `private: true` on the item itself to stay internal (**decided**). `external:` stays pinned for non-members | Decided |
|
|
692
|
-
|
|
693
|
-
| 6 | `teams:` = messaging-provider payload (per-human/shared) | `teams:` = **org team labels** (global / engineering / marketing); the messaging payload moves under `messaging:` so the word means one thing (**decided**) | Decided |
|
|
694
|
-
| 7 | Harness launched with ambient skills **excluded**, only injected skills visible | Harness starts **normally**; OATS copies capability skills into `<instance>/.agents/skills/` and lets machine/repo skills resolve (**decided**) | Decided |
|
|
695
|
-
|
|
696
|
-
**Kept intact:** kernel-neutral provider payloads and `binding` validation; the lock (now also carrying per-version approval); executable approval for packages (per version, once); retained resolutions, decision revisions and the confirmed-apply contract; the official catalog; every published Desktop CLI contract (previews report "materialized from X @ commit"). **Gone:** the installed-capability tier, `.oats/packages/`, `oats install` / `use` / `init` / `restore`.
|
|
697
|
-
|
|
698
|
-
---
|
|
699
|
-
|
|
700
|
-
## 10. No migration — a clean break, and 0.24.x keeps working
|
|
701
|
-
|
|
702
|
-
Decided (human, 2026-09-23; refined with the team): "no migration" means no converter and no dual-schema reader — **not** that existing deployments stop. A 0.24.x kernel keeps spawning 0.24.x deployments indefinitely; v2 is the **0.25 line** and reads only v2 files; an operator installs 0.25 when ready to rebuild and not before. A written **rebuild guide** ships with the v2 schemas. So:
|
|
703
|
-
|
|
704
|
-
- **v2 only.** The kernel reads `oats-workspace.yaml` v2, `oats-membership.yaml`, `soul.yaml` v2 and `oats-local.yaml`; it does not read v1 declaration files and does not carry an `oats migrate`. A v1 file at a v2 path is an error naming the schema, not a silent fallback.
|
|
705
|
-
- **No dual-schema window**, no back-fill of `private: true`, no compatibility shims in the resolver.
|
|
706
|
-
- The framework's own repos are converted by hand as the first real workspace: the `oats` repo's workspace file drops its six `imports`, each of the five/six soul editions turns its `source: git:…@vX#oats-package` lines into `from: package` and drops its `stores.inherit` block, and each member repo gains its one-line `oats-membership.yaml`.
|
|
707
|
-
- The classic `oats-config.yaml` / `init` / `use` surface is **replaced**, not wrapped — `oats-local.yaml` + `oats sync` are the surface. (What remains of `oats-config.yaml`'s job is host paths and disabled souls; that is all `local.yaml` carries.)
|
|
708
|
-
|
|
709
|
-
## 11. Open questions
|
|
710
|
-
|
|
711
|
-
None. Every question raised in this brainstorm was closed with the human on 2026-09-23; the decisions are listed at the top of this document. Next step: write this up as a `Decision` concept in the oats-expert knowledge bundle (context, the model, the eleven decisions, what is removed, what is kept), update the adoption plan, and then plan the implementation — a clean v2 with no migration.
|