@awebai/oats 0.25.9 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/bin/oats.mjs +576 -1714
- package/capabilities/oats-authoring/oats-package.json +2 -2
- package/capabilities/oats-authoring/oats.json +2 -2
- package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +46 -25
- package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +13 -6
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +279 -93
- package/capabilities/oats-aweb/injects/aweb.md +7 -2
- package/capabilities/oats-aweb/lib/binding-wire.mjs +89 -13
- package/capabilities/oats-aweb/lib/captured-native.mjs +1 -1
- package/capabilities/oats-aweb/lib/grant-custody.mjs +38 -0
- package/capabilities/oats-aweb/oats.json +8 -4
- package/capabilities/oats-jira/bin/oats-jira.mjs +4 -4
- package/capabilities/oats-jira/oats.json +2 -2
- package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +6 -3
- package/capabilities/oats-linear/bin/oats-linear-hook.mjs +6 -4
- package/capabilities/oats-linear/oats.json +2 -2
- package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +6 -0
- package/capabilities/oats-review/oats.json +3 -2
- package/docs/capabilities.md +218 -47
- package/docs/capability-manifest.schema.json +13 -4
- package/docs/configuration.md +17 -5
- package/docs/conventions.md +16 -26
- package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +1 -1
- package/docs/design/2026-09-13-knowledge-and-memory-direction.md +3 -3
- package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +2 -2
- package/docs/design/2026-09-15-portable-souls-handoff.md +2 -2
- package/docs/design/2026-09-15-portable-souls-implementation.md +1 -1
- package/docs/design/2026-09-20-redesign-program-board.md +2 -2
- package/docs/design/2026-09-23-workspace-module-contracts.md +1 -1
- package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +1 -1
- package/docs/design/2026-09-24-desktop-phase-f-boundary.md +34 -1
- package/docs/design/2026-09-24-phase-d-plan.md +57 -0
- package/docs/design/2026-09-25-teams-contract.md +226 -0
- package/docs/design/README.md +3 -3
- package/docs/design/launch-configurations.md +20 -16
- package/docs/design/operations-contract.md +27 -10
- package/docs/desktop-cli-api.md +537 -261
- package/docs/desktop-instance-start.md +1 -1
- package/docs/desktop.md +7 -13
- package/docs/execution-targets.md +16 -18
- package/docs/first-team.md +14 -17
- package/docs/implementation.md +28 -59
- package/docs/integrations.md +64 -33
- package/docs/knowledge-capability-authoring.md +1 -1
- package/docs/knowledge-reference/package-craft.md +10 -8
- package/docs/knowledge-theory.md +1 -1
- package/docs/knowledge.md +10 -11
- package/docs/layers.md +16 -17
- package/docs/oats-local.schema.json +29 -1
- package/docs/oats-membership.schema.json +5 -3
- package/docs/oats-package.schema.json +2 -2
- package/docs/oats-workspace.schema.json +1 -1
- package/docs/{official-marketplace.md → official-catalog.md} +15 -16
- package/docs/packages.md +75 -52
- package/docs/release-notes/v0.22.0.md +1 -1
- package/docs/release-notes/v0.23.1.md +1 -1
- package/docs/release-notes/v0.26.0.md +670 -0
- package/docs/schedules.md +48 -126
- package/docs/soul.schema.json +11 -4
- package/docs/souls-and-instances.md +56 -43
- package/docs/workspaces.md +80 -58
- package/injects/instance-boundary.md +1 -1
- package/injects/work-attached.md +1 -1
- package/injects/work-workspace.md +2 -2
- package/lib/{portable-files.mjs → bounded-read.mjs} +6 -6
- package/lib/{portable-values.mjs → canonical-json.mjs} +3 -12
- package/lib/capability-contract.mjs +110 -0
- package/lib/config-data.mjs +2 -2
- package/lib/core.mjs +700 -4824
- package/lib/digest.mjs +12 -0
- package/lib/instance-inspect.mjs +396 -0
- package/lib/instance-lifecycle.mjs +3 -4
- package/lib/instance-resolution.mjs +212 -26
- package/lib/instruction-composition.mjs +0 -20
- package/lib/materialize.mjs +6 -4
- package/lib/operator-dispatch.mjs +33 -13
- package/lib/packages.mjs +25 -190
- package/lib/provider-binding.mjs +4 -2
- package/lib/provider-reasons.mjs +3 -68
- package/lib/resolve.mjs +204 -68
- package/lib/schedule.mjs +97 -272
- package/lib/servers.mjs +13 -13
- package/lib/{portable-shape.mjs → shape.mjs} +4 -3
- package/lib/tree-copy.mjs +44 -0
- package/lib/workspace.mjs +125 -20
- package/package-catalog.json +6 -6
- package/package.json +1 -1
- package/skills/integration-authoring/SKILL.md +48 -40
- package/skills/oats-getting-started/SKILL.md +105 -110
- package/skills/oats-support/SKILL.md +2 -2
- package/skills/soul-craft/SKILL.md +13 -6
- package/bin/oats-pi-sdk-host.mjs +0 -17
- package/docs/2026-09-03-architecture-proposal.md +0 -642
- package/docs/artifact-approvals.schema.json +0 -7
- package/docs/captured-invocation-context.schema.json +0 -7
- package/docs/captured-resolution.schema.json +0 -7
- package/docs/design/package-engine-contract.md +0 -813
- package/docs/design/package-runtime-api.md +0 -588
- package/docs/desktop-succession.md +0 -57
- package/docs/execution-capsule.schema.json +0 -108
- package/docs/first-team-demo.md +0 -92
- package/docs/knowledge-migration.md +0 -147
- package/docs/migration-from-oas.md +0 -103
- package/docs/oats-config.schema.json +0 -172
- package/docs/oats-lock-v3.schema.json +0 -7
- package/docs/oats-lock.schema.json +0 -175
- package/docs/operating-team-migration.md +0 -470
- package/docs/portable.schema.json +0 -2512
- package/docs/provider-check-input.schema.json +0 -7
- package/docs/rebuild-to-v2.md +0 -511
- package/docs/workspace-adoption.md +0 -74
- package/injects/framework-workspace.md +0 -7
- package/injects/local-soul.md +0 -19
- package/injects/oats-portable.md +0 -20
- package/injects/oats.md +0 -11
- package/injects/portable-instance-boundary.md +0 -39
- package/injects/portable-work-directory.md +0 -29
- package/lib/artifact-approvals.mjs +0 -120
- package/lib/artifact-tree.mjs +0 -141
- package/lib/capability-artifacts.mjs +0 -179
- package/lib/capability-execution.mjs +0 -15
- package/lib/capability-inputs.mjs +0 -39
- package/lib/capability-provenance.mjs +0 -231
- package/lib/captured-action-shape.mjs +0 -21
- package/lib/captured-admission-shape.mjs +0 -20
- package/lib/captured-binding-file.mjs +0 -36
- package/lib/captured-dispatch.mjs +0 -66
- package/lib/captured-instance-index.mjs +0 -277
- package/lib/captured-invocation-context.mjs +0 -130
- package/lib/captured-launch-request.mjs +0 -66
- package/lib/captured-operation-process.mjs +0 -15
- package/lib/captured-pi-custody.mjs +0 -29
- package/lib/captured-pi-host.mjs +0 -167
- package/lib/captured-pi-outcome.mjs +0 -172
- package/lib/captured-resolutions.mjs +0 -275
- package/lib/captured-scaffold.mjs +0 -87
- package/lib/captured-selector.mjs +0 -28
- package/lib/captured-session-backend.mjs +0 -52
- package/lib/captured-source-receipt-file.mjs +0 -72
- package/lib/helper-injection-policy.mjs +0 -104
- package/lib/legacy-lock-codec.mjs +0 -106
- package/lib/manifest-settings.mjs +0 -84
- package/lib/package-closure.mjs +0 -48
- package/lib/package-materialization.mjs +0 -83
- package/lib/pi-sdk-host.mjs +0 -229
- package/lib/portable-artifacts.mjs +0 -115
- package/lib/portable-choices.mjs +0 -82
- package/lib/portable-composition.mjs +0 -136
- package/lib/portable-digest.mjs +0 -105
- package/lib/portable-identity.mjs +0 -40
- package/lib/portable-lock.mjs +0 -117
- package/lib/portable-onboarding-request.mjs +0 -49
- package/lib/portable-onboarding.mjs +0 -256
- package/lib/portable-package-preparation.mjs +0 -188
- package/lib/portable-policy.mjs +0 -44
- package/lib/portable-soul.mjs +0 -42
- package/lib/portable-state.mjs +0 -80
- package/lib/prepare-composition.mjs +0 -170
- package/lib/prepared-bindings.mjs +0 -92
- package/lib/prepared-resources.mjs +0 -127
- package/lib/provider-binding-broker.mjs +0 -65
- package/lib/provider-binding-wire.mjs +0 -116
- package/lib/readiness.mjs +0 -225
- package/lib/repository-observation.mjs +0 -226
- package/lib/resolution-shape.mjs +0 -393
- package/lib/schedule-capsule.mjs +0 -206
- package/lib/soul-constraints.mjs +0 -40
- package/lib/source-projection.mjs +0 -84
- package/lib/source-spec.mjs +0 -189
- package/lib/workspace-definition.mjs +0 -126
- package/lib/workspace-discovery.mjs +0 -146
- package/skills/oats/SKILL.md +0 -162
- package/skills/oats-config/SKILL.md +0 -164
- package/skills/oats-packages/SKILL.md +0 -184
- package/skills/oats-portable/SKILL.md +0 -115
- package/skills/oats-portable-artifacts/SKILL.md +0 -63
package/docs/schedules.md
CHANGED
|
@@ -3,16 +3,12 @@
|
|
|
3
3
|
A schedule launches an agent, runs an oats command, or wakes an existing
|
|
4
4
|
instance on a cron. Definitions belong to a scope and are committable; every
|
|
5
5
|
`oats schedule` command run anywhere inside that scope, including from an
|
|
6
|
-
instance home, reads and writes the same file.
|
|
7
|
-
(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
is the team workspace (the config level that declares the team, else the
|
|
13
|
-
outermost `oats-config.yaml` level). Execution belongs to the host that holds
|
|
14
|
-
the scope, so a schedule on a registered server keeps running while your laptop
|
|
15
|
-
sleeps.
|
|
6
|
+
instance home, reads and writes the same file. The scope is the deployment
|
|
7
|
+
directory ([workspaces.md](workspaces.md)) — the one holding `oats-local.yaml`
|
|
8
|
+
and the `agents/` root, found walking up; with none in reach, `oats schedule`
|
|
9
|
+
is `E_LOCAL_MISSING`. Scheduled spawns materialize exactly like `oats spawn`.
|
|
10
|
+
Execution belongs to the host that holds the scope, so a schedule on a
|
|
11
|
+
registered server keeps running while your laptop sleeps.
|
|
16
12
|
|
|
17
13
|
There is no daemon. One host timer (a launchd user agent on macOS, a systemd
|
|
18
14
|
user timer on Linux) runs `oats schedule tick --host` once a minute; the tick
|
|
@@ -25,15 +21,9 @@ and no queue.
|
|
|
25
21
|
## Files
|
|
26
22
|
|
|
27
23
|
- `<workspace>/oats-schedules.json` — the definitions (`{version: 1|2, jobs:
|
|
28
|
-
{<id>: ...}}`).
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
entries may remain visibly unmigrated; new entries in a v2 file must declare
|
|
32
|
-
their policy. Commit the file if you want the schedule shared with the team.
|
|
33
|
-
Automatic wake creation uses this same document-version gate. Remote captured
|
|
34
|
-
mutations require advertised numeric schedule API 2 before forwarding; the old
|
|
35
|
-
feature-only gate is insufficient. Unclassifiable remote spec files also require
|
|
36
|
-
API 2. Legacy inline specs/read operations remain compatible with older hosts.
|
|
24
|
+
{<id>: ...}}`). A new file is version 1. A version-2 file (written by 0.24–0.25
|
|
25
|
+
for captured definitions) is still read; it is never rewritten to version 1.
|
|
26
|
+
Commit the file if you want the schedule shared with the team.
|
|
37
27
|
- `<workspace>/.agents/schedules/state.json` — last attempted minute and
|
|
38
28
|
last run per job (gitignored), plus one lock directory per running job.
|
|
39
29
|
- `~/.oats/schedules/registry.json` — the host registry: which scopes the
|
|
@@ -43,9 +33,8 @@ and no queue.
|
|
|
43
33
|
with the directory to remove, and the holder removes its own lock on exit
|
|
44
34
|
and on SIGINT/SIGTERM. Definition edits take a short per-scope lock.
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
editing UI remains later Desktop work; use the explicit CLI for those definitions.
|
|
36
|
+
Captured (versioned) definitions are refused (the captured/portable path was removed in 0.26):
|
|
37
|
+
see [Captured definitions](#captured-definitions-removed-in-026).
|
|
49
38
|
|
|
50
39
|
## Kinds
|
|
51
40
|
|
|
@@ -55,7 +44,10 @@ editing UI remains later Desktop work; use the explicit CLI for those definition
|
|
|
55
44
|
options `oats spawn` takes. `agentsRoot` names the exact agents root that
|
|
56
45
|
holds the soul (it must lie inside the workspace and defaults to the
|
|
57
46
|
workspace's own root); it is what tells same-named souls in different
|
|
58
|
-
member repositories apart. `repo` is the work repository, as `--repo`.
|
|
47
|
+
member repositories apart. `repo` is the work repository, as `--repo`.
|
|
48
|
+
Each run is named `<agent>-<purpose or id>-<YYYYMMDDHHMM>`. Instance names
|
|
49
|
+
are at most 64 characters, so a definition whose run names would be longer
|
|
50
|
+
is refused when it is saved (`E_SCHEDULE_INVALID`, field `purpose` or `id`). The task gets a trailing schedule block naming the job and the
|
|
59
51
|
minute and ending with `oats retire --self`. An optional `wake` object
|
|
60
52
|
(`{cron, tz, message}`) attaches a wake schedule to each launched instance;
|
|
61
53
|
nothing is attached unless you ask.
|
|
@@ -66,8 +58,8 @@ editing UI remains later Desktop work; use the explicit CLI for those definition
|
|
|
66
58
|
from durable context; the job follows that worker until its home is gone.
|
|
67
59
|
Command return is not task completion. Avoid binding durable work to a
|
|
68
60
|
disposable source-home cwd; see [OKF v2 source jobs](#okf-v2-source-jobs).
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
An argv carrying a captured selector (`--deployment`, `--resolution`,
|
|
62
|
+
`--artifact-set`) is refused when saved (`E_SCHEDULE_INVALID`, field `argv`).
|
|
71
63
|
- **wake** `{id, enabled, cron, tz, kind: "wake", home, message}` — every
|
|
72
64
|
due minute inspects the instance at `home` through its session receipts.
|
|
73
65
|
Running: `message` is delivered once with `session input`. Not running
|
|
@@ -97,87 +89,28 @@ required IANA zone; both are evaluated by the croner library. `--wake-every
|
|
|
97
89
|
N` at spawn time means `*/N * * * *`: every 7 fires at :00, :07, ... :56 and
|
|
98
90
|
then :00 again, so 1, 5, 10, 15 and 30 give an even cadence.
|
|
99
91
|
|
|
100
|
-
## Captured
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The admitted-attempt wire is published as
|
|
125
|
-
[`execution-capsule.schema.json`](execution-capsule.schema.json). Runtime
|
|
126
|
-
validation checks selector/target agreement. A canonical `oats.json.v1` digest
|
|
127
|
-
of all fields except `executionId` is the separate content witness;
|
|
128
|
-
`executionId` itself is opaque admission identity.
|
|
129
|
-
|
|
130
|
-
`capture` requires the explicit deployment/resolution selector pair and
|
|
131
|
-
`--json` in the **saved argv**. The scheduler never appends an unrecorded
|
|
132
|
-
protocol argument to a captured target. Adding or updating the definition
|
|
133
|
-
derives an immutable `execution` template containing that exact target,
|
|
134
|
-
resolution, input references and explicitly supplied responsible-human value.
|
|
135
|
-
It contains no execution ID; `executionStatus.contentIntegrity` exposes its
|
|
136
|
-
canonical content witness. At each due tick the
|
|
137
|
-
scheduler verifies the retained action first, then mints a fresh opaque
|
|
138
|
-
`executionId`, writes the resulting capsule into the attempt before reserving a
|
|
139
|
-
slot, and only then invokes the CLI. Thus two attempts with identical content
|
|
140
|
-
have the same capsule digest but remain different intents. Definition edits
|
|
141
|
-
affect later admissions only; an unknown attempt, `run`, or reconciliation never
|
|
142
|
-
replaces its capsule with the edited definition or today's config/lock. Captured
|
|
143
|
-
attempts carry their own `schemaVersion:1`; their launch-slot lock names the same
|
|
144
|
-
`executionId`. A mismatching lock or malformed/unknown attempt version stays
|
|
145
|
-
unresolved and cannot dispatch. Scheduler launch also scrubs ambient
|
|
146
|
-
`OATS_DEPLOYMENT` and `OATS_RESOLUTION`; only the saved argv is authority.
|
|
147
|
-
|
|
148
|
-
`prepare-on-tick` is a distinct explicit policy for a genuinely new command
|
|
149
|
-
tick. Its `preparation` object maps directly to the generic
|
|
150
|
-
`prepareCapturedComposition({deployment,source,workspace?,member?,operator?,mode?})`
|
|
151
|
-
input; scheduler code does not parse source/workspace policy itself. Production
|
|
152
|
-
uses the core adapter and tests may inject the same contract. Direct-source and
|
|
153
|
-
workspace-alias requests are supported; `mode` is a work-mode string, not a nested
|
|
154
|
-
launch object. A complete result must preserve the requested deployment and
|
|
155
|
-
returned resolution, and contain `executionBinding` and an explicit
|
|
156
|
-
`responsibleHuman` (`null` means messaging was actually disabled). The scheduler
|
|
157
|
-
then inserts the exact selector pair before `--`, verifies the captured action,
|
|
158
|
-
mints and persists the attempt, and dispatches. Missing adapters and incomplete
|
|
159
|
-
results return typed `migration-required`/`needs-configuration` with no attempt.
|
|
160
|
-
A dry run never invokes preparation or mints intent. There is no current-context
|
|
161
|
-
fallback. Captured spawn and
|
|
162
|
-
operation definitions remain unavailable until their public captured consumer
|
|
163
|
-
adapters exist. A captured wake definition is accepted only when its target
|
|
164
|
-
`instance.json` has an exact `executionBinding`; the binding is copied into the
|
|
165
|
-
execution template and checked again at admission without consulting source or
|
|
166
|
-
configuration. Actual captured wake delivery/start remains blocked with
|
|
167
|
-
`migration-required` until the parent-owned lifecycle consumer lands. Legacy
|
|
168
|
-
wakes continue through the old lifecycle boundary in this release.
|
|
169
|
-
|
|
170
|
-
Definitions without `definitionVersion`/`recurrencePolicy` are legacy v1
|
|
171
|
-
definitions. They retain the old release behavior during migration and are not
|
|
172
|
-
reported as captured execution. `list`/`show` report their `executionStatus` as
|
|
173
|
-
`{kind:"legacy",capture:"unknown",migrationRequired:true}`. A captured definition
|
|
174
|
-
reports only `capture:"recorded"` until action admission verifies the retained
|
|
175
|
-
record and current exact approval; it does not claim launch readiness. While an
|
|
176
|
-
attempt is unresolved or its confirmed launched work still holds a slot,
|
|
177
|
-
`executionStatus.intent` separately reports captured, legacy-unknown or invalid
|
|
178
|
-
authority, so editing a future definition cannot hide an older admitted capsule.
|
|
179
|
-
Partial, malformed or unsupported versioned
|
|
180
|
-
definitions/attempts are invalid or blocked, never reinterpreted as legacy.
|
|
92
|
+
## Captured definitions (removed in 0.26)
|
|
93
|
+
|
|
94
|
+
0.24–0.25 could save captured command definitions: `definitionVersion`,
|
|
95
|
+
`recurrencePolicy` (`capture` or `prepare-on-tick`), an `execution` template and a
|
|
96
|
+
`preparation` request, run against a captured deployment/resolution. That path
|
|
97
|
+
was removed in 0.26:
|
|
98
|
+
|
|
99
|
+
- `add` and `update` refuse any of those four keys (`E_SCHEDULE_INVALID`, the
|
|
100
|
+
key as `field`), locally and, with `--server`, before anything is forwarded.
|
|
101
|
+
- A stored captured definition is invalid on its own job: every tick reports it
|
|
102
|
+
(`invalid`, "captured schedules are refused (the captured/portable path was removed in 0.26) …") and never runs it;
|
|
103
|
+
the rest of the scope's jobs continue. `list`/`show` report its
|
|
104
|
+
`executionStatus` as `{kind:"invalid", …, reason}`.
|
|
105
|
+
- A captured attempt or job lock left mid-run by 0.25 is reported on that job
|
|
106
|
+
(`executionStatus.intent`, `reconcile` refuses with `E_SCHEDULE_INVALID`) and is
|
|
107
|
+
never run, adopted or released. A held captured lock keeps its launch slot
|
|
108
|
+
until the job is gone: remove it with `oats schedule remove --force <id>`, or
|
|
109
|
+
re-add it without the captured keys.
|
|
110
|
+
|
|
111
|
+
Every other definition is a plain one; `list`/`show` report its `executionStatus`
|
|
112
|
+
as `{kind:"legacy",capture:"unknown",migrationRequired:true}` (a released wire,
|
|
113
|
+
kept as it was).
|
|
181
114
|
|
|
182
115
|
## Commands
|
|
183
116
|
|
|
@@ -202,27 +135,23 @@ running}], scheduler: {installed, active, lastTick, maxConcurrent, ...}}`.
|
|
|
202
135
|
|
|
203
136
|
## What a run reports
|
|
204
137
|
|
|
205
|
-
`launched` (spawn or command returned), `
|
|
206
|
-
admission refused before a launch slot or child process), `active` (the instance is running;
|
|
138
|
+
`launched` (spawn or command returned), `active` (the instance is running;
|
|
207
139
|
a home whose retirement is pending still counts, its runtime may be alive),
|
|
208
140
|
`ended` (its home is gone), `stopped` (home present, nothing running: needs
|
|
209
141
|
attention, never removed for you), `launch-failed`, `unknown`, and for wake
|
|
210
142
|
jobs `delivered`, `started` or `skipped`. The kernel never claims a task
|
|
211
143
|
succeeded.
|
|
212
144
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
`errorCode`; no attempt capsule or launch lock is created.
|
|
145
|
+
A run recorded by 0.24–0.25 may also read `blocked` (a captured admission that
|
|
146
|
+
refused before a launch slot); 0.26 never produces it.
|
|
216
147
|
|
|
217
148
|
`unknown` means the launch's side effects are unconfirmed: a command timed
|
|
218
149
|
out or answered no envelope, an envelope named an instance the roster
|
|
219
150
|
cannot place, or an attempt was never recorded. The job keeps its slot and
|
|
220
151
|
is skipped until `oats schedule reconcile <id>`. Reconcile adopts only an
|
|
221
|
-
attributable receipt: a
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
current-config roster lookup or a previous attempt's name cannot establish it.
|
|
225
|
-
Nothing is inferred from file times. Observation validates custody before releasing
|
|
152
|
+
attributable receipt: a spawn job's instance is named deterministically for its
|
|
153
|
+
minute; a command job's, only the instance its answer named. Nothing is inferred
|
|
154
|
+
from file times. Observation validates custody before releasing
|
|
226
155
|
slots, and unresolved attempts remain held even in the crash gap before a lock
|
|
227
156
|
exists. Ordinary removal refuses those attempts; force-forget remains explicit. A command whose answer named nothing stays
|
|
228
157
|
unknown; check the roster and the host by hand, then
|
|
@@ -244,9 +173,8 @@ continues.
|
|
|
244
173
|
|
|
245
174
|
`disable` never stops anything. `update` never touches a running instance,
|
|
246
175
|
and while a job holds a slot or has an unresolved attempt its complete
|
|
247
|
-
execution identity
|
|
248
|
-
change; cron, tz and enabled can.
|
|
249
|
-
compatibility behavior until migrated. A cold wake persists its slot before
|
|
176
|
+
execution identity, kind and target cannot
|
|
177
|
+
change; cron, tz and enabled can. A cold wake persists its slot before
|
|
250
178
|
the session start runs and keeps it on any start exception, whatever its code
|
|
251
179
|
(the kernel can refuse while recording, after the session exists); the next
|
|
252
180
|
observation releases it once the runtime is proven stopped or absent, one tick
|
|
@@ -262,13 +190,7 @@ listed with its skipped reason.
|
|
|
262
190
|
saves a wake job `wake-<instance>` bound to the new home after the spawn
|
|
263
191
|
succeeded. If the spawn succeeds but the save fails, the spawn result still
|
|
264
192
|
carries the full instance receipt, plus `wakeScheduleError` and a warning;
|
|
265
|
-
the instance is neither hidden nor spawned again.
|
|
266
|
-
supplies both the returned `executionBinding` and `responsibleHuman`,
|
|
267
|
-
`saveWakeForHome` creates a version-2 captured wake from the matching binding in
|
|
268
|
-
the new home. Supplying only one, or a result binding that differs from the
|
|
269
|
-
home, refuses. The current parent-owned spawn caller still needs to pass these
|
|
270
|
-
fields when its captured lifecycle path lands; omission retains explicit legacy
|
|
271
|
-
behavior rather than inventing a binding.
|
|
193
|
+
the instance is neither hidden nor spawned again.
|
|
272
194
|
|
|
273
195
|
## OKF v2 source jobs
|
|
274
196
|
|
package/docs/soul.schema.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://oats.dev/schemas/soul-v2.json",
|
|
4
4
|
"title": "Soul declaration v2 (soul.yaml)",
|
|
5
|
-
"description": "Authored shape only. A soul names each capability WITH WHERE IT COMES FROM (`from: here | <repo key> | package`) — a location, never a version.
|
|
5
|
+
"description": "Authored shape only. A soul names each capability WITH WHERE IT COMES FROM (`from: here | <repo key> | package`) — a location, never a version. Core-capability payloads (knowledge, messaging, tasks) are opaque to the kernel; `none` empties the slot. Membership, privacy and team semantics are enforced by discovery/resolution, not here.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["schemaVersion", "name", "description", "work"],
|
|
8
8
|
"additionalProperties": false,
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"name": { "$ref": "#/$defs/slug" },
|
|
12
12
|
"description": { "type": "string" },
|
|
13
13
|
"work": { "enum": ["worktree", "checkout", "directory", "workspace"] },
|
|
14
|
-
"team": { "$ref": "#/$defs/
|
|
15
|
-
"private": { "type": "boolean", "
|
|
14
|
+
"team": { "$ref": "#/$defs/teamLabels", "description": "Team label, or a non-empty list of distinct labels (the first is the primary); overrides the repo's default from oats-membership.yaml. Each label's messaging payload reaches the provider as an eligible team (OATS_TEAMS); joining is the provider's explicit act." },
|
|
15
|
+
"private": { "type": "boolean", "deprecated": true,
|
|
16
|
+
"description": "Ignored since 0.26.0: souls have no private mode. Every soul of a confirmed member is listed and spawnable; discovery warns soul-private-ignored. Accepted so existing files still validate; remove it." },
|
|
16
17
|
"capabilities": {
|
|
17
18
|
"type": "object",
|
|
18
19
|
"propertyNames": { "$ref": "#/$defs/capabilityName" },
|
|
@@ -31,6 +32,12 @@
|
|
|
31
32
|
"$defs": {
|
|
32
33
|
"slug": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
|
|
33
34
|
"label": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
35
|
+
"teamLabels": {
|
|
36
|
+
"anyOf": [
|
|
37
|
+
{ "$ref": "#/$defs/label" },
|
|
38
|
+
{ "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/label" } }
|
|
39
|
+
]
|
|
40
|
+
},
|
|
34
41
|
"capabilityName": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
|
|
35
42
|
"repoKey": { "type": "string", "pattern": "^[^\\s@/][^\\s@]*/[^\\s@]+$" },
|
|
36
43
|
"fromLocation": {
|
|
@@ -49,7 +56,7 @@
|
|
|
49
56
|
"capabilityChoice": { "anyOf": [{ "$ref": "#/$defs/capabilityRef" }, { "const": "off" }] },
|
|
50
57
|
"slotPayload": {
|
|
51
58
|
"anyOf": [{ "const": "none" }, { "type": "object" }],
|
|
52
|
-
"description": "Opaque
|
|
59
|
+
"description": "Opaque payload for the slot's core capability, or `none` to leave the slot empty."
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
}
|
|
@@ -40,7 +40,6 @@ name: release-manager # must equal the directory name
|
|
|
40
40
|
description: Cuts, verifies and announces releases.
|
|
41
41
|
work: worktree # worktree | checkout | directory | workspace
|
|
42
42
|
team: engineering # optional label; else the repo's default (oats-membership.yaml); else unassigned
|
|
43
|
-
private: true # optional: not discoverable; spawnable only from this repo
|
|
44
43
|
|
|
45
44
|
capabilities: # WHERE each capability comes from — a location, never a version
|
|
46
45
|
acme-release-tooling: { from: here } # here = this soul's own repo
|
|
@@ -62,16 +61,19 @@ compatibility: # optional floors on PACKAGE versions
|
|
|
62
61
|
| Key | Meaning |
|
|
63
62
|
|---|---|
|
|
64
63
|
| `name`, `description`, `work` | Required. `work` is the work mode below. |
|
|
65
|
-
| `team` | A label declared in the workspace's `teams:`; may add `defaults.byTeam` capabilities. Never gates or restricts. |
|
|
66
|
-
| `private` |
|
|
64
|
+
| `team` | A label, or a list of labels (the first the primary), declared in the workspace's `teams:`; each may add `defaults.byTeam` capabilities and is an eligible messaging team. Never gates or restricts. |
|
|
65
|
+
| `private` | **Ignored since 0.26.0:** souls have no private mode. Every soul of a confirmed member is listed and spawnable; a soul that still carries the field gets a `soul-private-ignored` warning. Remove it. |
|
|
67
66
|
| `capabilities` | `<cap>: { from: here \| <repo key> \| package }` or `<cap>: off`. Composed over `defaults.<slot>` ⊕ `defaults.capabilities` ⊕ `defaults.byTeam[team]`; the soul wins. |
|
|
68
67
|
| `knowledge` / `messaging` / `tasks` | The slot's provider payload (true of every instance of the soul), or `none`. Merged with `oats-local.yaml` `settings.<cap>` and `spawn --provider <cap>`; the provider's `binding` contract validates the result — and refuses keys it does not declare. For `oats.okf` 2.1.3 the admitted keys are its settings (`bindings-file`, `state-dir`, `harvest-runtime`, `harvest-model`); the soul's `owns`/`reads` live in `souls/<name>/okf.json`, which OKF reads from the soul directory. |
|
|
69
68
|
| `compatibility` | `<cap>: <semver range>` checked against the locked package version (`E_COMPATIBILITY`). |
|
|
70
69
|
|
|
71
70
|
Schema: [`soul.schema.json`](soul.schema.json). Not in v2: `kind`, `type`,
|
|
72
|
-
`repo`, `runtime`, `model`, `
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
`repo`, `runtime`, `model`, `backend`, `yolo`, `launch-config`, `children`,
|
|
72
|
+
`requires`, `source:`, `stores.inherit`. Runtime, model, backend, yolo and the
|
|
73
|
+
launch configuration are spawn-time host choices (`--runtime`, `--model`,
|
|
74
|
+
`--backend`, `--yolo`, `--launch-config`, or a launch configuration in
|
|
75
|
+
`oats-local.yaml`), not soul identity: a soul is model-agnostic as an artifact.
|
|
76
|
+
A child-spawn policy is a spawn flag too (`--no-child-spawns`).
|
|
75
77
|
|
|
76
78
|
A soul never runs by itself. It is incarnated as an instance. Editing a soul
|
|
77
79
|
is a code change, reviewed in its repo.
|
|
@@ -84,9 +86,10 @@ souls — is ordinary capability content: **`oats.core`** (package
|
|
|
84
86
|
`defaults.capabilities: { oats.core: { from: package } }`; a soul may say
|
|
85
87
|
`oats.core: off`. **`oats.setup`** (same package) carries the whole-architecture
|
|
86
88
|
knowledge an onboarding expert needs. Neither is kernel magic; the kernel still
|
|
87
|
-
composes its own instance-boundary and work-mode briefings
|
|
88
|
-
`oats.core`
|
|
89
|
-
|
|
89
|
+
composes its own instance-boundary and work-mode briefings, and the "You run
|
|
90
|
+
on OATS" briefing is `oats.core`'s inject (the kernel ships no copy since 0.26:
|
|
91
|
+
a soul without `oats.core` gets no OATS operating instructions, and
|
|
92
|
+
`oats doctor --soul` says so).
|
|
90
93
|
|
|
91
94
|
## Instance anatomy
|
|
92
95
|
|
|
@@ -102,7 +105,6 @@ full copy** of every capability the soul resolved to:
|
|
|
102
105
|
|
|
103
106
|
```text
|
|
104
107
|
<agents-root>/<soul>/instances/<instance>/
|
|
105
|
-
soul → ../../soul # the soul, for reference (read-only)
|
|
106
108
|
AGENTS.md # generated: soul AGENTS.md + kernel/work-mode blocks + each module's inject
|
|
107
109
|
CLAUDE.md → AGENTS.md
|
|
108
110
|
.agents/skills/ # canonical skill tree — soul skills + <capability>/<skill>/ full copies
|
|
@@ -111,7 +113,7 @@ full copy** of every capability the soul resolved to:
|
|
|
111
113
|
.oats/modules/<capability>/ # the whole capability: oats.json, bin/, injects/, skills/ (hooks run from here)
|
|
112
114
|
work/ # worktree, checkout symlink, attached tree, or private directory
|
|
113
115
|
TASK.md # briefing and task
|
|
114
|
-
instance.json # provenance (below)
|
|
116
|
+
instance.json # provenance (below); `soulDir` = the soul directory hooks get as OATS_SOUL
|
|
115
117
|
STATE.md, log.md, notes/ # optional, from the knowledge capability
|
|
116
118
|
```
|
|
117
119
|
|
|
@@ -187,6 +189,11 @@ oats spawn release-manager --preview --json # decide ever
|
|
|
187
189
|
oats spawn release-manager --provider oats.aweb identity.source=/abs/path/to/retained/.aw # instance-level payload
|
|
188
190
|
```
|
|
189
191
|
|
|
192
|
+
An instance is named `<soul>-<purpose>` by default, or exactly `--name <slug>`.
|
|
193
|
+
Names are unique per deployment (a workspace-model deployment has one agents
|
|
194
|
+
root): a derived name in use gets `-2`, `-3`…; an explicit `--name` in use is
|
|
195
|
+
refused (`E_INSTANCE_NAME_TAKEN`).
|
|
196
|
+
|
|
190
197
|
From a deployment (where `oats-local.yaml` is), a spawn: reads the local file →
|
|
191
198
|
discovers the workspace over its remotes and confirms membership → finds the
|
|
192
199
|
soul among the confirmed members (or `external:`; an ambiguous bare name is
|
|
@@ -194,7 +201,7 @@ soul among the confirmed members (or `external:`; an ambiguous bare name is
|
|
|
194
201
|
`<agents-root>/<soul>/souls/<commit12>/` at its commit (the home links that
|
|
195
202
|
directory; `<agents-root>/<soul>/soul` points at the current one) → resolves
|
|
196
203
|
every capability by
|
|
197
|
-
`from:` (member = latest, package = locked
|
|
204
|
+
`from:` (member = latest, package = locked) → creates the home →
|
|
198
205
|
**materializes each module whole** into `.oats/modules/` and copies its skills
|
|
199
206
|
into `.agents/skills/` (a transaction: any failure leaves nothing behind) →
|
|
200
207
|
composes `AGENTS.md` → records `modules`/`providers`/`workspace` in
|
|
@@ -282,9 +289,9 @@ an agent's environment variables — is operator-origin and appears top-level.
|
|
|
282
289
|
Agents spawning sub-agents should pass `--parent "$OATS_INSTANCE"` (or the
|
|
283
290
|
relation that fits).
|
|
284
291
|
|
|
285
|
-
If the workspace has a messaging
|
|
292
|
+
If the workspace has a messaging capability such as aweb, spawned instances
|
|
286
293
|
can also receive identities and coordinate with each other automatically. The
|
|
287
|
-
|
|
294
|
+
tasks capability can provide shared work state while messaging provides conversation.
|
|
288
295
|
|
|
289
296
|
### Retire
|
|
290
297
|
|
|
@@ -316,7 +323,7 @@ follow. Every mode sits inside the same home/work boundary, which the generated
|
|
|
316
323
|
instructions state first (`injects/instance-boundary.md`):
|
|
317
324
|
|
|
318
325
|
- `<instance-home>` — the gitignored instance directory, `$OATS_INSTANCE_HOME` —
|
|
319
|
-
holds the brain (`AGENTS.md
|
|
326
|
+
holds the brain (the composed `AGENTS.md`; there is no soul link), the task, the provenance
|
|
320
327
|
(`instance.json`) and the episodic state (`STATE.md`, `log.md`, `notes/`), and
|
|
321
328
|
is where OATS operational/lifecycle commands — and the commands of whatever
|
|
322
329
|
capabilities are active, `aw` among them when aweb messaging is — are run,
|
|
@@ -325,9 +332,11 @@ instructions state first (`injects/instance-boundary.md`):
|
|
|
325
332
|
- `<instance-home>/work` — the repository or workspace view — is where
|
|
326
333
|
repository reading, editing, building, testing, git and commits happen, to the
|
|
327
334
|
extent the mode below permits.
|
|
328
|
-
- The home
|
|
329
|
-
|
|
330
|
-
|
|
335
|
+
- The home has no soul link: the composed `AGENTS.md` already carries the
|
|
336
|
+
soul's instructions, and `instance.json` `soulDir` records the (read-only,
|
|
337
|
+
per-commit) soul directory every hook and dispatched command receives as
|
|
338
|
+
`OATS_SOUL`. Durable soul edits go through tracked paths under `work/` under
|
|
339
|
+
the applicable review rules. OKF v2 harvest edits external
|
|
331
340
|
owned knowledge, not canonical soul files or skills.
|
|
332
341
|
|
|
333
342
|
Agents move between the two as the task needs; the boundary is what each
|
|
@@ -472,8 +481,7 @@ with **`E_NO_CANONICAL_ROOT`** and creates nothing.
|
|
|
472
481
|
|
|
473
482
|
### Deployment prerequisite: the agents directory must be operator-owned
|
|
474
483
|
|
|
475
|
-
The canonical deployment (the agents root
|
|
476
|
-
homes under them) **must be owned by the operator and not writable by untrusted
|
|
484
|
+
The canonical deployment (the agents root and the instance homes under it) **must be owned by the operator and not writable by untrusted
|
|
477
485
|
users or processes.** OATS validates resolved destinations and re-checks the home
|
|
478
486
|
immediately before creating anything in it, but it cannot defeat a concurrent
|
|
479
487
|
local attacker who already has write access there: Node offers no
|
|
@@ -486,33 +494,38 @@ something the kernel can close from inside.
|
|
|
486
494
|
Default layout:
|
|
487
495
|
|
|
488
496
|
```text
|
|
489
|
-
<
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
497
|
+
<deployment>/
|
|
498
|
+
oats-local.yaml
|
|
499
|
+
agents/
|
|
500
|
+
docs-expert/ # a workspace soul, defined in a member repository's
|
|
501
|
+
souls/<commit12>/ # souls/docs-expert/ and copied here per commit
|
|
493
502
|
instances/
|
|
494
|
-
|
|
495
|
-
scratch-agent/
|
|
496
|
-
soul/
|
|
503
|
+
memory-harvest/ # a capability-defined agent: only instances/, no soul
|
|
497
504
|
instances/
|
|
498
505
|
```
|
|
499
506
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
507
|
+
A capability-defined agent (declared by a package or member module, such as
|
|
508
|
+
the OKF harvester) homes under the agents root exactly like a soul; its
|
|
509
|
+
directory holds only `instances/`. A name that is both a workspace soul and a
|
|
510
|
+
capability agent is ambiguous (`E_SOUL_AMBIGUOUS`).
|
|
511
|
+
|
|
512
|
+
There are no local souls. A soul is a member repository's `souls/<name>`
|
|
513
|
+
(`soul.yaml` + `AGENTS.md`); author it there and run `oats sync`. OATS 0.25
|
|
514
|
+
and earlier kept local souls and capability-agent homes under
|
|
515
|
+
`<scope>/local-agents/`: this kernel never reads, spawns into or retires from
|
|
516
|
+
that directory; it only detects it. Onboarding refuses into a directory that
|
|
517
|
+
holds one, and `oats status` and `oats doctor` report it once, as the
|
|
518
|
+
`legacy-local-agents` problem naming the instances found there; retire them
|
|
519
|
+
with the 0.25 kernel, or delete the directory once they are stopped.
|
|
520
|
+
|
|
521
|
+
A *captured home* (spawned through 0.24–0.25's captured path, removed in 0.26:
|
|
522
|
+
its `instance.json` records `executionBinding`, `incarnationId` or `captured`) is
|
|
523
|
+
reported by `oats status` and `oats doctor` as the `legacy-captured-home`
|
|
524
|
+
problem. It has no 0.26 runtime: start, restart, inspect/readiness/operation
|
|
525
|
+
`--home` and its in-home commands refuse it (`E_UNSUPPORTED_MODE`). `oats retire`
|
|
526
|
+
still works; it warns once per capability whose retire hook did NOT run, since
|
|
527
|
+
identities and memberships those capabilities created are not revoked — remove
|
|
528
|
+
them with the provider's own tooling. Re-spawn the soul from the deployment.
|
|
516
529
|
|
|
517
530
|
Alternative agents-root layouts are planned but not built. Today the default
|
|
518
531
|
layout is the only implemented layout.
|