@awebai/oats 0.24.13 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/oats.mjs +994 -2837
- package/docs/capabilities.md +136 -323
- package/docs/configuration.md +68 -533
- package/docs/conventions.md +51 -24
- package/docs/design/2026-09-16-fresh-operator-walkthrough.md +19 -14
- package/docs/design/2026-09-16-portable-migration-evidence.md +2 -0
- package/docs/design/2026-09-16-portable-onboarding.md +4 -2
- package/docs/design/2026-09-20-redesign-program-board.md +1 -1
- package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +2 -0
- package/docs/design/2026-09-23-simplified-workspace-model.md +711 -0
- package/docs/design/2026-09-23-workspace-module-contracts.md +460 -0
- package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +65 -0
- package/docs/design/README.md +20 -8
- package/docs/design/operations-contract.md +1 -0
- package/docs/design/package-engine-contract.md +1 -1
- package/docs/design/package-runtime-api.md +1 -1
- package/docs/desktop-cli-api.md +356 -5
- package/docs/desktop-succession.md +12 -6
- package/docs/desktop.md +9 -4
- package/docs/execution-targets.md +16 -4
- package/docs/first-team.md +107 -224
- package/docs/implementation.md +41 -11
- package/docs/integrations.md +50 -47
- package/docs/knowledge-capability-authoring.md +10 -4
- package/docs/knowledge-migration.md +21 -12
- package/docs/knowledge-reference/package-craft.md +11 -3
- package/docs/knowledge.md +60 -18
- package/docs/layers.md +3 -3
- package/docs/migration-from-oas.md +20 -9
- package/docs/oats-local.schema.json +50 -0
- package/docs/oats-membership.schema.json +23 -0
- package/docs/oats-workspace.schema.json +133 -48
- package/docs/official-marketplace.md +9 -6
- package/docs/packages.md +229 -440
- package/docs/rebuild-to-v2.md +347 -0
- package/docs/release-notes/v0.25.0.md +99 -0
- package/docs/release-notes/v0.25.1.md +94 -0
- package/docs/schedules.md +12 -6
- package/docs/soul.schema.json +41 -68
- package/docs/souls-and-instances.md +175 -108
- package/docs/workspace-adoption.md +70 -345
- package/docs/workspaces.md +436 -119
- package/lib/core.mjs +462 -61
- package/lib/instance-resolution.mjs +387 -0
- package/lib/materialize.mjs +580 -0
- package/lib/operator-dispatch.mjs +117 -0
- package/lib/packages.mjs +558 -1269
- package/lib/remote.mjs +718 -0
- package/lib/resolve.mjs +638 -0
- package/lib/schedule.mjs +90 -16
- package/lib/workspace.mjs +654 -0
- package/package.json +1 -1
- package/lib/portable-migration-artifacts.mjs +0 -135
- package/lib/portable-migration-evidence.mjs +0 -305
- package/lib/portable-migration-store.mjs +0 -199
- package/lib/portable-migration.mjs +0 -104
- package/lib/portable-onboarding-acceptance.mjs +0 -66
- package/lib/setup-expert-source.mjs +0 -100
|
@@ -88,6 +88,7 @@ name the provider answered is kept for `oats schedule reconcile`.
|
|
|
88
88
|
|
|
89
89
|
## Mutations
|
|
90
90
|
|
|
91
|
+
*(0.24 only — `oats use` was removed by the workspace model v2; activation is the soul's `capabilities:` + workspace defaults. Kept for history.)*
|
|
91
92
|
`oats use ... --json` answers `{ capability, action: enable|disable|
|
|
92
93
|
layer-none|inherit, target, layer, level, file, settings, before, after
|
|
93
94
|
{..., effective}, remaining?, note?, missingRequires }`. `--inherit`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Package engine contract (capability materialization, lock v2)
|
|
2
2
|
|
|
3
|
-
Status: **FROZEN** for the capability-materialization delivery. This document is
|
|
3
|
+
Status: **SUPERSEDED** by the workspace model v2 ([2026-09-23-workspace-module-contracts.md](2026-09-23-workspace-module-contracts.md) §4–5, [../packages.md](../packages.md)): the installed-capability tier, `oats install`/`restore`/`use`/`trust`, config templates and lock v2 described here were removed; the package tier is now `lib/packages.mjs` (lock v3) + `lib/materialize.mjs`. Kept as history. Original status: **FROZEN** for the capability-materialization delivery. This document is
|
|
4
4
|
the resolver / projection / lock API that the config-and-CLI lane builds
|
|
5
5
|
against. It implements the accepted Decision "Packages materialize capabilities
|
|
6
6
|
while config templates remain explicitly adopted local policy" (2026-07-29) as
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Package-runtime API contract (addendum to the package-engine contract)
|
|
2
2
|
|
|
3
|
-
Status: **FROZEN** for the capability-materialization delivery, as an addendum to
|
|
3
|
+
Status: **SUPERSEDED** with its parent (workspace model v2 — see [2026-09-23-workspace-module-contracts.md](2026-09-23-workspace-module-contracts.md)); kept as history. Original status: **FROZEN** for the capability-materialization delivery, as an addendum to
|
|
4
4
|
[`package-engine-contract.md`](./package-engine-contract.md). It answers the
|
|
5
5
|
maintainer's four clarifications on the M1 freeze (maintainer review of
|
|
6
6
|
1db919b): the public package-runtime boundary, the npm runtime closure,
|
package/docs/desktop-cli-api.md
CHANGED
|
@@ -18,7 +18,7 @@ prints exactly one JSON object on stdout:
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
`version` is the installed package's exact semver (e.g. `0.20.0`).
|
|
21
|
-
Desktop 0.
|
|
21
|
+
Desktop 0.25 accepts `desktopApi === 1` and semver `>=0.22.0 <0.26.0`
|
|
22
22
|
(the earlier Desktop 0.23 band was `>=0.22.0 <0.24.0`). This admits the paired
|
|
23
23
|
0.24 CLI without changing Desktop API v1. It does not establish complete captured
|
|
24
24
|
UI, backend, plugin, retirement or recovery parity; capability checks and explicit
|
|
@@ -58,8 +58,10 @@ infers a field that is not there:
|
|
|
58
58
|
since 0.24.8: `{spawn: boolean}`, see readiness policy).
|
|
59
59
|
- `provenance: { kind, source, revision, path, workspaceRevision } | null` —
|
|
60
60
|
where this soul copy came from, as recorded by the kernel when it created
|
|
61
|
-
it (
|
|
62
|
-
`exported-edition-copy
|
|
61
|
+
it (the 0.24 bootstrap recorded `packaged-definition` or
|
|
62
|
+
`exported-edition-copy`; the 0.25 `oats onboard` creates no soul and records
|
|
63
|
+
nothing here — see [`oats onboard`](#oats-onboard-onboardapi-2)).
|
|
64
|
+
Souls created before 0.24.7 or authored by hand
|
|
63
65
|
read `null`; render that as *unrecorded*, not as local or as anything else.
|
|
64
66
|
- `readiness` — the soul's **declared sources**, joined against
|
|
65
67
|
`result.capabilities[]` from the same payload. Distinct from launchability
|
|
@@ -448,6 +450,26 @@ the pre-fix marker and is never accepted for dispatch.
|
|
|
448
450
|
|
|
449
451
|
## Readiness quartet, signatures, enforced policy (`oats readiness`, `readinessApi: 1`, OATS 0.24.8+)
|
|
450
452
|
|
|
453
|
+
> **0.25 status — the producers below are the 0.24 tier.** The readiness DTO
|
|
454
|
+
> (`readinessApi: 1`) still ships unchanged, but its four checks are *produced*
|
|
455
|
+
> by the classic observers: `installed` by `oats list` over the
|
|
456
|
+
> `.agents/capabilities/installed/` tier, `trusted` by the per-artifact approval
|
|
457
|
+
> that `oats trust` wrote, `configured` by `oats-config.yaml` activation, and
|
|
458
|
+
> `enrolled` by the `oats.yaml` backlink. On a **workspace deployment**
|
|
459
|
+
> (`oats-local.yaml` present) none of those sources exists: nothing is installed,
|
|
460
|
+
> approval is per package version in `oats-lock.json` v3 (`oats sync`), activation
|
|
461
|
+
> is derived (workspace defaults ⊕ soul `capabilities:`), and membership is
|
|
462
|
+
> `oats-membership.yaml` observed over the remotes. `oats list` and `oats trust`
|
|
463
|
+
> are removed verbs (`E_UNKNOWN_COMMAND`), so a `remedy` naming them cannot be
|
|
464
|
+
> run. Treat the field names and producer strings as the stable wire shape they
|
|
465
|
+
> are; for the workspace-model facts read `oats spawn <soul> --preview --json`
|
|
466
|
+
> (`modules[]` with from/commit/digest — the "installed" and "configured"
|
|
467
|
+
> truth), `oats sync --json` `approvalNeeded[]` (the "trusted" truth) and
|
|
468
|
+
> `oats workspace status --json` (the "enrolled" truth). Re-basing the quartet on
|
|
469
|
+
> those producers is an open thread of [the workspace model](#workspace-model-workspaceapi-2);
|
|
470
|
+
> when it lands it will be announced as a new feature name, not a silent change of
|
|
471
|
+
> `readinessApi: 1`.
|
|
472
|
+
|
|
451
473
|
`oats readiness [--soul <name>] [--home <abs>] [--verify-signatures] [--policy] [--dir <d>] --json`
|
|
452
474
|
is the first-run readiness view (frame 09) and the Capabilities readiness rows
|
|
453
475
|
(frame 04). Every fact is derived from the **same** data `oats inspect` reports
|
|
@@ -483,6 +505,9 @@ is the first-run readiness view (frame 09) and the Capabilities readiness rows
|
|
|
483
505
|
deployment (no `workspace:` in `oats.yaml`), `unknown` until admission is
|
|
484
506
|
verified against the workspace observation, `pass`/`fail` when it is. Never
|
|
485
507
|
login, never team registration; "Skip" leaves it not-applicable, never pass.
|
|
508
|
+
*(The readiness producer still reads the 0.24 `oats.yaml` backlink; under the
|
|
509
|
+
workspace model membership is `oats-membership.yaml` observed by
|
|
510
|
+
`oats workspace status` — re-basing this item is an open thread.)*
|
|
486
511
|
- Subject: `--soul <name>` scopes required items to the soul's declared
|
|
487
512
|
requirements; without it, to the scope's active capabilities.
|
|
488
513
|
|
|
@@ -680,14 +705,328 @@ location. The receipt says so:
|
|
|
680
705
|
|
|
681
706
|
### Feature advertisement — gate every new command on the probe
|
|
682
707
|
|
|
683
|
-
`oats version --json` `features` now lists: `
|
|
708
|
+
`oats version --json` `features` now lists: `instance-git`,
|
|
684
709
|
`instance-git-remote`, `souls-declarations`, `lifecycle-plans`,
|
|
685
710
|
`retire-retention`, `readiness`, `spawn-preview`, `instance-events`,
|
|
686
711
|
`schedule-history`, and carries the API integers (`instanceGitApi`, `soulsApi`,
|
|
687
712
|
`lifecycleApi`, `readinessApi`, `spawnPreviewApi`, `eventsApi`,
|
|
688
713
|
`scheduleHistoryApi`). **Gate on these, never on a version string and never by
|
|
689
714
|
optimistic invocation**: an older CLI ignores an unknown `--plan` on `retire`
|
|
690
|
-
and *retires*. Absent feature → the view is unavailable.
|
|
715
|
+
and *retires*. Absent feature → the view is unavailable. (`catalog` was the
|
|
716
|
+
0.24 `oats catalog` verb's flag; the verb is removed under the workspace model
|
|
717
|
+
and the flag is no longer advertised — the official catalog is reached through
|
|
718
|
+
`packages:` + `oats sync`, not a command.)
|
|
719
|
+
|
|
720
|
+
## Workspace model (`workspaceApi: 2`)
|
|
721
|
+
|
|
722
|
+
Features: **`workspace-v2`** (the declaration files, `sync`, `package`,
|
|
723
|
+
`workspace status`, `capabilities`, `souls`; `init`/`use`/`install`/`restore`
|
|
724
|
+
removed), **`instance-modules`** (`instance.json.modules` / `providers` /
|
|
725
|
+
`workspace`; `status --json` module drift; preview `modules[]`),
|
|
726
|
+
**`spawn-provider-payload`** (`oats spawn … --provider <cap> k=v`). The probe
|
|
727
|
+
carries `workspaceApi: 2`. Model: [workspaces.md](workspaces.md).
|
|
728
|
+
|
|
729
|
+
Every command below needs a deployment with `oats-local.yaml` (walked up from
|
|
730
|
+
`--dir`/cwd) — else `E_LOCAL_MISSING { dir, searched[] }` — and reads the
|
|
731
|
+
workspace over Git remotes with the operator's credentials, never prompting
|
|
732
|
+
(`E_REMOTE_UNREADABLE { url, reason: "auth"|"not-found"|"network"|"timeout" }`).
|
|
733
|
+
Every `commit` is a full 40-hex OID; every digest is `sha256-<hex>`; every
|
|
734
|
+
`at`/`observedAt` is ISO-8601 UTC. Repo keys are canonical
|
|
735
|
+
(`github.com/org/repo`; `local/<abs-path>` for file remotes).
|
|
736
|
+
|
|
737
|
+
### Removed verbs answer `E_UNKNOWN_COMMAND` with a replacement
|
|
738
|
+
|
|
739
|
+
`install`, `restore`, `init`, `use`, `trust`, `list`, `catalog`, `remove`,
|
|
740
|
+
`migrate`, `config` — checked before capability dispatch, both modes:
|
|
741
|
+
|
|
742
|
+
```json
|
|
743
|
+
{"schemaVersion":1,"ok":false,"error":{"code":"E_UNKNOWN_COMMAND","message":"unknown command \"install\" — removed by the workspace model v2; use oats sync","details":{"removed":"install","replacement":"oats sync"}}}
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
### oats onboard (onboardApi 2)
|
|
747
|
+
|
|
748
|
+
`oats onboard [<dir>] --workspace <repo ref> [--json]`
|
|
749
|
+
|
|
750
|
+
The **bootstrap** of a deployment (decision 9): realizes a workspace on this
|
|
751
|
+
machine in the taught `<name>-workspace/` layout. It writes
|
|
752
|
+
`<dir>/oats-local.yaml` (`{ schemaVersion: 2, workspace: <ref> }`), creates
|
|
753
|
+
`<dir>/agents/` (the instance homes), then runs exactly the `oats sync` body
|
|
754
|
+
over the directory just written — discover over the remotes, confirm
|
|
755
|
+
membership, resolve `packages:`, approve (TTY) or list what needs approval,
|
|
756
|
+
write `oats-lock.json`. It installs nothing, creates no soul, spawns nothing
|
|
757
|
+
and writes no `oats-config.yaml`; the member clones and the setup-expert spawn
|
|
758
|
+
are printed as next steps. `<dir>` defaults to cwd; `--dir <d>` is the same
|
|
759
|
+
argument (give it once). `--workspace` is required and must be a ref
|
|
760
|
+
`lib/remote.mjs` parses (`E_REPO_REF`) — checked **before** anything is
|
|
761
|
+
written. Captured selectors are refused (`E_BAD_ARGS`).
|
|
762
|
+
|
|
763
|
+
```json
|
|
764
|
+
{"onboardApi":2,
|
|
765
|
+
"local":"/abs/acme-workspace/oats-local.yaml","dir":"/abs/acme-workspace","agents":"/abs/acme-workspace/agents",
|
|
766
|
+
"lock":"/abs/acme-workspace/oats-lock.json",
|
|
767
|
+
"sync":{"syncApi":1,"…":"the full sync report (next section)"},
|
|
768
|
+
"hosting":{"host":"github.com/acme/agents","hostIsMember":true,
|
|
769
|
+
"rule":"If any member is private, host oats-workspace.yaml in a private repo that is not a public member (a dedicated <org>/workspace repo); public contributors then use the standalone case (from: here capabilities + oats.core)."},
|
|
770
|
+
"next":{"clone":[{"key":"github.com/acme/agents","name":"agents","url":"https://github.com/acme/agents.git","dir":"/abs/acme-workspace/agents-repo"},
|
|
771
|
+
{"key":"github.com/acme/platform","name":"platform","url":"https://github.com/acme/platform.git","dir":"/abs/acme-workspace/platform"}],
|
|
772
|
+
"spawn":"oats spawn oats-setup-expert --dir /abs/acme-workspace"}}
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
- `sync` is the `syncApi: 1` report of the first sync (members, packages,
|
|
776
|
+
changes, `approvalNeeded`, `problems`); `lock` is the lock it wrote.
|
|
777
|
+
- **Exit `2` with `ok: true`** when `sync.approvalNeeded` is non-empty (approval
|
|
778
|
+
is interactive-only; tell the operator to run `oats sync --dir <dir>` in a
|
|
779
|
+
terminal). Exit `0` otherwise.
|
|
780
|
+
- `hosting` states decision 26 (the kernel cannot see forge visibility, so it
|
|
781
|
+
reports `hostIsMember` and the rule rather than judging).
|
|
782
|
+
- `next.clone[]` is one row per **confirmed** member (`url` = what the
|
|
783
|
+
workspace's `members:` ref resolves to; `dir` = `<dir>/<name>`, or
|
|
784
|
+
`<dir>/agents-repo` for a member called `agents`, since `agents/` is the
|
|
785
|
+
instance homes). `next.spawn` is the setup-expert spawn command string.
|
|
786
|
+
- Errors (all `E_*`): `E_BAD_ARGS` (usage; missing `--workspace`; dir given
|
|
787
|
+
twice), `E_REPO_REF`, `E_ALREADY_ONBOARDED { local, dir }` — **this**
|
|
788
|
+
directory already has `oats-local.yaml` (an enclosing deployment's file does
|
|
789
|
+
not count; run `oats sync` there instead), `E_ONBOARD_FAILED { dir }`
|
|
790
|
+
(cannot inspect/write the directory; `<dir>` exists and is not a directory).
|
|
791
|
+
Failures while **discovering** — `E_REMOTE_UNREADABLE`, `E_WORKSPACE_SCHEMA`
|
|
792
|
+
(not a workspace host), `E_LOCAL_MISSING`, plus `E_PACKAGE_MISSING` /
|
|
793
|
+
`E_PACKAGE_INTEGRITY` / `E_LOCK_SCHEMA` and the other `sync` errors raised
|
|
794
|
+
before the workspace was read — roll back the files onboarding created and
|
|
795
|
+
carry `details.rolledBack: true` and `details.dir`; a typo'd ref never
|
|
796
|
+
leaves a half-onboarded directory that looks finished. Once the workspace
|
|
797
|
+
has been read, a later failure keeps the files (a lock may exist) and
|
|
798
|
+
carries `details.dir` + `details.local` instead.
|
|
799
|
+
|
|
800
|
+
### `oats sync [--dir <d>] --json` → `syncApi: 1`
|
|
801
|
+
|
|
802
|
+
Discovers, confirms membership, resolves `packages:` to commits, writes
|
|
803
|
+
`oats-lock.json` (lockfileVersion 3), reports. **Exit `2` with `ok: true`** when
|
|
804
|
+
the lock was written but approvals are pending (`approvalNeeded` non-empty);
|
|
805
|
+
approval is interactive-only, so a Desktop must tell the operator to run
|
|
806
|
+
`oats sync` in a terminal. Exit `0` otherwise.
|
|
807
|
+
|
|
808
|
+
```json
|
|
809
|
+
{"syncApi":1,
|
|
810
|
+
"workspace":{"name":"acme","key":"github.com/acme/agents","url":"https://github.com/acme/agents.git","commit":"<oid>","observedAt":"<iso>",
|
|
811
|
+
"local":"/abs/acme-workspace/oats-local.yaml","lock":"/abs/acme-workspace/oats-lock.json"},
|
|
812
|
+
"members":[{"key":"github.com/acme/agents","name":"agents","commit":"<oid>","confirmed":true,"status":"confirmed","detail":null,"team":"global",
|
|
813
|
+
"souls":["release-manager"],"capabilities":["acme-house-style"],"publishes":null},
|
|
814
|
+
{"key":"github.com/acme/tools","name":"tools","commit":"<oid>","confirmed":true,"status":"confirmed","detail":null,"team":"engineering",
|
|
815
|
+
"souls":["tools-expert"],"capabilities":["acme-tools-dev"],"publishes":{"package":"acme.tools","version":"0.4.0"}},
|
|
816
|
+
{"key":"github.com/acme/billing","name":"billing","commit":"<oid>","confirmed":false,"status":"no-backlink","detail":"github.com/acme/billing@… has no oats-membership.yaml","team":null,
|
|
817
|
+
"souls":[],"capabilities":[],"publishes":null}],
|
|
818
|
+
"packages":[{"id":"oats.okf","version":"2.1.3","source":"catalog:oats.okf","commit":"<oid>","integrity":"sha256-…","capabilities":["oats.okf"],
|
|
819
|
+
"approved":{"executables":"sha256-…","at":"<iso>"}},
|
|
820
|
+
{"id":"acme.tools","version":"0.4.0","source":"git:github.com/acme/tools@v0.4.0","commit":"<oid>","integrity":"sha256-…","capabilities":["acme-deploy","acme-lint"],"approved":null}],
|
|
821
|
+
"changes":[{"id":"acme.tools","from":null,"to":"0.4.0","commit":"<oid>","approvalNeeded":true}],
|
|
822
|
+
"approvalNeeded":[{"id":"acme.tools","version":"0.4.0","commit":"<oid>","executables":"sha256-…",
|
|
823
|
+
"targets":["acme-deploy: command apply → bin/acme-deploy.mjs","acme-deploy: hook spawn → bin/acme-deploy.mjs"]}],
|
|
824
|
+
"problems":[]}
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
- `members[].status`: `confirmed` | `not-listed` | `no-backlink` |
|
|
828
|
+
`backlink-elsewhere` | `cannot-read`; `detail` explains an unconfirmed row.
|
|
829
|
+
`publishes` reports a member's `oats-package/` (informational — its
|
|
830
|
+
capabilities are **not** in `capabilities[]`; the non-collapse rule).
|
|
831
|
+
- `changes[]`: `from` = previously locked version or `null`; `to` = `null` when
|
|
832
|
+
the package was dropped from `packages:` and from the lock.
|
|
833
|
+
- `approvalNeeded[].targets` are human-readable lines
|
|
834
|
+
(`<cap>: command|hook <name> → <relpath>`); `executables` is the digest an
|
|
835
|
+
approval would record.
|
|
836
|
+
- `problems[]`: `{ code, path, message, repoKey? }` — per-item discovery
|
|
837
|
+
problems (`E_WORKSPACE_SCHEMA`, `E_TEAM_UNKNOWN`, `E_REMOTE_*`, …). Never an
|
|
838
|
+
abort: an unreadable member directory is a problem of that member.
|
|
839
|
+
- Errors: `E_LOCAL_MISSING`, `E_WORKSPACE_SCHEMA { path, problems[] }`,
|
|
840
|
+
`E_REMOTE_UNREADABLE`, `E_LOCK_SCHEMA`, `E_PACKAGE_MISSING` (catalog has no
|
|
841
|
+
such id), `E_PACKAGE_INTEGRITY { why: "branch" | locked/observed }`,
|
|
842
|
+
`E_PACKAGE_UNAPPROVED` (approval digest no longer matches),
|
|
843
|
+
`E_PACKAGE_MANIFEST`, `E_REPO_REF`.
|
|
844
|
+
|
|
845
|
+
### `oats package add <id> <version|git:<repo>@<ref>> | remove <id> [--dir] --json`
|
|
846
|
+
|
|
847
|
+
Edits `packages:` **only** when `oats-workspace.yaml` is tracked by the Git
|
|
848
|
+
checkout walked up from `--dir`; otherwise reports the line to add.
|
|
849
|
+
|
|
850
|
+
```json
|
|
851
|
+
{"action":"add","id":"oats.aweb","value":"v1.11.2","previous":null,"edited":true,"file":"/abs/agents/oats-workspace.yaml"}
|
|
852
|
+
{"action":"add","id":"oats.aweb","value":"v1.11.2","edited":false,"file":null,"line":"packages:\n oats.aweb: v1.11.2","hint":"oats-workspace.yaml is not in this checkout; commit the change in the workspace repo, then `oats sync`"}
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
`remove` → `{ action: "remove", id, value: null, previous: "<old value>", edited: true, file }`
|
|
856
|
+
on the tracked branch. On the untracked branch the shape is
|
|
857
|
+
`{ action: "remove", id, value: null, edited: false, file: null, line: null, hint }`
|
|
858
|
+
— **no `previous`** (nothing was read), `line: null` (there is no line to add
|
|
859
|
+
for a removal). **Both branches** answer `E_PACKAGE_MISSING { id, path? }` when
|
|
860
|
+
`<id>` is not declared in `packages:` — the untracked branch reads the file it
|
|
861
|
+
found to check the declaration even though it does not edit it. `E_USAGE`,
|
|
862
|
+
`E_WORKSPACE_SCHEMA` (bad id/value, or the edit would make the file invalid),
|
|
863
|
+
`E_REPO_REF`. No network.
|
|
864
|
+
|
|
865
|
+
### `oats workspace status [--dir] --json` → `workspaceStatusApi: 1`
|
|
866
|
+
|
|
867
|
+
```json
|
|
868
|
+
{"workspaceStatusApi":1,
|
|
869
|
+
"workspace":{"name":"acme","key":"github.com/acme/agents","url":"…","commit":"<oid>","observedAt":"<iso>","local":"/abs/…/oats-local.yaml","teams":["global","engineering"]},
|
|
870
|
+
"members":[ … same rows as sync … ],
|
|
871
|
+
"packages":[ … same rows as sync (from the lock) … ],
|
|
872
|
+
"declaredPackages":["acme.tools","oats.okf"],
|
|
873
|
+
"unsynced":[],
|
|
874
|
+
"stale":[],
|
|
875
|
+
"approval":{"approved":["oats.okf"],"needed":["acme.tools"]},
|
|
876
|
+
"external":[{"source":"git:github.com/oss-collective/experts@<oid>","soul":"security-reviewer","team":"unassigned"}],
|
|
877
|
+
"problems":[]}
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
`unsynced` = declared in `packages:` but not in the lock (run `sync`);
|
|
881
|
+
`stale` = locked but no longer declared. Read-only: does not write the lock.
|
|
882
|
+
|
|
883
|
+
### `oats capabilities [--dir] --json` → `capabilitiesApi: 1` · `oats souls [--dir] --json` → `soulsApi: 1`
|
|
884
|
+
|
|
885
|
+
Every **non-private** item of every confirmed member, external souls, and
|
|
886
|
+
locked package capabilities, sorted by name then origin. `origin` is the
|
|
887
|
+
human string (`member <key> @ <8-char commit>` | `package <id> v<version>` |
|
|
888
|
+
`external <key> @ <commit>`); `kind` is the machine field. `team` is the label
|
|
889
|
+
or `"unassigned"`.
|
|
890
|
+
|
|
891
|
+
```json
|
|
892
|
+
{"capabilitiesApi":1,"workspace":{"name":"acme","key":"github.com/acme/agents","commit":"<oid>"},
|
|
893
|
+
"capabilities":[
|
|
894
|
+
{"name":"acme-house-style","origin":"member github.com/acme/agents @ 3f2a9c1e","kind":"member","repoKey":"github.com/acme/agents","commit":"<oid>",
|
|
895
|
+
"team":"global","private":false,"path":"capabilities/acme-house-style","layer":null,"version":"0.0.0-workspace"},
|
|
896
|
+
{"name":"oats.okf","origin":"package oats.okf v2.1.3","kind":"package","package":"oats.okf","version":"2.1.3","commit":"<oid>",
|
|
897
|
+
"team":"unassigned","private":false,"approved":true}],
|
|
898
|
+
"problems":[]}
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
```json
|
|
902
|
+
{"soulsApi":1,"workspace":{…},
|
|
903
|
+
"souls":[
|
|
904
|
+
{"name":"release-manager","origin":"member github.com/acme/agents @ 3f2a9c1e","kind":"member","repoKey":"github.com/acme/agents","commit":"<oid>",
|
|
905
|
+
"team":"engineering","private":false,"path":"souls/release-manager","work":"worktree","description":"Cuts, verifies and announces releases."},
|
|
906
|
+
{"name":"security-reviewer","origin":"external github.com/oss-collective/experts @ 9c4e1f2a","kind":"external",…}],
|
|
907
|
+
"problems":[]}
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
Package capabilities of declared-but-unsynced packages are absent until `sync`.
|
|
911
|
+
(`soulsApi: 1` is also the integer of the existing `oats inspect --json`
|
|
912
|
+
declarations block; the two payloads are distinguished by their command.)
|
|
913
|
+
|
|
914
|
+
### `oats spawn <soul> … --preview --json` — additions (Preview API 2 unchanged)
|
|
915
|
+
|
|
916
|
+
On a workspace deployment the preview carries four extra top-level fields, and
|
|
917
|
+
`decision.resolution` binds the resolution revision (so a member that moved
|
|
918
|
+
between preview and apply is `E_DECISION_STALE`):
|
|
919
|
+
|
|
920
|
+
```json
|
|
921
|
+
{"modules":[
|
|
922
|
+
{"name":"acme-release-tooling","from":{"kind":"member","repoKey":"github.com/acme/agents","commit":"<oid>"},"layer":null,"private":false,
|
|
923
|
+
"changedSince":{"instance":"release-manager-v2","was":"<old oid>"}},
|
|
924
|
+
{"name":"oats.okf","from":{"kind":"package","package":"oats.okf","version":"2.1.3","commit":"<oid>","integrity":"sha256-…","repoKey":"github.com/awebai/oats-okf"},
|
|
925
|
+
"layer":"knowledge","private":false,"changedSince":false}],
|
|
926
|
+
"team":"engineering",
|
|
927
|
+
"resolution":"6e3050c0d005879441ab017d",
|
|
928
|
+
"workspace":"github.com/acme/agents",
|
|
929
|
+
"spawnPreviewApi":2,"preview":true,"agent":"release-manager","instance":"release-manager-cut","home":"/abs/…",
|
|
930
|
+
"decision":{"instance":"…","home":"…","branch":"…","base":{…},"effective":{…},"resolution":"6e3050c0d005879441ab017d","revision":"<24 hex>"},
|
|
931
|
+
"…":"every Preview API 2 field as before"}
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
- `modules[].from` is exactly the `from` recorded in `instance.json` on apply.
|
|
935
|
+
- `changedSince`: `null` (no previous instance of this soul), `false`
|
|
936
|
+
(unchanged since the newest previous instance), or
|
|
937
|
+
`{ instance, was }` (`was` = the previous commit, or `null` when the previous
|
|
938
|
+
instance had no such module).
|
|
939
|
+
- `capabilities[]` / `skills[]` keep their Preview-1 meaning; on a workspace
|
|
940
|
+
spawn the authoritative module set is `modules[]` (`capabilities[]` may be
|
|
941
|
+
empty there, since capability rows are filled after materialization).
|
|
942
|
+
- `workspace` is the workspace host's canonical key, `team` the soul's label
|
|
943
|
+
(or `null`), `resolution` the 24-hex revision `decision.resolution` binds.
|
|
944
|
+
- `--provider <cap> <key>=<value>` (repeatable; `a.b=c` nests) is accepted by
|
|
945
|
+
preview and apply. `E_BAD_ARGS` for a malformed pair or when the deployment
|
|
946
|
+
has no `oats-local.yaml`; `E_CAPABILITY_MISSING { capability, soul, modules[] }`
|
|
947
|
+
when the soul does not resolve that capability. `byTeam` is a **reserved
|
|
948
|
+
key**: legal only at the top level of the workspace file's `messaging:`;
|
|
949
|
+
anywhere else in any payload layer (soul, `oats-local.yaml` `settings`,
|
|
950
|
+
`--provider`, at any depth) it is `E_WORKSPACE_SCHEMA { reason: "reserved-key", path, key }`.
|
|
951
|
+
- Soul lookup: `E_SOUL_UNKNOWN { name, members[] }` (not among confirmed
|
|
952
|
+
members or externals), `E_SOUL_AMBIGUOUS { name, repos[] }` (name it
|
|
953
|
+
`<repo>/<soul>`). Resolution errors keep their codes (`E_NOT_A_MEMBER`,
|
|
954
|
+
`E_MEMBERSHIP_UNCONFIRMED { repoKey, reason }`, `E_CAPABILITY_MISSING { hint? }`,
|
|
955
|
+
`E_CAPABILITY_PRIVATE`, `E_PACKAGE_MISSING`, `E_PACKAGE_UNAPPROVED { id, version, commit }`,
|
|
956
|
+
`E_SLOT_CONFLICT { slot, modules[], reason? }`, `E_SKILL_DUPLICATE { name, modules[] }`,
|
|
957
|
+
`E_COMPATIBILITY { capability, package, version, range, why? }`).
|
|
958
|
+
|
|
959
|
+
The apply result (`oats spawn … --json`) is unchanged in shape; the new facts
|
|
960
|
+
live in the home's `instance.json`.
|
|
961
|
+
|
|
962
|
+
### `instance.json` — `modules`, `providers`, `workspace` (feature `instance-modules`)
|
|
963
|
+
|
|
964
|
+
Written by materialization inside the spawn transaction; read back by
|
|
965
|
+
`oats status --json` and the roster.
|
|
966
|
+
|
|
967
|
+
```json
|
|
968
|
+
{"modules":{
|
|
969
|
+
"acme-release-tooling":{"from":{"kind":"member","repoKey":"github.com/acme/agents","commit":"<oid>"},
|
|
970
|
+
"commit":"<oid>","digest":"sha256-…","materializedAt":"<iso>"},
|
|
971
|
+
"oats.okf":{"from":{"kind":"package","package":"oats.okf","version":"2.1.3","commit":"<oid>","integrity":"sha256-…","repoKey":"github.com/awebai/oats-okf"},
|
|
972
|
+
"commit":"<oid>","digest":"sha256-…","materializedAt":"<iso>"}},
|
|
973
|
+
"providers":{"acme-release-tooling":{},"oats.okf":{"owns":"release-manager","reads":["platform-engineer"],"state-dir":"/Users/ana/.oats/okf"}},
|
|
974
|
+
"workspace":{"key":"github.com/acme/agents","commit":"<oid>","resolution":"<24 hex>","standalone":false,
|
|
975
|
+
"soul":{"repoKey":"github.com/acme/agents","commit":"<oid>","team":"engineering"}},
|
|
976
|
+
"capabilities":[{"id":"oats.okf","capability":"oats.okf","origin":"package:oats.okf@2.1.3","…":"one row per module"}]}
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
`workspace.standalone` is `true` when the instance was spawned from the
|
|
980
|
+
**standalone view** (decisions 10/25: a *member* whose workspace could not be
|
|
981
|
+
read — `workspace.key` is then the member repo's key, and `modules` holds the
|
|
982
|
+
soul's `from: here` capabilities plus `oats.core`); `false` for a workspace
|
|
983
|
+
spawn. The same view is marked `standalone: true` in `oats sync --json` (with
|
|
984
|
+
`workspace.name` = `standalone:<repo>`) and in the roster. `capabilities[]` is
|
|
985
|
+
the per-module row set (`toCapabilityRows`) that `oats inspect`/`status` read.
|
|
986
|
+
|
|
987
|
+
`digest` is the sha256 of the copied module tree (`<home>/.oats/modules/<cap>/`);
|
|
988
|
+
`providers.<cap>` is the merged payload (soul ⊕ `oats-local.yaml`
|
|
989
|
+
`settings.<cap>` ⊕ `--provider`), `{}` for a capability with none. Copies live at
|
|
990
|
+
`<home>/.oats/modules/<cap>/` and `<home>/.agents/skills/<cap>/<skill>/`.
|
|
991
|
+
|
|
992
|
+
### `oats status [--dir] --json` — module drift
|
|
993
|
+
|
|
994
|
+
On a workspace deployment the roster does one discovery and rewrites each
|
|
995
|
+
instance's `modules` from the recorded map into **drift rows**, and adds a
|
|
996
|
+
top-level `workspace` reachability field:
|
|
997
|
+
|
|
998
|
+
```json
|
|
999
|
+
{"root":"/abs/acme-workspace/agents",
|
|
1000
|
+
"agents":[{"name":"release-manager",…,"instances":[{"instance":"release-manager-cut",…,
|
|
1001
|
+
"modules":[
|
|
1002
|
+
{"name":"acme-release-tooling","from":{"kind":"member","repoKey":"github.com/acme/agents","commit":"<oid>"},"commit":"<oid>",
|
|
1003
|
+
"current":{"commit":"<new oid>"},"status":"moved"},
|
|
1004
|
+
{"name":"acme-house-style","from":{…},"commit":"<oid>","current":{"commit":"<oid>"},"status":"missing","reason":"capability-absent"},
|
|
1005
|
+
{"name":"oats.okf","from":{"kind":"package",…},"commit":"<oid>","current":{"commit":"<oid>","version":"2.1.3"},"status":"current"}]}]}],
|
|
1006
|
+
"workspace":{"reachable":true}}
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
- `status`: `current` | `moved` (member or locked package now at another
|
|
1010
|
+
commit) | `missing` with `reason`: `capability-absent` (gone from the member /
|
|
1011
|
+
package), `package-absent` (no longer locked), or the member's unconfirmed
|
|
1012
|
+
reason (`no-backlink`, `cannot-read`, `unconfirmed`, …; `current: null`).
|
|
1013
|
+
- Package modules without a lock are reported `current`.
|
|
1014
|
+
- Offline: `"workspace":{"reachable":false,"code":"E_REMOTE_UNREADABLE","reason":"E_REMOTE_UNREADABLE: network","message":"…"}`
|
|
1015
|
+
and `modules` stays the recorded map (no drift rows). A deployment without
|
|
1016
|
+
`oats-local.yaml` has no `workspace` field and `modules` as recorded.
|
|
1017
|
+
- Text mode prints `modules: <cap> from <member|package …> @ <7-char>` lines
|
|
1018
|
+
for non-current modules (`--verbose` for all).
|
|
1019
|
+
|
|
1020
|
+
### Probe
|
|
1021
|
+
|
|
1022
|
+
```json
|
|
1023
|
+
{"…":"…","features":["…","workspace-v2","instance-modules","spawn-provider-payload"],"workspaceApi":2}
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
A feature is listed only once the binary implements it. Gate `sync`/`package`/
|
|
1027
|
+
`workspace status`/`capabilities`/`souls` on `workspace-v2`; gate reading
|
|
1028
|
+
`instance.json.modules` and preview `modules[]` on `instance-modules`; gate
|
|
1029
|
+
`--provider` on `spawn-provider-payload`.
|
|
691
1030
|
|
|
692
1031
|
## Instruction refresh (`oats session recompose`, feature `session-recompose`, OATS 0.24.8+)
|
|
693
1032
|
|
|
@@ -707,6 +1046,18 @@ refreshes the home in place:
|
|
|
707
1046
|
schedule; the receipt's `note` says so. Refuses a retiring home
|
|
708
1047
|
(`E_INSTANCE_RETIRING`), captured incarnations and capability-defined souls
|
|
709
1048
|
(`E_UNSUPPORTED_MODE`: those are refreshed by a new resolution / package).
|
|
1049
|
+
- **Module homes (0.25+) are `E_UNSUPPORTED_MODE` too.** A home whose
|
|
1050
|
+
`instance.json` carries `modules{}` (spawned on a workspace deployment,
|
|
1051
|
+
`instance-modules`) answers `E_UNSUPPORTED_MODE` ("recompose from
|
|
1052
|
+
materialized modules is not supported yet; re-spawn"): its `AGENTS.md` was
|
|
1053
|
+
composed from the soul at a recorded member commit plus the materialized
|
|
1054
|
+
modules' injects, and the instance never changes under itself (decision 7).
|
|
1055
|
+
The refresh path for such a home is a new spawn (the soul is re-fetched at
|
|
1056
|
+
the member's current commit). `session-recompose` **stays advertised** in
|
|
1057
|
+
`features[]` because the verb still works for classic homes; gate the UI
|
|
1058
|
+
action on the feature AND on the absence of `instance.json.modules`
|
|
1059
|
+
(`oats status --json` `instances[].modules` is non-empty for a module home),
|
|
1060
|
+
and render the typed refusal otherwise.
|
|
710
1061
|
- Gate on `features.includes("session-recompose")`. It is an **operator
|
|
711
1062
|
action** (the human or the instance's parent), never something a Desktop
|
|
712
1063
|
poll or an agent runs on itself.
|
|
@@ -12,10 +12,17 @@ the OATS Desktop app (`packages/desktop/` in the framework repo):
|
|
|
12
12
|
|
|
13
13
|
## Migrating a deployment that used `oats.web`
|
|
14
14
|
|
|
15
|
+
Under the **0.25 workspace model** there is nothing to uninstall: remove
|
|
16
|
+
`oats.web` from `oats-workspace.yaml` `packages:` / `defaults.capabilities`
|
|
17
|
+
and from any `soul.yaml` `capabilities:`, run `oats sync` (the lock v3 entry
|
|
18
|
+
disappears with the declaration), and use the Desktop app (step 3 below).
|
|
19
|
+
|
|
20
|
+
For a **0.24 classic** deployment:
|
|
21
|
+
|
|
15
22
|
1. Remove the `oats.web` entry from `capabilities.additive` in every
|
|
16
23
|
`oats-config.yaml` in your config chain.
|
|
17
|
-
2. Remove the `oats.web` entry from `oats-lock.json` at the same scope(s),
|
|
18
|
-
delete any stale installed copy under `.agents/capabilities/installed/`.
|
|
24
|
+
2. Remove the `oats.web` entry from `oats-lock.json` (v2) at the same scope(s),
|
|
25
|
+
and delete any stale installed copy under `.agents/capabilities/installed/`.
|
|
19
26
|
3. Use the OATS Desktop app instead: `cd packages/desktop && npm install &&
|
|
20
27
|
npm run rebuild && npm start` (see `packages/desktop/README.md`).
|
|
21
28
|
|
|
@@ -23,10 +30,9 @@ The CLI diagnoses stale references instead of failing opaquely:
|
|
|
23
30
|
|
|
24
31
|
- `oats doctor` warns when an `oats-lock.json` still pins `oats.web`, with the
|
|
25
32
|
fix spelled out.
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
message naming the successor and the exact cleanup steps.
|
|
33
|
+
- A soul or workspace default naming `oats.web` fails at resolution with a
|
|
34
|
+
message naming the successor and the exact cleanup steps (remove it from
|
|
35
|
+
`packages:` / the soul's `capabilities:`).
|
|
30
36
|
|
|
31
37
|
## Migrating `oats pane` usage
|
|
32
38
|
|
package/docs/desktop.md
CHANGED
|
@@ -84,10 +84,15 @@ The probe/mutation contract is specified in
|
|
|
84
84
|
|
|
85
85
|
The app starts on the directory it was launched with (its own folder by
|
|
86
86
|
default). To view a deployment, open the workspace switcher in the sidebar
|
|
87
|
-
and choose **Add workspace → Browse**, then point it at an OATS
|
|
88
|
-
a directory containing `agents
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
and choose **Add workspace → Browse**, then point it at an OATS deployment —
|
|
88
|
+
a directory containing `agents/` (under the 0.25 workspace model that is the
|
|
89
|
+
`<name>-workspace/` directory holding `oats-local.yaml` and `agents/`;
|
|
90
|
+
under 0.24, an `agents/` root, a `local-agents/` root for machine-local souls,
|
|
91
|
+
or a team scope whose `oats-config.yaml` declares `team:`). *The Desktop's own
|
|
92
|
+
multi-repo roster ("team scopes show every member repo's agents under one
|
|
93
|
+
roster") still keys on the 0.24 `oats-config.yaml` `team:` declaration; reading
|
|
94
|
+
the member set from `oats-local.yaml` / `oats workspace status` is the Phase F
|
|
95
|
+
follow-up named in the [0.25.0 notes](release-notes/v0.25.0.md#desktop).*
|
|
91
96
|
Added workspaces are remembered and offered as suggestions next time.
|
|
92
97
|
|
|
93
98
|
Local souls (uncommitted, machine-local agents under `local-agents/`) are
|
|
@@ -231,10 +231,22 @@ and needs equivalent registration glue when switched to session delivery.
|
|
|
231
231
|
|
|
232
232
|
## Shared permission setting
|
|
233
233
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
the
|
|
234
|
+
The opt-in is per launch or per soul: `oats spawn --yolo` / `--no-yolo`
|
|
235
|
+
(`oats create` accepts the same flags), an optional `yolo` in `soul.yaml`
|
|
236
|
+
(0.24 schema; the v2 `soul.yaml` schema does not carry it — use the spawn flag
|
|
237
|
+
or a launch configuration), and the Desktop's per-launch choice. With no
|
|
238
|
+
setting, native policy is retained.
|
|
239
|
+
|
|
240
|
+
*0.24 classic deployments* may also set `yolo: true` in an `oats-config.yaml`
|
|
241
|
+
to apply it to that scope; the closest scope wins, soul overrides scope, the
|
|
242
|
+
spawn flag overrides both. *Under the workspace model* `oats-config.yaml` is
|
|
243
|
+
not configuration ([configuration.md](configuration.md)); the kernel's
|
|
244
|
+
`composeInstance` still consults the classic chain for the machine-level knobs
|
|
245
|
+
`yolo` and `launch-configs` when such a file happens to sit above the
|
|
246
|
+
deployment, but nothing writes one and the rebuild guide tells you to delete
|
|
247
|
+
it — treat a scope-level `yolo` as a 0.24 feature and prefer the explicit
|
|
248
|
+
spawn flag.
|
|
249
|
+
|
|
238
250
|
Autonomous or unattended execution is not permission to synthesize `yolo: true`.
|
|
239
251
|
Explicit user CLI/UI input or a user-selected configuration is the opt-in; explicit
|
|
240
252
|
`false` remains false.
|