@awebai/oats 0.28.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/bin/oats.mjs +298 -107
  2. package/capabilities/oats-okf/bin/oats-okf.mjs +28 -8
  3. package/capabilities/oats-okf/injects/okf.md +33 -33
  4. package/capabilities/oats-okf/lib/binding-wire.mjs +4 -1
  5. package/capabilities/oats-okf/lib/config.mjs +2 -1
  6. package/capabilities/oats-okf/lib/consult.mjs +1 -5
  7. package/capabilities/oats-okf/lib/harvest-status.mjs +88 -0
  8. package/capabilities/oats-okf/lib/harvest-switch.mjs +81 -0
  9. package/capabilities/oats-okf/lib/okf-validate.mjs +123 -0
  10. package/capabilities/oats-okf/lib/sources.mjs +28 -3
  11. package/capabilities/oats-okf/lib/stores.mjs +9 -4
  12. package/capabilities/oats-okf/lib/worker.mjs +82 -8
  13. package/capabilities/oats-okf/oats.json +14 -8
  14. package/capabilities/oats-okf/skills/okf-consultation/SKILL.md +8 -6
  15. package/capabilities/oats-okf/skills/okf-consultation/references/consult.md +1 -1
  16. package/capabilities/oats-okf/skills/okf-instance-knowledge/SKILL.md +104 -0
  17. package/capabilities/oats-okf-harvest/bin/okf-harvest.mjs +140 -0
  18. package/capabilities/oats-okf-harvest/injects/harvester.md +12 -0
  19. package/capabilities/oats-okf-harvest/oats.json +26 -0
  20. package/capabilities/oats-okf-harvest/skills/knowledge-harvest/SKILL.md +168 -0
  21. package/capabilities/oats-okf-harvest/skills/knowledge-theory/SKILL.md +192 -0
  22. package/capabilities/{oats-okf/skills/okf → oats-okf-harvest/skills/okf-authoring}/SKILL.md +15 -30
  23. package/capabilities/oats-okf-maintenance/bin/okf-maintenance.mjs +149 -0
  24. package/capabilities/oats-okf-maintenance/injects/maintainer.md +12 -0
  25. package/capabilities/oats-okf-maintenance/lib/provenance.mjs +45 -0
  26. package/capabilities/oats-okf-maintenance/oats.json +21 -0
  27. package/capabilities/oats-okf-maintenance/skills/knowledge-review/SKILL.md +144 -0
  28. package/capabilities/oats-okf-maintenance/skills/knowledge-theory/SKILL.md +192 -0
  29. package/capabilities/oats-okf-maintenance/skills/okf-authoring/SKILL.md +151 -0
  30. package/capabilities/oats-okf-maintenance/skills/okf-authoring/scripts/okf-validate.mjs +123 -0
  31. package/capabilities/oats-okf-maintenance/skills/okf-trigger-setup/SKILL.md +146 -0
  32. package/capabilities/oats-review/injects/review.md +3 -2
  33. package/capabilities/oats-review/oats.json +3 -4
  34. package/docs/capabilities.md +41 -9
  35. package/docs/capability-manifest.schema.json +0 -7
  36. package/docs/desktop-cli-api.md +277 -15
  37. package/docs/implementation.md +1 -1
  38. package/docs/knowledge-capability-authoring.md +8 -2
  39. package/docs/knowledge-reference/package-craft.md +8 -5
  40. package/docs/knowledge.md +101 -0
  41. package/docs/oats-local.schema.json +31 -1
  42. package/docs/official-catalog.md +7 -4
  43. package/docs/packages.md +11 -5
  44. package/docs/release-lane.md +1 -1
  45. package/docs/release-notes/v0.29.0.md +240 -0
  46. package/docs/release-notes/v0.29.1.md +79 -0
  47. package/docs/schedules.md +133 -5
  48. package/docs/souls-and-instances.md +4 -6
  49. package/docs/workspaces.md +11 -2
  50. package/lib/automations.mjs +369 -0
  51. package/lib/core.mjs +65 -154
  52. package/lib/instance-git.mjs +30 -1
  53. package/lib/instance-inspect.mjs +12 -4
  54. package/lib/instance-resolution.mjs +31 -182
  55. package/lib/materialize.mjs +5 -7
  56. package/lib/operator-dispatch.mjs +1 -2
  57. package/lib/packages.mjs +17 -0
  58. package/lib/remote.mjs +21 -1
  59. package/lib/resolve.mjs +51 -7
  60. package/lib/schedule.mjs +211 -41
  61. package/lib/triggers.mjs +182 -49
  62. package/lib/workspace.mjs +1 -1
  63. package/package-catalog.json +6 -4
  64. package/package.json +1 -1
  65. package/capabilities/oats-okf/agents/memory-harvest/AGENTS.md +0 -26
  66. package/capabilities/oats-okf/agents/memory-harvest/soul.yaml +0 -5
  67. package/capabilities/oats-okf/skills/memory-harvest/SKILL.md +0 -285
  68. package/capabilities/oats-review/agents/reviewer/AGENTS.md +0 -53
  69. package/capabilities/oats-review/agents/reviewer/soul.yaml +0 -6
  70. /package/capabilities/{oats-okf/skills/okf → oats-okf-harvest/skills/okf-authoring}/scripts/okf-validate.mjs +0 -0
package/docs/packages.md CHANGED
@@ -74,8 +74,8 @@ members:
74
74
  - git:github.com/acme/agents
75
75
  - git:github.com/acme/platform
76
76
  packages:
77
- oats.framework: v1.1.3
78
- oats.okf: v3.0.0
77
+ oats.framework: v1.3.0
78
+ oats.okf: v4.0.0
79
79
  oats.aweb: v1.14.2
80
80
  teams:
81
81
  global: { description: Org-wide }
@@ -263,7 +263,13 @@ oats-package/
263
263
  `agents/<package>--<soul>/` (the package id with `.` as `-`:
264
264
  `agents/oats-okf--knowledge-maintainer/`), which is also its agent name
265
265
  (`OATS_AGENT`, the `oats status` row); its instances are named from it
266
- (`oats-okf-knowledge-maintainer-<purpose>`). A soul name never holds `--`,
266
+ (`oats-okf-knowledge-maintainer-<purpose>`). That prefix counts toward the
267
+ 64-character instance-name limit, so a package soul's purposes are short:
268
+ `oats-okf-knowledge-maintainer-` is 30 characters, which leaves 34 for the
269
+ purpose (fewer when a `-2` suffix de-duplicates it). A longer one is
270
+ `E_INSTANCE_NAME_INVALID { prefix, purpose, maxPurpose }`, naming the budget;
271
+ a trigger's or schedule's purpose template obeys the same limit when it
272
+ renders. A soul name never holds `--`,
267
273
  so a member soul of the same bare name keeps its own `agents/<soul>/`.
268
274
  Two packages whose ids sanitise alike (`a.b`, `a-b`) and that ship a
269
275
  same-named soul would share a directory: both are listed with an
@@ -338,8 +344,8 @@ A soul that names one of the package's capabilities with
338
344
  }
339
345
  ```
340
346
 
341
- `ref` carries the tag convention: a workspace's `oats.framework: v1.2.0`
342
- resolves to tag `oats-framework/v1.2.0`. Resolving through the catalog never
347
+ `ref` carries the tag convention: a workspace's `oats.framework: v1.3.0`
348
+ resolves to tag `oats-framework/v1.3.0`. Resolving through the catalog never
343
349
  advances a lock by itself — `oats sync` does, and
344
350
  says so.
345
351
 
@@ -30,7 +30,7 @@ under `stage/<tag>/logs/`; a failing step exits non-zero with the log path.
30
30
 
31
31
  | Phase | Mirrors in `release.yml` | Writes |
32
32
  | --- | --- | --- |
33
- | `build --tag vX.Y.Z [--sha <commit>]` | job `build-and-test`: notes gate, three-manifest bump, `node --check`, `npm ci`, `npm run check`, Desktop test deps, `npm test`, `pack:check` and the tarball greps, `smoke:tarball`, the `version --json` probe | `npm/*.tgz`, `MANIFEST.json` |
33
+ | `build --tag vX.Y.Z [--sha <commit>]` | jobs `build-and-test` and `tests` (the lane runs the suite unsharded): notes gate, three-manifest bump, `node --check`, `npm ci`, `npm run check`, Desktop test deps, `npm test`, `pack:check` and the tarball greps, `smoke:tarball`, the `version --json` probe | `npm/*.tgz`, `MANIFEST.json` |
34
34
  | `desktop --tag vX.Y.Z --arch arm64\|x64` | one `desktop-build` matrix leg: desktop `npm ci`, `npm test`, `npm run dist -- --<arch>`, strict deep `codesign --verify` (macOS), `dist:smoke` in build-verify mode | `assets/oats-desktop-*` |
35
35
  | `stage --tag vX.Y.Z` | publish job, "Checksums" (`shasum -a 256`) | `assets/SHA256SUMS.txt` |
36
36
  | `publish-npm --tag vX.Y.Z [--dry-run] --yes` | publish job, the two guarded `npm publish --access public` steps, kernel then adapter | — |
@@ -0,0 +1,240 @@
1
+ # OATS 0.29.0
2
+
3
+ ## Added
4
+
5
+ - **Workspace triggers and schedules** (feature `automations`). A trigger or a
6
+ schedule can now be declared in Git, in any confirmed member, and shared with the
7
+ team. It is named `<member>/<id>`, and a machine's own ones are named
8
+ `local/<id>`. See
9
+ [schedules.md#workspace-triggers-and-schedules](../schedules.md#workspace-triggers-and-schedules).
10
+ - Triggers and schedules stay separate:
11
+
12
+ | | triggers | schedules |
13
+ | --- | --- | --- |
14
+ | folder | `oats-triggers/` | `oats-schedules/` |
15
+ | file name anywhere in the member | `*.oats-trigger.yaml` | `*.oats-schedule.yaml` |
16
+ | `kind:` | `oats-trigger` | `oats-schedule` |
17
+ | commands and list | `oats trigger …` | `oats schedule …` |
18
+ | opt-out | `triggers.disabled` | `schedules.disabled` |
19
+
20
+ `oats-package/`, `.git/` and `node_modules/` are never scanned.
21
+ - Every file carries `kind`, `schemaVersion: 1`, `runsOn` (the host that runs it)
22
+ and `owner` (the GitHub account it acts as). The wrong kind is
23
+ `E_AUTOMATION_SCHEMA`, and a duplicate id is `E_AUTOMATION_DUPLICATE`.
24
+ - A host runs one only when `runsOn` is its new `oats-local.yaml` `host.name`
25
+ **and** its `gh` is logged in as `owner`. Otherwise the item is listed as
26
+ `assigned-elsewhere`, `owner-mismatch` or `host-unnamed`.
27
+ - `oats trigger disable <member>/<id>` and `oats schedule disable <member>/<id>`
28
+ stop it on this host without a commit, by writing `triggers.disabled` or
29
+ `schedules.disabled` in `oats-local.yaml`.
30
+ - `oats sync` takes a snapshot of them. The host tick reads the snapshot and
31
+ refreshes it every ten minutes (`oats automations refresh`).
32
+ - `oats trigger add … --workspace <member> --runs-on <host> --owner <host>/<login>`
33
+ writes the file in a checkout of the member, or prints it. `oats schedule add`
34
+ takes the same options.
35
+ - `oats trigger list --json` and `oats schedule list --json` answer the Desktop's
36
+ rows for both levels: the owner, where it runs and why (not), the soul and
37
+ where it comes from, the task verbatim, the event or cron, and the last and
38
+ next run. Local schedule rows keep their bare `id` and add `qualifiedId`. See
39
+ [desktop-cli-api.md](../desktop-cli-api.md).
40
+ - Each row's `origin` carries `url` (the file on GitHub at its commit) and
41
+ `localPath` (the file in this machine's clone of the member), each `null` when
42
+ there is none. Both lists carry `host.ghUser` (who `gh` is logged in as, per
43
+ GitHub host) and the host `scheduler`. "When it next runs" is `nextDue`
44
+ everywhere.
45
+ - **Desktop facts** (feature `desktop-facts`): kernel facts the Desktop's Workspace
46
+ view shows, so it never derives them. Every field is an addition. See
47
+ [desktop-cli-api.md](../desktop-cli-api.md#desktop-facts-feature-desktop-facts-oats-0290).
48
+ - `oats inspect --soul --json`: each capability's `composedFrom` (`workspace`,
49
+ `team:<label>` or `soul`), and `capabilitiesOff[]`, the defaults the soul
50
+ turned off (`<id>: off` or `<slot>: none`).
51
+ - `oats souls --json` rows: the default `harness`/`model` a spawn starts with,
52
+ and `spawnable` and `problem`, the refusal a spawn would meet (it spawns
53
+ nothing). Also `file`.
54
+ - `oats capabilities --json` rows: `layer` on package rows too, `description`,
55
+ `skills`/`commands`/`hooks` by name, `file`, and a member capability's `tree`
56
+ (its Git tree id).
57
+ - `oats workspace status --json`:
58
+ - the workspace and team `defaults` as rows;
59
+ - this computer's member `clones` and the rule that found each;
60
+ - `disabledSouls`;
61
+ - `lock` (`path`, `lockfileVersion`);
62
+ - `packages[].latest` when the shipped catalog has a newer version;
63
+ - file locations (`workspace.file`, `members[].url`,
64
+ `members[].membershipFile`).
65
+ - `oats status --json` instance rows: `startedAt` (the last start or restart),
66
+ `modelFrom` (also recorded in `instance.json`) and `identityAddress`. A member
67
+ module's drift `current` gains `version`.
68
+ - URLs are GitHub pages at the row's commit, `null` for any other host.
69
+ - `oats help` lists `spawn --provider`.
70
+ - **`oats schedule test <id>`**: where a schedule runs, whether its soul resolves
71
+ (a spawn preview) and when it is next due. It spawns nothing, like
72
+ `oats trigger test`.
73
+ - **`launchConfig`** on a trigger's `spawn` and on a spawn schedule: the soul starts
74
+ on that launch configuration of the running host (`oats-local.yaml`
75
+ `launch-configs`). A package trigger template can expose it as a parameter.
76
+ - `oats trigger status --json` rows add `nextDue`, `concurrency` and `liveCount`;
77
+ `oats trigger test --json` `wouldFire` items add `repo`.
78
+ - **`OATS_SETTINGS_ORIGINS`** beside `OATS_SETTINGS`, for every hook and
79
+ capability command (and readiness probes): where each leaf of the payload came
80
+ from, a JSON pointer → `{ kind, at }` (`manifest-default`, `workspace`, `soul`,
81
+ `host`, `spawn`). A provider can tell a soul-set value from a host-set one
82
+ without reading `soul.yaml`. `instance.json` records it with the settings
83
+ (`capabilities[].settingsOrigins`, `capabilityRuntime[].settingsOrigins`).
84
+
85
+ ## Changed
86
+
87
+ - **oats.framework 1.3.0 pinned.** The official catalog pins `oats.framework` to
88
+ `oats-framework/v1.3.0` (this repository's workspace pins it too). 0.28.1 was never
89
+ released, so this pin covers three framework releases:
90
+ - **1.2.0:** the setup-admin skills. oats.setup 2.1.0 adds `oats-setup-model`,
91
+ `oats-workspace-config`, `oats-teams`, `oats-automations` and a setup inject,
92
+ and oats.core 2.1.0 is current for an instance's view. The `oats-setup-admin`
93
+ soul uses them.
94
+ - **1.2.1:** OKF knowledge operations in onboarding (oats.setup 2.1.1,
95
+ `oats-onboarding`).
96
+ - **1.3.0:** `knowledge-theory-expert` is a package soul
97
+ (`oats spawn oats.framework/knowledge-theory-expert`), with
98
+ oats.knowledge-theory 1.1.0.
99
+
100
+ A workspace picks it up by pinning `oats.framework: v1.3.0` and running
101
+ `oats sync`.
102
+ - **A local trigger's id is `local/<id>`** in `oats trigger` rows, in its dedup keys
103
+ and state, and in a triggered instance's `instance.json.trigger.id` and event
104
+ file. It was the bare id in 0.28.0. Every `oats trigger` verb still accepts the
105
+ bare id.
106
+
107
+ ## Removed
108
+
109
+ - **BREAKING: capability-defined agents.** A capability manifest's `agents:` is
110
+ refused at resolution, with
111
+ `E_CAPABILITY_AGENTS_REMOVED { capability, agents, from }`. The remedy names the
112
+ replacement: a **package soul** (`souls/<name>/` in the package, spawned as
113
+ `oats spawn <package>/<name>`) or a **member soul**. `oats spawn <name>` no
114
+ longer falls back to an agent declared by a materialized or locked module; an
115
+ unknown name is `E_SOUL_UNKNOWN`. The manifest schema drops `agents`.
116
+ - A home an earlier kernel spawned for one (its agent directory holds only
117
+ `instances/`) is still listed by `oats status`, may be a `--parent`, and
118
+ retires. Nothing creates one any more.
119
+ - This repository's users moved:
120
+ - oats.okf 4.0.0's harvester is a package soul;
121
+ - the post-commit **`reviewer`** is an oats.dev **1.1.0** package soul
122
+ (`oats.dev/reviewer`, beside oats.review 1.3.0; the pin moves to
123
+ `v1.1.0`), and oats.review's inject spawns it unchanged, now named
124
+ `oats-dev-reviewer-<short-sha>`;
125
+ - **`knowledge-theory-expert`** is an oats.framework **1.3.0** package soul
126
+ (`oats spawn oats.framework/knowledge-theory-expert`), with
127
+ oats.knowledge-theory 1.1.0.
128
+ - A v2 soul.yaml declares no harness or model, so the reviewer's harness and
129
+ model now come from the **spawner's launch configuration** (its former pin was
130
+ pi, gpt-5.6-sol).
131
+
132
+ ## Fixed
133
+
134
+ - A package soul's derived instance name is checked and de-duplicated as the name
135
+ the home gets (`acme-pkg-keeper-<purpose>`, not `acme-pkg--keeper-…`). A
136
+ purpose inside the limit is no longer refused, and a second spawn with the same
137
+ purpose is `…-2` instead of a collision. An over-long purpose is
138
+ `E_INSTANCE_NAME_INVALID` naming how many characters the purpose may have
139
+ (`details.maxPurpose`).
140
+
141
+ - Concurrent spawns of the same instance: a spawn that loses the race now refuses
142
+ with `E_PLACEMENT_TAKEN` (it created nothing). It used to fail with an uncoded
143
+ "instance already exists" error, surfaced as `E_SPAWN_FAILED`.
144
+ - Disabled-here messages name the per-kind key (`triggers.disabled`,
145
+ `schedules.disabled`).
146
+
147
+ ## Desktop
148
+
149
+ - **Schedules and Triggers tabs** on the automations contract. Rows are grouped by
150
+ where they run: on this computer, needing attention here, or elsewhere. Workspace
151
+ and local items are listed together, with an origin chip, a filter and a search.
152
+ - Each row has an on-here switch, the soul and where it comes from, the cron in
153
+ words or the trigger's event, and where it runs and as whom. It also shows the
154
+ last and next run, and a menu (Open, Test, Run now, on/off here, Open file).
155
+ - A row opens a detail page: the prompt verbatim, the schedule or event, recent
156
+ runs, the kernel's placement verdict, where it comes from, and the test result.
157
+ - The old Schedules read path is gone.
158
+ - **Why each capability is there.** The soul page and an instance's soul tab tag
159
+ each capability `workspace`, `team · <label>` or `soul`, and list the defaults the
160
+ soul turned off (including a slot it emptied), from the kernel's Desktop facts.
161
+ - **A moved module names its versions**: "moved 2.1.5 → 2.2.0" in the instance
162
+ panel's module drift.
163
+ - The Desktop accepts OATS CLIs `>=0.25.8 <0.30.0`.
164
+
165
+ ## Internal
166
+
167
+ - The release workflow runs the test suite in six parallel shards, like PR CI, and
168
+ publication waits for every shard.
169
+
170
+ ## Upgrading from 0.28
171
+
172
+ > **0.29.0 and oats.okf 4.0.0 move in lockstep.** On kernel 0.29.0, oats.okf ≤3.x
173
+ > is refused because it declares a capability agent, and oats.okf 4.0.0 requires
174
+ > kernel 0.29.0. A deployment on okf 3.x therefore **stays on kernel 0.28 until it
175
+ > moves its pins**. It then upgrades in one sitting, in this order:
176
+
177
+ 1. **Upgrade the kernel**: the npm package, the pi adapter and the Desktop, all
178
+ 0.29.0.
179
+ 2. **Move the pins** to the official catalog's: `oats.okf: v4.0.0`,
180
+ `oats.dev: v1.1.0`, `oats.framework: v1.3.0`.
181
+ 3. **Run `oats sync`.**
182
+
183
+ Between step 1 and step 3, a package pinned below its 0.29 release still declares
184
+ `agents:`. A spawn, preview or `inspect --soul` of any soul that composes it
185
+ refuses with `E_CAPABILITY_AGENTS_REMOVED`:
186
+ - **oats.okf ≤3.x** (`memory-harvest`): this is **every soul with oats.okf in its
187
+ knowledge slot**;
188
+ - **oats.dev 1.0.x** (`reviewer`);
189
+ - **oats.framework ≤1.2.x** (`knowledge-theory-expert`).
190
+
191
+ Harvest is off by default in okf 4.0.0. Switch it on
192
+ (`oats okf setup --harvest on`) where you want it.
193
+
194
+ Homes spawned earlier keep loading their recorded modules. Homes spawned for a
195
+ capability agent stay listed and retirable.
196
+
197
+ ## oats.okf 4.0.0 (catalog pin and bundled mirror)
198
+
199
+ The official catalog now pins `oats.okf` to `v4.0.0` (tag object `239f2885`,
200
+ commit `1f0ba12f`). The copy bundled in this package is its byte mirror.
201
+
202
+ **BREAKING:**
203
+ - The package requires `oats >=0.29.0`; an older kernel refuses it
204
+ (`E_CAPABILITY_INCOMPATIBLE`).
205
+ - The `okf` and `memory-harvest` skills are gone from `oats.okf`.
206
+
207
+ - **Three capabilities.** The package now exports:
208
+ - `oats.okf`: the knowledge slot;
209
+ - `oats.okf-harvest`: the harvester's completion and status commands;
210
+ - `oats.okf-maintenance`: the maintainer's review context.
211
+
212
+ The catalog maps `oats.okf-harvest` and `oats.okf-maintenance` to the
213
+ `oats.okf` package.
214
+ - **Working souls get two skills and the inject.** A soul with `oats.okf` in
215
+ its knowledge slot gets `okf-consultation` and `okf-instance-knowledge`, and
216
+ the okf inject.
217
+ - **The harvester is a package soul.** `oats okf run-source` (and `oats okf
218
+ harvest`) spawns `oats.okf/knowledge-harvester`. It is named
219
+ `okf-harvester-<run>` and homes under
220
+ `agents/oats-okf--knowledge-harvester/`. It is no longer the `memory-harvest`
221
+ capability agent. After a successful completion it stays alive in the `okf`
222
+ team until its PR is merged or closed. `oats.okf/knowledge-maintainer` is the
223
+ package's second soul.
224
+ - **The harvest-review trigger.** The package ships the trigger template
225
+ `harvest-review` (`triggers/harvest-review.json`). It watches the labelled
226
+ harvest PRs.
227
+ - **`harvest: on|off`** (default **off**). Harvest is a host switch in
228
+ `oats-local.yaml` `settings.oats.okf.harvest` (`oats okf setup --harvest
229
+ on|off`). Off means no source registration, capture or custody. A soul can
230
+ only opt out (`knowledge: { harvest: off }`).
231
+ - **`oats okf read` is removed** (`E_REMOVED`). Use `oats okf cat --base
232
+ <alias> <path>`, which takes the same path and gives the same text and
233
+ receipt.
234
+
235
+ The bundled mirror now covers the three capability directories
236
+ (`capabilities/oats-okf`, `capabilities/oats-okf-harvest`,
237
+ `capabilities/oats-okf-maintenance`). The package's souls and trigger are
238
+ checked byte for byte in `scripts/okf-source-inventory.json` (schemaVersion 2).
239
+ The npm package does not ship them, because the kernel reads a package's souls
240
+ and triggers from Git at its locked commit.
@@ -0,0 +1,79 @@
1
+ # OATS 0.29.1
2
+
3
+ ## Added
4
+
5
+ - **Per-file line counts in `oats instance git`.** Each tracked file entry has
6
+ `additions` and `deletions` (integers) and `binary`, so the Desktop can show
7
+ `+84 −3` beside a changed file. They come from one `git diff --numstat`
8
+ against the observed commit, counting staged and unstaged changes together,
9
+ which is the same baseline as the status letters and `oats instance diff`.
10
+ - A binary file has `additions: null, deletions: null, binary: true`.
11
+ - An untracked file or a submodule has all three `null`.
12
+ - A rename is counted on its new path.
13
+ - `instanceGitApi` stays 1: the fields are additive. The text output shows
14
+ `+N -M` after each path. See
15
+ [desktop-cli-api.md](../desktop-cli-api.md#instance-git-state-oats-instance-gitdiff-instancegitapi-1-oats-0247).
16
+
17
+ ## Changed
18
+
19
+ - **The `oats-setup-admin` soul is never harvested.** Its `soul.yaml` opts out
20
+ of OKF harvest with `knowledge: { harvest: off }`: its sessions work on the
21
+ deployment's own config and carry deployment specifics that must not reach
22
+ the shared knowledge base. oats.okf 4.0.0 makes a soul's opt-out absolute, so
23
+ a deployment that switches harvest on (`settings.oats.okf.harvest: on`)
24
+ still registers no source, captures nothing and takes no custody for its
25
+ instances. `oats okf harvest-status` in one of its homes reports
26
+ `harvest: off` with the soul's reason.
27
+
28
+ ## Desktop
29
+
30
+ The Desktop now shows the kernel's 0.29 Desktop facts and the Workspace v4
31
+ design's Git & GitHub section. On an older kernel, each fact is absent and its
32
+ view shows nothing new.
33
+
34
+ - **Souls say when a spawn here would refuse** (#228, #231). A soul the kernel
35
+ reports as not spawnable shows "Can't spawn here" with the kernel's reason on
36
+ its card and page, and its Spawn and Schedule… are disabled with that reason.
37
+ A soul page offers Open file for a hosted soul file, and shows the file's path
38
+ when it has no web address.
39
+ - **The server passes the kernel's Desktop facts through** (#230). Its souls,
40
+ capabilities, workspace status and instance projections keep those fields,
41
+ bounded, instead of dropping them. A soul's spawn default is nested as
42
+ `spawnDefault`, so it is never read as the soul's own harness or model.
43
+ - **Capability pages** (#232) show the description, what the capability
44
+ provides (skills, commands and hooks by name, or "Not listable"), its file and
45
+ its fingerprint.
46
+ - **Setup names the files and this computer's state** (#233). It names the
47
+ workspace and membership files, and links them when they are hosted. A member
48
+ panel has Open repository and its clone on this computer. This computer lists
49
+ the lock file, disabled souls and each member's clone, or "not cloned here".
50
+ Packages with a newer version say "X available".
51
+ - **Setup shows the workspace defaults** (#237): each slot and its source ("not
52
+ set" or "none" when empty), the default capabilities, and what each team adds
53
+ or turns off.
54
+ - **The instance page** (#235) says when the session started, where its model
55
+ came from (the soul, the spawn, the start, the launch configuration or the
56
+ harness default), and its messaging address.
57
+ - **Each local instance's pull request on its roster row** (#234, #236). A new
58
+ `POST /api/forge-roster` maps each instance to its member's clone from the
59
+ kernel's workspace status and reads the branch's PR with `gh`, cached for a
60
+ minute. The row shows `#N`, with draft, merged or closed in words. Remote
61
+ instances, and hosts without a signed-in `gh`, show no badge.
62
+ - **W6 Git & GitHub** (#239, #240, #241, #242, #243). The instance's Git panel
63
+ follows the design:
64
+ - **Branch** shows the work mode, the distance from the default branch and
65
+ whether the tree is clean, with the rest behind Details.
66
+ - **Changes** is a list of status letters and paths, with Open diff.
67
+ - **Pull request** shows the title and state, the issues it closes and the
68
+ checks: failing first, with how long each took. It also shows the review
69
+ decision with the count of unresolved review threads, and has Open on
70
+ GitHub.
71
+ - Check marks are icons. The thread count is read only for the open
72
+ instance's PR, never for the roster.
73
+ - **Automations through the app proxy** (#224). `/api/automations` has its own
74
+ proxy route, pinned to the verified workspace like the other workspace
75
+ endpoints. It has a 90 s deadline, so `trigger test` (which polls the forge)
76
+ is no longer cut off in the packaged app. The automations docs describe the
77
+ API and the proxy.
78
+ - **Docs** (#227): the documented Desktop band is `>=0.25.8 <0.30.0`.
79
+ - The Desktop still accepts OATS CLIs `>=0.25.8 <0.30.0`.
package/docs/schedules.md CHANGED
@@ -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
@@ -153,7 +153,10 @@ logged in with the keyring or its config file under your HOME works there. A
153
153
  request's title and body are untrusted and never reach the task (a template
154
154
  naming any other field is refused). `teams` becomes the messaging
155
155
  capability's `join=` setting (as `--provider <messaging cap> join=<labels>`).
156
- `harness`, `model`, `yolo`, `backend` are as for schedules.
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"`).
157
160
  - **The event reaches the instance** as `OATS_TRIGGER_EVENT_FILE`
158
161
  (`<home>/.oats/trigger-event.json`: `{ trigger, source, repo, number, url,
159
162
  event, headSha, labels, observedAt, key }`), given to the spawn hooks and the
@@ -169,7 +172,7 @@ oats trigger add --from oats.okf:harvest-review --set repo=github.com/acme/knowl
169
172
  oats trigger list | show <id> | enable <id> | disable <id> | remove <id>
170
173
  oats trigger test <id> # dry run: gh auth + credential source, repo + permissions (push/maintain/admin), the soul resolves,
171
174
  # its messaging capability, the teams declared, what WOULD fire now; spawns nothing
172
- oats trigger status [<id>] # last poll, pending, fired keys, live instances, last error
175
+ oats trigger status [<id>] # last poll, next due, pending, fired keys (time, instance), live vs max, last error
173
176
  ```
174
177
 
175
178
  All take `--dir` and `--json` (`triggerApi: 1`). `remove` leaves the instances
@@ -187,6 +190,119 @@ comma-separated); a required parameter without a value is `E_BAD_ARGS
187
190
  { missing }` naming it. The trigger records `template: { package, version,
188
191
  commit, template }`.
189
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
+
190
306
  ## Captured definitions (removed in 0.26)
191
307
 
192
308
  0.24–0.25 could save captured command definitions: `definitionVersion`,
@@ -217,6 +333,7 @@ oats schedule add <id> --file spec.json --dir <workspace> --json
217
333
  oats schedule update <id> --file spec.json
218
334
  oats schedule list | show <id> | enable <id> | disable <id> | remove <id>
219
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
220
337
  oats schedule tick --dry-run # what would run this minute, launching nothing
221
338
  oats schedule reconcile <id> [--clear] # resolve an attempt whose result was never recorded
222
339
  oats schedule host install # register this scope and install the ONE host timer (idempotent while active)
@@ -227,8 +344,9 @@ oats spawn <agent> ... --wake-every 15 --wake-message "Anything new?" # or --w
227
344
  Every subcommand takes `--server <id>` instead of `--dir`: it then runs on
228
345
  that host, in its registered workspace, because schedules are host-owned.
229
346
 
230
- `list --json` answers `{schedules: [{id, ...definition, nextRun, lastRun,
231
- 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`).
232
350
  `active` is what the OS reports about the timer, not whether a file exists.
233
351
 
234
352
  ## What a run reports
@@ -292,6 +410,16 @@ the instance is neither hidden nor spawned again.
292
410
 
293
411
  ## OKF v2 source jobs
294
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
+
295
423
  The [prepared OKF v2 runtime](knowledge.md) registers **one command job per
296
424
  source**, not a fleet sweep or a home-bound operation job. It runs from stable
297
425
  deployment context with argv equivalent to:
@@ -516,14 +516,12 @@ Default layout:
516
516
  docs-expert/ # a workspace soul, defined in a member repository's
517
517
  souls/<commit12>/ # souls/docs-expert/ and copied here per commit
518
518
  instances/
519
- memory-harvest/ # a capability-defined agent: only instances/, no soul
520
- instances/
521
519
  ```
522
520
 
523
- A capability-defined agent (declared by a package or member module, such as
524
- the OKF harvester) homes under the agents root exactly like a soul; its
525
- directory holds only `instances/`. A name that is both a workspace soul and a
526
- capability agent is ambiguous (`E_SOUL_AMBIGUOUS`).
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.
527
525
 
528
526
  There are no local souls. A soul is a member repository's `souls/<name>`
529
527
  (`soul.yaml` + `AGENTS.md`); author it there and run `oats sync`. OATS 0.25
@@ -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.1.3 # bare version → resolves through the official catalog
63
- oats.okf: v3.0.0
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
@@ -169,8 +169,17 @@ settings: # host-owned values the manifests ask
169
169
  state-dir: /Users/ana/.oats/okf
170
170
  souls:
171
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