@awebai/oats 0.23.2 → 0.24.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 (172) hide show
  1. package/README.md +224 -391
  2. package/bin/oats-pi-sdk-host.mjs +17 -0
  3. package/bin/oats.mjs +470 -51
  4. package/capabilities/oats-okf/bin/oats-okf-binding.mjs +14 -0
  5. package/capabilities/oats-okf/bin/oats-okf.mjs +79 -11
  6. package/capabilities/oats-okf/lib/binding-wire.mjs +268 -0
  7. package/capabilities/oats-okf/lib/captured-worker.mjs +109 -0
  8. package/capabilities/oats-okf/lib/config.mjs +2 -1
  9. package/capabilities/oats-okf/lib/inspection.mjs +16 -1
  10. package/capabilities/oats-okf/lib/invocation-context.mjs +111 -0
  11. package/capabilities/oats-okf/lib/invocation-shape.mjs +135 -0
  12. package/capabilities/oats-okf/lib/io.mjs +1 -1
  13. package/capabilities/oats-okf/lib/portable-binding.mjs +199 -0
  14. package/capabilities/oats-okf/lib/source-contract.mjs +46 -0
  15. package/capabilities/oats-okf/lib/sources.mjs +123 -3
  16. package/capabilities/oats-okf/lib/stores.mjs +104 -25
  17. package/capabilities/oats-okf/lib/worker.mjs +69 -10
  18. package/capabilities/oats-okf/oats.json +35 -7
  19. package/capabilities/oats-okf/schemas/okf-portable-declaration.schema.json +87 -0
  20. package/capabilities/oats-okf/schemas/okf-portable-payload.schema.json +113 -0
  21. package/capabilities/oats-okf/skills/memory-harvest/SKILL.md +23 -5
  22. package/capabilities/oats-okf/skills/okf/SKILL.md +42 -1
  23. package/docs/artifact-approvals.schema.json +7 -0
  24. package/docs/capabilities.md +4 -0
  25. package/docs/capability-manifest.schema.json +37 -66
  26. package/docs/captured-invocation-context.schema.json +7 -0
  27. package/docs/captured-resolution.schema.json +7 -0
  28. package/docs/design/2026-09-14-artifact-retention-contract.md +190 -0
  29. package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +708 -0
  30. package/docs/design/2026-09-14-portable-souls-contract-amendments.md +85 -0
  31. package/docs/design/2026-09-14-portable-souls-explainer.md +750 -0
  32. package/docs/design/2026-09-15-captured-dispatch.md +127 -0
  33. package/docs/design/2026-09-15-captured-resolution-records.md +143 -0
  34. package/docs/design/2026-09-15-package-preparation.md +100 -0
  35. package/docs/design/2026-09-15-portable-data-contract.md +121 -0
  36. package/docs/design/2026-09-15-portable-declarations.md +189 -0
  37. package/docs/design/2026-09-15-portable-souls-handoff.md +150 -0
  38. package/docs/design/2026-09-15-portable-souls-implementation.md +417 -0
  39. package/docs/design/2026-09-15-selection-lock-and-approval.md +122 -0
  40. package/docs/design/2026-09-15-source-observation.md +119 -0
  41. package/docs/design/2026-09-16-captured-admission.md +77 -0
  42. package/docs/design/2026-09-16-captured-helper-dispatch.md +105 -0
  43. package/docs/design/2026-09-16-captured-launch-inputs.md +42 -0
  44. package/docs/design/2026-09-16-command-profile-preparation.md +86 -0
  45. package/docs/design/2026-09-16-fresh-install-first-rollout.md +47 -0
  46. package/docs/design/2026-09-16-fresh-operator-walkthrough.md +277 -0
  47. package/docs/design/2026-09-16-knowledge-capability-contract.md +61 -0
  48. package/docs/design/2026-09-16-messaging-capability-contract.md +59 -0
  49. package/docs/design/2026-09-16-portable-migration-evidence.md +156 -0
  50. package/docs/design/2026-09-16-portable-onboarding.md +177 -0
  51. package/docs/design/2026-09-16-prepare-request-transport.md +26 -0
  52. package/docs/design/2026-09-16-provider-binding-codecs.md +98 -0
  53. package/docs/design/2026-09-16-provider-binding-wire.md +247 -0
  54. package/docs/design/2026-09-17-capability-helper-input-contract.md +95 -0
  55. package/docs/design/2026-09-17-captured-backend-parity.md +53 -0
  56. package/docs/design/2026-09-17-captured-native-start.md +58 -0
  57. package/docs/design/2026-09-17-portable-boundary-hookup.md +19 -0
  58. package/docs/design/2026-09-17-portable-boundary-resources.md +52 -0
  59. package/docs/design/2026-09-17-public-captured-start.md +108 -0
  60. package/docs/design/2026-09-17-public-prepare-request.md +90 -0
  61. package/docs/design/2026-09-18-captured-pi-host.md +205 -0
  62. package/docs/design/2026-09-18-first-cut-release-checklist.md +131 -0
  63. package/docs/design/2026-09-18-herdr-protocol-compatibility.md +60 -0
  64. package/docs/design/2026-09-20-redesign-program-board.md +70 -0
  65. package/docs/design/2026-09-20-workspace-and-portable-adoption-plan.md +287 -0
  66. package/docs/design/2026-09-20-workspace-onboarding-public.md +124 -0
  67. package/docs/design/README.md +42 -0
  68. package/docs/desktop-cli-api.md +5 -2
  69. package/docs/execution-capsule.schema.json +108 -0
  70. package/docs/execution-targets.md +20 -7
  71. package/docs/first-team.md +1 -1
  72. package/docs/knowledge-theory.md +353 -111
  73. package/docs/knowledge.md +10 -1
  74. package/docs/layers.md +89 -354
  75. package/docs/oats-lock-v3.schema.json +7 -0
  76. package/docs/oats-member.schema.json +38 -0
  77. package/docs/oats-workspace.schema.json +68 -0
  78. package/docs/official-marketplace.md +79 -0
  79. package/docs/packages.md +4 -0
  80. package/docs/portable.schema.json +2512 -0
  81. package/docs/provider-check-input.schema.json +7 -0
  82. package/docs/release-notes/v0.24.0.md +104 -0
  83. package/docs/release-notes/v0.24.1.md +17 -0
  84. package/docs/schedules.md +126 -14
  85. package/docs/soul.schema.json +82 -0
  86. package/docs/souls-and-instances.md +20 -7
  87. package/docs/workspace-adoption.md +285 -0
  88. package/docs/workspaces.md +154 -0
  89. package/injects/oats-portable.md +16 -0
  90. package/injects/portable-instance-boundary.md +39 -0
  91. package/injects/portable-work-directory.md +29 -0
  92. package/lib/artifact-approvals.mjs +120 -0
  93. package/lib/artifact-tree.mjs +141 -0
  94. package/lib/capability-artifacts.mjs +179 -0
  95. package/lib/capability-execution.mjs +15 -0
  96. package/lib/capability-inputs.mjs +39 -0
  97. package/lib/capability-provenance.mjs +231 -0
  98. package/lib/captured-action-shape.mjs +21 -0
  99. package/lib/captured-admission-shape.mjs +20 -0
  100. package/lib/captured-binding-file.mjs +36 -0
  101. package/lib/captured-dispatch.mjs +66 -0
  102. package/lib/captured-instance-index.mjs +277 -0
  103. package/lib/captured-invocation-context.mjs +130 -0
  104. package/lib/captured-launch-request.mjs +46 -0
  105. package/lib/captured-operation-process.mjs +15 -0
  106. package/lib/captured-pi-custody.mjs +29 -0
  107. package/lib/captured-pi-host.mjs +167 -0
  108. package/lib/captured-pi-outcome.mjs +172 -0
  109. package/lib/captured-resolutions.mjs +275 -0
  110. package/lib/captured-scaffold.mjs +87 -0
  111. package/lib/captured-selector.mjs +28 -0
  112. package/lib/captured-session-backend.mjs +52 -0
  113. package/lib/captured-source-receipt-file.mjs +72 -0
  114. package/lib/config-data.mjs +104 -0
  115. package/lib/core.mjs +961 -566
  116. package/lib/errors.mjs +7 -0
  117. package/lib/helper-injection-policy.mjs +98 -0
  118. package/lib/herdr.mjs +18 -7
  119. package/lib/instruction-composition.mjs +31 -0
  120. package/lib/legacy-lock-codec.mjs +106 -0
  121. package/lib/manifest-settings.mjs +84 -0
  122. package/lib/package-closure.mjs +48 -0
  123. package/lib/package-materialization.mjs +83 -0
  124. package/lib/pi-sdk-host.mjs +229 -0
  125. package/lib/portable-artifacts.mjs +115 -0
  126. package/lib/portable-choices.mjs +82 -0
  127. package/lib/portable-composition.mjs +136 -0
  128. package/lib/portable-digest.mjs +105 -0
  129. package/lib/portable-files.mjs +26 -0
  130. package/lib/portable-identity.mjs +40 -0
  131. package/lib/portable-lock.mjs +117 -0
  132. package/lib/portable-migration-artifacts.mjs +135 -0
  133. package/lib/portable-migration-evidence.mjs +305 -0
  134. package/lib/portable-migration-store.mjs +199 -0
  135. package/lib/portable-migration.mjs +104 -0
  136. package/lib/portable-onboarding-acceptance.mjs +66 -0
  137. package/lib/portable-onboarding-request.mjs +49 -0
  138. package/lib/portable-onboarding.mjs +249 -0
  139. package/lib/portable-package-preparation.mjs +188 -0
  140. package/lib/portable-policy.mjs +44 -0
  141. package/lib/portable-shape.mjs +35 -0
  142. package/lib/portable-soul.mjs +38 -0
  143. package/lib/portable-state.mjs +80 -0
  144. package/lib/portable-values.mjs +181 -0
  145. package/lib/prepare-composition.mjs +151 -0
  146. package/lib/prepared-bindings.mjs +78 -0
  147. package/lib/prepared-resources.mjs +127 -0
  148. package/lib/provider-binding-broker.mjs +59 -0
  149. package/lib/provider-binding-wire.mjs +110 -0
  150. package/lib/provider-binding.mjs +22 -0
  151. package/lib/repository-observation.mjs +226 -0
  152. package/lib/resolution-shape.mjs +393 -0
  153. package/lib/schedule-capsule.mjs +206 -0
  154. package/lib/schedule.mjs +259 -38
  155. package/lib/servers.mjs +15 -0
  156. package/lib/soul-constraints.mjs +40 -0
  157. package/lib/source-projection.mjs +84 -0
  158. package/lib/source-spec.mjs +189 -0
  159. package/lib/workspace-definition.mjs +126 -0
  160. package/lib/workspace-discovery.mjs +146 -0
  161. package/package-catalog.json +2 -1
  162. package/package.json +3 -2
  163. package/packages/record/lib/capture-cc.mjs +14 -6
  164. package/packages/record/lib/formats.mjs +14 -3
  165. package/packages/record/lib/native-history.mjs +277 -7
  166. package/packages/record/lib/session-snapshot.mjs +25 -5
  167. package/packages/record/lib/sessions-for-home.mjs +30 -13
  168. package/skills/oats/SKILL.md +12 -7
  169. package/skills/oats-config/SKILL.md +11 -9
  170. package/skills/oats-packages/SKILL.md +12 -8
  171. package/skills/oats-portable/SKILL.md +115 -0
  172. package/skills/oats-portable-artifacts/SKILL.md +63 -0
@@ -0,0 +1,285 @@
1
+ # Adopt the OATS development workspace
2
+
3
+ OATS hosts the shared `oats-workspace.yaml`. Its separate `oats.yaml` advertises
4
+ source-complete exports and declares its own reciprocal membership. `oats-dev`
5
+ remains a development-capability repository, including `oats.review`; membership
6
+ neither activates that package nor replaces its existing configuration templates.
7
+
8
+ This is phase 1: a shared repository graph and a transitional portable edition of
9
+ **the existing oats-expert**. It is not the five-role rebuild, the curated knowledge
10
+ cutover, a shared live runtime, a private-team enrollment or Desktop feature parity.
11
+ The [phase plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) and
12
+ [knowledge model](knowledge-theory.md) retain those separate boundaries.
13
+
14
+ ## Shared versus local
15
+
16
+ | Git-shared declaration | Operator-local input or evidence |
17
+ | --- | --- |
18
+ | Workspace membership candidates and reviewed source import pins | Local source access and qualified repository observations |
19
+ | A repository's backlink and real package/soul export paths | Working checkout mappings and the explicitly chosen work target |
20
+ | Intrinsic capability requirements and logical knowledge interests | Provider settings, explicit store binding, private human/team choices |
21
+ | Complete immutable instructions and skill resources | Native harness/model/auth, backend endpoint, home and durable state |
22
+ | A reviewed source revision | Exact executable approval, current readiness and deployment acceptance |
23
+
24
+ No machine paths, credentials, private team identifiers, accepted-store locator or
25
+ owner registry belongs in the public workspace. The uninitialized phase-2 knowledge
26
+ repository is not advertised as a ready knowledge export. Preserve the parked
27
+ roster/curation and every old home, lock, source, pending job, history and worktree.
28
+
29
+ ## Planned onboarding: OATS Soul Setup (D3)
30
+
31
+ **Not shipped in OATS 0.24.** The planned onboarding flow creates and instantiates
32
+ `oats-setup-expert`, declaring both `oats.core` and `oats.setup` from the
33
+ [official marketplace](official-marketplace.md). Their package releases and this
34
+ onboarding flow are future work, not existing catalog entries or a new command
35
+ introduced by this guide.
36
+
37
+ - The setup expert will help the operator adopt repositories, select capabilities
38
+ and carry out the normal prepare/approve/scaffold/start steps. It bypasses no
39
+ executable approval, provider readiness, identity or permission boundary.
40
+ - Every soul created by that flow will declare `requires.capabilities.oats.core`
41
+ and its source explicitly. The operator can remove or replace that dependency
42
+ by editing the authored definition, not a captured record; the kernel will not
43
+ silently reinsert an absent one.
44
+ - The CLI/Desktop entry point remains separately implemented and reviewed. Do not
45
+ invent a workspace init/adopt command, create a setup soul from this sketch, or
46
+ treat a planned package as installed. Existing instances and retained resources
47
+ are not rewritten by the plan.
48
+
49
+ ## What this first source commit establishes
50
+
51
+ - `oats-workspace.yaml` explicitly admits `oats` and the six intended capability
52
+ repositories: `oats-dev`, `oats-okf`, `oats-aweb`, `oats-authoring`, `oats-jira`
53
+ and `oats-linear`. It activates no additional capability; tasks default to none.
54
+ - `oats.yaml` advertises `souls/oats-expert` and the actual framework package roots
55
+ `oats-package` and `capabilities/oats-authoring`, not the npm root as a fictitious
56
+ OATS distribution. Its workspace backlink names the same framework repository.
57
+ - `souls/oats-expert/` is parallel to, not a replacement for, the live `agents/`
58
+ source. It contains canonical instructions, `CLAUDE.md -> AGENTS.md`, and the
59
+ existing reviewed PR/release procedure closure. No durable KB is copied into it.
60
+ - The role preserves its knowledge owner, owned node and four cross-read interests.
61
+ Store `oats` requires the explicit `stores.oats` binding; no publisher writer,
62
+ production store or grants are supplied. An acceptance fixture is parent-owned
63
+ and cannot be counted as production knowledge adoption.
64
+ - Knowledge **oats.okf@2.1.1** and messaging **oats.aweb@1.10.3** are explicit hard
65
+ requirements, not optional defaults. They are published starting revisions,
66
+ **not proof that their combined bindings/runtime profile is ready**. The provider
67
+ owner supplies that evidence and any subsequently reviewed compatible revision.
68
+ Do not replace either requirement with none or erase a read edge to launch.
69
+
70
+ At these starting pins, the provider boundary is concrete:
71
+
72
+ - Published OKF2.1.0 already supports `inherit: stores.oats`, normalized to
73
+ `/bindings/knowledge/stores/oats`. The explicit `destination: oats` preserves
74
+ routing; omitting it would instead require `write.default`. No new schema,
75
+ owner or production locator is needed for this declaration.
76
+ - Released aweb1.10.3 (`24efa6f9`) has **no mandatory portable binding interface**,
77
+ so it currently blocks this pilot's portable preparation. Candidate
78
+ [aweb PR2](https://github.com/awebai/oats-aweb/pull/2), `165b20e7`, adds codecs;
79
+ it is not a reviewed/published successor or native lifecycle qualification.
80
+ Human/native-principal, private-context, admin/grant and admitted-lifecycle
81
+ requirements remain provider/integration-owner work.
82
+ - Published OKF2.1.0's captured worker profile retains its strict Pi,
83
+ explicit-model and sole-OKF limitation. Candidate
84
+ [OKF PR4](https://github.com/awebai/oats-okf/pull/4), `7cff887c`, preserves retained
85
+ Claude/Codex/null-model intent and the approved helper capability closure;
86
+ review is pending, not published2.1.0 behavior. Pi plus messaging is still
87
+ unqualified. Do not silently switch runtimes, force a model, or drop capabilities.
88
+
89
+ These are explicit readiness holds, not reasons to weaken the source. Parent must
90
+ select reviewed compatible provider revisions and update the source pin deliberately
91
+ before claiming an operational pilot; metadata-only repository indexes change none
92
+ of these runtime facts.
93
+
94
+ The workspace intentionally starts with **`imports: []`**. A source cannot pin a
95
+ future commit containing itself. This first commit is publishable source metadata,
96
+ not an already usable/adopted pilot graph or a phase-1 exit verdict.
97
+
98
+ ## Publish in this order
99
+
100
+ 1. Review and publish this source/export commit to the framework repository. Save
101
+ the **actual reviewed immutable source commit** containing the complete soul.
102
+ Do not put an invented SHA, a mutable branch or an unreviewed local candidate
103
+ in the workspace import and describe it as the accepted source.
104
+ 2. In each of the six repositories, review a root `oats.yaml` against its actual
105
+ source head and actual `oats-package/oats-package.json`. The declaration is:
106
+
107
+ ```yaml
108
+ schemaVersion: 1
109
+ workspace:
110
+ source: git:github.com/awebai/oats
111
+ exports:
112
+ packages:
113
+ - path: oats-package
114
+ ```
115
+
116
+ Preserve payloads, versions, old tags and legacy templates. This does not
117
+ activate oats.dev, messaging or either optional task integration.
118
+ 3. In a subsequent reviewed framework commit, replace the empty imports list with
119
+ an import of the source commit from step 1:
120
+
121
+ ```yaml
122
+ imports:
123
+ - source: git:github.com/awebai/oats
124
+ soul: souls/oats-expert
125
+ revision: <actual-reviewed-published-source-commit>
126
+ alias: oats-expert
127
+ ```
128
+
129
+ The placeholder is explanatory text, never a value to commit. Update the
130
+ staged-import test with that real publication evidence at this step. Do not
131
+ change the stable export path or owner merely because the workspace advances.
132
+ 4. Qualify reciprocal admission at the now-published observations. A missing
133
+ backlink, a fork's copied file or a stale workspace observation is not membership.
134
+ Cross-repository indexes may land separately; until both sides exist, report the
135
+ specific unqualified member rather than claim the whole graph is ready.
136
+
137
+ Membership selectors and backlinks omit `revision` deliberately: the repository
138
+ adapter observes the hosting provider's actual default branch, not a guessed
139
+ `main`. Within one preparation, observations are frozen. In particular, the
140
+ framework's self-member and workspace backlink must resolve to the **same commit**.
141
+ A separately pinned older workspace with backlinks resolving to a later head is
142
+ correctly stale; choose a fresh coherent observation, never rewrite an old retained
143
+ record. Imports have their own immutable source revision and need not track each
144
+ new workspace metadata commit.
145
+
146
+ Importing the exported soul directly does **not** follow the publisher's workspace
147
+ as adopter policy. A different workspace, or an explicitly standalone operator,
148
+ may consume it without membership in the OATS development workspace.
149
+
150
+ ## Inspect source metadata before preparation
151
+
152
+ The public source inspector is implemented in **PR24, commit
153
+ `bc598c484fd097fc5707fd4a33b7877ca00e5da3`**. Use this section only after the
154
+ integration owner supplies a reviewed CLI containing that implementation. It is
155
+ **not a command supported by the original 0.24.0 release**: that older inspect
156
+ route can ignore the request flag and consult ambient classic configuration.
157
+ Do not infer availability from the version floor of a capability.
158
+
159
+ ```sh
160
+ oats inspect --request /absolute/inspection.json --json
161
+ ```
162
+
163
+ After the real workspace import from publication step 3 exists, the authored
164
+ inspection input may use the same repository for workspace, member and source:
165
+
166
+ ```json
167
+ {
168
+ "deployment": "/operator/deployments/oats-pilot",
169
+ "workTarget": "/operator/projects/oats",
170
+ "source": "oats-expert",
171
+ "origin": {
172
+ "kind": "operator",
173
+ "document": {"kind": "operator", "id": "workspace-adoption"},
174
+ "pointer": "/source"
175
+ },
176
+ "workspace": {
177
+ "source": "git:github.com/awebai/oats",
178
+ "origin": {
179
+ "kind": "operator",
180
+ "document": {"kind": "operator", "id": "workspace-adoption"},
181
+ "pointer": "/workspace"
182
+ }
183
+ },
184
+ "member": {
185
+ "source": "git:github.com/awebai/oats",
186
+ "origin": {
187
+ "kind": "operator",
188
+ "document": {"kind": "operator", "id": "workspace-adoption"},
189
+ "pointer": "/member"
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ The paths are operator-selected examples, not host defaults or new grants.
196
+ Independent adoption uses the full source/soul/revision/alias reference and an
197
+ explicit standalone context instead of workspace/member. Do not mix this inspect
198
+ mode with current-context flags or captured deployment/resolution selectors.
199
+
200
+ The result is **non-authorizing metadata**, not provider readiness: even `ok:true`
201
+ may carry `needs-configuration` or `separate-deployment-required`. A
202
+ `ready-for-preparation` observation still has no approval or enrollment effect.
203
+ Provider payloads and opaque adoption values are deliberately omitted. Preserve
204
+ the original authored inputs; neither the result nor its inspection request is a
205
+ preparation request or an issued mutation witness. In particular, `workTarget`
206
+ and inspection catalog wrappers are not accepted preparation fields.
207
+
208
+ The inspector owns transient repository scratch but writes no deployment state.
209
+ Missing paths need explicit operator provisioning and reinspection, not automatic
210
+ repair. Observing a project work target does not change the separate captured H/work
211
+ placement. Existing retained inspect remains the later exact-record inspection.
212
+
213
+ ## Prepare a fresh local pilot only after the profile is qualified
214
+
215
+ Use the selected installed compatible CLI. Do not turn this source check into a
216
+ global install, a daemon start or a model/GUI test on another operator's machine.
217
+ Keep native HOME/profile/auth and explicit permission choices; no credential copy
218
+ or empty profile. Knowledge, messaging and tasks have distinct authority contracts.
219
+
220
+ Before preparing, the integration lead must supply:
221
+
222
+ - The published workspace/source observations and an explicit fresh physical
223
+ deployment/home placement. Do not copy old locks, retained records or identities.
224
+ - An operator-owned nonsecret request with `workspace` (its source and origin),
225
+ `source: "oats-expert"` after the real import is published, and `mode: "directory"`.
226
+ Standalone callers instead give the complete `{source,soul,revision,alias}`
227
+ reference and an explicit standalone context; they do not inherit this workspace.
228
+ - Explicit provider-specific settings and bindings. OKF preparation needs selected
229
+ absolute `bindings-file` and `state-dir`, `harvest-runtime`, and the `stores.oats`
230
+ binding; an omitted `harvest-model` preserves native-default intent. The parent-owned
231
+ acceptance fixture must supply an accepted node registry supporting the preserved
232
+ owner **and all four read nodes**. This is not accepted production KB publication;
233
+ Git destinations remain PR-only.
234
+ - Actual messaging human/context inputs and the pilot's explicit **`delivery: session`**
235
+ setting (aweb's default is channel). Supply it in the complete supported
236
+ `operator.policy.messaging` selection: capability, matching selected source and
237
+ `settings: {delivery: session}`. Retain host requirements, session `ifInstalled`
238
+ minimums and any selected authoring requirements. Selecting session delivery neither
239
+ adds the missing1.10.3 binding adapter nor supplies captured wake/input authority.
240
+ - A qualified primary/helper runtime/model/resource profile. Capture the intended
241
+ helper selection in `helperLaunches["oats.okf:memory-harvest"]`, not the legacy
242
+ `souls.memory-harvest` configuration. Do not replace retained intent to fit an easier
243
+ runtime profile. An old default-OKF-only learning gate does not qualify a combined
244
+ aweb profile. If provider or kernel support is missing, stop at that typed result;
245
+ do not bypass it with a legacy route, a dropped capability or a fabricated identity.
246
+
247
+ The existing public routes are stepwise (D/R/H are returned or explicitly approved
248
+ values, not names inferred from cwd):
249
+
250
+ ```sh
251
+ oats prepare --request /absolute/operator-preparation.json --json
252
+ # Review returned exact artifacts/problems; approve only explicitly authorized code.
253
+ oats trust <capability-id> --deployment "$D" --artifact-set "$ARTIFACT_SET" --json
254
+ oats prepare --request /absolute/operator-preparation.json --json
255
+ oats inspect --deployment "$D" --resolution "$R" --composition --json
256
+ oats spawn oats-expert --deployment "$D" --resolution "$R" --home "$H" --no-launch --json
257
+ oats session start --deployment "$D" --resolution "$R" --home "$H" \
258
+ --request /absolute/approved-native-request.json --json
259
+ ```
260
+
261
+ Do not mix other preparation flags into request-file mode. A needs-configuration or
262
+ approval result is not a ready instance. A scaffold materializes resources and may
263
+ run approved hooks; it is not a message exchange or model session. Actual dispatch,
264
+ continuation, native capture, messaging and learning require the integration owner's
265
+ qualified profile and receipts. Captured wake/input and public captured retirement
266
+ remain unsupported; a stopped-home observation is not delivery or retirement authority.
267
+ A session-delivered messaging profile therefore cannot pass on start-only evidence.
268
+ Do not route it through legacy input/retire or remove the messaging requirement.
269
+ Consult the current installed public help and the provider's supported commands;
270
+ this guide introduces no new CLI grammar. The source inspector above is a separate
271
+ implementation dependency, not a change to the existing prepare request contract.
272
+
273
+ ## Local checks and limits
274
+
275
+ `node --test test/workspace-repository-layout.test.mjs` checks the actual declarations
276
+ against the shipped codecs/schemas, required providers and owner/read mapping, and
277
+ contained source resources. An isolated native-Git fixture exercises source-before-
278
+ import publication, host-default observations, reciprocal/self admission, refusal of
279
+ missing/stale backlinks, and independent public source projection. Fixture member
280
+ indexes are not evidence that the six real repositories are already published.
281
+
282
+ Source and metadata checks do not enroll users, initialize the phase-2 store, register
283
+ production writers or qualify private messaging. Parent alone coordinates publication,
284
+ local operator approval and actual adoption. Full Desktop parity follows usable
285
+ infrastructure adoption, not merely seven YAML files passing validation.
@@ -0,0 +1,154 @@
1
+ # Workspaces, repositories and portable souls
2
+
3
+ A **workspace definition** describes a shared agent setup in Git. A **local deployment** is one operator's realization of it. A **portable soul** declares its role, requirements and software sources independently of either operator's directory layout.
4
+
5
+ This is the current OATS architecture. Start here for the model, then use [first-team onboarding](first-team.md) and the version-scoped [configuration](configuration.md) and [packages](packages.md) guides for operations. The [0.24 release notes](release-notes/v0.24.0.md) distinguish shipped foundations from unqualified profiles; an accepted architecture is not proof that every capability is ready.
6
+
7
+ ## Four independent things
8
+
9
+ | Thing | What it decides | What it does not imply |
10
+ |---|---|---|
11
+ | Workspace | Intended repository membership, shared defaults, source imports and provider declarations | Installed software, executable approval, messaging enrollment or a shared live session |
12
+ | Source repository | The soul/package/store definitions it actually exports | Membership of every consumer in the publisher's workspace |
13
+ | Local deployment | Local mappings, retained artifacts/resolutions, operator inputs and execution state | Permission to change source requirements or copy another operator's credentials |
14
+ | Work target | Where an instance is assigned to work | Where its soul must be published, where knowledge must live or which team it joins |
15
+
16
+ A workspace needs no OATS account, registry or OATS-operated control plane. Git hosting, messaging and model providers retain their own access and authentication requirements.
17
+
18
+ ## The three declaration files
19
+
20
+ ### `oats-workspace.yaml` — the shared workspace
21
+
22
+ The workspace names intended members and may provide defaults, knowledge-store declarations, team aliases, catalogs and external soul imports. Omitted lists admit or activate nothing.
23
+
24
+ A workspace is a role, not a requirement for a separate repository. It can live in a dedicated repository or beside project code. For OATS development, the selected home is the `oats` framework repository; `oats-dev` remains a development-capability repository.
25
+
26
+ This schematic example uses placeholder sources, not a runnable published team:
27
+
28
+ ```yaml
29
+ schemaVersion: 1
30
+ name: example-development
31
+ members:
32
+ - source: git:github.com/example/service
33
+ imports:
34
+ - source: git:github.com/example/experts
35
+ soul: souls/domain-expert
36
+ revision: reviewed-source-ref
37
+ alias: domain-expert
38
+ ```
39
+
40
+ Use actual reviewed source revisions when preparing work. When a repository reference omits its optional revision, discovery observes the hosting provider's intended default branch; it must not guess `main` or silently reuse unrelated local branch state.
41
+
42
+ ### `oats.yaml` — a repository's advertised exports
43
+
44
+ A repository advertises the souls, package roots and provider-owned knowledge declarations it actually supplies. A member also points back to its workspace:
45
+
46
+ ```yaml
47
+ schemaVersion: 1
48
+ workspace:
49
+ source: git:github.com/example/workspace
50
+ exports:
51
+ souls:
52
+ - path: souls/domain-expert
53
+ definition: souls/domain-expert/soul.yaml
54
+ packages:
55
+ - path: oats-package
56
+ ```
57
+
58
+ Only include exports that exist at the selected revision. A repository need not export every kind. A package export identifies a real directory containing `oats-package.json`; it is not an arbitrary npm package directory.
59
+
60
+ `oats-workspace.yaml` and `oats.yaml` may coexist. If the workspace host also participates as a member, it is explicitly admitted and has a matching backlink just like another member.
61
+
62
+ ### `soul.yaml` — a source-complete specialist
63
+
64
+ A portable soul is an authored definition, not a dependency on whatever happens to be installed on its publisher's machine. It contains canonical `AGENTS.md`, a relative `CLAUDE.md` alias, its reviewed skill/resource closure and a versioned declaration.
65
+
66
+ For example, this declaration excerpt requires a particular knowledge capability **and names where it comes from**:
67
+
68
+ ```yaml
69
+ schemaVersion: 1
70
+ name: domain-expert
71
+ requires:
72
+ knowledge:
73
+ capability: oats.okf
74
+ source: git:github.com/awebai/oats-okf@v2.1.1#oats-package
75
+ ```
76
+
77
+ This illustrates software selection, not complete OKF provisioning: the chosen capability also needs its own valid knowledge declaration, bindings and accepted base.
78
+
79
+ - `requires` expresses hard requirements. A fundamental provider can be required by presence or as a concrete capability/source selection.
80
+ - `defaults` supplies choices that remain rebindable within those requirements.
81
+ - Additive capabilities are named under `requires.capabilities` or `defaults.capabilities`; each concrete selection has a `source`, with optional provider-owned settings.
82
+ - `git:` selects versioned software from a repository/package root. `repo:` refers to a contained path in the declaring source repository, not the caller's working directory. `path:` is an explicitly authorised local development choice, not a remotely portable ambient fallback.
83
+ - Capability IDs alone do not establish software origin. An old `from: installed` config entry is not a substitute for a portable source declaration.
84
+ - A source may contain authored knowledge snapshots or resources, but retained artifacts are not writable knowledge stores. Learning locations and procedures belong to the selected capability.
85
+
86
+ See the [soul schema](soul.schema.json) and [declaration contract](design/2026-09-15-portable-declarations.md). Classic fields such as `kind`, `type` and a machine-local `repo` are not portable declaration fields; do not relabel an old file without validating it.
87
+
88
+ ## Membership and adoption are different
89
+
90
+ **Repository membership is reciprocal:** the workspace admits the repository and the repository's `oats.yaml` points back to that workspace. Both observations must have compatible identity, access context and revision evidence. A copied backlink, neighbouring folder or URL is not admission.
91
+
92
+ **Source adoption is by reference:** an import identifies `source`, exported `soul` path, `revision` and a local `alias`. It may carry supported adoption choices. Importing does not create an adopter-maintained copy of the soul or automatically follow the publisher's workspace backlink.
93
+
94
+ A team can therefore use a public expert without joining its publisher's organization. One source can serve several workspaces or an explicit standalone context, with different legitimate work targets and knowledge bindings.
95
+
96
+ Publish source/export revisions before pinning imports to them. Do not use invented future SHAs or require two repositories to contain each other's not-yet-created commit IDs.
97
+
98
+ ## How requirements and defaults meet
99
+
100
+ The kernel uses one resolver:
101
+
102
+ - Workspace defaults establish shared fallback choices.
103
+ - The soul's own defaults can specialise them.
104
+ - Explicit adoption/operator choices select supported alternatives or supply missing inputs.
105
+ - Hard source requirements remain constraints; a conflicting override is an error, not a reason to discard the requirement.
106
+
107
+ Provider-owned declarations remain opaque to the kernel until the selected provider interprets them through its contract. There is no portable repository-level capability policy tier silently inherited from the publisher, and no mandatory agent-type hierarchy replacing a soul's own requirements.
108
+
109
+ Repository briefing/worktree setup remains work-target behavior with its own supported authority. Merely placing a repository `AGENTS.md` nearby does not guarantee it is composed into every harness's instructions.
110
+
111
+ ## From a definition to a running instance
112
+
113
+ 1. Select an explicit workspace or standalone context, source reference, deployment location and work target.
114
+ 2. Observe actual source identities/revisions and check requested reciprocal membership.
115
+ 3. Resolve requirements, defaults and operator inputs; retain the selected source and software closure.
116
+ 4. Review and approve exact executable artifacts before provider code runs.
117
+ 5. Obtain honest provider readiness and a retained resolution; missing configuration or unsupported behavior remains visible.
118
+ 6. Scaffold and start through the supported captured lifecycle. Preserve the exact source/resources and evidence needed for continuation.
119
+
120
+ An existing instance does not silently adopt a new upstream commit, changed workspace default or different curriculum. Updates prepare new choices deliberately; required knowledge refresh and native credential rotation are separate from rewriting its retained software.
121
+
122
+ A successful lookup is not execution, an accepted dispatch is not completed work, and a declared knowledge destination is not accepted learning.
123
+
124
+ ## What each operator shares or keeps local
125
+
126
+ Share reviewed definitions, relevant nonsecret configuration/provenance, published source references and accepted knowledge through their chosen Git repositories. Keep credentials, private runtime evidence, instance homes and machine-specific realization local. A messaging roster does not replicate any of these.
127
+
128
+ An adopted package config template is an editable local snapshot, not live inheritance from the package. Updating the kernel or package does not rewrite it, migrate a knowledge base or update a running instance's loaded instructions.
129
+
130
+ ## Compatibility and current readiness
131
+
132
+ Classic `oats-config.yaml` scopes, `oats init`, `oats use`, local `agents/` lookup and lock-v2 package restore still have their own supported contracts. They are not renamed portable workspace commands. See [configuration](configuration.md) and [packages](packages.md) for that compatibility surface; do not apply classic lifecycle commands blindly to captured instances.
133
+
134
+ At the documented0.24 baseline, workspace/declaration/retained-execution foundations are shipped. The released `oats.aweb`1.10.3 package lacks the captured provider-binding interface, so its legacy messaging success does not qualify a new captured profile requiring it. Capability adaptation is implementation work, not a YAML setting that can honestly turn readiness green. Follow current [release scope](release-notes/v0.24.0.md) and the provider's actual version/readiness rather than removing requirements.
135
+
136
+ The project's [adoption plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) puts workspace/source adoption first, centralised knowledge and five experts second, and full Desktop parity afterward.
137
+
138
+ ## How a soul knows OATS (accepted direction, not yet shipped)
139
+
140
+ An agent's knowledge of OATS itself — how to check status, spawn and retire, find other souls — is ordinary capability content, not kernel magic:
141
+
142
+ - **`oats.core`** carries day-to-day operation (skills `oats-operate`, `oats-souls`, the "you run on OATS" briefing). Every soul gets it **by default at creation, written explicitly into its definition**; you can remove or replace it.
143
+ - **`oats.setup`** carries deployment/workspace configuration and package knowledge ("OATS Soul Setup"). Onboarding a workspace creates and starts an **`oats-setup-expert`** soul with both, which then adopts repositories and creates the team's other souls.
144
+ - The **official marketplace** is the reviewed package list in the `oats` repository; a package becomes official through an approved PR to that list, and official packages are discoverable from the CLI and Desktop. Discoverable is not installed; installed is not approved.
145
+
146
+ At the0.24 baseline these skills still ship inside the kernel. Work packages D1–D4 of the [adoption plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) track the move.
147
+
148
+ ## Related references
149
+
150
+ - [Souls and instances](souls-and-instances.md)
151
+ - [Capability contracts](layers.md) and [capability authoring/distribution](capabilities.md)
152
+ - [Knowledge model](knowledge-theory.md) and [version-scoped operations](knowledge.md)
153
+ - [Workspace schema](oats-workspace.schema.json) and [repository export schema](oats-member.schema.json)
154
+ - [Design/contract navigation](design/README.md)
@@ -0,0 +1,16 @@
1
+ ## You run on a captured OATS composition
2
+
3
+ You are an instance of a retained soul/helper composition selected by
4
+ `instance.json.executionBinding`. Managed instructions, skills, capabilities,
5
+ settings, provider bindings, and executable resources come from that exact
6
+ `deployment` + `resolution`; do not replace them with a current checkout,
7
+ configuration cascade, package lock, similarly named capability, or source path.
8
+
9
+ Load **oats-portable** before invoking or reasoning about captured OATS commands.
10
+ Load **oats-portable-artifacts** for exact retained inspection and approval. Do not load the legacy **oats**,
11
+ **oats-config**, or **oats-packages** procedures to fill a captured input.
12
+
13
+ Captured start/restart use exact retained launch inputs and supported native
14
+ endpoints. Captured wake/retire, unqualified runtime contributions and non-directory
15
+ work remain held. If a command is unsupported or retained authority is missing,
16
+ stop and report it; never remove selectors or fall back to ambient configuration.
@@ -0,0 +1,39 @@
1
+ ## Captured instance: home, source and work
2
+
3
+ **Your instance home** is the specific OATS instance directory supplied as
4
+ `OATS_INSTANCE_HOME`, not your user home, source repository or work target.
5
+ `instance.json.executionBinding` names the explicit captured **deployment and
6
+ resolution**. Home-bound actions must also match this owned home's incarnation
7
+ and recorded custody. Do not invent, copy or rewrite those identifiers to make
8
+ another home or composition appear authorized.
9
+
10
+ - **Home holds composed instructions and instance state.** `AGENTS.md` is the
11
+ canonical composed instruction file; `CLAUDE.md -> AGENTS.md` is its relative
12
+ compatibility alias, not a second instruction source. Preserve the generated
13
+ instructions, aliases and metadata; do not hand-edit them to change authority.
14
+ Task material and provider-managed state belong where their owning contract
15
+ specifies. The selected capabilities define any knowledge or memory protocol.
16
+ - **`./soul` is a read-only retained source link, not your edit surface.** Reading
17
+ it must not depend on the publisher's current checkout. Never write through it
18
+ or modify retained artifacts. If a task authorizes source changes, use its
19
+ explicitly authorized tracked work surface and review path instead.
20
+ - **`./work` is the task's work surface.** The work-mode instructions determine
21
+ whether it is an owned directory or another permitted repository view. Make
22
+ task edits only on that authorized surface, not in deployment stores or a
23
+ convenient source checkout. Reading an external input is not permission to
24
+ modify it or its owner.
25
+
26
+ For supported captured commands, keep the explicit `--deployment` and
27
+ `--resolution` pair from the recorded binding; supply the exact owned home when
28
+ an action requires one. Running from home preserves the invocation's working
29
+ location, but **cwd and a recorded `repo` path never select configuration or
30
+ execution authority**. Source location, deployment, work target and team
31
+ membership are separate facts. Do not fill missing inputs from a config cascade,
32
+ a current lock, an alias match or another instance's environment.
33
+
34
+ Load **oats-portable** for the running kernel's supported captured operations.
35
+ A no-launch scaffold or `launchPending` receipt is not a running agent. Where
36
+ captured launch, start/restart/wake/retire or recovery is unsupported, stop and
37
+ report the limitation; do not strip selectors or use a legacy command as a
38
+ workaround. Preserve work, knowledge, native history, identities and outstanding
39
+ cleanup receipts. Missing authority is a hold, never permission to erase state.
@@ -0,0 +1,29 @@
1
+ ## Portable work mode: owned directory
2
+
3
+ Your `./work` is an **instance-owned execution directory**, not a Git worktree,
4
+ a checkout, or a link to the source, deployment or another instance. No Git
5
+ repository or branch is created by this mode. Do not initialize a fake repository
6
+ to satisfy a workflow; a containing Git repository does not grant authority over
7
+ its contents.
8
+
9
+ - Do task work inside `./work`. External inputs and delivery destinations require
10
+ explicit task/capability authorization. Neither a source link nor a recorded
11
+ `repo` or work-target path grants permission to edit that external directory.
12
+ - Execution uses the explicit captured deployment/resolution and, for home-bound
13
+ actions, the matching owned home/incarnation binding. Cwd does not resolve
14
+ configuration or select a provider; do not rebind from a current checkout,
15
+ config cascade, package lock or another instance.
16
+ - Preserve home/work separation and canonical instruction aliases:
17
+ `AGENTS.md` in home, `CLAUDE.md -> AGENTS.md`, and the generated skill aliases.
18
+ The home's `./soul` link and retained software are read-only, not edit surfaces.
19
+ - Deliver results using the task and selected capability's supported protocol.
20
+ This mode imposes no knowledge layout, harvester, storage backend or publication
21
+ policy. A recovery copy, if independently verified, is not publication or
22
+ accepted delivery.
23
+
24
+ Keep nonempty work and its custody evidence intact. This mode does not promise
25
+ implemented captured launch, start/restart/wake/retire or automatic recovery.
26
+ Before any supported, explicitly authorized teardown, require verified
27
+ preservation of outstanding work and receipts; if that capability is unavailable,
28
+ hold and report rather than deleting or moving the home/work yourself. A
29
+ `launchPending` result means runtime launch remains pending.
@@ -0,0 +1,120 @@
1
+ /** Exact-artifact local approval authority. Presence/catalog/legacy trust and
2
+ * captured booleans never grant approval. No current selection-lock lookup. */
3
+ import { join } from "node:path";
4
+ import { canonicalJson, parseStrictJson } from "./portable-values.mjs";
5
+ import { jsonIntegrity } from "./portable-digest.mjs";
6
+ import { objectAt, versionAt } from "./portable-shape.mjs";
7
+ import { validateArtifactRef, validateOrigin } from "./resolution-shape.mjs";
8
+ import { verifyResolutionInputs, verifyRetainedCapability } from "./captured-resolutions.mjs";
9
+ import { verifyPortableArtifact } from "./portable-artifacts.mjs";
10
+ import { readLock3 } from "./portable-lock.mjs";
11
+ import { executableSurfaceOf, hasExecutableSurface } from "./capability-execution.mjs";
12
+ import { isMaterializedCapabilityId } from "./capability-provenance.mjs";
13
+ import { readPortableBytes } from "./portable-files.mjs";
14
+ import { portableStateDirectory, withPortableStateWrite, writeGuardedPortableDocument } from "./portable-state.mjs";
15
+ import { oatsError } from "./errors.mjs";
16
+
17
+ const emptyLedger = () => ({ schemaVersion: 1, capabilities: Object.create(null) });
18
+ const invalid = (message) => { throw oatsError("invalid-approval", message); };
19
+ export function artifactApprovalKey(artifact) {
20
+ validateArtifactRef(artifact);
21
+ if (artifact.kind !== "capability") invalid("capability approval cannot authorize an unrelated resource bundle");
22
+ return `${artifact.integrity.format}:${artifact.integrity.value}`;
23
+ }
24
+ export function validateApprovalLedger(ledger) {
25
+ canonicalJson(ledger);
26
+ objectAt(ledger, ["schemaVersion", "capabilities"], ["schemaVersion", "capabilities"]);
27
+ versionAt(ledger.schemaVersion); objectAt(ledger.capabilities, null, []);
28
+ for (const [id, entries] of Object.entries(ledger.capabilities)) {
29
+ if (!isMaterializedCapabilityId(id)) invalid("invalid approval capability identity");
30
+ objectAt(entries, null, []);
31
+ for (const [key, entry] of Object.entries(entries)) {
32
+ objectAt(entry, ["artifact", "approved", "provenance"], ["artifact", "approved", "provenance"]);
33
+ if (artifactApprovalKey(entry.artifact) !== key || entry.artifact.capability !== id || entry.approved !== true) invalid("approval key, artifact or capability differs");
34
+ if (!Array.isArray(entry.provenance) || !entry.provenance.length) invalid("approval requires explicit operator provenance");
35
+ for (const origin of entry.provenance) {
36
+ validateOrigin(origin);
37
+ if (origin.kind !== "operator" || origin.document.kind !== "operator") invalid("approval cannot inherit source or legacy authority");
38
+ }
39
+ }
40
+ }
41
+ return ledger;
42
+ }
43
+ export function readApprovalLedger(scope) {
44
+ const root = portableStateDirectory(scope);
45
+ const bytes = root === null ? null : readPortableBytes(join(root, "approvals.json"), { allowMissing: true, invalidCode: "invalid-approval" });
46
+ if (bytes === null) return { ledger: emptyLedger(), integrity: null };
47
+ const ledger = parseStrictJson(bytes);
48
+ validateApprovalLedger(ledger);
49
+ if (!bytes.equals(Buffer.from(canonicalJson(ledger)))) invalid("approval ledger must use canonical JSON bytes");
50
+ return { ledger, integrity: jsonIntegrity(ledger) };
51
+ }
52
+ function approved(ledger, artifact) {
53
+ const key = artifactApprovalKey(artifact);
54
+ return Object.hasOwn(ledger.capabilities, artifact.capability) && Object.hasOwn(ledger.capabilities[artifact.capability], key);
55
+ }
56
+ function manifestFor(verified, id) {
57
+ return verified.manifests.get(id);
58
+ }
59
+
60
+ /** Diagnostic projection for this record's capabilities, not an action permit.
61
+ * Dedicated helper records get their own approval check when used. */
62
+ export function inspectCapturedApprovals(scope, reference) {
63
+ const verified = verifyResolutionInputs(scope, reference), { ledger } = readApprovalLedger(scope);
64
+ return { reference, capabilities: evaluateCapturedApprovals(verified, ledger) };
65
+ }
66
+
67
+ /** Shared evaluation over already verified inputs and a freshly read ledger.
68
+ * This remains data; the action loader decides which surfaces the action uses. */
69
+ export function evaluateCapturedApprovals(verified, ledger) {
70
+ validateApprovalLedger(ledger);
71
+ return Object.entries(verified.record.artifacts.capabilities).map(([id, row]) => {
72
+ const manifest = manifestFor(verified, id), required = hasExecutableSurface(manifest);
73
+ return { artifact: row.artifact, required, surface: executableSurfaceOf(manifest),
74
+ status: !required ? "not-required" : approved(ledger, row.artifact) ? "approved" : "approval-required" };
75
+ });
76
+ }
77
+
78
+ function grantApproval(context, artifact, manifest, origin) {
79
+ const key = artifactApprovalKey(artifact), id = artifact.capability;
80
+ const { ledger, integrity } = readApprovalLedger(context.deployment);
81
+ if (!hasExecutableSurface(manifest)) return { artifact, status: "not-required" };
82
+ if (approved(ledger, artifact)) return { artifact, status: "already-approved" };
83
+ if (!Object.hasOwn(ledger.capabilities, id)) ledger.capabilities[id] = Object.create(null);
84
+ ledger.capabilities[id][key] = { artifact, approved: true, provenance: [origin] };
85
+ validateApprovalLedger(ledger);
86
+ writeGuardedPortableDocument(context, join(context.root, "approvals.json"), ledger, { absent: integrity === null });
87
+ return { artifact, status: "approved" };
88
+ }
89
+
90
+ /** Prospective approval must be possible BEFORE running an executable provider
91
+ * codec to complete a resolution. Address an exact retained artifact set, never
92
+ * today's selected capability ID or a fabricated partial resolution. */
93
+ export function approveAvailableCapability(scope, setKey, id, origin, validateManifest) {
94
+ validateOrigin(origin);
95
+ if (origin.kind !== "operator" || origin.document.kind !== "operator") invalid("approval requires an explicit operator input");
96
+ if (typeof setKey !== "string" || !/^sha256-[a-f0-9]{64}$/.test(setKey) || typeof id !== "string") invalid("invalid artifact-set approval target");
97
+ if (typeof validateManifest !== "function") throw new TypeError("prospective approval requires the complete kernel manifest codec");
98
+ return withPortableStateWrite(scope, (context) => {
99
+ const { lock } = readLock3(context.deployment);
100
+ const set = lock?.artifactSets[setKey];
101
+ if (!set || !Object.hasOwn(set.capabilities, id)) invalid("capability is not in that exact retained artifact set");
102
+ const artifact = set.capabilities[id].artifact;
103
+ const root = verifyPortableArtifact(context.deployment, artifact).dir;
104
+ const manifest = verifyRetainedCapability(root, set, id, validateManifest(root));
105
+ return grantApproval(context, artifact, manifest, origin);
106
+ });
107
+ }
108
+
109
+ /** Explicit approval writer. Called by the explicit operator approval operation,
110
+ * not preparation/discovery. Approval still does not qualify provider/host readiness
111
+ * or replace full manifest/launch compilation at the eventual action boundary. */
112
+ export function approveCapturedCapability(scope, reference, id, origin) {
113
+ validateOrigin(origin);
114
+ if (origin.kind !== "operator" || origin.document.kind !== "operator") invalid("approval requires an explicit operator input");
115
+ return withPortableStateWrite(scope, (context) => {
116
+ const verified = verifyResolutionInputs(context.deployment, reference);
117
+ if (typeof id !== "string" || !Object.hasOwn(verified.record.artifacts.capabilities, id)) invalid("approval capability is not selected in this captured record");
118
+ return grantApproval(context, verified.record.artifacts.capabilities[id].artifact, manifestFor(verified, id), origin);
119
+ });
120
+ }