@awebai/oats 0.25.8 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +8 -6
  2. package/bin/oats.mjs +576 -1714
  3. package/capabilities/oats-authoring/oats-package.json +2 -2
  4. package/capabilities/oats-authoring/oats.json +2 -2
  5. package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +46 -25
  6. package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +13 -6
  7. package/capabilities/oats-aweb/bin/oats-aweb.mjs +334 -72
  8. package/capabilities/oats-aweb/injects/aweb.md +7 -2
  9. package/capabilities/oats-aweb/lib/binding-wire.mjs +107 -5
  10. package/capabilities/oats-aweb/lib/captured-native.mjs +1 -1
  11. package/capabilities/oats-aweb/lib/grant-custody.mjs +38 -0
  12. package/capabilities/oats-aweb/oats.json +14 -4
  13. package/capabilities/oats-jira/bin/oats-jira.mjs +4 -4
  14. package/capabilities/oats-jira/oats.json +2 -2
  15. package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +6 -3
  16. package/capabilities/oats-linear/bin/oats-linear-hook.mjs +6 -4
  17. package/capabilities/oats-linear/oats.json +2 -2
  18. package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +6 -0
  19. package/capabilities/oats-okf/bin/oats-okf.mjs +1 -1
  20. package/capabilities/oats-okf/lib/binding-wire.mjs +1 -1
  21. package/capabilities/oats-okf/lib/migration.mjs +2 -2
  22. package/capabilities/oats-okf/lib/sources.mjs +5 -4
  23. package/capabilities/oats-okf/lib/stores.mjs +40 -9
  24. package/capabilities/oats-okf/lib/worker.mjs +3 -3
  25. package/capabilities/oats-okf/oats.json +1 -1
  26. package/capabilities/oats-review/oats.json +3 -2
  27. package/docs/capabilities.md +218 -47
  28. package/docs/capability-manifest.schema.json +13 -4
  29. package/docs/configuration.md +17 -5
  30. package/docs/conventions.md +16 -26
  31. package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +1 -1
  32. package/docs/design/2026-09-13-knowledge-and-memory-direction.md +3 -3
  33. package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +2 -2
  34. package/docs/design/2026-09-15-portable-souls-handoff.md +2 -2
  35. package/docs/design/2026-09-15-portable-souls-implementation.md +1 -1
  36. package/docs/design/2026-09-20-redesign-program-board.md +2 -2
  37. package/docs/design/2026-09-23-workspace-module-contracts.md +1 -1
  38. package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +1 -1
  39. package/docs/design/2026-09-24-desktop-phase-f-boundary.md +54 -10
  40. package/docs/design/2026-09-24-phase-d-plan.md +77 -0
  41. package/docs/design/2026-09-25-teams-contract.md +226 -0
  42. package/docs/design/README.md +3 -3
  43. package/docs/design/launch-configurations.md +20 -16
  44. package/docs/design/operations-contract.md +27 -10
  45. package/docs/desktop-cli-api.md +546 -264
  46. package/docs/desktop-instance-start.md +1 -1
  47. package/docs/desktop.md +7 -13
  48. package/docs/execution-targets.md +16 -18
  49. package/docs/first-team.md +14 -17
  50. package/docs/implementation.md +28 -59
  51. package/docs/integrations.md +88 -32
  52. package/docs/knowledge-capability-authoring.md +1 -1
  53. package/docs/knowledge-reference/package-craft.md +10 -8
  54. package/docs/knowledge-theory.md +1 -1
  55. package/docs/knowledge.md +10 -11
  56. package/docs/layers.md +16 -17
  57. package/docs/oats-local.schema.json +29 -1
  58. package/docs/oats-membership.schema.json +5 -3
  59. package/docs/oats-package.schema.json +2 -2
  60. package/docs/oats-workspace.schema.json +1 -1
  61. package/docs/{official-marketplace.md → official-catalog.md} +15 -16
  62. package/docs/packages.md +75 -52
  63. package/docs/release-notes/v0.22.0.md +1 -1
  64. package/docs/release-notes/v0.23.1.md +1 -1
  65. package/docs/release-notes/v0.25.9.md +23 -0
  66. package/docs/release-notes/v0.26.0.md +670 -0
  67. package/docs/schedules.md +48 -126
  68. package/docs/soul.schema.json +11 -4
  69. package/docs/souls-and-instances.md +56 -43
  70. package/docs/workspaces.md +80 -58
  71. package/injects/instance-boundary.md +1 -1
  72. package/injects/work-attached.md +1 -1
  73. package/injects/work-workspace.md +2 -2
  74. package/lib/{portable-files.mjs → bounded-read.mjs} +6 -6
  75. package/lib/{portable-values.mjs → canonical-json.mjs} +3 -12
  76. package/lib/capability-contract.mjs +110 -0
  77. package/lib/config-data.mjs +2 -2
  78. package/lib/core.mjs +700 -4824
  79. package/lib/digest.mjs +12 -0
  80. package/lib/instance-inspect.mjs +396 -0
  81. package/lib/instance-lifecycle.mjs +3 -4
  82. package/lib/instance-resolution.mjs +212 -26
  83. package/lib/instruction-composition.mjs +0 -20
  84. package/lib/materialize.mjs +6 -4
  85. package/lib/operator-dispatch.mjs +33 -13
  86. package/lib/packages.mjs +25 -190
  87. package/lib/provider-binding.mjs +4 -2
  88. package/lib/provider-reasons.mjs +3 -68
  89. package/lib/resolve.mjs +204 -68
  90. package/lib/schedule.mjs +97 -272
  91. package/lib/servers.mjs +13 -13
  92. package/lib/{portable-shape.mjs → shape.mjs} +4 -3
  93. package/lib/tree-copy.mjs +44 -0
  94. package/lib/workspace.mjs +125 -20
  95. package/package-catalog.json +7 -7
  96. package/package.json +1 -1
  97. package/skills/integration-authoring/SKILL.md +48 -40
  98. package/skills/oats-getting-started/SKILL.md +105 -110
  99. package/skills/oats-support/SKILL.md +2 -2
  100. package/skills/soul-craft/SKILL.md +13 -6
  101. package/bin/oats-pi-sdk-host.mjs +0 -17
  102. package/docs/2026-09-03-architecture-proposal.md +0 -642
  103. package/docs/artifact-approvals.schema.json +0 -7
  104. package/docs/captured-invocation-context.schema.json +0 -7
  105. package/docs/captured-resolution.schema.json +0 -7
  106. package/docs/design/package-engine-contract.md +0 -813
  107. package/docs/design/package-runtime-api.md +0 -588
  108. package/docs/desktop-succession.md +0 -57
  109. package/docs/execution-capsule.schema.json +0 -108
  110. package/docs/first-team-demo.md +0 -92
  111. package/docs/knowledge-migration.md +0 -147
  112. package/docs/migration-from-oas.md +0 -103
  113. package/docs/oats-config.schema.json +0 -172
  114. package/docs/oats-lock-v3.schema.json +0 -7
  115. package/docs/oats-lock.schema.json +0 -175
  116. package/docs/operating-team-migration.md +0 -470
  117. package/docs/portable.schema.json +0 -2512
  118. package/docs/provider-check-input.schema.json +0 -7
  119. package/docs/rebuild-to-v2.md +0 -511
  120. package/docs/workspace-adoption.md +0 -74
  121. package/injects/framework-workspace.md +0 -7
  122. package/injects/local-soul.md +0 -19
  123. package/injects/oats-portable.md +0 -20
  124. package/injects/oats.md +0 -11
  125. package/injects/portable-instance-boundary.md +0 -39
  126. package/injects/portable-work-directory.md +0 -29
  127. package/lib/artifact-approvals.mjs +0 -120
  128. package/lib/artifact-tree.mjs +0 -141
  129. package/lib/capability-artifacts.mjs +0 -179
  130. package/lib/capability-execution.mjs +0 -15
  131. package/lib/capability-inputs.mjs +0 -39
  132. package/lib/capability-provenance.mjs +0 -231
  133. package/lib/captured-action-shape.mjs +0 -21
  134. package/lib/captured-admission-shape.mjs +0 -20
  135. package/lib/captured-binding-file.mjs +0 -36
  136. package/lib/captured-dispatch.mjs +0 -66
  137. package/lib/captured-instance-index.mjs +0 -277
  138. package/lib/captured-invocation-context.mjs +0 -130
  139. package/lib/captured-launch-request.mjs +0 -66
  140. package/lib/captured-operation-process.mjs +0 -15
  141. package/lib/captured-pi-custody.mjs +0 -29
  142. package/lib/captured-pi-host.mjs +0 -167
  143. package/lib/captured-pi-outcome.mjs +0 -172
  144. package/lib/captured-resolutions.mjs +0 -275
  145. package/lib/captured-scaffold.mjs +0 -87
  146. package/lib/captured-selector.mjs +0 -28
  147. package/lib/captured-session-backend.mjs +0 -52
  148. package/lib/captured-source-receipt-file.mjs +0 -72
  149. package/lib/helper-injection-policy.mjs +0 -104
  150. package/lib/legacy-lock-codec.mjs +0 -106
  151. package/lib/manifest-settings.mjs +0 -84
  152. package/lib/package-closure.mjs +0 -48
  153. package/lib/package-materialization.mjs +0 -83
  154. package/lib/pi-sdk-host.mjs +0 -229
  155. package/lib/portable-artifacts.mjs +0 -115
  156. package/lib/portable-choices.mjs +0 -82
  157. package/lib/portable-composition.mjs +0 -136
  158. package/lib/portable-digest.mjs +0 -105
  159. package/lib/portable-identity.mjs +0 -40
  160. package/lib/portable-lock.mjs +0 -117
  161. package/lib/portable-onboarding-request.mjs +0 -49
  162. package/lib/portable-onboarding.mjs +0 -256
  163. package/lib/portable-package-preparation.mjs +0 -188
  164. package/lib/portable-policy.mjs +0 -44
  165. package/lib/portable-soul.mjs +0 -42
  166. package/lib/portable-state.mjs +0 -80
  167. package/lib/prepare-composition.mjs +0 -170
  168. package/lib/prepared-bindings.mjs +0 -92
  169. package/lib/prepared-resources.mjs +0 -127
  170. package/lib/provider-binding-broker.mjs +0 -65
  171. package/lib/provider-binding-wire.mjs +0 -116
  172. package/lib/readiness.mjs +0 -225
  173. package/lib/repository-observation.mjs +0 -226
  174. package/lib/resolution-shape.mjs +0 -393
  175. package/lib/schedule-capsule.mjs +0 -206
  176. package/lib/soul-constraints.mjs +0 -40
  177. package/lib/source-projection.mjs +0 -84
  178. package/lib/source-spec.mjs +0 -189
  179. package/lib/workspace-definition.mjs +0 -126
  180. package/lib/workspace-discovery.mjs +0 -146
  181. package/skills/oats/SKILL.md +0 -162
  182. package/skills/oats-config/SKILL.md +0 -164
  183. package/skills/oats-packages/SKILL.md +0 -184
  184. package/skills/oats-portable/SKILL.md +0 -115
  185. package/skills/oats-portable-artifacts/SKILL.md +0 -63
@@ -1,588 +0,0 @@
1
- # Package-runtime API contract (addendum to the package-engine contract)
2
-
3
- Status: **SUPERSEDED** with its parent (workspace model v2 — see [2026-09-23-workspace-module-contracts.md](2026-09-23-workspace-module-contracts.md)); kept as history. Original status: **FROZEN** for the capability-materialization delivery, as an addendum to
4
- [`package-engine-contract.md`](./package-engine-contract.md). It answers the
5
- maintainer's four clarifications on the M1 freeze (maintainer review of
6
- 1db919b): the public package-runtime boundary, the npm runtime closure,
7
- incremental transaction semantics, and runtime-validated schema invariants.
8
- Changes go through the coordinator to the maintainer.
9
-
10
- **What capability materialization changed here.** §1 (the public CLI boundary) is
11
- unchanged. §2 keeps every npm rule and moves the materialization root from the
12
- package root to each declared *capability* root, because the closure now lives
13
- inside the materialized artifact. §3 becomes incremental with respect to the
14
- *capability store*. §4 states the current lock invariants and the prototype-safety
15
- requirement. §5 records that a `"."` capability root is read compatibility only,
16
- discriminated by `configTemplates` rather than `configs`. §6 records that v1 is
17
- the only legacy format supported, and that the earlier transitional package-root
18
- `lockfileVersion: 2` is unsupported input rather than something to migrate.
19
-
20
- ## 1. Public package-runtime boundary (structured CLI API)
21
-
22
- **Transport choice: the structured CLI API.** Rationale (tradeoff surfaced to
23
- the coordinator/maintainer before freezing, mail 09447984): a process contract
24
- is a true version boundary — it survives kernel-internal refactors and node/ESM
25
- changes, nothing private is importable by construction, and it extends the
26
- already-proven Desktop CLI API v1 envelope discipline instead of creating a
27
- second public JS surface that must be kept in semver lockstep with the CLI
28
- forever. The rejected alternative (a blessed `lib/runtime.mjs` import resolved
29
- via `oats root`) preserves exactly the dynamic-import coupling the maintainer
30
- ruled out.
31
-
32
- **Rule: independently released packages MUST NOT import kernel-private
33
- `lib/core.mjs` (including via `oats root` + dynamic import).** Package
34
- commands/hooks execute the CLI at the exact absolute path the dispatcher
35
- provides in `OATS_CLI_BIN` (§1 item 4) — never by resolving `oats` from PATH,
36
- which is untrusted inside worktrees.
37
-
38
- ### Envelope and versioning
39
-
40
- Every boundary command supports `--json` with the Desktop CLI API v1 envelope:
41
- exactly one JSON object on stdout — `{ schemaVersion: 1, ok: true, result }`
42
- or `{ schemaVersion: 1, ok: false, error: { code, message } }` — nonzero exit
43
- on failure; progress prose only on stderr.
44
-
45
- - **Versioning** (maintainer ruling): the boundary is versioned by the
46
- **compatibility floor plus a pinned consumer fixture** — the boundary shipped
47
- in kernel **0.19.0** and is unchanged by capability materialization; the
48
- materialized store and the capability-materialization lock (which REPLACES the
49
- earlier package-root spelling in place and remains `lockfileVersion: 2`) raise
50
- the floor for packages that rely on the new manifest surface
51
- (`configTemplates`, dedicated capability roots), which
52
- declare the materialization release's floor instead. Official packages declare
53
- their floor as `compatibility.oats: ">=<floor>"` in `oats-package.json` (and
54
- capability `compatibility.oats` likewise), and each consumer repo pins the kernel
55
- consumer-fixture version its CI probes against. The exact Desktop
56
- `oats version --json` probe payload is NOT extended (no `packageRuntimeApi`
57
- field) — Desktop API compatibility is a separate contract.
58
- - Kernels below the floor are rejected by the consumer's normal
59
- compatibility check (`incompatible-oats` at acquire; the consumer fixture
60
- asserts the rejection).
61
-
62
- ### Commands (exact surface, boundary v1 — maintainer-ruled minimal)
63
-
64
- The public boundary is HIGHER-LEVEL than the private core calls it replaces:
65
- private `findAgent`/`upsertLocalAgent`/`spawnInstance`/`resolveOatsConfig`
66
- usage maps onto capability-defined agents, `oats spawn`, and dispatch-provided
67
- settings — not onto one-for-one public equivalents. File-of-record for the
68
- consumer inventory: `packaging/oats-okf/KERNEL-API-NEEDS.md` on kernel branch
69
- `integrations-expert/official-packages-staging` @ `60d5eb6` (design input;
70
- this contract remains authoritative).
71
-
72
- 1. **Capability-defined agents own lookup/registration/ephemerality.** A
73
- package capability declares its service agents in its manifest `agents:`
74
- (package-relative soul dirs, e.g. oats.okf ships
75
- `agents/memory-harvest/{soul.yaml,AGENTS.md}`). `oats spawn <agent>`
76
- resolves capability-defined agents for the active context, scaffolds a
77
- fresh soul homed locally, and applies ephemeral (`kind: "capability"`)
78
- semantics automatically. There is NO public `oats agent show`,
79
- `oats agent upsert`, or generic `--ephemeral` flag — add such a surface
80
- only when a reusable use case proves it.
81
- 2. **Spawn** — `oats spawn <agent> ... --json` with the EXISTING flags:
82
- `--purpose <slug>` (deterministic derived naming
83
- `<agent>-<purpose>`; no raw instance-name authority), `--parent`,
84
- `--repo`, `--work attached|worktree|checkout|workspace|directory`, `--work-dir`,
85
- `--branch`, `--model`, `--task`/`--task-file` (owner-only tempfiles:
86
- mode 0600, removed on every outcome). Existing validation and error codes
87
- (`E_BAD_ARGS`, `E_PARENT_NOT_FOUND`, `E_SPAWN_FAILED`, ...) are part of
88
- the contract; result is the fixed Desktop CLI API v1 spawn shape
89
- (`{ instance, agent, home, work, tmux, ... }`). If an accepted consumer
90
- mode cannot be expressed by an existing flag, ONE narrow flag is added
91
- with JSON tests — never a general override.
92
- 3. **Settings via dispatch** — `oats <namespace> <command>` passes the active
93
- capability's EFFECTIVE settings to the dispatched process as
94
- `OATS_SETTINGS` (JSON; from the instance metadata snapshot or the resolved
95
- context), the same contract lifecycle hooks already have. Capabilities
96
- read their settings (e.g. oats.okf's `harvest-model`) from `OATS_SETTINGS`;
97
- there is NO public resolved-config read command.
98
- 4. **Consumer rules**: a package command executes the CLI at the exact
99
- absolute path the dispatcher or lifecycle runner provides in the
100
- **`OATS_CLI_BIN`** environment variable (beside `OATS_SETTINGS`), via
101
- `execFile` on that path — **never** by resolving `oats` from `PATH` and
102
- never through a shell: PATH is not a trusted runtime boundary, and package
103
- commands run in worktrees where it can be shadowed. The consumer parses
104
- the one schema-v1 envelope, emits its own envelope, and never imports
105
- `lib/core.mjs` or calls `oats root` for kernel-file resolution.
106
-
107
- Error codes are part of the contract: `E_USAGE`, `E_BAD_ARGS`,
108
- `E_UNKNOWN_COMMAND`, `E_SPAWN_FAILED`, `E_PARENT_NOT_FOUND`,
109
- `E_RELATIVE_NOT_FOUND`, `E_RELATIVE_AMBIGUOUS`, `E_CAPABILITY_BLOCKED`,
110
- `E_CAPABILITY_INACTIVE`.
111
-
112
- ### Directory execution for capability workers
113
-
114
- A worker may explicitly select `work: directory` in its packaged `soul.yaml`,
115
- pass `--work directory` to spawn, or use `spawnInstance(..., {work: "directory"})`.
116
- This is a generic execution mode, independent of any knowledge provider.
117
- Consumers using it must declare the directory-mode release as their
118
- `compatibility.oats` floor, not the older boundary-v1 floor alone.
119
-
120
- - `repo` / `--repo` is an **existing config context directory** in this mode,
121
- not a Git requirement or an edit target. Relative paths resolve from the
122
- agents root's parent; absent a selector it defaults to that deployment scope.
123
- The CLI does not substitute its ambient Git checkout. A configured workspace
124
- can discover and spawn declared package agents before it has an `agents/` or
125
- `local-agents/` directory. Laptop config alone does not declare a deployment.
126
- - `<home>/work` is a new, owned directory, not a symlink and not a fake Git
127
- repository. The kernel creates no branch, copies no source tree, and does not
128
- require Git in a non-Git deployment. Git-owned deployment placement still
129
- requires readable Git metadata to establish the canonical home location.
130
- - `--work-dir` / `workDir` and `--branch` / `branch` are contradictory and
131
- rejected with `E_BAD_ARGS`, even if empty or inherited from a caller bug.
132
- Directory execution never takes ownership of a caller-selected filesystem
133
- path. Existing modes retain their Git/context requirements and semantics;
134
- failed Git operations never implicitly fall back to directory execution.
135
- - Canonical `AGENTS.md` / `CLAUDE.md`, skill composition, provider trust,
136
- lifecycle hooks, frozen launch recipes, runtime preflight and no-launch
137
- metadata are unchanged. Hooks receive `OATS_WORK=directory`, an empty
138
- `OATS_BRANCH`, and the context in `OATS_REPO` / `OATS_CONTEXT` at spawn.
139
- Worktree-only setup scripts are not run in this mode.
140
- - Retirement authenticates directory ownership against the independent spawn
141
- baseline. Nonempty execution work is preserved in verified recovery custody
142
- (`workRecovery.path/work`, with home bytes under `home/`) before removal;
143
- post-hook changes produce another verified snapshot. No work is designated
144
- disposable in this initial mode, including hook-created work. Symlinks inside
145
- work are copied as links, never followed; an exchanged work-root symlink,
146
- unsupported filesystem entry, or unverifiable copy fails closed. Recovery is
147
- not provider delivery or publication, and retains the existing single-host,
148
- quiesced-runtime safety model rather than a hostile-filesystem atomicity claim.
149
-
150
- ### Lifecycle and scheduled-command context
151
-
152
- Lifecycle hooks receive `OATS_CLI_BIN` as the real, absolute `bin/oats.mjs`
153
- path belonging to the **running kernel**. This is authored by
154
- `runLifecycleHooks` itself, including direct core callers; neither ambient
155
- `OATS_CLI_BIN` nor a caller's `extraEnv.OATS_CLI_BIN` can override it. Spawn
156
- hooks also receive the known agents root as `OATS_ROOT`, rather than an empty
157
- value or the ambient caller's root.
158
-
159
- Scheduled command execution starts without the invoking instance's identity:
160
- `OATS_INSTANCE`, `OATS_INSTANCE_HOME`, legacy `OATS_HOME`, the `PI_AGENT_*`
161
- aliases and `PI_AGENTS_ROOT`, plus kernel-authored soul, root, context, work,
162
- team, capability, operation, settings and lifecycle metadata are removed.
163
- The command's explicit cwd and selectors (for example `--soul`) determine
164
- its dispatch; a scheduler invoked from another home must not select that
165
- home's frozen capabilities/settings. Host configuration (`HOME`,
166
- `OATS_HOME_DIR`, package catalog configuration) and ordinary credentials are
167
- preserved. No job schema or knowledge-provider policy is implied by this
168
- isolation.
169
-
170
- ### Native record capture result
171
-
172
- `oats capture --home <dir>` (also `turn-record capture --home <dir>` and the
173
- standalone `capture.mjs`) answers **native JSON**, not a Desktop schema-v1
174
- `{ok,result}` envelope. Do not add `--json`: `--home` already selects JSON.
175
- Diagnostics go to stderr, including lock contention without `--quiet`.
176
- Existing home/owner/appended/session boundary fields remain; the outcome adds:
177
-
178
- - `status`: `complete`, `skipped`, `held`, `incomplete`, or `failed` (failure
179
- takes priority, then skip/held/incomplete).
180
- - `complete`: true only for a performed pass with no holds, incomplete source
181
- records, unattributed candidates or reported errors.
182
- An unchanged performed pass may be complete with `appended: 0`.
183
- - `skipped`: true when another pass owns the capture lock. `lock` then carries
184
- holder/liveness/recovery details; no capture or indexing was performed.
185
- - `held`: count of sessions the underlying pass held pending a timestamp.
186
- - `incomplete`: count of source files with pending torn, oversized, invalid
187
- UTF-8 or otherwise incomplete records; later complete input can recover.
188
- - `issues`: optional metadata-only diagnostics identifying source paths and
189
- reasons; no record bodies are embedded. `unattributed` candidates also make
190
- the pass incomplete rather than silently certifying missing source evidence.
191
- - `failed`: zero on success, nonzero for a capture/read/index/lock-release
192
- failure; `error` describes the failure. `appended: null` on a thrown failure
193
- means the number appended before the failure is unknown, not zero.
194
- - `ignored`: count excluded by configured privacy rules, distinct from a
195
- whole-pass skip. Home capture pins exactly attributed source files; sharing
196
- a Codex day directory does not authorize capturing unrelated records.
197
-
198
- Lock skips, held sessions and incomplete input retain exit status 0 (background reconciliation
199
- must stay nonfatal on contention); errors and failed lock release exit 1.
200
- Previously captured visible boundaries may still be returned on a skipped or
201
- held pass. They are **not** evidence that final capture ran. Consumers requiring
202
- a final pass must check `complete === true`, not exit status or the presence of
203
- boundaries alone; older results lacking that field cannot certify a pass.
204
-
205
- **Snapshot boundary:** completion describes a performed pass over the exact
206
- attributed source files, not a promise about future appends. Discovery carries
207
- an open-descriptor-derived identity and content witness through capture-lock
208
- acquisition. Capture stages bytes from one descriptor and validates that witness
209
- and source stability **before appending**: replacement, truncation and prefix
210
- rewrites fail without appending the replacement's bytes. Same-inode append
211
- growth is allowed only when the witnessed prefix is unchanged. Discovery/read
212
- failures and files disappearing during the pass fail closed; pending trailing
213
- records and unattributed candidates cannot certify completion. A retirement
214
- consumer must first quiesce its writers and then preserve the captured evidence
215
- under its own durable-input protocol. `complete:true` alone does not mean a
216
- harvest was delivered or that a consumer stored those inputs. Configured privacy
217
- exclusions remain exclusions, not an invitation to copy excluded source bytes.
218
-
219
- **Native roots:** managed `--home` capture uses independent execution history,
220
- not the observer's environment or the latest relaunch recipe. New scaffolds
221
- initialize `<instances>/.oats-native-record/<sha256(canonical-home)>/history.json`.
222
- Each managed spawn/start/restart writes a separate pending receipt before
223
- backend dispatch. Inside the backend shell, under the exact environment prefix
224
- and cwd that will exec the harness, the native recorder atomically replaces
225
- that receipt with the effective absolute **record locations** and runtime. Only
226
- these allowlisted locations, home, start id/time and custody state are saved;
227
- no environment map, credential reference value, task or argv is persisted.
228
- The saved `instance.json` command/recipe remains a relaunch **template**, not
229
- execution evidence: use `oats session start`, not a manual shell replay of it.
230
-
231
- Location rules at execution are `CLAUDE_CONFIG_DIR/projects` (default exactly
232
- `$HOME/.claude/projects`), `PI_CODING_AGENT_DIR/sessions` (default
233
- `$HOME/.pi/agent/sessions`), and `CODEX_HOME/sessions` (default
234
- `$HOME/.codex/sessions`). Pi's `--session-dir` wins over
235
- `PI_CODING_AGENT_SESSION_DIR`, which wins over its agent-dir location; Pi tilde
236
- paths expand against the effective HOME. Relative paths resolve from the source
237
- home. Existing symlinks resolve at recording time, including existing ancestors
238
- of not-yet-created roots. Inherited overrides and resolved `fromEnv` location
239
- inputs are thereby retained **after backend shell startup**, independently of
240
- later observer/config/reference changes. The recorder runs before the native
241
- exec; unsupported explicit Pi `--session` or a receipt write failure refuses
242
- that exec and leaves pending custody, rather than claiming a default root.
243
- Wrappers must preserve this native storage contract: arbitrary scripts which
244
- change storage internally cannot be inferred from their executable name.
245
-
246
- History is never replaced by a newer runtime selection, truncated with the
247
- bounded restart log, or deleted with the source home. Capture unions all
248
- historically recorded locations for each runtime and still attributes every
249
- file by its own cwd. Missing/unreadable historical roots, unreadable/invalid
250
- receipts, and pending/unfinished launches fail closed. A newly scaffolded home
251
- with no managed launches has an authoritative empty managed-launch inventory.
252
- A legacy home without that scaffold authority cannot acquire proof of its
253
- **earlier** roots merely by restarting: later starts retain new locations but
254
- its history remains incomplete. Do not remove pending/history receipts just
255
- to get a green capture; recovery requires establishing the source inventory.
256
-
257
- Standalone fixtures and explicit legacy inventories can opt into
258
- `capture --home <dir> --current-roots` (`sourceRoots: "current-env"` in JSON),
259
- or use `sessionsForHome(home, {roots: {cc: [...], pi: [...], codex: [...]}})`.
260
- Explicit API roots exclude unspecified formats, and every supplied root must
261
- exist. The CLI fallback uses current environment plus recorded hook/config
262
- location overrides; `fromEnv` resolves from that **current** base environment.
263
- Its `complete:true` certifies only that chosen observer-time inventory, **not**
264
- all historical roots; do not enable it implicitly for final-capture consumers.
265
- Normal managed reports say `sourceRoots: "launch-history"`. Background capture
266
- without `--home` retains observer-time discovery (including `.claude*` profiles)
267
- and optional absent native defaults. Neither fallback introduces knowledge
268
- policy into the kernel.
269
-
270
- **Claude children:** discovery also enumerates the native
271
- `<project>/<sessionId>/subagents/*.jsonl` layout, including children whose parent
272
- transcript is absent. Each child requires its own cwd attribution; neither its
273
- parent's cwd nor its directory supplies missing attribution. Child streams use
274
- `cc.<sessionId>.<child-file-stem>` (threads
275
- `cc:session:<sessionId>.<child-file-stem>`) so identical child filenames under
276
- different sessions cannot collide. Complete native lines are preserved verbatim;
277
- torn, unstamped or unattributed child evidence blocks certification, and child
278
- read/discovery failures fail the pass. Ignore rules run before child opens and
279
- can match its path, filename, qualified id, native child id or parent session id.
280
-
281
- **Piped recall:** native `oats recall` JSON responses drain stdout before process
282
- termination, including large thread windows and individual `--show` records.
283
- Consumers must still bound their own reads/buffers (use `--ids-only` for sizing);
284
- a successful producer does not imply an unbounded consumer buffer.
285
-
286
- ### Consumer fixture
287
-
288
- The engine ships a consumer fixture driving the full oats.okf pattern
289
- exclusively through this surface: a capability-defined `memory-harvest`
290
- agent resolved and spawned via `oats spawn --json` in all three source modes
291
- (local-soul / workspace-mode / repo-resident), parent relation,
292
- purpose-derived naming + debounce, model via `OATS_SETTINGS` dispatch,
293
- task-file privacy/cleanup, clean JSON success/failure, no private
294
- import/`oats root` lookup, Pi + Claude scaffold parity, and sub-floor kernel
295
- rejection. WS3 reuses the fixture shape as each official repo's per-repo CI
296
- probe, combined with the acquire → lock → trust → activate → spawn probe
297
- from `test/packages.test.mjs`. (The oats.okf tree changes themselves —
298
- `agents/memory-harvest`, dropping the core import — are WS3 deliverables.)
299
-
300
- ## 2. Capability-local npm runtime closure
301
-
302
- - **Detection and placement**: materialization roots are the manifest-declared
303
- CAPABILITY roots — each one carrying BOTH `package.json` AND
304
- `package-lock.json` is materialized independently, and the resulting
305
- `node_modules` becomes part of that capability's materialized artifact. This
306
- is what lets an inner `oats.json` resolve resources via `node_modules/...`
307
- relative to its own manifest (e.g. oats-aweb's
308
- `node_modules/@awebai/pi/skills/...`) inside a self-contained artifact.
309
- A **package-root-only** closure has no durable home and is NOT
310
- materialized: it is package tooling. If a capability actually depends on it,
311
- self-containment fails and the package is rejected
312
- (`capability-not-self-contained`) rather than silently installing a broken
313
- artifact. For a legacy `"."` capability root the capability root *is* the
314
- package root, so that package-root lock is the capability's own closure (it is
315
- detected once, not twice). Directories not enumerated by the manifest are
316
- never scanned.
317
- - **When and how**: materialization runs IN STAGING during acquire, update and
318
- restore, after payload integrity verification and BEFORE the capability
319
- artifact's integrity is computed or swapped in. The command is exactly
320
- `npm ci --omit=dev --omit=peer --ignore-scripts` (plus `--no-audit
321
- --no-fund` noise suppression) per materialization root — **dev AND host
322
- peer dependencies are omitted**; **no npm lifecycle scripts ever run**, at
323
- any phase. A package may consume host-provided peer APIs only through an
324
- explicit supported host boundary (§1) — never by auto-materializing an
325
- unrelated harness peer into its closure.
326
- - **Closure/integrity/audit scope**: the runtime-closure contract covers the
327
- ACTUALLY MATERIALIZED production dependency tree, not the full lock
328
- metadata (a lockfile may describe dev/peer subtrees that are never
329
- materialized and are out of contract). Vulnerability audit uses the
330
- identical scope: `npm audit --omit=dev --omit=peer --ignore-scripts`.
331
- Consumer/package CI must include a fixture asserting omitted peer
332
- dependencies are ABSENT from the materialized tree.
333
- - **Integrity coverage**: the lock has TWO digests at two levels, and the
334
- closure sits inside one of them.
335
- - The package row's `integrity` covers the staged package PAYLOAD only —
336
- every `node_modules` (at any depth) and a root `oats-lock.json` are excluded,
337
- so it is stable whether or not materialization has run. Root source-control
338
- metadata (`.git`) is stripped before staging; if it later appears in a
339
- managed artifact it is ordinary drift, not an integrity exclusion.
340
- - The capability row's `integrity` covers the MATERIALIZED ARTIFACT with **no
341
- exclusions at all**: capability source bytes, the materialized
342
- `node_modules`, and the generated `.oats-installation.json` provenance file.
343
- - There is consequently NO separate dependency digest anywhere in the model —
344
- tampering with a materialized dependency changes the capability artifact
345
- integrity directly, which invalidates `trusted` exactly like source drift and
346
- makes bare restore reproject. A lock row carrying `depsIntegrity` is
347
- evidence of the unsupported transitional shape (contract §4.1), not a field
348
- to honour.
349
- - `npm ci` fails closed on any lockfile mismatch. Doctor reports the package
350
- payload integrity and each capability artifact's integrity/trust state.
351
- - **Reproducibility (v1 MUST: platform-invariant closures)**: `node_modules`
352
- is a derived artifact — never part of the package payload hash, never
353
- committed, always reproduced from the locked `package-lock.json` and verified
354
- through the capability artifact integrity that contains it. Because that
355
- single artifact digest lives in a shared lock, **v1 packages MUST have
356
- platform-invariant materialized closures**: no native builds, no
357
- platform-specific optional dependencies, no install-time variance of any kind.
358
- A closure that cannot materialize byte-identically across supported platforms
359
- is UNSUPPORTED in v1 — the package must vendor a pure-JS closure or drop the
360
- dependency; official dependency-bearing packages gate this across their
361
- published platforms in CI. The engine ENFORCES this at materialization as a
362
- transaction-wide preflight PLUS a post-materialization scan: every
363
- materialization root's lockfile (every declared capability root, kept and
364
- fresh) is scanned BEFORE any `npm ci` — only entries in the materialized
365
- non-dev/non-peer closure are evaluated (omitted metadata cannot fail an
366
- otherwise valid closure); an INCLUDED entry with os/cpu/libc constraints,
367
- optional-dependency variance, or an install script is rejected (an included
368
- install script is disallowed even though `--ignore-scripts` inerts it — the
369
- runtime almost certainly expects the artifacts it would have built). After
370
- `npm ci`, before digest/swap, the materialized tree is scanned for `.node`
371
- native binaries alongside symlink containment. npm lockfileVersion 1 (no
372
- `packages` map) fails closed — regenerate with modern npm. (A future keyed
373
- per-platform closure map may relax this.)
374
- - **Containment**: capability code/hook/skill/agent paths must resolve inside
375
- the CAPABILITY root after symlink resolution — that is what makes the
376
- materialized artifact self-contained and independently hashable. Materialized
377
- `node_modules` trees under that root are inside the boundary by construction —
378
- and ENFORCED: after `npm ci`, before any digest or swap, every symlink under
379
- every materialized `node_modules` is realpath-checked to resolve inside the
380
- capability root; a broken or escaping link fails the transaction
381
- (`path-escape`) with full rollback. Node import resolution follows symlinks,
382
- so this check is global, not best-effort.
383
- - **Rollback**: materialization happens IN STAGING before any destination
384
- mutation; a materialization failure fails the whole acquire/update
385
- transaction with the capability store and lock unchanged, and a restore whose
386
- reprojected artifact does not reproduce the locked capability `integrity`
387
- fails as `integrity-drift` with the prior artifact left in place. Staging
388
- directories are removed wholesale on any failure.
389
-
390
- ## 3. Incremental transaction semantics
391
-
392
- Acquire/update of one package closure is **incremental with respect to the
393
- scope's capability store**, never a wholesale store replacement:
394
-
395
- - Capability artifacts, package rows and capability rows belonging to packages
396
- NOT in the resolved closure are untouched — bytes on disk and lock JSON both.
397
- - Within the closure, a capability whose newly projected artifact integrity
398
- EQUALS its currently locked integrity is kept in place ("kept" in reports) and
399
- its `trusted` flag is preserved verbatim.
400
- - Only capabilities whose artifact integrity CHANGES have their artifact
401
- replaced and their `trusted` reset to `false`. Trust is per capability, so an
402
- unchanged capability inside a changed package keeps its approval.
403
- - All validation (manifests, self-containment, cycles, identity and
404
- capability-ID collisions, compatibility, platform invariance) completes against
405
- a staging area BEFORE any destination mutation; the artifact swaps and the lock
406
- write happen only after full-closure validation. On any failure before that
407
- point the staging area is removed and the destination store + lock are
408
- byte-identical to the pre-operation state.
409
- - An update replaces ALL of one package's exports together or none of them; a
410
- removed export is retired only when no config references it (otherwise
411
- `remove-blocked`, with nothing changed).
412
- - Restore is per-capability transactional: a failure (`integrity-drift`,
413
- `capability-list-mismatch`) leaves that capability absent or untouched — never
414
- partially installed — and does not affect other capabilities' restores.
415
-
416
- ## 4. Runtime-validated schema invariants
417
-
418
- JSON Schema cannot express these in the current shapes, so they are normative
419
- SEMANTIC validation rules with tests; validators of the schemas alone are not
420
- complete:
421
-
422
- - `oats-package.json`:
423
- - `capabilities` is REQUIRED and non-empty — config-only and empty packages
424
- are `invalid-package-manifest`;
425
- - `configTemplates` is OPTIONAL and is the canonical spelling; `configs` is a
426
- deprecated read-only alias; both spellings normalize to one descriptor shape
427
- carrying a diagnostic `legacySpelling`, and carrying BOTH is
428
- `invalid-package-manifest`;
429
- - a `"."` capability root is accepted only when the manifest does NOT carry
430
- `configTemplates` (§5), and remains exclusive with any other capability path;
431
- authoring never emits it;
432
- - at most one `configTemplates.*.default === true` (equivalently
433
- `configs.*.default`) per manifest → `invalid-package-manifest`;
434
- - `compatibility.oats` is REQUIRED with exactly the grammar `>=x.y.z`,
435
- `^x.y.z`, or `x.y.z` — schema and runtime agree; malformed/missing →
436
- `invalid-package-manifest`, valid-but-unsatisfied → `incompatible-oats`;
437
- - every declared capability must be projectable self-contained — each declared
438
- resource exists and realpath-resolves inside its own capability root →
439
- `capability-not-self-contained` / `path-escape`. JSON Schema cannot see this
440
- at all: it is a filesystem property of the staged payload.
441
- - `oats-lock.json`, validated BEFORE restore, trust/approval, update/remove
442
- planning, migration planning, the locked-template reader, and doctor/list
443
- consumption → `invalid-lock` (fail closed before executable approval or
444
- artifact replacement; no normalization, no auto-repair, NO side effects;
445
- message/provenance carry lock file, package or capability identity, and the
446
- violated field/edge):
447
- - both top-level `packages` and `capabilities` maps are required;
448
- - `dependencies` is required on every package row (empty array when none), so
449
- a reader never distinguishes absent from empty;
450
- - normalized source prefix (`git:`/`path:`/`catalog:`) and source/commit
451
- pairing: `path:` requires `commit: "local"` AND `path: "."`; `git:`/`catalog:`
452
- require an exact 40-hex `commit`;
453
- - canonical `path` spelling on both row kinds — a non-canonical spelling is
454
- invalid, never repaired;
455
- - every `capabilities.*.package` is a key of the same lock's `packages` map
456
- (the provider back-reference is the single truth for which capabilities a
457
- package supplies — package rows never list them);
458
- - every `packages.*.dependencies[]` id is a key of the same lock's `packages`
459
- map; no self-dependency and no cycle in the locked dependency graph;
460
- - `trusted` is a boolean, and it is the ONLY trust field: there is no
461
- package-level approval anywhere in the model;
462
- - `integrity` digests are well-formed sha256 on both row kinds;
463
- - arrays retain schema uniqueness (no duplicates);
464
- - `.oats-installation.json` inside a materialized artifact must AGREE with the
465
- capability and package rows it was projected from (§3.1 of the contract);
466
- disagreement is `invalid-lock`, modification is `integrity-drift`;
467
- - the unsupported transitional v2 shape is rejected centrally by the exact
468
- predicate of contract §4.1, using direct raw lock-scope reads rather than
469
- `configChain` so lock-only scopes are visible, with own-property presence —
470
- never truthiness or array length — as the row test;
471
- - v1 documents are validated against their own historical shape when read, so
472
- migration planning and doctor operate on verified data.
473
-
474
- **Prototype safety is required at EVERY lookup or membership check keyed by a
475
- package or capability ID** — central read, dependency graph, provider
476
- resolution, trust, approval, update and remove alike, not merely at the
477
- transitional tell fields. Raw parsed JSON objects return inherited
478
- `constructor`, `toString` or `valueOf` for `map[id]` even when no own entry
479
- exists, so identity keys are charset-validated and every map is null-prototype
480
- or accessed through `Object.hasOwn`. A prototype-named or hostile raw-JSON ID
481
- must never impersonate a provider, a dependency or a trust entry, nor bypass a
482
- membership check. Fixtures cover empty transitional arrays and falsey values
483
- plus prototype-named package AND capability IDs across central read, graph,
484
- provider and trust lookups.
485
-
486
- Fail-closed enforcement points: `parseLockFileStrict`, `readPackageLocks` and
487
- `listInstalledPackages` RAISE `invalid-lock` — consumers never see invalid
488
- locks as absent or usable data; `writePackageLock` and
489
- `writeCapabilityLockEntry` validate the complete prospective document (both
490
- maps, together) before writing; restore, trust queries, approval, update/remove
491
- planning, migration planning and the locked-template reader validate before
492
- acting. Doctor (human and `--json`) catches the typed error and renders the
493
- actionable diagnosis — it is the only consumer that continues past an invalid
494
- lock, and it never uses the invalid data.
495
-
496
- `invalid-lock` joins the error taxonomy of the main contract (§8).
497
-
498
- ## 5. Flat single-capability packages (`capabilities: ["."]`)
499
-
500
- **Read compatibility only.** A capability directory may BE the package root —
501
- `oats-package.json` and `oats.json` side by side with `capabilities: ["."]` — in
502
- an already-published manifest. The discriminator is `configTemplates`, NOT
503
- `configs`: `oats.authoring@1.0.0` is `capabilities: ["."]` and ships no template
504
- map at all, so keying acceptance on the deprecated spelling would strand a
505
- package the kernel is required to keep reading. A manifest carrying
506
- `configTemplates` is unambiguously new and its `"."` is
507
- `invalid-package-manifest`; authoring tooling never emits `"."` either way.
508
- Semantics for the layouts that still exist:
509
-
510
- - **The projection is still a capability artifact.** The capability root equals
511
- the package root, so the materialized artifact under
512
- `.agents/capabilities/installed/<id>/` contains the whole package root
513
- including `oats-package.json` and any config templates. That is a superset, not
514
- a leak: everything in it is validated payload from one exact locked source,
515
- and the artifact remains self-contained, independently hashable and
516
- independently trustable. Its `integrity` is the artifact hash like any other.
517
- - **Two digests, no double counting.** The package row's payload `integrity` and
518
- the capability row's artifact `integrity` cover overlapping bytes on purpose:
519
- one proves the distribution, the other proves the installation. Trust binds to
520
- the capability digest only.
521
- - **Resource indexing**: only the manifest-declared `.` is indexed; `oats.json`
522
- loads from the root with normal capability validation. `oats-package.json`
523
- living inside the capability's file set is harmless — each file has exactly
524
- one loader (`oats-package.json` → package manifest, `oats.json` → capability
525
- manifest), so no manifest-kind ambiguity can arise.
526
- - **Constraint**: `.` implies a SINGLE-capability package. Listing `.` together
527
- with any other capability path would nest one capability inside another and is
528
- rejected as `invalid-package-manifest`.
529
- - Per-capability npm closures (§2) degenerate to the package root: a root
530
- `package.json` + `package-lock.json` pair is the capability's closure (it is
531
- detected once, not twice).
532
- - **Fail rather than degrade**: if such a package's capability cannot be
533
- projected self-contained, acquisition and migration fail
534
- (`capability-not-self-contained`) instead of silently retaining package-only
535
- paths.
536
-
537
- ## 6. Legacy locks: v1 compatibility, and no transitional-v2 compatibility
538
-
539
- There is exactly one legacy format to support, and it is v1.
540
-
541
- 1. The kernel **writes only** the capability-materialization lock.
542
- `writePackageLock` and `writeCapabilityLockEntry` refuse an existing v1
543
- file — **including an empty one** — with `legacy-lock`. Only an ABSENT lock
544
- is a fresh document; an empty v1 file still carries a format decision the
545
- user has not made, and converting it implicitly would contradict explicit
546
- migration.
547
- 2. **v1 stays usable.** Runtime discovery, exact restore, trust checks,
548
- approval updates and doctor/list diagnosis keep working against v1 locks and
549
- the existing v1 artifacts in `.agents/capabilities/installed/`. Ordinary use
550
- of an unconverted deployment never requires migration; only lifecycle
551
- mutation through the package surface does. `readPackageLocks` surfaces v1
552
- files in `legacy` and in `migration` (with kind `v1` or `v1-empty`), and
553
- nothing is normalized, repaired or rewritten on read.
554
- 3. **Conversion is explicit, transactional and all-or-nothing per scope.** The
555
- lock has no residue container, so a v1 scope with even one unmappable entry
556
- stays v1 in full — reported as `hold`/`manual` — and keeps working.
557
- Re-running `oats migrate` retries it once the catalog can map it. Guided
558
- official migration converts directly into flat capability materialization.
559
- 4. **Trust is never carried over from v1.** A v1 capability artifact and a
560
- materialized artifact are different bytes, so every executable surface is
561
- re-earned and listed in the returned `trust[]`.
562
- 5. **Rollback is byte-exact.** Any conversion failure restores the original v1
563
- lock byte-identically, removes every artifact the conversion created, leaves
564
- superseded v1 artifacts in place, and rolls back the ignore bytes. Owned/path
565
- capabilities are never touched.
566
- 6. **The earlier transitional package-root v2 is not supported at all.** It is
567
- detected centrally by contract §4.1 and rejected as `invalid-lock` with an
568
- actionable message naming the unsupported shape and scope recreation. It is
569
- never converted, never partially interpreted, and there is no
570
- `.agents/packages/installed/` handling, offline projection, or trust
571
- carry-over anywhere in the engine. Existing local pre-adoption state is
572
- recreated by reinstalling. The one exception is the state-free empty
573
- document `{ "lockfileVersion": 2, "packages": {} }`, which carries no state
574
- and normalizes to the empty current lock.
575
- 7. **Cutover gate**: zero lockfileVersion 1 files (including empty
576
- `{capabilities:{}}` ones) and zero `.agents/packages/` directories across
577
- every reconciled scope. Doctor reports each remaining one with its exact
578
- command.
579
-
580
- Required engine tests (`test/package-engine.test.mjs`): v1 empty file stays
581
- pending (never implicitly converted), v1 partial-mappability hold with the scope
582
- untouched, v1 full conversion with trust not carried, byte-exact rollback on
583
- failure, unsupported transitional v2 rejected with no side effects (both
584
- predicate arms, including empty transitional arrays and a dependency-free old
585
- row), state-free empty transitional v2 normalization, prototype-named package
586
- and capability IDs across central read / graph / provider / trust lookups, and
587
- `.oats-installation.json` determinism, field agreement, tamper failure and
588
- future-kernel restore.
@@ -1,57 +0,0 @@
1
- # BREAKING: desktop succession — `oats.web`, `oats pane`, and the control-pane library are retired
2
-
3
- **The next release of `@awebai/oats` containing this change is a
4
- BREAKING release.** Three previously shipped surfaces were removed in favor of
5
- the OATS Desktop app (`packages/desktop/` in the framework repo):
6
-
7
- | Removed surface | Replacement |
8
- |---|---|
9
- | `oats.web` marketplace capability (`oats web start`, browser panel) | OATS Desktop app — the same zero-dependency loopback server is bundled at `packages/desktop/server/` and spawned by the app |
10
- | `oats pane` CLI command and the Control Pane TUI | OATS Desktop app (Active overview / instance roster) |
11
- | `@awebai/oats/control-pane` package export (`lib/control-pane/model.mjs`) | The roster model moved into the Desktop app; under workspace model v2 the app reads the kernel's `oats status --json` instead ([deployment model](../packages/desktop/docs/desktop-deployment-model.md)). It is not a public kernel export |
12
-
13
- ## Migrating a deployment that used `oats.web`
14
-
15
- Under the **0.25 workspace model** there is nothing to uninstall: remove
16
- `oats.web` from `oats-workspace.yaml` `packages:` / `defaults.capabilities`
17
- and from any `soul.yaml` `capabilities:`, run `oats sync` (the lock v3 entry
18
- disappears with the declaration), and use the Desktop app (step 3 below).
19
-
20
- For a **0.24 classic** deployment:
21
-
22
- 1. Remove the `oats.web` entry from `capabilities.additive` in every
23
- `oats-config.yaml` in your config chain.
24
- 2. Remove the `oats.web` entry from `oats-lock.json` (v2) at the same scope(s),
25
- and delete any stale installed copy under `.agents/capabilities/installed/`.
26
- 3. Use the OATS Desktop app instead: `cd packages/desktop && npm install &&
27
- npm run rebuild && npm start` (see `packages/desktop/README.md`).
28
-
29
- The CLI diagnoses stale references instead of failing opaquely:
30
-
31
- - `oats doctor` warns when an `oats-lock.json` still pins `oats.web`, with the
32
- fix spelled out.
33
- - A soul or workspace default naming `oats.web` fails at resolution with a
34
- message naming the successor and the exact cleanup steps (remove it from
35
- `packages:` / the soul's `capabilities:`).
36
-
37
- ## Migrating `oats pane` usage
38
-
39
- `oats pane` now exits with a pointer to the desktop app. Scripts or docs
40
- invoking it should launch OATS Desktop instead. The `--theme` themes (dark,
41
- solarized) exist in the app's theme system.
42
-
43
- ## Consumers of the `./control-pane` export
44
-
45
- `import ... from "@awebai/oats/control-pane"` no longer resolves. The
46
- model's pure helpers (`readMarkdownSection`, `parseTmuxWindows`,
47
- `parseGitStatus`, `parseGitDiffStat`, `buildConstellation`, `relativeAge`)
48
- moved into the private Desktop app and were retired with its workspace-model v2
49
- rebuild. If you depended on this export, vendor the helpers from a released tag
50
- or open an issue — no known external consumer existed at removal time.
51
-
52
- ## Release gating (maintainers)
53
-
54
- Downstream installers/packaging for the desktop app must exist **before** the
55
- next release ships; this migration note travels with the release notes and
56
- the release must be flagged **BREAKING** (major or clearly-marked minor per
57
- the project's pre-1.0 conventions).