@awebai/oats 0.25.9 → 0.27.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 +648 -1755
- 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 +229 -58
- package/docs/capability-manifest.schema.json +29 -9
- package/docs/configuration.md +17 -5
- package/docs/conventions.md +18 -28
- 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 +604 -271
- package/docs/desktop-instance-start.md +3 -3
- package/docs/desktop.md +7 -13
- package/docs/execution-targets.md +16 -18
- package/docs/first-team.md +15 -18
- package/docs/implementation.md +31 -62
- 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 +30 -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 +76 -53
- 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/release-notes/v0.27.0.md +100 -0
- package/docs/schedules.md +54 -132
- package/docs/servers.md +4 -4
- package/docs/soul.schema.json +11 -4
- package/docs/souls-and-instances.md +60 -47
- package/docs/workspaces.md +80 -58
- package/injects/instance-boundary.md +2 -2
- 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 +947 -5023
- package/lib/deprecation.mjs +24 -0
- package/lib/digest.mjs +12 -0
- package/lib/instance-inspect.mjs +397 -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/process-group.mjs +1 -1
- package/lib/provider-binding.mjs +4 -2
- package/lib/provider-reasons.mjs +3 -68
- package/lib/remote.mjs +1 -1
- package/lib/resolve.mjs +204 -68
- package/lib/schedule.mjs +136 -292
- package/lib/servers.mjs +70 -38
- package/lib/{portable-shape.mjs → shape.mjs} +4 -3
- package/lib/tree-copy.mjs +44 -0
- package/lib/workspace.mjs +132 -20
- package/package-catalog.json +6 -6
- package/package.json +1 -1
- package/packages/record/lib/session-roots.mjs +8 -6
- 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
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# OATS 0.27.0
|
|
2
|
+
|
|
3
|
+
What starts an instance (pi, claude or codex) is now called its **harness**
|
|
4
|
+
everywhere the kernel used to say `runtime`: in flags, configuration, records,
|
|
5
|
+
JSON and error codes. Nothing already written stops working. The rule is read
|
|
6
|
+
either, write new: every spelling from before 0.27.0 is still read, and the
|
|
7
|
+
next write records the new one. A command that reads an old spelling answers
|
|
8
|
+
one `deprecated-runtime-name` warning, and a later release drops the old
|
|
9
|
+
spellings. See [Upgrading from 0.26](#upgrading-from-026).
|
|
10
|
+
|
|
11
|
+
## Changed
|
|
12
|
+
|
|
13
|
+
- **runtime → harness.** [The Desktop CLI API](../desktop-cli-api.md#the-harness-rename-feature-harness-oats-0270)
|
|
14
|
+
has the complete table. In short:
|
|
15
|
+
- Flags: `--harness` replaces `--runtime` on `spawn` (and `--preview`),
|
|
16
|
+
`session start|restart` and `launch-config preview`, including their
|
|
17
|
+
`--server` forms. `--runtime` is still accepted, with the warning. The
|
|
18
|
+
two given with different values are refused (`E_BAD_ARGS`).
|
|
19
|
+
- `oats-local.yaml`: a launch configuration names `harness:`. `runtime:` is
|
|
20
|
+
still read, with the warning. Both, disagreeing, is a schema error
|
|
21
|
+
(`E_WORKSPACE_SCHEMA`). `oats launch-config set` writes `harness`.
|
|
22
|
+
- Schedules: a spawn job names `harness`. A job stored with `runtime` is
|
|
23
|
+
read as `harness`, with the warning, and saved in the new name next time.
|
|
24
|
+
Both, disagreeing, makes that job invalid (`E_SCHEDULE_INVALID`).
|
|
25
|
+
`lastRun`/`recentRuns` record `startedHarness` (was `startedRuntime`).
|
|
26
|
+
- Homes: `instance.json` records `harness`, and the launch recipe is version
|
|
27
|
+
**2** (`harness`; version 1 said `runtime`). A home spawned by 0.26.0 is
|
|
28
|
+
read in the new names, with the warning naming the home. It inspects,
|
|
29
|
+
starts, restarts and retires as before, and its next start or restart
|
|
30
|
+
records the new names.
|
|
31
|
+
- `soul.yaml` names `harness:`. `runtime:` is still read, **without** a
|
|
32
|
+
warning, because released capabilities ship it (oats.aweb 1.13.1's agents)
|
|
33
|
+
and an operator cannot fix a provider's file. Both, disagreeing:
|
|
34
|
+
`E_BAD_MANIFEST`. The same holds for a capability manifest's
|
|
35
|
+
`requires[]` harness package (`harness`, or `runtime`, never both).
|
|
36
|
+
- Hooks get `OATS_HARNESS` and `OATS_PREVIOUS_HARNESS` beside
|
|
37
|
+
`OATS_RUNTIME` and `OATS_PREVIOUS_RUNTIME`, with the same values.
|
|
38
|
+
- JSON outputs speak only the new names:
|
|
39
|
+
- `oats version --json` lists `harnesses` (no `runtimes`) and the feature
|
|
40
|
+
`harness`;
|
|
41
|
+
- `harness` replaces `runtime` in the status, inspect, spawn, preview,
|
|
42
|
+
session, launch-config, schedule and event documents;
|
|
43
|
+
- `harnessPackages` and `harnessPosture` replace `runtimePackages` and
|
|
44
|
+
`runtimePosture` in `composition.materialized`;
|
|
45
|
+
- the launch plan's package check (`launch-config preview` `problems[]`)
|
|
46
|
+
is `harness-packages`, and package verification's `loadedBy` is
|
|
47
|
+
`harness-discovery`.
|
|
48
|
+
- Error codes: `E_UNSUPPORTED_HARNESS`, `E_HARNESS_PACKAGE` and
|
|
49
|
+
`E_HARNESS_RESOURCE_MISSING` replace `E_UNSUPPORTED_RUNTIME`,
|
|
50
|
+
`E_RUNTIME_PACKAGE` and `E_RUNTIME_RESOURCE_MISSING`.
|
|
51
|
+
- JSON envelopes may carry `warnings: [...]`, only when there is something
|
|
52
|
+
to say. `oats status --json` carries it beside `problems`. In text mode,
|
|
53
|
+
a warning is one `oats: warning: …` line on stderr.
|
|
54
|
+
- Routed commands (`--server`) speak each host's own vocabulary. A host
|
|
55
|
+
without the `harness` feature (0.26.x and older) is sent `--runtime` and
|
|
56
|
+
`runtime` keys, and its `runtimes` list and `runtime` roster rows are read
|
|
57
|
+
as harnesses.
|
|
58
|
+
- A spawn decision previewed by a 0.26 kernel is `E_DECISION_STALE` at a
|
|
59
|
+
0.27 apply (the revision covers the key names), with the fresh decision
|
|
60
|
+
attached.
|
|
61
|
+
- Unchanged, because they do not name the harness: the session endpoint's
|
|
62
|
+
`runtimeAuthority`, `runtimeState` and `runtimeError`, the
|
|
63
|
+
`E_RUNTIME_ENDPOINT_*`, `E_RUNTIME_AUTHORITY_MISMATCH` and
|
|
64
|
+
`E_RUNTIME_QUIESCE_FAILED` codes, `capabilityRuntime`, the retirement
|
|
65
|
+
baseline, and oats.okf's `harvest-runtime` setting.
|
|
66
|
+
|
|
67
|
+
## Desktop
|
|
68
|
+
|
|
69
|
+
- **The Desktop speaks the harness names** on a kernel that declares feature
|
|
70
|
+
`harness` (`--harness`, `harness`/`harnesses`), and the old names on released
|
|
71
|
+
0.25.8–0.26.x kernels. It reads either spelling everywhere, shows only the
|
|
72
|
+
harness the kernel reports (no `pi` default for an instance that doesn't say),
|
|
73
|
+
and accepts kernels `>=0.25.8 <0.28.0`.
|
|
74
|
+
- **Core capabilities name their origin** (soul, workspace or team) on the soul
|
|
75
|
+
page and the instance sidebar, on a kernel with feature `layers-from`.
|
|
76
|
+
- The unused "the workspace's team settings" origin label is gone (0.26.0's
|
|
77
|
+
teams amendment K stopped emitting it).
|
|
78
|
+
|
|
79
|
+
## Fixed
|
|
80
|
+
|
|
81
|
+
- **0.26.0's notes said per-workspace personal teams need undeployed aweb
|
|
82
|
+
server support.** The aweb service (0.8.13 and later) and CLI (1.36.8 and
|
|
83
|
+
later) already carry personal enrollment; what remains is oats.aweb 1.15
|
|
84
|
+
adopting it. The bundled oats.aweb is still 1.13.1 (the personal team only);
|
|
85
|
+
the team verbs come with oats.aweb 1.14.1 in a 0.27.x patch.
|
|
86
|
+
|
|
87
|
+
## Upgrading from 0.26
|
|
88
|
+
|
|
89
|
+
Nothing to do. Old spellings keep working with a `deprecated-runtime-name`
|
|
90
|
+
warning, and a later release drops them. To stop the warning:
|
|
91
|
+
|
|
92
|
+
- write `harness:` for `runtime:` in `oats-local.yaml` launch configurations
|
|
93
|
+
(or re-save them with `oats launch-config set`);
|
|
94
|
+
- pass `--harness` for `--runtime` in scripts;
|
|
95
|
+
- re-save any schedule the warning names (`oats schedule update`). A stored
|
|
96
|
+
job is also rewritten on its next save.
|
|
97
|
+
|
|
98
|
+
A 0.26.0 home stops warning after its next start or restart. A Desktop that
|
|
99
|
+
gates on the `harness` feature reads the new names; an older Desktop reads
|
|
100
|
+
`runtimes` and `runtime` and needs its update.
|
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,19 +33,21 @@ 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
|
|
|
52
41
|
- **spawn** `{id, enabled, cron, tz, kind: "spawn", agent, agentsRoot?,
|
|
53
|
-
repo?, backend?, purpose?, task,
|
|
42
|
+
repo?, backend?, purpose?, task, harness?, model?, yolo?, wake?}` — every
|
|
54
43
|
due minute launches one disposable instance of `agent` with the same
|
|
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
|
-
|
|
207
|
-
a home whose retirement is pending still counts, its runtime may be alive),
|
|
138
|
+
`launched` (spawn or command returned), `active` (the instance is running;
|
|
139
|
+
a home whose retirement is pending still counts, its harness 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
|
|
@@ -230,13 +159,13 @@ unknown; check the roster and the host by hand, then
|
|
|
230
159
|
slot (or `remove --force` forgets the job).
|
|
231
160
|
|
|
232
161
|
A wake job that starts a stopped home holds a launch slot while that
|
|
233
|
-
|
|
234
|
-
the
|
|
162
|
+
harness is starting, active, retiring or unobservable, and releases it when
|
|
163
|
+
the harness is proven stopped (the session start receipt's exit marker for
|
|
235
164
|
that launch, or a home that no longer has a session) or the home is gone.
|
|
236
165
|
A persistent home that outlives its process does not keep a slot. Delivering
|
|
237
166
|
a message to a home that is already running takes no slot. The host tick
|
|
238
167
|
observes every registered scope first, then admits due jobs in one
|
|
239
|
-
host-wide order, least recently launched first (only an actual
|
|
168
|
+
host-wide order, least recently launched first (only an actual harness
|
|
240
169
|
launch counts; a skipped or pending job keeps its place at the front), so
|
|
241
170
|
one frequent job in one scope cannot keep the only slot forever. An invalid
|
|
242
171
|
or malformed definition is reported on that job and the rest of the tick
|
|
@@ -244,12 +173,11 @@ 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
|
-
observation releases it once the
|
|
180
|
+
observation releases it once the harness is proven stopped or absent, one tick
|
|
253
181
|
at worst.
|
|
254
182
|
`remove` refuses while the job's instance is still tracked (`--force`
|
|
255
183
|
forgets the job without stopping anything). Retiring an instance removes the
|
|
@@ -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/servers.md
CHANGED
|
@@ -25,8 +25,8 @@ oats server list
|
|
|
25
25
|
- `--path` names directories to prepend to the remote PATH for every routed
|
|
26
26
|
command (`~/.local/bin:/opt/pi/bin`). A non-interactive ssh command runs in
|
|
27
27
|
the login shell's minimal PATH, and the remote kernel's spawn preflight looks
|
|
28
|
-
for the
|
|
29
|
-
|
|
28
|
+
for the harness binary (`claude`, `pi`, `codex`) there; without this, a
|
|
29
|
+
harness installed under the user's home is "not found" even though it runs
|
|
30
30
|
fine in an interactive shell on that host.
|
|
31
31
|
- Registrations live in `~/.oats/servers.json` on this machine, never in a
|
|
32
32
|
repository scope.
|
|
@@ -44,13 +44,13 @@ worktree, identity, launch, retirement. The local side only routes: a local
|
|
|
44
44
|
`--task-file` travels as text, every argument is quoted for the remote login
|
|
45
45
|
shell, and the remote's version and envelope are checked before either
|
|
46
46
|
mutation (spawn and retire). A spawn is also held to what the remote
|
|
47
|
-
advertises: a
|
|
47
|
+
advertises: a harness it does not list (including the soul's own default as
|
|
48
48
|
the remote roster reports it), a session backend it lacks, or a launch option
|
|
49
49
|
such as `--yolo` it does not know is refused with `E_REMOTE_INCOMPATIBLE`
|
|
50
50
|
saying what was established. A remote that advertises nothing (any kernel
|
|
51
51
|
before 0.22.2) is assumed to run pi and claude on tmux with no options, and
|
|
52
52
|
the refusal says so rather than claiming the remote lacks the feature; a soul
|
|
53
|
-
the remote roster does not list with a
|
|
53
|
+
the remote roster does not list with a harness is validated by the remote
|
|
54
54
|
kernel itself at spawn. `--dir` and `--server` do not combine; the remote
|
|
55
55
|
workspace comes from the registration.
|
|
56
56
|
|
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
|
}
|