@awebai/oats 0.25.7 → 0.25.8
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 +6 -6
- package/docs/design/2026-09-20-redesign-program-board.md +1 -1
- package/docs/design/2026-09-24-desktop-phase-f-boundary.md +16 -0
- package/docs/design/2026-09-24-phase-d-plan.md +57 -6
- package/docs/desktop-succession.md +4 -4
- package/docs/release-notes/v0.25.8.md +48 -0
- package/injects/instance-boundary.md +10 -12
- package/injects/oats.md +4 -4
- package/lib/core.mjs +35 -3
- package/package.json +1 -3
- package/souls/oats-setup-expert/AGENTS.md +0 -60
- package/souls/oats-setup-expert/soul.yaml +0 -14
package/bin/oats.mjs
CHANGED
|
@@ -2938,7 +2938,7 @@ async function paneCmd() {
|
|
|
2938
2938
|
* remotes, confirm membership, resolve `packages:`, approve (TTY) or list what
|
|
2939
2939
|
* needs approval (exit 2), write `oats-lock.json`. Nothing is installed, no soul
|
|
2940
2940
|
* is created, nothing is spawned, no `oats-config.yaml` is written: the member
|
|
2941
|
-
* clones and the
|
|
2941
|
+
* clones and the operator expert are the operator's next steps, printed here. */
|
|
2942
2942
|
async function onboardCmd() {
|
|
2943
2943
|
const bail = (code, message, details) => (JSON_MODE ? jsonFail(code, message, details) : die(message));
|
|
2944
2944
|
const usage = "usage: oats onboard [<dir>] --workspace <repo ref> [--json] (or --dir <dir>)";
|
|
@@ -3015,11 +3015,11 @@ async function onboardCmd() {
|
|
|
3015
3015
|
// (4) The taught layout as next steps (design doc §4), and the envelope.
|
|
3016
3016
|
const standalone = synced.discovery.standalone === true;
|
|
3017
3017
|
const members = synced.report.members;
|
|
3018
|
-
// The
|
|
3018
|
+
// The operator expert is suggested only when THIS workspace lists a soul by that name (a
|
|
3019
3019
|
// confirmed member's or, standalone, the repo's own); otherwise any listed soul is spawnable.
|
|
3020
3020
|
const soulNames = synced.items.souls.map((s) => s.name);
|
|
3021
|
-
const setupExpert = soulNames.includes("oats-
|
|
3022
|
-
const spawnHint = setupExpert ? `oats spawn oats-
|
|
3021
|
+
const setupExpert = soulNames.includes("oats-operator-expert");
|
|
3022
|
+
const spawnHint = setupExpert ? `oats spawn oats-operator-expert --dir ${shortPath(dir)}` : null;
|
|
3023
3023
|
const anySoulHint = `spawn any listed soul: oats spawn <soul> --dir ${shortPath(dir)}${soulNames.length ? ` (e.g. ${soulNames.slice(0, 3).join(", ")})` : ""}`;
|
|
3024
3024
|
// A member's clone goes beside oats-local.yaml under its repo name; `agents/` is the instance
|
|
3025
3025
|
// homes, so a member called "agents" is cloned as `agents-repo/` (design doc §4). The HOST is
|
|
@@ -3060,7 +3060,7 @@ Next:
|
|
|
3060
3060
|
2. Check who may read the host: ${synced.discovery.key}${hostIsMember ? " is itself a member" : " is a dedicated host"}. The workspace file
|
|
3061
3061
|
names every member, so if any member is private the host must be a private repo that is not
|
|
3062
3062
|
a public member; public contributors then get the standalone case (from: here + oats.core).
|
|
3063
|
-
3. ${setupExpert ? "Spawn the
|
|
3063
|
+
3. ${setupExpert ? "Spawn the operator expert to guide the rest (souls, teams, provider settings, approvals):" : "No soul named oats-operator-expert is listed here —"}
|
|
3064
3064
|
${spawnHint ?? anySoulHint}${synced.approvalNeeded.length ? `\n (first: \`oats sync --dir ${shortPath(dir)}\` in a terminal to approve ${synced.approvalNeeded.map((a) => `${a.id} ${a.version}`).join(", ")})` : ""}`);
|
|
3065
3065
|
process.exitCode = synced.approvalNeeded.length ? 2 : 0;
|
|
3066
3066
|
}
|
|
@@ -3911,7 +3911,7 @@ Usage:
|
|
|
3911
3911
|
[--json] and agents/, then runs the oats sync path (lock v3;
|
|
3912
3912
|
exit 2 while approvals are pending) and prints the
|
|
3913
3913
|
next steps (clone members you work IN, spawn
|
|
3914
|
-
oats-
|
|
3914
|
+
oats-operator-expert); creates no soul, spawns nothing
|
|
3915
3915
|
oats create <name> [--local] [--no-oats-core] create an agent soul; --local = full
|
|
3916
3916
|
[--description <d>] [--repo <r>] soul under local-agents/ (uncommitted,
|
|
3917
3917
|
[--work <mode>] [--runtime pi|claude|codex] gitignored; same memory + lifecycle)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Purpose:** the one accurate view of every work stream in the redesign, what is on main, what is in flight, who owns it, and what blocks it. Lead: `oats-expert` (redesign lead). Updated whenever anything merges, is returned, or reality changes. Older per-lane boards are superseded by this file.
|
|
4
4
|
|
|
5
|
-
**Last update:** 2026-09-24
|
|
5
|
+
**Last update:** 2026-09-24 14:10Z · **0.25.0–0.25.7 PUBLISHED** (0.25.7 = v2 deployment root is a configuration boundary) (0.25.6 = decision 27 kernel half + Desktop 10B-0 terminal owner leases, native gate 23/23) (workspace model A–C; team-review fixes; operator-rebuild round; OATS_SOUL_ID; quarantine-retry fix; launch meta + catalog pins) · **OKF v2.1.4 + oats.aweb v1.12.0 TAGGED and pinned** · **decision 27 accepted; K1′/K1″/K2 kernel PR next** · **oats.aweb 1.13.0 (#110) queued** · **Desktop 10B-0 resumed** · Phase D plan next · **Desktop engineer paused by the human** (10B-0 uncommitted foundation preserved; resume is the human's call; 0.24.14 to be cut from a maintenance branch off `e5cdaf95` when its PR lands) · parity pipeline ⏸.
|
|
6
6
|
|
|
7
7
|
Legend: ✅ on main/published · 🔄 in flight (PR/branch) · 🟡 preserved, not adopted · ⬜ not started · ⛔ blocked
|
|
8
8
|
|
|
@@ -81,6 +81,22 @@ identity.mode=… identity.resident=…` (decision 27 — there is no kernel fla
|
|
|
81
81
|
`SPAWN_ARG_RULES` gains one `provider` rule (capability id, dotted key, value
|
|
82
82
|
grammar); no identity-named rules. Work mode select includes `workspace`.
|
|
83
83
|
|
|
84
|
+
**F3 amended by the human (2026-09-24). This supersedes design frame 02 and the
|
|
85
|
+
text above wherever they differ.** The dialog leads with the **instance name**:
|
|
86
|
+
the purpose field becomes a name field that shows `<soul>-<purpose>` live and
|
|
87
|
+
then the kernel's final name from the preview. A no-prefix toggle maps to
|
|
88
|
+
`spawn --name <slug>`, gated on the `spawn-name` feature; `--purpose` stays the
|
|
89
|
+
default. **Runtime and model** are always visible, with their resolved value and
|
|
90
|
+
its source. **Work** comes from the soul's `work:` mode, and a `checkout` soul is
|
|
91
|
+
offered "Use a worktree instead?" (`--work worktree`). There is **no**
|
|
92
|
+
modules/capabilities list and no attach-knowledge / child-spawn / open-PR
|
|
93
|
+
toggles, because those behaviours come from capabilities. There is **no**
|
|
94
|
+
preview button either. The preview runs in the background to fill the real
|
|
95
|
+
defaults, and apply still binds with `--expect-decision` (`E_DECISION_STALE`
|
|
96
|
+
re-previews). A collapsed **Advanced** section holds harness permissions, launch
|
|
97
|
+
config, relation, messaging identity (`--provider <cap> identity.mode=…`,
|
|
98
|
+
decision 27), branch/base overrides and the execution server. Every modal gets a darker backdrop.
|
|
99
|
+
|
|
84
100
|
**F4 — Instance card and roster on v2 facts.** The served-identity line (`acts
|
|
85
101
|
as <address> via grant, expires <t>` / `alias <a> on <team>`); module rows with
|
|
86
102
|
"moved since" markers and a **re-spawn** action (preview → apply, then retire
|
|
@@ -22,7 +22,7 @@ pushes. Agreed by both on 2026-09-24:
|
|
|
22
22
|
| oats.aweb 1.13.0 re-land end to end | Antares | assigned |
|
|
23
23
|
| D1 operator node + integrations node | Antares | assigned (draft PR `d1/operator-node` handed over) |
|
|
24
24
|
| aweb and okf package-expert seams | Antares | assigned |
|
|
25
|
-
| D2, D3, D4, desktop + kernel bundle migrations (D1 remainder) |
|
|
25
|
+
| D2, D3, D4, desktop + kernel bundle migrations (D1 remainder) | lead, driven by the child instance `oats-expert-phase-d` | assigned (human, 2026-09-24: picked up by the lead's side after all, so as not to wait on the other deployment's human). The lead reviews and merges; Class B items go to Antares for ACK; D3's aweb/okf seams are drafted by the driver and settled with Antares. **Antares is a REQUIRED cross-reviewer** on D4's `oats.setup` rewrite (it must not drift from the operator node) and on D3's `aweb-expert` and `okf-expert` souls (the seams); the rest of the driver's PRs it reads without gating. |
|
|
26
26
|
|
|
27
27
|
**Push protocol.**
|
|
28
28
|
- **Class A** — notify after, one line: stewardship, docs and knowledge inside
|
|
@@ -118,14 +118,44 @@ for, never named by convention — decision 9) is the acceptance: `oats onboard`
|
|
|
118
118
|
|
|
119
119
|
### D3 — Souls to `souls/<name>` and the six package-expert souls (decision 20)
|
|
120
120
|
|
|
121
|
-
Each package repo carries `souls
|
|
122
|
-
|
|
123
|
-
package, with a node in the central base
|
|
124
|
-
|
|
121
|
+
Each package repo carries `souls/oats-<pkg>-expert` (oats-okf-expert,
|
|
122
|
+
oats-aweb-expert, oats-jira-expert, oats-linear-expert, oats-authoring-expert,
|
|
123
|
+
oats-dev-expert), the expert in that package, with a node in the central base
|
|
124
|
+
from day one. **Messaging (human, 2026-09-24; supersedes the lead's per-soul rule):**
|
|
125
|
+
`oats.aweb` is the workspace's messaging **default**
|
|
126
|
+
(`defaults.messaging: { oats.aweb: { from: package } }`, oats#140); a soul
|
|
127
|
+
without messaging says `messaging: none`. The human calls it "the most
|
|
128
|
+
important capability, and most workspaces will use it as default", so the
|
|
129
|
+
provider must work well as a default. Open items (oats.aweb unless noted):
|
|
130
|
+
an unconfigured default must not make every soul unspawnable (onboarding sets
|
|
131
|
+
the messaging root before the first spawn, and/or an unconfigured provider
|
|
132
|
+
reports what is missing instead of refusing); error texts and `setup` must stop
|
|
133
|
+
pointing at `oats-config.yaml`; the deployment names its messaging root
|
|
134
|
+
explicitly rather than by search; `aw mail` usable from `work/`; retired aliases
|
|
135
|
+
reusable. Kernel (lead): in v2 the team scope is the deployment directory and
|
|
136
|
+
the team id comes from the messaging payload, not the classic `team:` block.
|
|
137
|
+
#140 merges together with the first answer to the unspawnable-default item.
|
|
138
|
+
**Teams (human, 2026-09-24): seamless by default.** (R1) Every person gets a
|
|
139
|
+
**personal team per workspace**, created on first use with no invite and no
|
|
140
|
+
manual initialisation — two people, or one person on two workspaces, get
|
|
141
|
+
separate teams; stable across one person's machines. (R2) When a soul whose
|
|
142
|
+
`team:` label the workspace maps to a shared team (`messaging.byTeam.<label>.team`)
|
|
143
|
+
is spawned, the instance **joins that team seamlessly**. Authorization for R2
|
|
144
|
+
(what entitles a person to join without an invite) is oats.aweb's design call
|
|
145
|
+
with the aweb project, fail-closed and visible when the entitlement is missing.
|
|
146
|
+
Kernel (lead): pass the soul's team label and the workspace identity so the
|
|
147
|
+
provider derives the personal team deterministically; an unmapped team means
|
|
148
|
+
"personal". The onboarding skill's manual invite-then-join step is the 1.12.0
|
|
149
|
+
path and is rewritten when the provider ships R1/R2.
|
|
150
|
+
**Naming (lead, 2026-09-24):** the `oats-` prefix on all six —
|
|
151
|
+
it matches the repository names and the roster's `oats-kernel-`/`oats-desktop-`/
|
|
152
|
+
`oats-operator-expert`, and it keeps instance aliases from colliding with the
|
|
153
|
+
messaging project's own `aweb-expert` soul on a shared team. **Seams named in the
|
|
154
|
+
charters** (roster amendment): `oats-aweb-expert` READS
|
|
125
155
|
`aweb-protocol-expert` in base `aweb-oss-knowledge` (repo
|
|
126
156
|
`github.com/awebai/aweb`, root `knowledge/`, branch `main`, OKF 2.1.x
|
|
127
157
|
descriptor at `knowledge/okf-base.json`; owner `1913b77b-…`) through a
|
|
128
|
-
read-only store reference; `okf-expert` names its seam to the knowledge-theory
|
|
158
|
+
read-only store reference; `oats-okf-expert` names its seam to the knowledge-theory
|
|
129
159
|
material in `oats-expert`. Whether the aweb bookshelf decisions the program
|
|
130
160
|
rests on are published into that node is the aweb side's call (asked).
|
|
131
161
|
|
|
@@ -140,6 +170,27 @@ rule, the rebuild guide as procedure with the operator node as rationale.
|
|
|
140
170
|
Developer souls in `oats.dev` gain `promotesTo: <node>` (roster amendment);
|
|
141
171
|
the harvester delivers to that node as a PR the owning expert reviews.
|
|
142
172
|
|
|
173
|
+
**D4 also removes the legacy the v2 model already declared gone** (human,
|
|
174
|
+
2026-09-24; boundary §3b's native-rework rule applied to the repository):
|
|
175
|
+
- **Docs, skills, examples** (driver, in D4): delete what v2 removed rather than
|
|
176
|
+
rewriting it (e.g. the OAS migration guide, the legacy Desktop succession
|
|
177
|
+
doc, `oats-config.yaml` examples, the `oats-config` skill); rewrite what
|
|
178
|
+
survives against `oats-local.yaml` and the workspace file; every remaining
|
|
179
|
+
mention of `oats-config.yaml` either describes its removal or is gone.
|
|
180
|
+
- **Kernel** (lead, one Class B PR after D2 lands, because the OATS workspace
|
|
181
|
+
itself stops reading `oats-config.yaml` only once D2 converts it): the
|
|
182
|
+
`oats-config.yaml` scope chain and its readers, the `local-agents/` and
|
|
183
|
+
`tmp-agents/` layouts, the OAS-scope probes, the installed-capability tier
|
|
184
|
+
remnants. Removed, not flagged; the `REMOVED_VERBS` answers stay.
|
|
185
|
+
- **In-repo package copies** (`capabilities/oats-{okf,aweb,jira,linear,authoring}`)
|
|
186
|
+
are NOT removed in D4: `package.json` ships `capabilities/` as the kernel's
|
|
187
|
+
bundled providers, pinned by the mirror-parity, release-packaging and
|
|
188
|
+
clean-room tests. Whether 0.26.0 still bundles them is a release decision
|
|
189
|
+
for D5 (lead); until then they stay unmarked. `private` becomes a schema key
|
|
190
|
+
(the kernel already reads it); `oats-review` is marked private.
|
|
191
|
+
- **Legacy souls** (`agents/*` and their knowledge bundles) are NOT part of D4:
|
|
192
|
+
they go when the live instances linking them retire (human rule).
|
|
193
|
+
|
|
143
194
|
### D5 — Catalog update and 0.26.0
|
|
144
195
|
|
|
145
196
|
Catalog pins for the new package versions; **widen Desktop `ACCEPT_RANGE` and
|
|
@@ -8,7 +8,7 @@ the OATS Desktop app (`packages/desktop/` in the framework repo):
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| `oats.web` marketplace capability (`oats web start`, browser panel) | OATS Desktop app — the same zero-dependency loopback server is bundled at `packages/desktop/server/` and spawned by the app |
|
|
10
10
|
| `oats pane` CLI command and the Control Pane TUI | OATS Desktop app (Active overview / instance roster) |
|
|
11
|
-
| `@awebai/oats/control-pane` package export (`lib/control-pane/model.mjs`) | The roster model moved into `packages/desktop/
|
|
11
|
+
| `@awebai/oats/control-pane` package export (`lib/control-pane/model.mjs`) | The roster model moved into the Desktop app; under workspace model v2 the app reads the kernel's `oats status --json` instead ([deployment model](../packages/desktop/docs/desktop-deployment-model.md)). It is not a public kernel export |
|
|
12
12
|
|
|
13
13
|
## Migrating a deployment that used `oats.web`
|
|
14
14
|
|
|
@@ -45,9 +45,9 @@ solarized) exist in the app's theme system.
|
|
|
45
45
|
`import ... from "@awebai/oats/control-pane"` no longer resolves. The
|
|
46
46
|
model's pure helpers (`readMarkdownSection`, `parseTmuxWindows`,
|
|
47
47
|
`parseGitStatus`, `parseGitDiffStat`, `buildConstellation`, `relativeAge`)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
no known external consumer existed at removal time.
|
|
48
|
+
moved into the private Desktop app and were retired with its workspace-model v2
|
|
49
|
+
rebuild. If you depended on this export, vendor the helpers from a released tag
|
|
50
|
+
or open an issue — no known external consumer existed at removal time.
|
|
51
51
|
|
|
52
52
|
## Release gating (maintainers)
|
|
53
53
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# OATS 0.25.8
|
|
2
|
+
|
|
3
|
+
## Fixed
|
|
4
|
+
|
|
5
|
+
- **Desktop: quotes are escaped in attribute contexts** (#139). The views share
|
|
6
|
+
one escaper (`escapeHtml`) for element content and attribute values.
|
|
7
|
+
|
|
8
|
+
- **The roster reports an instance where it actually is.** `oats status`
|
|
9
|
+
reports each instance at the directory the kernel enumerated
|
|
10
|
+
(`<soul dir>/instances/<name>`), under that directory's name. An
|
|
11
|
+
`instance.json` whose `home` or `instance` disagrees no longer relocates or
|
|
12
|
+
renames the instance; the disagreeing values appear only as the diagnostics
|
|
13
|
+
`recordedHome` / `recordedInstance`. Before this, a hostile or corrupted
|
|
14
|
+
`instance.json` could make every consumer that acts on `home` (retire,
|
|
15
|
+
`inspect --home`, the Desktop's file roots) target a path outside the
|
|
16
|
+
deployment. Found by the Desktop engineer in Phase F slice F1.
|
|
17
|
+
|
|
18
|
+
## Added
|
|
19
|
+
|
|
20
|
+
- **Team facts for workspace-model hooks** (human decisions 2026-09-24:
|
|
21
|
+
`oats.aweb` is the messaging default; teams are seamless). A workspace
|
|
22
|
+
deployment has no classic `team:` block, so lifecycle hooks of a workspace
|
|
23
|
+
spawn now receive: `OATS_TEAM_SCOPE` = the deployment directory;
|
|
24
|
+
`OATS_TEAM_ID` = the messaging slot's merged payload `team` (workspace base ⊕
|
|
25
|
+
`byTeam[<soul team>]` ⊕ soul ⊕ host ⊕ spawn), **empty when no shared team is
|
|
26
|
+
mapped — meaning "personal"**; and new `OATS_TEAM_LABEL` (the soul's team
|
|
27
|
+
label), `OATS_WORKSPACE_NAME` and `OATS_WORKSPACE_KEY` (canonical repository
|
|
28
|
+
key), so a messaging provider can derive a personal team per person per
|
|
29
|
+
workspace deterministically. Classic deployments are unchanged.
|
|
30
|
+
- **Desktop F2: Capabilities, Sources, sync and approval, onboarding** (#143).
|
|
31
|
+
The Workspace view gains a Capabilities table (Capability | Status | Used
|
|
32
|
+
by, from `oats capabilities --json`, filtered by team and source) and a
|
|
33
|
+
Sources tab. It can run `oats sync` and approve pending packages: the Desktop
|
|
34
|
+
admits an approval only when its (id, version, executables digest) exactly
|
|
35
|
+
match the latest sync report it holds, and refuses a mismatch with
|
|
36
|
+
`E_APPROVAL_STALE`. A picked folder that isn't yet a workspace can be
|
|
37
|
+
onboarded through single-use offers held by the main process. The 0.24
|
|
38
|
+
Deployment inventory and Workspace readiness blocks are removed.
|
|
39
|
+
- **Desktop: design parity with Redesign v3 and brand artwork** (#137, #128).
|
|
40
|
+
The Desktop F1 deployment model on kernel JSON (#126) is included too.
|
|
41
|
+
- **`oats.aweb` is the workspace messaging default** (#140, human decision).
|
|
42
|
+
The onboarding skill makes messaging setup its own step before the first
|
|
43
|
+
spawn (#141).
|
|
44
|
+
- **The onboarding next-step hint names `oats-operator-expert`** (#134).
|
|
45
|
+
- **Phase D:**
|
|
46
|
+
- The OATS repository hosts a workspace-model workspace (D2, #127).
|
|
47
|
+
- `oats-operator-expert` and `integrations-expert` souls, with the experts' instructions on the workspace model (D3, #129).
|
|
48
|
+
- `oats.core` and `oats.setup` rewritten for the workspace model (D4, #133).
|
|
@@ -6,24 +6,22 @@ hook as `$OATS_INSTANCE_HOME`. It is not your user home (`~`), not the repositor
|
|
|
6
6
|
root, and not the work tree. Anything that says "your home" means this directory.
|
|
7
7
|
|
|
8
8
|
- **Your brain and your state live here**: `AGENTS.md` (your composed
|
|
9
|
-
instructions), `
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
instructions), `TASK.md` (this task), `instance.json` (what you were given
|
|
10
|
+
and from where), and whatever working state your role keeps — your knowledge
|
|
11
|
+
layer names those files, if you have one. They belong here, not in the work
|
|
12
|
+
tree.
|
|
13
13
|
- **Run OATS operational/lifecycle commands, and commands from active
|
|
14
14
|
capabilities, from instance home** — `oats status`, `oats doctor`, `oats spawn`,
|
|
15
|
-
|
|
15
|
+
and whatever your own capabilities add; for example, when the
|
|
16
16
|
aweb messaging capability is active, run `aw` there too. They resolve their
|
|
17
17
|
scope from the directory you run them in, so running them from the work tree
|
|
18
18
|
points them at the wrong deployment. To act on a different package or config
|
|
19
19
|
scope deliberately, pass an explicit resolved path: `oats <cmd> --dir <path>`.
|
|
20
|
-
- **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
rest. How your own learnings reach your soul is your knowledge layer's
|
|
26
|
-
business, and its instructions below say so if you have one.
|
|
20
|
+
- **Soul work is repository work.** If your TASK is to change soul content that
|
|
21
|
+
lives in this repository, that is ordinary code work — do it on tracked paths
|
|
22
|
+
under `work/`, reviewed like the rest. How your own learnings reach your soul
|
|
23
|
+
is your knowledge layer's business, and its instructions below say so if you
|
|
24
|
+
have one.
|
|
27
25
|
|
|
28
26
|
**`<instance-home>/work` is your repository or workspace view** — whatever your
|
|
29
27
|
work mode grants you of the code.
|
package/injects/oats.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
## You run on OATS
|
|
2
2
|
|
|
3
3
|
You are an agent instance in the OATS (Open Agent Team Specification) framework.
|
|
4
|
-
You incarnate a durable soul
|
|
5
|
-
|
|
6
|
-
your home layout, the agent roster (`oats status`), spawning
|
|
7
|
-
|
|
4
|
+
You incarnate a durable soul and you work in `./work/`.
|
|
5
|
+
The **oats** skill teaches the essentials —
|
|
6
|
+
your home layout, the agent roster (`oats status`), spawning
|
|
7
|
+
instances (only when instructed), inspecting your configuration
|
|
8
8
|
(`oats doctor`, `./instance.json`), and your lifecycle. **Load the oats skill
|
|
9
9
|
before your first `oats` command of a session** and any time you reason about
|
|
10
10
|
agents, spawning, or the framework itself — do not guess `oats` flags or
|
package/lib/core.mjs
CHANGED
|
@@ -4299,7 +4299,8 @@ export function composeInstanceAgentsMd(soulDir, contextDir, soulName, workMode,
|
|
|
4299
4299
|
resolved.capabilities = Array.isArray(prepared.capabilityRows) && prepared.capabilityRows.length
|
|
4300
4300
|
? prepared.capabilityRows
|
|
4301
4301
|
: plannedCapabilityRows(prepared.resolution);
|
|
4302
|
-
resolved.workspace = { key: prepared.discovery?.key ?? null, commit: prepared.discovery?.commit ?? null, standalone: prepared.discovery?.standalone === true, revision: prepared.resolution.revision, team: prepared.resolution.soul?.team ?? null, slots: prepared.resolution.slots };
|
|
4302
|
+
resolved.workspace = { key: prepared.discovery?.key ?? null, name: prepared.discovery?.workspace?.name ?? null, deployment: prepared.deployment ?? null, commit: prepared.discovery?.commit ?? null, standalone: prepared.discovery?.standalone === true, revision: prepared.resolution.revision, team: prepared.resolution.soul?.team ?? null, slots: prepared.resolution.slots };
|
|
4303
|
+
resolved.payloads = prepared.resolution.payloads ?? {};
|
|
4303
4304
|
resolved.layers = Object.fromEntries(Object.entries(prepared.resolution.slots || {}).map(([slot, mod]) => [slot, mod ? { capability: mod } : null]));
|
|
4304
4305
|
}
|
|
4305
4306
|
const wanted = [];
|
|
@@ -4837,6 +4838,28 @@ export function stableSoulId({ soulId, home, soulDir, agentName } = {}) {
|
|
|
4837
4838
|
}
|
|
4838
4839
|
export const workspaceSoulId = (repoKey, name) => `${repoKey}#${name}`;
|
|
4839
4840
|
|
|
4841
|
+
/** The team facts a lifecycle hook receives. Classic deployment: the config
|
|
4842
|
+
* chain's `team:` block (name, id, the declaring scope). Workspace model: there is
|
|
4843
|
+
* no `team:` block — the team SCOPE is the deployment directory, the team ID is the
|
|
4844
|
+
* messaging slot's merged payload `team` (workspace base ⊕ byTeam[<soul team>] ⊕
|
|
4845
|
+
* soul ⊕ host ⊕ spawn), and the provider also gets the soul's team LABEL and the
|
|
4846
|
+
* workspace's name and canonical key, so it can derive a per-person, per-workspace
|
|
4847
|
+
* personal team when no shared team is mapped (empty OATS_TEAM_ID = "personal").
|
|
4848
|
+
* Human decision 2026-09-24 (messaging default; seamless teams). */
|
|
4849
|
+
export function teamEnv(resolved) {
|
|
4850
|
+
const ws = resolved?.workspace;
|
|
4851
|
+
if (!ws || typeof ws !== "object") {
|
|
4852
|
+
return { OATS_TEAM_NAME: resolved?.team?.name || "", OATS_TEAM_ID: resolved?.team?.id || "", OATS_TEAM_SCOPE: resolved?.team?.scope || "" };
|
|
4853
|
+
}
|
|
4854
|
+
const messaging = ws.slots?.messaging;
|
|
4855
|
+
const payload = messaging ? resolved.payloads?.[messaging] : null;
|
|
4856
|
+
const teamId = payload && typeof payload === "object" && typeof payload.team === "string" ? payload.team : "";
|
|
4857
|
+
return {
|
|
4858
|
+
OATS_TEAM_NAME: "", OATS_TEAM_ID: teamId, OATS_TEAM_SCOPE: ws.deployment || "",
|
|
4859
|
+
OATS_TEAM_LABEL: typeof ws.team === "string" ? ws.team : "",
|
|
4860
|
+
OATS_WORKSPACE_NAME: typeof ws.name === "string" ? ws.name : "", OATS_WORKSPACE_KEY: typeof ws.key === "string" ? ws.key : "",
|
|
4861
|
+
};
|
|
4862
|
+
}
|
|
4840
4863
|
export function runLifecycleHooks(event, { home, instance, agentName, soulDir, soulId, contextDir, workspaceDir, rootDir, resolved, priorMeta = {}, extraEnv = {}, assertRoots }) {
|
|
4841
4864
|
const results = { meta: {}, briefs: [], warnings: [], order: [], launch: {}, env: {}, failures: [], contributions: [] };
|
|
4842
4865
|
const envOwners = new Map();
|
|
@@ -4866,7 +4889,7 @@ export function runLifecycleHooks(event, { home, instance, agentName, soulDir, s
|
|
|
4866
4889
|
OATS_EVENT: event, OATS_INSTANCE: instance, OATS_INSTANCE_HOME: home, OATS_HOME: home, OATS_AGENT: agentName,
|
|
4867
4890
|
OATS_CAPABILITY: cap.id, OATS_LAYER: cap.layer || "", OATS_ROOT: rootDir || "",
|
|
4868
4891
|
OATS_SOUL: soulDir || "", OATS_SOUL_ID: stableSoulId({ soulId, home, soulDir, agentName }), OATS_CONTEXT: contextDir, OATS_WORKSPACE: workspaceDir || "", OATS_LEVEL: cap.level || "",
|
|
4869
|
-
|
|
4892
|
+
...teamEnv(resolved),
|
|
4870
4893
|
...extraEnv,
|
|
4871
4894
|
// Hooks also run through direct core callers (not only bin/oats).
|
|
4872
4895
|
// Author this from the running kernel, never PATH, ambient env or
|
|
@@ -7428,7 +7451,16 @@ export function listInstances(root, tmuxSession = DEFAULT_TMUX_SESSION) {
|
|
|
7428
7451
|
catch (error) { liveness = { running: null, runtimeState: "unreachable", runtimeError: error.message }; }
|
|
7429
7452
|
}
|
|
7430
7453
|
const identity = servedIdentityOf(meta);
|
|
7431
|
-
|
|
7454
|
+
// The home IS the directory enumerated here, and the instance its name:
|
|
7455
|
+
// a file inside it cannot relocate or rename itself in the roster (every
|
|
7456
|
+
// consumer acting on `home` — retire, inspect --home, the Desktop's file
|
|
7457
|
+
// roots — would inherit the claim). A disagreeing claim survives only as
|
|
7458
|
+
// a diagnostic.
|
|
7459
|
+
const claims = {
|
|
7460
|
+
...(meta.home !== undefined && meta.home !== home ? { recordedHome: meta.home } : {}),
|
|
7461
|
+
...(meta.instance !== undefined && meta.instance !== e.name ? { recordedInstance: meta.instance } : {}),
|
|
7462
|
+
};
|
|
7463
|
+
return { ...meta, ...claims, home, instance: e.name, ...(identity ? { identity } : {}), ...(meta.launch && typeof meta.launch === "object" ? { launch: redactLaunchRecipe(meta.launch) } : {}), ...(typeof meta.command === "string" ? { command: redactLaunchCommand(meta.command) } : {}), ...liveness, ...(rollbackIncomplete ? { rollbackIncomplete } : {}), ...(retirePending ? { retirePending } : {}) };
|
|
7432
7464
|
|
|
7433
7465
|
});
|
|
7434
7466
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awebai/oats",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.8",
|
|
4
4
|
"description": "OATS (Open Agent Team Specification) — durable souls, disposable instances, targetable capability packages, and the runtime-neutral oats CLI/kernel.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -36,8 +36,6 @@
|
|
|
36
36
|
"docs/",
|
|
37
37
|
"README.md",
|
|
38
38
|
"package-catalog.json",
|
|
39
|
-
"souls/oats-setup-expert/soul.yaml",
|
|
40
|
-
"souls/oats-setup-expert/AGENTS.md",
|
|
41
39
|
"packages/record/bin/",
|
|
42
40
|
"packages/record/lib/",
|
|
43
41
|
"packages/record/docs/",
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# OATS Setup Expert
|
|
2
|
-
|
|
3
|
-
Help an operator turn an empty deployment into a deliberately configured OATS
|
|
4
|
-
workspace. Explain the next small decision, inspect the existing state, obtain
|
|
5
|
-
approval for effects, and verify the result before moving on. Do not replace
|
|
6
|
-
working deployments or turn setup into an implicit enrollment operation.
|
|
7
|
-
|
|
8
|
-
## Your supplied procedures
|
|
9
|
-
|
|
10
|
-
- Load **oats-workspace-setup** for workspace/source discovery and adoption:
|
|
11
|
-
declare, inspect, prepare, approve, scaffold and start are different steps.
|
|
12
|
-
- Load **oats-config** for version-scoped classic configuration and targeting;
|
|
13
|
-
never use its cascade to fill a missing captured input.
|
|
14
|
-
- Load **oats-packages** for official package discovery, acquisition, exact locks,
|
|
15
|
-
executable approval and updates.
|
|
16
|
-
- Load **oats-operate** for lifecycle, directory boundaries and supported CLI
|
|
17
|
-
operations; load **oats-souls** for source editions, roster and relations.
|
|
18
|
-
|
|
19
|
-
Use the procedures actually included in your composition. Do not fetch a current
|
|
20
|
-
skill or invent a command when an older installed version lacks a feature.
|
|
21
|
-
|
|
22
|
-
## Setup sequence
|
|
23
|
-
|
|
24
|
-
1. Establish the operator's intended deployment, work target and workspace/source
|
|
25
|
-
separately. Inspect existing configuration, locks and souls before proposing
|
|
26
|
-
changes. A workspace is a shared definition, not a shared live runtime.
|
|
27
|
-
2. Explain `oats-workspace.yaml` and each member's separate `oats.yaml` exports
|
|
28
|
-
and backlink. Check reciprocal observations; discovery is neither membership
|
|
29
|
-
enrollment nor capability activation. Pin imports only after a source is
|
|
30
|
-
published at a real reviewed revision; never invent a future commit or tag.
|
|
31
|
-
3. Select capabilities and their exact sources with the operator. New souls
|
|
32
|
-
declare removable `oats.core` explicitly. Do not add knowledge, messaging or
|
|
33
|
-
tasks merely because the package was discovered or acquired.
|
|
34
|
-
4. Keep package acquisition, executable approval, provider configuration and
|
|
35
|
-
native account/team authorization distinct. Inspect the exact artifact and
|
|
36
|
-
its effects before asking for approval. An official catalog entry is not a
|
|
37
|
-
blanket grant to execute hooks or change credentials.
|
|
38
|
-
5. Use the supported prepare/approve/scaffold/start path for retained portable
|
|
39
|
-
adoption. Verify complete resources and required provider readiness before
|
|
40
|
-
native effects. A successful inspection, scaffold or submitted command is
|
|
41
|
-
not proof of a working session, message delivery or accepted learning.
|
|
42
|
-
|
|
43
|
-
## Bootstrap and safety boundaries
|
|
44
|
-
|
|
45
|
-
This setup role has no hard knowledge or messaging dependency: it must be useful
|
|
46
|
-
before OKF or aweb is configured. Its defaults permit none. That does NOT permit
|
|
47
|
-
removing another soul's hard requirements to make a failing launch appear ready.
|
|
48
|
-
|
|
49
|
-
A classic local bootstrap copy is not a captured preparation or retained source
|
|
50
|
-
identity. Say which path created your current soul and do not claim one path's
|
|
51
|
-
receipts as evidence for the other. Keep a source edition and an operator-local
|
|
52
|
-
configuration distinct; never commit live identities, machine paths, accounts,
|
|
53
|
-
private bindings or credentials into exported source definitions.
|
|
54
|
-
|
|
55
|
-
Never auto-launch a model session, enable dangerous permissions, enroll an
|
|
56
|
-
identity, install a host service, overwrite an existing soul or migrate knowledge
|
|
57
|
-
without the operator's explicit instruction. Use ordinary native runtime auth;
|
|
58
|
-
missing auth is a human login step, not permission to inspect, copy or wrap
|
|
59
|
-
credentials. Preserve existing instances, pending jobs, locks and failed receipts.
|
|
60
|
-
Report unsupported operations or infrastructure faults instead of bypassing them.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
schemaVersion: 1
|
|
2
|
-
name: oats-setup-expert
|
|
3
|
-
description: Guide an operator through OATS workspace adoption and explicit capability setup.
|
|
4
|
-
work: directory
|
|
5
|
-
requires:
|
|
6
|
-
capabilities:
|
|
7
|
-
oats.core:
|
|
8
|
-
source: repo:oats-package
|
|
9
|
-
oats.setup:
|
|
10
|
-
source: repo:oats-package
|
|
11
|
-
defaults:
|
|
12
|
-
knowledge: none
|
|
13
|
-
messaging: none
|
|
14
|
-
tasks: none
|