@awebai/oats 0.27.2 → 0.29.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/bin/oats.mjs +445 -96
- package/capabilities/oats-okf/bin/oats-okf.mjs +55 -30
- package/capabilities/oats-okf/injects/okf.md +36 -28
- package/capabilities/oats-okf/lib/binding-wire.mjs +4 -1
- package/capabilities/oats-okf/lib/config.mjs +6 -1
- package/capabilities/oats-okf/lib/consult.mjs +496 -0
- package/capabilities/oats-okf/lib/harvest-status.mjs +88 -0
- package/capabilities/oats-okf/lib/harvest-switch.mjs +81 -0
- package/capabilities/oats-okf/lib/inspection.mjs +11 -3
- package/capabilities/oats-okf/lib/io.mjs +9 -2
- package/capabilities/oats-okf/lib/okf-validate.mjs +123 -0
- package/capabilities/oats-okf/lib/sources.mjs +42 -55
- package/capabilities/oats-okf/lib/stores.mjs +19 -11
- package/capabilities/oats-okf/lib/worker.mjs +90 -8
- package/capabilities/oats-okf/oats.json +24 -9
- package/capabilities/oats-okf/skills/okf-consultation/SKILL.md +144 -0
- package/capabilities/oats-okf/skills/okf-consultation/references/consult.md +86 -0
- package/capabilities/oats-okf/skills/okf-instance-knowledge/SKILL.md +104 -0
- package/capabilities/oats-okf-harvest/bin/okf-harvest.mjs +140 -0
- package/capabilities/oats-okf-harvest/injects/harvester.md +12 -0
- package/capabilities/oats-okf-harvest/oats.json +26 -0
- package/capabilities/oats-okf-harvest/skills/knowledge-harvest/SKILL.md +168 -0
- package/capabilities/oats-okf-harvest/skills/knowledge-theory/SKILL.md +192 -0
- package/capabilities/{oats-okf/skills/okf → oats-okf-harvest/skills/okf-authoring}/SKILL.md +15 -22
- package/capabilities/oats-okf-maintenance/bin/okf-maintenance.mjs +149 -0
- package/capabilities/oats-okf-maintenance/injects/maintainer.md +12 -0
- package/capabilities/oats-okf-maintenance/lib/provenance.mjs +45 -0
- package/capabilities/oats-okf-maintenance/oats.json +21 -0
- package/capabilities/oats-okf-maintenance/skills/knowledge-review/SKILL.md +144 -0
- package/capabilities/oats-okf-maintenance/skills/knowledge-theory/SKILL.md +192 -0
- package/capabilities/oats-okf-maintenance/skills/okf-authoring/SKILL.md +151 -0
- package/capabilities/oats-okf-maintenance/skills/okf-authoring/scripts/okf-validate.mjs +123 -0
- package/capabilities/oats-okf-maintenance/skills/okf-trigger-setup/SKILL.md +146 -0
- package/capabilities/oats-review/injects/review.md +3 -2
- package/capabilities/oats-review/oats.json +3 -4
- package/docs/capabilities.md +41 -9
- package/docs/capability-manifest.schema.json +0 -7
- package/docs/design/2026-09-24-phase-d-plan.md +11 -0
- package/docs/design/2026-09-26-desktop-design-brief-architecture.md +241 -0
- package/docs/design/2026-09-26-okf-knowledge-operations.md +389 -0
- package/docs/desktop-cli-api.md +342 -10
- package/docs/implementation.md +1 -1
- package/docs/knowledge-capability-authoring.md +8 -2
- package/docs/knowledge-reference/package-craft.md +8 -5
- package/docs/knowledge.md +101 -0
- package/docs/oats-local.schema.json +33 -2
- package/docs/oats-package.schema.json +39 -0
- package/docs/official-catalog.md +7 -4
- package/docs/packages.md +76 -6
- package/docs/release-lane.md +1 -1
- package/docs/release-notes/v0.28.0.md +144 -0
- package/docs/release-notes/v0.29.0.md +240 -0
- package/docs/schedules.md +230 -4
- package/docs/souls-and-instances.md +11 -9
- package/docs/workspaces.md +18 -3
- package/lib/automations.mjs +369 -0
- package/lib/core.mjs +87 -158
- package/lib/instance-inspect.mjs +16 -8
- package/lib/instance-resolution.mjs +90 -197
- package/lib/materialize.mjs +18 -7
- package/lib/operator-dispatch.mjs +1 -2
- package/lib/packages.mjs +107 -6
- package/lib/remote.mjs +21 -1
- package/lib/resolve.mjs +71 -9
- package/lib/schedule.mjs +228 -45
- package/lib/triggers.mjs +678 -0
- package/lib/workspace.mjs +81 -4
- package/package-catalog.json +6 -4
- package/package.json +1 -1
- package/capabilities/oats-okf/agents/memory-harvest/AGENTS.md +0 -21
- package/capabilities/oats-okf/agents/memory-harvest/soul.yaml +0 -5
- package/capabilities/oats-okf/skills/memory-harvest/SKILL.md +0 -285
- package/capabilities/oats-review/agents/reviewer/AGENTS.md +0 -53
- package/capabilities/oats-review/agents/reviewer/soul.yaml +0 -6
- /package/capabilities/{oats-okf/skills/okf → oats-okf-harvest/skills/okf-authoring}/scripts/okf-validate.mjs +0 -0
package/docs/schedules.md
CHANGED
|
@@ -10,7 +10,7 @@ is `E_LOCAL_MISSING`. Scheduled spawns materialize exactly like `oats spawn`.
|
|
|
10
10
|
Execution belongs to the host that holds the scope, so a schedule on a
|
|
11
11
|
registered server keeps running while your laptop sleeps.
|
|
12
12
|
|
|
13
|
-
There is no daemon. One host timer (a launchd user agent on macOS, a systemd
|
|
13
|
+
[Triggers](#triggers) are evaluated by the same tick. There is no daemon. One host timer (a launchd user agent on macOS, a systemd
|
|
14
14
|
user timer on Linux) runs `oats schedule tick --host` once a minute; the tick
|
|
15
15
|
is a short-lived process that evaluates only the current minute, launches
|
|
16
16
|
what is due through the same `spawn`, `session start` and `session input`
|
|
@@ -39,7 +39,7 @@ see [Captured definitions](#captured-definitions-removed-in-026).
|
|
|
39
39
|
## Kinds
|
|
40
40
|
|
|
41
41
|
- **spawn** `{id, enabled, cron, tz, kind: "spawn", agent, agentsRoot?,
|
|
42
|
-
repo?, backend?, purpose?, task, harness?, model?, yolo?, wake?}` — every
|
|
42
|
+
repo?, backend?, purpose?, task, launchConfig?, harness?, model?, yolo?, wake?}` — every
|
|
43
43
|
due minute launches one disposable instance of `agent` with the same
|
|
44
44
|
options `oats spawn` takes. `agentsRoot` names the exact agents root that
|
|
45
45
|
holds the soul (it must lie inside the workspace and defaults to the
|
|
@@ -89,6 +89,220 @@ required IANA zone; both are evaluated by the croner library. `--wake-every
|
|
|
89
89
|
N` at spawn time means `*/N * * * *`: every 7 fires at :00, :07, ... :56 and
|
|
90
90
|
then :00 again, so 1, 5, 10, 15 and 30 give an even cadence.
|
|
91
91
|
|
|
92
|
+
## Triggers
|
|
93
|
+
|
|
94
|
+
A **trigger** (OATS 0.28.0, feature `triggers`) is an event-driven schedule:
|
|
95
|
+
"when EVENT matches, spawn a NEW instance of SOUL with TASK, in TEAMS". It is
|
|
96
|
+
stored in the same `oats-schedules.json` as a job of `kind: "trigger"`,
|
|
97
|
+
managed with `oats trigger …` (never `oats schedule …`, which neither lists nor
|
|
98
|
+
edits one), and evaluated by the same host tick (`oats schedule tick --host`,
|
|
99
|
+
and `oats schedule tick` for one scope). There is no daemon and no webhook: it
|
|
100
|
+
runs only on the host that holds the scope, with **that host's own
|
|
101
|
+
credentials**; a definition carries none.
|
|
102
|
+
|
|
103
|
+
**Credentials reach the tick through the host timer, not your shell.** The
|
|
104
|
+
timer (a user LaunchAgent on macOS, a `systemd --user` unit on Linux) runs the
|
|
105
|
+
tick with its own environment, which sets only `PATH` and `OATS_HOME_DIR`. `gh`
|
|
106
|
+
logged in with the keyring or its config file under your HOME works there. A
|
|
107
|
+
`GH_TOKEN` or `GITHUB_TOKEN` exported in your shell does not reach it.
|
|
108
|
+
`oats trigger test` reports where `gh`'s credential comes from (`gh.credentialSource`:
|
|
109
|
+
`keyring`, `config`, `env:<VAR>`) and warns when the timer cannot reach it.
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{ "id": "okf-harvest-review", "enabled": true, "kind": "trigger",
|
|
113
|
+
"on": { "source": "github.pull_request", "repo": "github.com/acme/knowledge",
|
|
114
|
+
"events": ["opened", "reopened", "ready_for_review"],
|
|
115
|
+
"labels": ["okf-harvest"], "base": "main", "poll": "2m" },
|
|
116
|
+
"spawn": { "soul": "oats.okf/knowledge-maintainer", "purpose": "review-pr-{number}",
|
|
117
|
+
"task": "Review knowledge-base PR {repo}#{number}. Load knowledge-review first.",
|
|
118
|
+
"teams": ["okf"], "harness": "claude", "model": "opus" },
|
|
119
|
+
"concurrency": { "max": 2, "perKey": 1 } }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- **Source** `github.pull_request` (the only one in v1): the tick polls the
|
|
123
|
+
repository's open pull requests with the host's `gh` (`gh api repos/<owner>/<repo>/pulls`,
|
|
124
|
+
`state=open`, most recently updated first) every `poll` (default `2m`, at
|
|
125
|
+
least `1m`). `labels` (all must be present) and `base` filter them. A repo is
|
|
126
|
+
`github.com/<owner>/<repo>`; another host is passed to `gh` as `--hostname`.
|
|
127
|
+
- **Events** are inferred poll over poll: `opened` (a PR first seen, not a
|
|
128
|
+
draft; the first poll sees every open PR), `reopened` (seen closed, open
|
|
129
|
+
again), `ready_for_review` (was a draft), `labeled` (now carries the filter
|
|
130
|
+
labels it lacked; without a filter, any new label), `synchronize` (a new
|
|
131
|
+
head commit).
|
|
132
|
+
- **Dedup and retry.** Each event has a key
|
|
133
|
+
`<trigger>:<repo>#<number>:<event>:<stamp>` (`created_at` for `opened`, the
|
|
134
|
+
head SHA for `synchronize`, `updated_at` otherwise). A key is recorded as
|
|
135
|
+
fired **only after a successful spawn**; until then the event stays pending
|
|
136
|
+
and is retried at every poll, and dropped when its PR closes.
|
|
137
|
+
- **At least once, not exactly once.** The fired key is written after the
|
|
138
|
+
spawn returns. If the tick dies in between (a crash, a kill, the host going
|
|
139
|
+
down), the spawned instance exists but the key does not, and the next poll
|
|
140
|
+
spawns the event again. Concurrency still applies to that retry: with the
|
|
141
|
+
default `perKey: 1` the first instance is live, so the event is `held` rather
|
|
142
|
+
than spawned twice, and it fires once that instance retires. A trigger's soul
|
|
143
|
+
should therefore tolerate a second run on the same PR event (a review that
|
|
144
|
+
finds its own earlier review, for example).
|
|
145
|
+
- **Concurrency.** `max` (default 1) bounds the live instances of the trigger,
|
|
146
|
+
`perKey` (default 1) those of one PR; both are counted from the homes'
|
|
147
|
+
`instance.json.trigger` records, so a retired instance frees its slot. An
|
|
148
|
+
event over the bound stays pending (`held`).
|
|
149
|
+
- **The spawn** is `oats spawn` (the same path as a scheduled spawn). `soul` is
|
|
150
|
+
bare or qualified (`<package>/<soul>`). `purpose` (default
|
|
151
|
+
`{trigger}-{number}`, must render to a slug) and `task` are templated from
|
|
152
|
+
**only** `{repo} {number} {url} {event} {headSha} {trigger}`: a pull
|
|
153
|
+
request's title and body are untrusted and never reach the task (a template
|
|
154
|
+
naming any other field is refused). `teams` becomes the messaging
|
|
155
|
+
capability's `join=` setting (as `--provider <messaging cap> join=<labels>`).
|
|
156
|
+
`launchConfig` (a launch configuration in the running host's
|
|
157
|
+
`oats-local.yaml` `launch-configs`), `harness`, `model`, `yolo`, `backend`
|
|
158
|
+
are as for schedules; a package template may expose any of them as a
|
|
159
|
+
parameter (`"path": "spawn.launchConfig"`).
|
|
160
|
+
- **The event reaches the instance** as `OATS_TRIGGER_EVENT_FILE`
|
|
161
|
+
(`<home>/.oats/trigger-event.json`: `{ trigger, source, repo, number, url,
|
|
162
|
+
event, headSha, labels, observedAt, key }`), given to the spawn hooks and the
|
|
163
|
+
harness; `instance.json.trigger` records `{ id, key, source, repo, number,
|
|
164
|
+
url, event, headSha, observedAt, eventFile }`. The task ends with a short
|
|
165
|
+
block naming the event file.
|
|
166
|
+
- **State** lives in `<scope>/.agents/schedules/triggers.json` (last poll, the
|
|
167
|
+
PRs seen, pending events, fired keys, the last error).
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
oats trigger add --file trigger.json # or:
|
|
171
|
+
oats trigger add --from oats.okf:harvest-review --set repo=github.com/acme/knowledge [--id <id>]
|
|
172
|
+
oats trigger list | show <id> | enable <id> | disable <id> | remove <id>
|
|
173
|
+
oats trigger test <id> # dry run: gh auth + credential source, repo + permissions (push/maintain/admin), the soul resolves,
|
|
174
|
+
# its messaging capability, the teams declared, what WOULD fire now; spawns nothing
|
|
175
|
+
oats trigger status [<id>] # last poll, next due, pending, fired keys (time, instance), live vs max, last error
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
All take `--dir` and `--json` (`triggerApi: 1`). `remove` leaves the instances
|
|
179
|
+
it spawned running. `oats schedule list` does not list triggers, but it counts
|
|
180
|
+
them (`triggers: { count, command: "oats trigger list" }`, and a line in text
|
|
181
|
+
mode). Errors: `E_TRIGGER_INVALID { field }`, `E_TRIGGER_EXISTS`,
|
|
182
|
+
`E_TRIGGER_UNKNOWN`, `E_BAD_ARGS`.
|
|
183
|
+
|
|
184
|
+
**Package trigger templates.** A package may declare `triggers: [{ id, file }]`
|
|
185
|
+
in `oats-package.json`. Each file is `{ parameters: { <name>: { path,
|
|
186
|
+
required?, default?, description? } }, definition: { …a trigger… } }`.
|
|
187
|
+
`oats trigger add --from <package>:<id>` reads it at the locked commit;
|
|
188
|
+
`--set <name>=<value>` fills a parameter at its dotted `path` (a list value is
|
|
189
|
+
comma-separated); a required parameter without a value is `E_BAD_ARGS
|
|
190
|
+
{ missing }` naming it. The trigger records `template: { package, version,
|
|
191
|
+
commit, template }`.
|
|
192
|
+
|
|
193
|
+
## Workspace triggers and schedules
|
|
194
|
+
|
|
195
|
+
(OATS 0.29.0, feature `automations`.) A trigger or a schedule is defined at one of
|
|
196
|
+
two levels:
|
|
197
|
+
|
|
198
|
+
- **in the workspace**: a file committed in a confirmed member repository, shared
|
|
199
|
+
through Git and named `<member>/<id>`. This is the default for anything a team
|
|
200
|
+
relies on.
|
|
201
|
+
- **locally**: in the deployment's `oats-schedules.json` (`oats trigger add`,
|
|
202
|
+
`oats schedule add`), machine-private and named `local/<id>`.
|
|
203
|
+
|
|
204
|
+
The two kinds stay separate at every step. Each has its own folder, its own file
|
|
205
|
+
kind, its own ids, its own commands, its own list and its own opt-out.
|
|
206
|
+
|
|
207
|
+
| | trigger | schedule |
|
|
208
|
+
| --- | --- | --- |
|
|
209
|
+
| canonical folder (at the member's root) | `oats-triggers/` | `oats-schedules/` |
|
|
210
|
+
| file name anywhere in the member | `*.oats-trigger.yaml` | `*.oats-schedule.yaml` |
|
|
211
|
+
| `kind:` | `oats-trigger` | `oats-schedule` |
|
|
212
|
+
| body | `from:` + `set:` (a package template), or `on`, `spawn`, `concurrency` as above | `run: spawn \| command`, `cron`, `tz`, `agent`, `task`, `purpose`, `launchConfig`, `harness`, `model`, `yolo`, `backend`, `wake`, `argv`, `cwd` |
|
|
213
|
+
| commands | `oats trigger …` | `oats schedule …` |
|
|
214
|
+
| opt-out on this host | `triggers.disabled` | `schedules.disabled` |
|
|
215
|
+
|
|
216
|
+
Every `.yaml`/`.yml` under a canonical folder is a candidate, and so is a file with
|
|
217
|
+
the kind's suffix anywhere in the member (`.yml` works too), e.g.
|
|
218
|
+
`services/billing/nightly.oats-schedule.yaml` beside the code it concerns.
|
|
219
|
+
`oats-package/`, `.git/` and `node_modules/` are never scanned.
|
|
220
|
+
|
|
221
|
+
```yaml
|
|
222
|
+
# <member>/oats-triggers/okf-harvest-review.yaml
|
|
223
|
+
kind: oats-trigger
|
|
224
|
+
schemaVersion: 1
|
|
225
|
+
description: Review every harvest PR on the knowledge base
|
|
226
|
+
from: oats.okf:harvest-review # a package template at the locked commit, then its parameters
|
|
227
|
+
set: { repo: github.com/acme/knowledge }
|
|
228
|
+
runsOn: kb-bot-server # the host.name that runs it
|
|
229
|
+
owner: github.com/acme-kb-bot # the GitHub account it acts as
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```yaml
|
|
233
|
+
# <member>/services/billing/nightly.oats-schedule.yaml
|
|
234
|
+
kind: oats-schedule
|
|
235
|
+
schemaVersion: 1
|
|
236
|
+
run: spawn
|
|
237
|
+
cron: "0 7 * * *"
|
|
238
|
+
tz: Europe/Madrid
|
|
239
|
+
agent: digest-writer # resolved like `oats spawn <soul>` (member or package soul)
|
|
240
|
+
task: Write the nightly digest.
|
|
241
|
+
runsOn: ana-laptop
|
|
242
|
+
owner: github.com/ana
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
- **The file describes itself.** It carries `kind` and `schemaVersion: 1`. A
|
|
246
|
+
candidate of the wrong kind (a schedule in `oats-triggers/`) or without one is an
|
|
247
|
+
`E_AUTOMATION_SCHEMA` problem, never silently skipped.
|
|
248
|
+
- **The id** is `id:`, else the filename stem. The same id twice in one member for
|
|
249
|
+
one kind is `E_AUTOMATION_DUPLICATE`, naming both paths; the second file is not
|
|
250
|
+
listed. A trigger and a schedule may share an id: they are different things.
|
|
251
|
+
- **A workspace schedule is `run: spawn` or `run: command`.** A `command`'s `cwd` is
|
|
252
|
+
relative to the deployment. `wake` and `operation` target an instance home on one
|
|
253
|
+
machine, so they stay local.
|
|
254
|
+
|
|
255
|
+
**Who runs it.** A host runs a workspace trigger or schedule only when both of these
|
|
256
|
+
hold:
|
|
257
|
+
|
|
258
|
+
1. its `runsOn` is this host's `host.name` in `oats-local.yaml`;
|
|
259
|
+
2. the host's authenticated `gh` account (`gh api user`, asked once per tick) is its
|
|
260
|
+
`owner`.
|
|
261
|
+
|
|
262
|
+
Otherwise the item is listed with a reason:
|
|
263
|
+
|
|
264
|
+
- `assigned-elsewhere`: another host runs it;
|
|
265
|
+
- `owner-mismatch`: this host is named, but its `gh` is logged in as someone else or
|
|
266
|
+
not at all. Nothing runs, the tick reports it, and `oats trigger test` says so;
|
|
267
|
+
- `host-unnamed`: this host has no `host.name`.
|
|
268
|
+
|
|
269
|
+
So exactly one machine runs it, and consent is explicit: the machine's operator
|
|
270
|
+
named the host and is logged in as the account.
|
|
271
|
+
|
|
272
|
+
**Opting out** without a commit: `oats trigger disable <member>/<id>` writes
|
|
273
|
+
`triggers.disabled`, and `oats schedule disable <member>/<id>` writes
|
|
274
|
+
`schedules.disabled`, in `oats-local.yaml`. `enable` removes the entry. A
|
|
275
|
+
workspace definition is never edited or removed here (`update` and `remove` are
|
|
276
|
+
`E_AUTOMATION_WORKSPACE`): change the file in Git.
|
|
277
|
+
|
|
278
|
+
**Refresh.**
|
|
279
|
+
|
|
280
|
+
- `oats sync` discovers the workspace triggers and schedules of the confirmed
|
|
281
|
+
members into a snapshot, `.agents/automations/snapshot.json` in the deployment,
|
|
282
|
+
with one list per kind. It takes one tree listing per member commit.
|
|
283
|
+
- The host tick reads that snapshot. It refreshes it (`oats automations refresh`)
|
|
284
|
+
when the snapshot is more than ten minutes old, at most once per interval. When
|
|
285
|
+
the refresh fails, the last good snapshot keeps serving.
|
|
286
|
+
- A change in Git therefore reaches the named host within about ten minutes.
|
|
287
|
+
- The run state (dedup keys, last poll, last run) stays per host and local. A
|
|
288
|
+
workspace schedule's job lock and state are keyed `<member>~<id>`.
|
|
289
|
+
- A trigger template (`from:`) is instantiated when the snapshot is taken, at the
|
|
290
|
+
commit the host's lock pins.
|
|
291
|
+
|
|
292
|
+
**Writing one.** Add `--workspace <member> --runs-on <host> --owner <host>/<login>`
|
|
293
|
+
to `oats trigger add` or `oats schedule add`:
|
|
294
|
+
|
|
295
|
+
- Run inside a checkout of that member, it writes `oats-triggers/<id>.yaml` or
|
|
296
|
+
`oats-schedules/<id>.yaml` there, for you to commit and push.
|
|
297
|
+
- Anywhere else, it prints the file.
|
|
298
|
+
- Either way, the file is read back and validated first.
|
|
299
|
+
- `oats trigger test <member>/<id>` checks the placement, and everything else it
|
|
300
|
+
checked before, on this host.
|
|
301
|
+
|
|
302
|
+
Everything above still holds: the soul must resolve here, templates name only the
|
|
303
|
+
whitelisted fields, a PR's text is never interpolated, and no definition carries a
|
|
304
|
+
credential.
|
|
305
|
+
|
|
92
306
|
## Captured definitions (removed in 0.26)
|
|
93
307
|
|
|
94
308
|
0.24–0.25 could save captured command definitions: `definitionVersion`,
|
|
@@ -119,6 +333,7 @@ oats schedule add <id> --file spec.json --dir <workspace> --json
|
|
|
119
333
|
oats schedule update <id> --file spec.json
|
|
120
334
|
oats schedule list | show <id> | enable <id> | disable <id> | remove <id>
|
|
121
335
|
oats schedule run <id> # now, under the same lock and bound
|
|
336
|
+
oats schedule test <id> # dry run: where it runs, whether its soul resolves, when it is next due; spawns nothing
|
|
122
337
|
oats schedule tick --dry-run # what would run this minute, launching nothing
|
|
123
338
|
oats schedule reconcile <id> [--clear] # resolve an attempt whose result was never recorded
|
|
124
339
|
oats schedule host install # register this scope and install the ONE host timer (idempotent while active)
|
|
@@ -129,8 +344,9 @@ oats spawn <agent> ... --wake-every 15 --wake-message "Anything new?" # or --w
|
|
|
129
344
|
Every subcommand takes `--server <id>` instead of `--dir`: it then runs on
|
|
130
345
|
that host, in its registered workspace, because schedules are host-owned.
|
|
131
346
|
|
|
132
|
-
`list --json` answers `{schedules: [{id, ...definition,
|
|
133
|
-
running}], scheduler: {installed, active, lastTick, maxConcurrent, ...}}
|
|
347
|
+
`list --json` answers `{schedules: [{id, ...definition, nextDue, lastRun,
|
|
348
|
+
running}], scheduler: {installed, active, lastTick, maxConcurrent, ...}}`
|
|
349
|
+
(`oats trigger list --json` carries the same `scheduler`).
|
|
134
350
|
`active` is what the OS reports about the timer, not whether a file exists.
|
|
135
351
|
|
|
136
352
|
## What a run reports
|
|
@@ -194,6 +410,16 @@ the instance is neither hidden nor spawned again.
|
|
|
194
410
|
|
|
195
411
|
## OKF v2 source jobs
|
|
196
412
|
|
|
413
|
+
> **oats.okf 4.0.0:** a source and its job exist only where harvest is
|
|
414
|
+
> effectively on (`harvest: on|off`, default off), and the job spawns the
|
|
415
|
+
> harvester package soul. The review of its PR runs as a **trigger**, run by
|
|
416
|
+
> the same host tick: a workspace file (`oats-triggers/okf-harvest-review.yaml`
|
|
417
|
+
> in a member repo, `kind: oats-trigger`, with `runsOn` and `owner`), or a
|
|
418
|
+
> local one in this file. See
|
|
419
|
+
> [knowledge.md](knowledge.md#knowledge-operations), [Triggers](#triggers) and
|
|
420
|
+
> [Workspace triggers and schedules](#workspace-triggers-and-schedules); the
|
|
421
|
+
> trigger commands are `oats trigger …`.
|
|
422
|
+
|
|
197
423
|
The [prepared OKF v2 runtime](knowledge.md) registers **one command job per
|
|
198
424
|
source**, not a fleet sweep or a home-bound operation job. It runs from stable
|
|
199
425
|
deployment context with argv equivalent to:
|
|
@@ -196,9 +196,13 @@ refused (`E_INSTANCE_NAME_TAKEN`).
|
|
|
196
196
|
|
|
197
197
|
From a deployment (where `oats-local.yaml` is), a spawn: reads the local file →
|
|
198
198
|
discovers the workspace over its remotes and confirms membership → finds the
|
|
199
|
-
soul among the confirmed members
|
|
200
|
-
|
|
201
|
-
`<
|
|
199
|
+
soul among the confirmed members, `external:` souls and the locked packages'
|
|
200
|
+
souls (an ambiguous bare name is `E_SOUL_AMBIGUOUS`, naming each qualified
|
|
201
|
+
form: `<member>/<soul>` or `<package>/<soul>`; a soul listed in
|
|
202
|
+
`oats-local.yaml` `souls.disabled` is `E_SOUL_DISABLED`) → fetches the soul's
|
|
203
|
+
source into `<agents-root>/<soul>/souls/<commit12>/` at its commit (a package
|
|
204
|
+
soul at the locked commit, verified against the lock's digest — see
|
|
205
|
+
[package souls](packages.md#package-souls); the home links that
|
|
202
206
|
directory; `<agents-root>/<soul>/soul` points at the current one) → resolves
|
|
203
207
|
every capability by
|
|
204
208
|
`from:` (member = latest, package = locked) → creates the home →
|
|
@@ -512,14 +516,12 @@ Default layout:
|
|
|
512
516
|
docs-expert/ # a workspace soul, defined in a member repository's
|
|
513
517
|
souls/<commit12>/ # souls/docs-expert/ and copied here per commit
|
|
514
518
|
instances/
|
|
515
|
-
memory-harvest/ # a capability-defined agent: only instances/, no soul
|
|
516
|
-
instances/
|
|
517
519
|
```
|
|
518
520
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
521
|
+
Every agent is a soul — a member soul, or a package soul homed under
|
|
522
|
+
`agents/<package>--<soul>/`. A capability-defined agent (a manifest's
|
|
523
|
+
`agents:`) was removed in 0.29.0; a home an earlier kernel left for one (its
|
|
524
|
+
directory holds only `instances/`) is still listed and retirable.
|
|
523
525
|
|
|
524
526
|
There are no local souls. A soul is a member repository's `souls/<name>`
|
|
525
527
|
(`soul.yaml` + `AGENTS.md`); author it there and run `oats sync`. OATS 0.25
|
package/docs/workspaces.md
CHANGED
|
@@ -59,8 +59,8 @@ members: # repo refs, NO @revision (E_WORKSPAC
|
|
|
59
59
|
- git:github.com/acme/tools # a member that ALSO publishes a package (see below)
|
|
60
60
|
|
|
61
61
|
packages: # the ONLY versioned things
|
|
62
|
-
oats.framework: v1.
|
|
63
|
-
oats.okf:
|
|
62
|
+
oats.framework: v1.3.0 # bare version → resolves through the official catalog
|
|
63
|
+
oats.okf: v4.0.0
|
|
64
64
|
acme.tools: git:github.com/acme/tools@v0.4.0 # outside the catalog → git:<repo>@<tag|OID>; still a package
|
|
65
65
|
|
|
66
66
|
teams: # labels, declared once so they cannot drift
|
|
@@ -168,9 +168,18 @@ settings: # host-owned values the manifests ask
|
|
|
168
168
|
bindings-file: /Users/ana/.oats/okf-bindings.json
|
|
169
169
|
state-dir: /Users/ana/.oats/okf
|
|
170
170
|
souls:
|
|
171
|
-
disabled: [data-analyst] # not run on this machine
|
|
171
|
+
disabled: [data-analyst] # not run on this machine (E_SOUL_DISABLED); oats.okf/knowledge-harvester names a package soul
|
|
172
|
+
host:
|
|
173
|
+
name: ana-laptop # this machine's name: runs the workspace triggers/schedules whose runsOn names it
|
|
174
|
+
triggers:
|
|
175
|
+
disabled: [knowledge/okf-harvest-review] # workspace triggers this host does not run (oats trigger disable)
|
|
176
|
+
schedules:
|
|
177
|
+
disabled: [platform/nightly-digest] # workspace schedules this host does not run (oats schedule disable)
|
|
172
178
|
```
|
|
173
179
|
|
|
180
|
+
`host`, `triggers.disabled` and `schedules.disabled` (0.29.0) are machine facts:
|
|
181
|
+
see [schedules.md#workspace-triggers-and-schedules](schedules.md#workspace-triggers-and-schedules).
|
|
182
|
+
|
|
174
183
|
See [configuration.md](configuration.md). `oats-config.yaml` no longer exists.
|
|
175
184
|
|
|
176
185
|
### `oats-lock.json` — lock v3
|
|
@@ -230,6 +239,12 @@ read; the soul gets no member-tier capabilities of its own repo; it is
|
|
|
230
239
|
"source-complete" (its skills travel with it) and the workspace's defaults fill
|
|
231
240
|
its slots. An `external[].team` overrides the soul's own `team`.
|
|
232
241
|
|
|
242
|
+
**Package souls.** A package may ship souls (`souls:` in `oats-package.json`,
|
|
243
|
+
0.28.0): they are listed from the lock for each package the workspace declares,
|
|
244
|
+
named `<package>/<soul>` (a bare name when unique), resolved like any soul
|
|
245
|
+
(`from: here` = their own package at the locked commit) and trusted as the
|
|
246
|
+
package is. See [packages](packages.md#package-souls).
|
|
247
|
+
|
|
233
248
|
## Member tier vs package tier — the non-collapse rule
|
|
234
249
|
|
|
235
250
|
A repository may be a **member** (it completed the handshake; its `souls/*` and
|