@awebai/oats 0.24.1 → 0.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/oats.mjs +227 -19
- package/capabilities/oats-aweb/bin/oats-aweb-binding.mjs +11 -0
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +26 -0
- package/capabilities/oats-aweb/lib/binding-wire.mjs +214 -0
- package/capabilities/oats-aweb/lib/captured-execution.mjs +91 -0
- package/capabilities/oats-aweb/lib/captured-native.mjs +91 -0
- package/capabilities/oats-aweb/lib/invocation-shape.mjs +135 -0
- package/capabilities/oats-aweb/lib/portable-binding.mjs +146 -0
- package/capabilities/oats-aweb/lib/session-readiness.mjs +56 -0
- package/capabilities/oats-aweb/oats.json +12 -3
- package/docs/design/2026-09-20-redesign-program-board.md +28 -15
- package/docs/design/2026-09-20-workspace-onboarding-public.md +73 -7
- package/docs/first-team.md +42 -0
- package/docs/layers.md +1 -1
- package/docs/official-marketplace.md +14 -9
- package/docs/packages.md +11 -7
- package/docs/release-notes/v0.24.2.md +21 -0
- package/docs/release-notes/v0.24.3.md +13 -0
- package/docs/souls-and-instances.md +25 -0
- package/docs/workspace-adoption.md +94 -65
- package/injects/oats-portable.md +4 -0
- package/lib/core.mjs +65 -19
- package/lib/portable-onboarding.mjs +3 -3
- package/lib/prepared-bindings.mjs +21 -8
- package/lib/provider-binding-broker.mjs +6 -1
- package/lib/setup-expert-source.mjs +76 -0
- package/package-catalog.json +7 -4
- package/package.json +3 -1
- package/souls/oats-setup-expert/AGENTS.md +60 -0
- package/souls/oats-setup-expert/soul.yaml +14 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# OATS v0.24.2 — `oats onboard`, official capabilities in a soul's definition, aweb 1.11.0 pairing
|
|
2
|
+
|
|
3
|
+
Kernel/Pi/Desktop **0.24.2**. Publication is not deployment: every operator still installs, approves and qualifies locally.
|
|
4
|
+
|
|
5
|
+
## What changed
|
|
6
|
+
|
|
7
|
+
- **`oats onboard [--dir <deployment>] [--workspace <git:source[@rev]>] [--force-existing] [--json]`** — bootstrap a deployment with an **`oats-setup-expert`** soul that holds `oats.core` and `oats.setup`. Acquires the official `oats.framework` package through the existing engine (resources-only guard before commit, no catalog auto-trust), activates exactly those two capabilities for that soul, writes its definition with both pinned at the acquired immutable commit, and **prints** the spawn command — it never launches a model. Classic local bootstrap, not captured preparation. `oats setup` (record capture setup) is unchanged.
|
|
8
|
+
- **Soul creation declares `oats.core` explicitly.** `oats create` and new local souls write `requires.capabilities.oats.core` resolved from the official catalog; `--no-oats-core` opts out; nothing is invented when the catalog has no entry. When a soul declares `oats.core` or `oats.setup`, the kernel composes **neither** the legacy kernel skills (`oats`, `oats-config`, `oats-packages`) nor the `kernel:oats` injection — the capability's skills are the operational curriculum. Souls without it keep legacy behavior; `oats doctor` prints an informational line.
|
|
9
|
+
- **Official capabilities.** `oats.framework` **1.1.1** (tag `oats-framework/v1.1.1`) exports `oats.core` (`oats-operate`, `oats-souls`, "you run on OATS" briefing), `oats.setup` (`oats-config`, `oats-packages`, `oats-workspace-setup` — now documenting the operator request shape) and `oats.knowledge-theory`. Listed in the official catalog with capability aliases.
|
|
10
|
+
- **Retained inspection projects `launchSelection`** (`{runtime, model}` or `null`) for the primary from the verified retained record; provider binding codecs receive the same-kernel `OATS_CLI_BIN` after the environment scrub. These are what a provider `check` needs to be truthful about the primary's profile.
|
|
11
|
+
- **aweb 1.11.0 pairing.** The catalog and all framework soul editions pin `oats.aweb@v1.11.0`, which adds the portable binding interface (floor `>=0.24.2`). Its `check` qualifies HOME-route operational custody only: explicit private team, `delivery: session`, an input-capable Claude/Codex primary. A strict-Pi print primary reports `needs-configuration`; the requirement is never dropped.
|
|
12
|
+
- **Six framework soul editions** exported and imported by `oats-workspace.yaml`: the five knowledge-owning experts (`oats-expert`, `oats-kernel-expert`, `oats-desktop-expert`, `market-research-expert`, `oats-assistant`) at `caa341f3` and `oats-setup-expert` at `0aad753c`. All six declare `oats.core` from the repository's own payload.
|
|
13
|
+
- Baseline hygiene: golden fixtures use a genuinely empty catalog; the package check lazy-loads dev validators so syntax-only lanes work without `node_modules`.
|
|
14
|
+
|
|
15
|
+
## Second-operator gate
|
|
16
|
+
|
|
17
|
+
An independent operator on a fresh machine adopted the shared definition from public sources through `inspect` → `prepare` → approvals with 0.24.1: the whole graph (including `oats.core`/`oats.setup`) resolved and materialized; preparation stopped at aweb 1.10.3 as declared. Five usability seams were recorded (request-file mismatch between `inspect`/`prepare`, raw ENOENT on an absent deployment, `trust --dir` rejecting lock v3, `--artifact-set` missing from help, unattributed provider problems). **They are not fixed in this cut**; see the [program board](../design/2026-09-20-redesign-program-board.md).
|
|
18
|
+
|
|
19
|
+
## Not in this cut
|
|
20
|
+
|
|
21
|
+
Desktop marketplace view / soul creation UI, legacy `agents/` roster and in-soul knowledge decommission (after the fresh-reader proof against the public `oats-knowledge`), Pi session-input support.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# OATS v0.24.3 — second-operator `prepare` seams
|
|
2
|
+
|
|
3
|
+
Kernel/Pi/Desktop **0.24.3**. Fixes the five usability seams an independent second operator hit adopting the shared workspace definition on 0.24.1/0.24.2 (see the [program board](../design/2026-09-20-redesign-program-board.md)). No contract, schema or authority change.
|
|
4
|
+
|
|
5
|
+
- **Attributed provider problems.** Every preparation problem now carries `slot`, `capability` and its `origins`, with kernel-fixed text that names the missing item (for example `oats.okf knowledge normalize binding could not be prepared` / `oats.aweb@1.10.3 declares no binding interface; messaging cannot be prepared`). One unqualified slot no longer masks another slot's diagnostics: every slot that has a binding interface is normalized, and the single resolver reports each invalid choice under its slot. Provider free text still never crosses the wire.
|
|
6
|
+
- **`oats trust <capability> --dir <deployment>` on a lock v3 deployment** returns a typed problem with the exact working command (`oats trust <cap> --deployment <abs> --artifact-set <sha256-…>`) instead of `unsupported lockfileVersion 3`. No auto-approval.
|
|
7
|
+
- **Help** documents `--artifact-set` and how `prepare`'s `selections[].artifactSet` / `approvalRequired[]` pair with it.
|
|
8
|
+
- **`prepare` on an absent deployment path** returns a typed explicit-provisioning hold, not a raw `ENOENT` with a host path.
|
|
9
|
+
- **One request file for both commands.** `prepare --request` accepts the explicit `workTarget` that `inspect --request` requires (explicit beats cwd; it never implies captured placement or current config), and `oats inspect --request <f> --emit-prepare-request <out>` writes the converted preparation request through the existing builder.
|
|
10
|
+
|
|
11
|
+
The second operator's recorded requests and results are preserved verbatim as regression fixtures (`test/fixtures/second-operator/`). Their valid-vs-bogus `stores.oats` pair remains identical by design: both refused on missing OKF runtime settings (`bindings-file`, `state-dir`), which the messages now say.
|
|
12
|
+
|
|
13
|
+
Setup guidance for those settings lands in the next `oats.framework` payload.
|
|
@@ -54,6 +54,31 @@ in a soul bundle; see [knowledge](knowledge.md) for its prepared version scope.
|
|
|
54
54
|
Future integrations may add expert-specific artifacts such as rule files or
|
|
55
55
|
runtime-specific guidance, while keeping `AGENTS.md` canonical.
|
|
56
56
|
|
|
57
|
+
## OATS operational knowledge is a capability
|
|
58
|
+
|
|
59
|
+
New souls declare `requires.capabilities.oats.core` with a Git source resolved
|
|
60
|
+
from the official package catalog. `oats create` and new local-soul scaffolds
|
|
61
|
+
write that requirement; `--no-oats-core` explicitly omits it. If the catalog has
|
|
62
|
+
no published revision yet, creation reports `needs-configuration` (also in JSON
|
|
63
|
+
`notes`) and leaves the requirement absent rather than inventing a source.
|
|
64
|
+
Declaring a capability is not acquiring, activating or approving it: those remain
|
|
65
|
+
normal deployment/preparation steps. The Desktop server currently has no
|
|
66
|
+
soul-creation endpoint; `oats soul set` edits existing definitions only.
|
|
67
|
+
|
|
68
|
+
The dependency is visible and removable in `soul.yaml`. Updating an existing
|
|
69
|
+
local soul preserves its requirements—including a deliberate removal—rather
|
|
70
|
+
than applying the creation default again. For the one-release transition,
|
|
71
|
+
a declaration of **either `oats.core` or `oats.setup`** suppresses the entire
|
|
72
|
+
legacy kernel operational skill list (`oats`, `oats-config`, `oats-packages`)
|
|
73
|
+
and `kernel:oats` injection. This also prevents setup's moved skill names from
|
|
74
|
+
colliding with the kernel copies; no skill override is needed for this case.
|
|
75
|
+
Without either declaration, legacy composition is unchanged.
|
|
76
|
+
`oats doctor --soul <name>` reports an absent `oats.core` as an informational
|
|
77
|
+
deprecation notice, not an error. Instance-boundary, work-mode and
|
|
78
|
+
configuration-declared briefings remain kernel-owned. Existing captured records
|
|
79
|
+
keep their retained resources; this does not migrate them or retire the kernel
|
|
80
|
+
skill files yet.
|
|
81
|
+
|
|
57
82
|
## Instance anatomy
|
|
58
83
|
|
|
59
84
|
An instance has a lifecycle, but need not be short-lived. It is the identity of
|
|
@@ -5,12 +5,30 @@ source-complete exports and declares its own reciprocal membership. `oats-dev`
|
|
|
5
5
|
remains a development-capability repository, including `oats.review`; membership
|
|
6
6
|
neither activates that package nor replaces its existing configuration templates.
|
|
7
7
|
|
|
8
|
-
This
|
|
9
|
-
**the existing oats-expert**.
|
|
10
|
-
cutover, a shared
|
|
8
|
+
This guide covers the shared repository graph and portable expert source editions,
|
|
9
|
+
beginning with **the existing oats-expert**. Source publication is not a live
|
|
10
|
+
five-role roster or curated knowledge cutover, a shared runtime, private-team
|
|
11
|
+
enrollment or Desktop feature parity.
|
|
11
12
|
The [phase plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) and
|
|
12
13
|
[knowledge model](knowledge-theory.md) retain those separate boundaries.
|
|
13
14
|
|
|
15
|
+
## The five framework experts
|
|
16
|
+
|
|
17
|
+
The indexed source editions are `oats-expert`, `oats-kernel-expert`,
|
|
18
|
+
`oats-desktop-expert`, `market-research-expert` and `oats-assistant`. Each declares
|
|
19
|
+
`owns` for its own same-named node and `reads` for the other four through logical
|
|
20
|
+
store `oats`, preserving the reviewed owner UUIDs. These are knowledge-routing and
|
|
21
|
+
context declarations, not access grants or proof of accepted knowledge. The parallel
|
|
22
|
+
`souls/` editions neither replace the legacy `agents/` roster nor adopt the curated
|
|
23
|
+
KB or change live instances; actual adoption still needs compatible providers and
|
|
24
|
+
explicit bindings. All five now explicitly declare `oats.core` under
|
|
25
|
+
`requires.capabilities`, with `source: repo:oats-package`. This retains the complete
|
|
26
|
+
package from the same reviewed source revision.
|
|
27
|
+
|
|
28
|
+
The dependency is visible and removable in the authored definition, not a change
|
|
29
|
+
to existing captured records. An edited edition needs its own reviewed publication
|
|
30
|
+
and import update; changing today's source does not rewrite an older pinned import.
|
|
31
|
+
|
|
14
32
|
## Shared versus local
|
|
15
33
|
|
|
16
34
|
| Git-shared declaration | Operator-local input or evidence |
|
|
@@ -22,17 +40,18 @@ The [phase plan](design/2026-09-20-workspace-and-portable-adoption-plan.md) and
|
|
|
22
40
|
| A reviewed source revision | Exact executable approval, current readiness and deployment acceptance |
|
|
23
41
|
|
|
24
42
|
No machine paths, credentials, private team identifiers, accepted-store locator or
|
|
25
|
-
owner registry belongs in the public workspace.
|
|
26
|
-
|
|
43
|
+
owner registry belongs in the public workspace. Knowledge publication and acceptance
|
|
44
|
+
(S7) remain separate; no ready knowledge export is advertised. Preserve the parked
|
|
27
45
|
roster/curation and every old home, lock, source, pending job, history and worktree.
|
|
28
46
|
|
|
29
47
|
## Planned onboarding: OATS Soul Setup (D3)
|
|
30
48
|
|
|
31
|
-
**
|
|
49
|
+
**The D3 onboarding flow remains pending.** It will create and instantiate
|
|
32
50
|
`oats-setup-expert`, declaring both `oats.core` and `oats.setup` from the
|
|
33
|
-
[official marketplace](official-marketplace.md).
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
[official marketplace](official-marketplace.md). Those capabilities are now
|
|
52
|
+
published in `oats.framework` 1.1.0 and listed; the separate setup-expert edition
|
|
53
|
+
and onboarding entry point do not become available merely by listing the package.
|
|
54
|
+
This flow was not shipped in the 0.24.0 or 0.24.1 kernel releases.
|
|
36
55
|
|
|
37
56
|
- The setup expert will help the operator adopt repositories, select capabilities
|
|
38
57
|
and carry out the normal prepare/approve/scaffold/start steps. It bypasses no
|
|
@@ -41,27 +60,29 @@ introduced by this guide.
|
|
|
41
60
|
and its source explicitly. The operator can remove or replace that dependency
|
|
42
61
|
by editing the authored definition, not a captured record; the kernel will not
|
|
43
62
|
silently reinsert an absent one.
|
|
44
|
-
- The CLI/Desktop entry point
|
|
45
|
-
invent a workspace init/adopt command, create a setup soul from this
|
|
46
|
-
treat a
|
|
47
|
-
are not rewritten by the plan.
|
|
63
|
+
- The CLI/Desktop entry point still requires separate implementation and review.
|
|
64
|
+
Do not invent a workspace init/adopt command, create a setup soul from this
|
|
65
|
+
sketch, or treat a listed package as installed. Existing instances and retained
|
|
66
|
+
resources are not rewritten by the plan.
|
|
48
67
|
|
|
49
|
-
##
|
|
68
|
+
## Stage two: published experts and pinned imports
|
|
50
69
|
|
|
51
70
|
- `oats-workspace.yaml` explicitly admits `oats` and the six intended capability
|
|
52
71
|
repositories: `oats-dev`, `oats-okf`, `oats-aweb`, `oats-authoring`, `oats-jira`
|
|
53
72
|
and `oats-linear`. It activates no additional capability; tasks default to none.
|
|
54
|
-
- `oats.yaml`
|
|
55
|
-
`oats-package` and `capabilities/oats-authoring`, not
|
|
56
|
-
OATS distribution. Its workspace backlink names
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
- `oats.yaml` exports all five `souls/<name>` editions above and the actual package
|
|
74
|
+
roots `oats-package` (`oats.framework`) and `capabilities/oats-authoring`, not
|
|
75
|
+
the npm root as a fictitious OATS distribution. Its workspace backlink names
|
|
76
|
+
the same framework repository.
|
|
77
|
+
- The editions are parallel to, not replacements for, the live `agents/` roster.
|
|
78
|
+
Each contains canonical instructions, `CLAUDE.md -> AGENTS.md`, and its reviewed
|
|
79
|
+
private procedures where applicable. No durable KB is copied into them; legacy
|
|
80
|
+
roster cutover remains deferred until S7 knowledge publication.
|
|
81
|
+
- Each edition preserves its knowledge owner, owned node and four cross-reads.
|
|
61
82
|
Store `oats` requires the explicit `stores.oats` binding; no publisher writer,
|
|
62
83
|
production store or grants are supplied. An acceptance fixture is parent-owned
|
|
63
84
|
and cannot be counted as production knowledge adoption.
|
|
64
|
-
- Knowledge **oats.okf@2.1.1** and messaging **oats.aweb@1.
|
|
85
|
+
- Knowledge **oats.okf@2.1.1** and messaging **oats.aweb@1.11.0** are explicit hard
|
|
65
86
|
requirements, not optional defaults. They are published starting revisions,
|
|
66
87
|
**not proof that their combined bindings/runtime profile is ready**. The provider
|
|
67
88
|
owner supplies that evidence and any subsequently reviewed compatible revision.
|
|
@@ -69,38 +90,41 @@ introduced by this guide.
|
|
|
69
90
|
|
|
70
91
|
At these starting pins, the provider boundary is concrete:
|
|
71
92
|
|
|
72
|
-
- Published OKF2.1.
|
|
93
|
+
- Published OKF2.1.1 supports `inherit: stores.oats`, normalized to
|
|
73
94
|
`/bindings/knowledge/stores/oats`. The explicit `destination: oats` preserves
|
|
74
95
|
routing; omitting it would instead require `write.default`. No new schema,
|
|
75
96
|
owner or production locator is needed for this declaration.
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
- aweb 1.10.3 (`24efa6f9`) has no portable binding interface; **aweb 1.11.0**
|
|
98
|
+
(`v1.11.0`, OATS >=0.24.2) adds it and the five editions now pin it. Its `check`
|
|
99
|
+
qualifies only an input-capable Claude/Codex primary with an explicit private team
|
|
100
|
+
and `delivery: session`; strict-Pi print reports `needs-configuration`. Status is on
|
|
101
|
+
the [program board](design/2026-09-20-redesign-program-board.md). Qualification
|
|
102
|
+
is HOME-route operational custody only: not human/native-principal delegation,
|
|
103
|
+
private grants, broker delivery or model consumption.
|
|
104
|
+
- Published OKF2.1.1 accepts retained Claude/Codex helpers with the complete approved
|
|
105
|
+
capability closure and native-default model intent. Strict Pi still requires an
|
|
106
|
+
explicit model and the sole-OKF profile; Pi plus messaging remains unqualified.
|
|
107
|
+
This provider release alone is not combined-profile acceptance. Do not silently
|
|
108
|
+
switch runtimes, force a model, or drop capabilities.
|
|
88
109
|
|
|
89
110
|
These are explicit readiness holds, not reasons to weaken the source. Parent must
|
|
90
111
|
select reviewed compatible provider revisions and update the source pin deliberately
|
|
91
112
|
before claiming an operational pilot; metadata-only repository indexes change none
|
|
92
113
|
of these runtime facts.
|
|
93
114
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
115
|
+
Stage one used an empty imports list until source publication. Stage two is now
|
|
116
|
+
committed: all five imports pin **`caa341f34009e37006567419a983d5a743037a79`**, the
|
|
117
|
+
published edition revision containing explicit core requirements and the package.
|
|
118
|
+
The later workspace commit `375b9f42` added those imports. Live source inspection
|
|
119
|
+
against published main resolved all five as `ready-for-preparation`; this is
|
|
120
|
+
metadata readiness, not provider binding, approval, enrollment or a running pilot.
|
|
97
121
|
|
|
98
|
-
##
|
|
122
|
+
## Preserve source-before-import publication order
|
|
99
123
|
|
|
100
|
-
1.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
1. Publish complete, reviewed source editions before pinning them. The current
|
|
125
|
+
source is `caa341f34009e37006567419a983d5a743037a79`; future revisions must likewise
|
|
126
|
+
exist before their workspace import update. Never use an invented SHA, a mutable
|
|
127
|
+
branch or an unreviewed local candidate as the accepted source.
|
|
104
128
|
2. In each of the six repositories, review a root `oats.yaml` against its actual
|
|
105
129
|
source head and actual `oats-package/oats-package.json`. The declaration is:
|
|
106
130
|
|
|
@@ -114,21 +138,25 @@ not an already usable/adopted pilot graph or a phase-1 exit verdict.
|
|
|
114
138
|
```
|
|
115
139
|
|
|
116
140
|
Preserve payloads, versions, old tags and legacy templates. This does not
|
|
117
|
-
activate oats.dev, messaging or either optional task integration.
|
|
118
|
-
|
|
119
|
-
|
|
141
|
+
activate oats.dev, messaging or either optional task integration. Indexes are
|
|
142
|
+
published on `main` in all six capability repositories (oats-okf, oats-aweb,
|
|
143
|
+
oats-authoring, oats-jira, oats-dev, oats-linear); their publication proceeded
|
|
144
|
+
separately from the framework's own source imports.
|
|
145
|
+
3. A subsequent workspace commit pins the published source, never itself or a
|
|
146
|
+
future commit. The current first import is:
|
|
120
147
|
|
|
121
148
|
```yaml
|
|
122
149
|
imports:
|
|
123
150
|
- source: git:github.com/awebai/oats
|
|
124
151
|
soul: souls/oats-expert
|
|
125
|
-
revision:
|
|
152
|
+
revision: caa341f34009e37006567419a983d5a743037a79
|
|
126
153
|
alias: oats-expert
|
|
127
154
|
```
|
|
128
155
|
|
|
129
|
-
The
|
|
130
|
-
|
|
131
|
-
|
|
156
|
+
The [actual workspace](../oats-workspace.yaml) contains all five imports at that
|
|
157
|
+
same revision; this excerpt is not a replacement for the full list. The layout
|
|
158
|
+
test now checks stage-two imports and source-document declarations. Do not
|
|
159
|
+
change stable export paths or owners merely because the workspace advances.
|
|
132
160
|
4. Qualify reciprocal admission at the now-published observations. A missing
|
|
133
161
|
backlink, a fork's copied file or a stale workspace observation is not membership.
|
|
134
162
|
Cross-repository indexes may land separately; until both sides exist, report the
|
|
@@ -149,19 +177,18 @@ may consume it without membership in the OATS development workspace.
|
|
|
149
177
|
|
|
150
178
|
## Inspect source metadata before preparation
|
|
151
179
|
|
|
152
|
-
The public source inspector
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Do not infer availability from the version floor of a capability.
|
|
180
|
+
The public source inspector ships in [OATS 0.24.1](release-notes/v0.24.1.md),
|
|
181
|
+
following PR24 integration. Use an installed CLI containing that implementation.
|
|
182
|
+
It is **not supported by the original 0.24.0 release**: that older inspect route
|
|
183
|
+
can ignore the request flag and consult ambient classic configuration. Do not
|
|
184
|
+
infer command availability from a capability's version floor or today's catalog.
|
|
158
185
|
|
|
159
186
|
```sh
|
|
160
187
|
oats inspect --request /absolute/inspection.json --json
|
|
161
188
|
```
|
|
162
189
|
|
|
163
|
-
|
|
164
|
-
|
|
190
|
+
With the stage-two imports published, the authored inspection input can use the
|
|
191
|
+
same repository for workspace, member and source:
|
|
165
192
|
|
|
166
193
|
```json
|
|
167
194
|
{
|
|
@@ -222,7 +249,7 @@ Before preparing, the integration lead must supply:
|
|
|
222
249
|
- The published workspace/source observations and an explicit fresh physical
|
|
223
250
|
deployment/home placement. Do not copy old locks, retained records or identities.
|
|
224
251
|
- An operator-owned nonsecret request with `workspace` (its source and origin),
|
|
225
|
-
`source: "oats-expert"`
|
|
252
|
+
`source: "oats-expert"` (or another published expert alias), and `mode: "directory"`.
|
|
226
253
|
Standalone callers instead give the complete `{source,soul,revision,alias}`
|
|
227
254
|
reference and an explicit standalone context; they do not inherit this workspace.
|
|
228
255
|
- Explicit provider-specific settings and bindings. OKF preparation needs selected
|
|
@@ -236,7 +263,7 @@ Before preparing, the integration lead must supply:
|
|
|
236
263
|
`operator.policy.messaging` selection: capability, matching selected source and
|
|
237
264
|
`settings: {delivery: session}`. Retain host requirements, session `ifInstalled`
|
|
238
265
|
minimums and any selected authoring requirements. Selecting session delivery neither
|
|
239
|
-
|
|
266
|
+
makes a strict-Pi print primary input-capable nor supplies captured wake authority.
|
|
240
267
|
- A qualified primary/helper runtime/model/resource profile. Capture the intended
|
|
241
268
|
helper selection in `helperLaunches["oats.okf:memory-harvest"]`, not the legacy
|
|
242
269
|
`souls.memory-harvest` configuration. Do not replace retained intent to fit an easier
|
|
@@ -262,10 +289,12 @@ Do not mix other preparation flags into request-file mode. A needs-configuration
|
|
|
262
289
|
approval result is not a ready instance. A scaffold materializes resources and may
|
|
263
290
|
run approved hooks; it is not a message exchange or model session. Actual dispatch,
|
|
264
291
|
continuation, native capture, messaging and learning require the integration owner's
|
|
265
|
-
qualified profile and receipts.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
292
|
+
qualified profile and receipts. OATS 0.24.1 adds captured custody checks to the
|
|
293
|
+
existing HOME-only session inspect/input route; it does not supply the missing
|
|
294
|
+
messaging adapter or qualify every lifecycle route. Verify wake/input/retirement
|
|
295
|
+
support for the exact route and runtime. A stopped-home observation is not delivery
|
|
296
|
+
or retirement authority, and a messaging profile cannot pass on start-only evidence.
|
|
297
|
+
Do not bypass custody with a legacy fallback or remove the messaging requirement.
|
|
269
298
|
Consult the current installed public help and the provider's supported commands;
|
|
270
299
|
this guide introduces no new CLI grammar. The source inspector above is a separate
|
|
271
300
|
implementation dependency, not a change to the existing prepare request contract.
|
|
@@ -282,4 +311,4 @@ indexes are not evidence that the six real repositories are already published.
|
|
|
282
311
|
Source and metadata checks do not enroll users, initialize the phase-2 store, register
|
|
283
312
|
production writers or qualify private messaging. Parent alone coordinates publication,
|
|
284
313
|
local operator approval and actual adoption. Full Desktop parity follows usable
|
|
285
|
-
infrastructure adoption, not merely
|
|
314
|
+
infrastructure adoption, not merely source metadata passing validation.
|
package/injects/oats-portable.md
CHANGED
|
@@ -9,6 +9,10 @@ configuration cascade, package lock, similarly named capability, or source path.
|
|
|
9
9
|
Load **oats-portable** before invoking or reasoning about captured OATS commands.
|
|
10
10
|
Load **oats-portable-artifacts** for exact retained inspection and approval. Do not load the legacy **oats**,
|
|
11
11
|
**oats-config**, or **oats-packages** procedures to fill a captured input.
|
|
12
|
+
If this retained composition includes **oats.core**, its **oats-operate** and
|
|
13
|
+
**oats-souls** skills are capability resources, not implicit kernel additions.
|
|
14
|
+
Use only the resources actually included; a missing capability is not permission
|
|
15
|
+
to fetch or substitute a current version.
|
|
12
16
|
|
|
13
17
|
Captured start/restart use exact retained launch inputs and supported native
|
|
14
18
|
endpoints. Captured wake/retire, unqualified runtime contributions and non-directory
|
package/lib/core.mjs
CHANGED
|
@@ -51,6 +51,7 @@ import { buildCapturedInvocationContext, withCapturedInvocationContextFile } fro
|
|
|
51
51
|
import { readCapturedInstanceIndex, readCapturedInstanceMetadata, readCapturedInstanceAuthority, assertCapturedInstanceCustody,
|
|
52
52
|
recordCapturedCustodyFailure, markCapturedNativeScaffold, failCapturedNativeIntent, observeCapturedNativeTarget, setCapturedInstanceStatus, admitCapturedInstanceAction, beginCapturedIntent, settleCapturedIntent } from "./captured-instance-index.mjs";
|
|
53
53
|
import { validateExecutionBinding } from "./schedule-capsule.mjs";
|
|
54
|
+
import { parsePortableSource } from "./source-spec.mjs";
|
|
54
55
|
import { validateIntentRef } from "./captured-admission-shape.mjs";
|
|
55
56
|
export { readCapturedInstanceIndex, readCapturedInstanceMetadata, beginCapturedIntent, settleCapturedIntent };
|
|
56
57
|
export { buildCapturedInvocationContext, withCapturedInvocationContextFile };
|
|
@@ -61,7 +62,7 @@ import { validateCapturedLaunchRequest } from "./captured-launch-request.mjs";
|
|
|
61
62
|
import { validateCapabilityInputDeclarations } from "./capability-inputs.mjs";
|
|
62
63
|
import { validateCapturedSessionBackend, validateCapturedSessionTarget, assertCapturedSessionPlacement } from "./captured-session-backend.mjs";
|
|
63
64
|
import { createRepositoryTransaction } from "./repository-observation.mjs";
|
|
64
|
-
import { inspectPortableOnboarding as inspectOnboarding, describePortableOnboarding } from "./portable-onboarding.mjs";
|
|
65
|
+
import { inspectPortableOnboarding as inspectOnboarding, describePortableOnboarding, buildFreshPreparationRequest, inspectWorkTarget } from "./portable-onboarding.mjs";
|
|
65
66
|
import { readLock3 } from "./portable-lock.mjs";
|
|
66
67
|
import { portableScope, portableStateDirectory } from "./portable-state.mjs";
|
|
67
68
|
import { objectAt } from "./portable-shape.mjs";
|
|
@@ -112,6 +113,18 @@ export const OATS_VERSION = JSON.parse(readFileSync(join(PKG_ROOT, "package.json
|
|
|
112
113
|
/** Skills shipped with the kernel. Only oats-getting-started is ambient; spawn composes selected skills locally. */
|
|
113
114
|
export const PACKAGED_SKILLS_DIR = join(PKG_ROOT, "skills");
|
|
114
115
|
|
|
116
|
+
function soulRequirements(soulDir) {
|
|
117
|
+
const file = soulDir && join(soulDir, "soul.yaml");
|
|
118
|
+
return file && existsSync(file) ? withConfigFile(file, () => parseYamlNested(readFileSync(file, "utf8"))).requires : undefined;
|
|
119
|
+
}
|
|
120
|
+
function declaredOperationalCapabilities(soulDir) {
|
|
121
|
+
const capabilities = soulRequirements(soulDir)?.capabilities ?? {};
|
|
122
|
+
return ["oats.core", "oats.setup"].filter(id => Object.hasOwn(capabilities, id));
|
|
123
|
+
}
|
|
124
|
+
function legacyOperationalSkills(soulDir) {
|
|
125
|
+
return declaredOperationalCapabilities(soulDir).length ? [] : ["oats", "oats-config", "oats-packages"].map(name => ({ id: "kernel", path: join(PACKAGED_SKILLS_DIR, name) }));
|
|
126
|
+
}
|
|
127
|
+
|
|
115
128
|
// ---------- shell helpers ----------
|
|
116
129
|
function sh(cmdline) { return execSync(cmdline, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim(); }
|
|
117
130
|
function shTry(cmdline) { try { return sh(cmdline); } catch { return undefined; } }
|
|
@@ -1198,13 +1211,17 @@ export function approveAvailableCapability(deployment, artifactSet, capability,
|
|
|
1198
1211
|
/** Public read-only source/workspace inspection through the existing facade.
|
|
1199
1212
|
* Owns only transient repository scratch, never deployment state, provisioning,
|
|
1200
1213
|
* provider code, approvals or a serialized mutation witness. */
|
|
1201
|
-
export function inspectPortableOnboarding(input, { repositoryOptions = {} } = {}) {
|
|
1214
|
+
export function inspectPortableOnboarding(input, { repositoryOptions = {}, includePrepareRequest = false } = {}) {
|
|
1202
1215
|
canonicalJson(input);
|
|
1216
|
+
if (typeof includePrepareRequest !== "boolean") throw oatsError("invalid-declaration", "request conversion requires an explicit boolean option");
|
|
1203
1217
|
const directory = mkdtempSync(join(realpathSync(tmpdir()), "oats-source-inspection-")), owned = lstatSync(directory);
|
|
1204
1218
|
let repositories, primary;
|
|
1205
1219
|
try {
|
|
1206
1220
|
repositories = createRepositoryTransaction({ ...repositoryOptions, directory, accessContextKey: repositoryOptions.accessContextKey ?? "native" });
|
|
1207
|
-
|
|
1221
|
+
const inspection = inspectOnboarding(input, { repositories }), result = describePortableOnboarding(inspection);
|
|
1222
|
+
// Opt-in data export, not a serialized custody witness or executable grant.
|
|
1223
|
+
// Default metadata continues to omit unclassified adoption/provider values.
|
|
1224
|
+
return includePrepareRequest ? { ...result, prepareRequest: buildFreshPreparationRequest(inspection).preparation } : result;
|
|
1208
1225
|
} catch (error) { primary = error; throw error; }
|
|
1209
1226
|
finally {
|
|
1210
1227
|
try {
|
|
@@ -1226,21 +1243,28 @@ export function inspectPortableOnboarding(input, { repositoryOptions = {} } = {}
|
|
|
1226
1243
|
* a fabricated complete record. No lifecycle side effects run here. */
|
|
1227
1244
|
export function prepareCapturedComposition(input, { repositoryOptions = {} } = {}) {
|
|
1228
1245
|
canonicalJson(input);
|
|
1229
|
-
objectAt(input, ["deployment", "source", "origin", "workspace", "member", "operator", "mode", "allowLocalPaths", "standaloneContextKey", "launch", "helperLaunches"], ["deployment", "source"]);
|
|
1246
|
+
objectAt(input, ["deployment", "workTarget", "source", "origin", "workspace", "member", "operator", "mode", "allowLocalPaths", "standaloneContextKey", "launch", "helperLaunches"], ["deployment", "source"]);
|
|
1230
1247
|
if (input.launch !== undefined) validateCapturedLaunchRequest(input.launch, validateLaunchConfig);
|
|
1231
1248
|
if (input.helperLaunches !== undefined) {
|
|
1232
1249
|
objectAt(input.helperLaunches, null, []);
|
|
1233
1250
|
for (const request of Object.values(input.helperLaunches)) validateCapturedLaunchRequest(request, validateLaunchConfig);
|
|
1234
1251
|
}
|
|
1235
1252
|
if (input.mode !== undefined && !WORK_MODES.includes(input.mode)) throw oatsError("invalid-declaration", "invalid preparation work mode");
|
|
1236
|
-
const
|
|
1253
|
+
const { workTarget, ...preparationInput } = input;
|
|
1254
|
+
const target = Object.hasOwn(input, "workTarget") ? inspectWorkTarget(workTarget) : null;
|
|
1255
|
+
let deployment;
|
|
1256
|
+
try { deployment = portableScope(input.deployment); }
|
|
1257
|
+
catch (error) {
|
|
1258
|
+
if (error.code === "ENOENT") throw oatsError("needs-configuration", "deployment directory is absent; provision the explicitly selected directory and inspect again before preparation");
|
|
1259
|
+
throw error;
|
|
1260
|
+
}
|
|
1237
1261
|
const previous = readLock3(deployment); // Old state refuses before scratch/fetch.
|
|
1238
1262
|
const directory = mkdtempSync(join(portableStateDirectory(deployment, true), ".prepare-")), owned = lstatSync(directory);
|
|
1239
1263
|
const origin = input.origin ?? { kind: "operator", document: { kind: "operator", id: "oats-prepare" }, pointer: "/source" };
|
|
1240
1264
|
let repositories, primary, catalog;
|
|
1241
1265
|
try {
|
|
1242
1266
|
repositories = createRepositoryTransaction({ ...repositoryOptions, directory, accessContextKey: repositoryOptions.accessContextKey ?? "native" });
|
|
1243
|
-
|
|
1267
|
+
const result = prepareComposition({ ...preparationInput, deployment, origin, directory }, { repositories, previous, kernel: {
|
|
1244
1268
|
loadPackageManifestAt, capabilityCompatibility, assertPlatformInvariantLocks, materializeCapability,
|
|
1245
1269
|
manifest: loadRetainedManifest,
|
|
1246
1270
|
binding: runCapturedProviderBinding,
|
|
@@ -1253,6 +1277,8 @@ export function prepareCapturedComposition(input, { repositoryOptions = {} } = {
|
|
|
1253
1277
|
settings: assertCapabilitySettingValues, skills: skillEntriesIn, hooks: manifestHookDeclarations,
|
|
1254
1278
|
validateLaunchConfig, runtimeRequirements: applicableRequirements }),
|
|
1255
1279
|
} });
|
|
1280
|
+
// Explicit work context never selects source/config, cwd, or H/work placement.
|
|
1281
|
+
return target ? { ...result, workTarget: target } : result;
|
|
1256
1282
|
} catch (error) { primary = error; throw error; }
|
|
1257
1283
|
finally {
|
|
1258
1284
|
try {
|
|
@@ -4083,6 +4109,10 @@ export function composeInstanceAgentsMd(soulDir, contextDir, soulName, workMode,
|
|
|
4083
4109
|
if (!existsSync(agentsMd)) throw new Error(`canonical soul instructions missing: ${agentsMd}`);
|
|
4084
4110
|
const resolved = resolveOatsConfig(contextDir, soulName);
|
|
4085
4111
|
const wanted = [];
|
|
4112
|
+
const declaredOperations = declaredOperationalCapabilities(soulDir);
|
|
4113
|
+
const oatsCoreDeclared = declaredOperations.includes("oats.core");
|
|
4114
|
+
if (declaredOperations.length) resolved.kernelInjection = { inject: undefined,
|
|
4115
|
+
provenance: `declared ${declaredOperations.join(", ")} ${declaredOperations.length === 1 ? "capability" : "capabilities"}` };
|
|
4086
4116
|
const kernelInject = resolved.kernelInjection?.inject;
|
|
4087
4117
|
if (kernelInject && existsSync(kernelInject)) wanted.push(["kernel:oats", kernelInject]);
|
|
4088
4118
|
if (kind === "local") {
|
|
@@ -4104,7 +4134,7 @@ export function composeInstanceAgentsMd(soulDir, contextDir, soulName, workMode,
|
|
|
4104
4134
|
}
|
|
4105
4135
|
for (const inj of resolved.injects) wanted.push([`config:${inj.source}`, inj.file]);
|
|
4106
4136
|
const blocks = wanted.map(([source, file]) => ({ source, file, content: readFileSync(file, "utf8").trim() }));
|
|
4107
|
-
return { text: renderInstructionText(readFileSync(agentsMd, "utf8"), blocks), blocks, resolved };
|
|
4137
|
+
return { text: renderInstructionText(readFileSync(agentsMd, "utf8"), blocks), blocks, resolved, oatsCoreDeclared };
|
|
4108
4138
|
}
|
|
4109
4139
|
|
|
4110
4140
|
/** The skill entries a tree contributes — THE discovery rule, shared by preflight
|
|
@@ -4162,7 +4192,7 @@ export function planInstanceResources({ resolved, soulDir, agent, contextDir, co
|
|
|
4162
4192
|
}
|
|
4163
4193
|
};
|
|
4164
4194
|
|
|
4165
|
-
for (const path of
|
|
4195
|
+
for (const { path } of legacyOperationalSkills(soulDir)) {
|
|
4166
4196
|
add({ type: "skill-tree", source: "kernel", declared: basename(path), path: existsSync(path) ? path : undefined });
|
|
4167
4197
|
}
|
|
4168
4198
|
const soulSkills = soulDir && join(soulDir, "skills");
|
|
@@ -5110,15 +5140,31 @@ export function resolveYolo(value) {
|
|
|
5110
5140
|
throw new Error("yolo must be true or false");
|
|
5111
5141
|
}
|
|
5112
5142
|
|
|
5113
|
-
|
|
5143
|
+
/** Creation chooses a declared source, never acquisition/activation or a made-up
|
|
5144
|
+
* future release. Existing definitions (including deliberate removal) are kept. */
|
|
5145
|
+
function defaultOatsCoreRequirement() {
|
|
5146
|
+
const mapping = officialCapabilityPackage("oats.core");
|
|
5147
|
+
const entry = mapping.available && mapping.migratedCapability === "oats.core" && officialPackageCatalog()[mapping.package];
|
|
5148
|
+
if (entry && typeof entry.url === "string" && typeof entry.ref === "string" && entry.ref) {
|
|
5149
|
+
const parsed = parsePortableSource(`git:${entry.url}@${entry.ref}#${entry.path ?? DEFAULT_PACKAGE_PATH}`);
|
|
5150
|
+
return { requires: { capabilities: { "oats.core": { source: `${parsed.source}#${parsed.path}` } } }, notes: [] };
|
|
5151
|
+
}
|
|
5152
|
+
return { requires: undefined, notes: [{ code: "needs-configuration", message: "oats.core has no published revision in the official package catalog; no source was invented. Add its explicit requirement after the catalog entry is available, or use --no-oats-core to opt out at creation." }] };
|
|
5153
|
+
}
|
|
5154
|
+
|
|
5155
|
+
export function writeSoul(root, { name, kind, repo, work, runtime, model, yolo, description, type, instructions, oatsCore = true }) {
|
|
5114
5156
|
yolo = resolveYolo(yolo);
|
|
5157
|
+
if (typeof oatsCore !== "boolean") throw oatsError("E_BAD_ARGS", "oatsCore must be a boolean");
|
|
5115
5158
|
const agentDir = agentDirOf(root, name, kind);
|
|
5116
|
-
const soulDir = soulOf(agentDir);
|
|
5159
|
+
const soulDir = soulOf(agentDir), soulFile = join(soulDir, "soul.yaml");
|
|
5160
|
+
const { requires, notes } = existsSync(soulFile)
|
|
5161
|
+
? { requires: soulRequirements(soulDir), notes: [] }
|
|
5162
|
+
: oatsCore ? defaultOatsCoreRequirement() : { requires: undefined, notes: [] };
|
|
5117
5163
|
mkdirSync(soulDir, { recursive: true });
|
|
5118
5164
|
mkdirSync(join(agentDir, "instances"), { recursive: true });
|
|
5119
|
-
writeFileSync(
|
|
5165
|
+
writeFileSync(soulFile, yamlFlat({
|
|
5120
5166
|
name, kind, description, type, repo, work: work || "checkout", runtime: runtime || "pi", model, yolo,
|
|
5121
|
-
}));
|
|
5167
|
+
}) + (requires === undefined ? "" : `requires: ${JSON.stringify(requires)}\n`));
|
|
5122
5168
|
const agentsMd = join(soulDir, "AGENTS.md");
|
|
5123
5169
|
if (instructions !== undefined || !existsSync(agentsMd)) {
|
|
5124
5170
|
writeFileSync(agentsMd, instructions ?? defaultSoulAgentsMd(name, description));
|
|
@@ -5132,7 +5178,7 @@ export function writeSoul(root, { name, kind, repo, work, runtime, model, yolo,
|
|
|
5132
5178
|
home: soulDir, instance: name, agentName: name, soulDir,
|
|
5133
5179
|
contextDir: ctx, workspaceDir: workspaceOf(root), rootDir: root, resolved,
|
|
5134
5180
|
});
|
|
5135
|
-
return { agentDir, soulDir };
|
|
5181
|
+
return { agentDir, soulDir, ...(notes.length ? { notes } : {}) };
|
|
5136
5182
|
}
|
|
5137
5183
|
function defaultSoulAgentsMd(name, description) {
|
|
5138
5184
|
return `# ${name}
|
|
@@ -5154,8 +5200,8 @@ export function createAgent(root, o) {
|
|
|
5154
5200
|
// kind: "local" → a FULL soul (memory, skills, instances) under the scope's
|
|
5155
5201
|
// local-agents/ — uncommitted by contract; otherwise a committed persistent soul.
|
|
5156
5202
|
const kind = o.local || o.kind === "local" ? "local" : "persistent";
|
|
5157
|
-
const { agentDir } = writeSoul(root, { ...o, name, kind });
|
|
5158
|
-
return { agent: name, kind, soul: soulOf(agentDir) };
|
|
5203
|
+
const { agentDir, notes } = writeSoul(root, { ...o, name, kind });
|
|
5204
|
+
return { agent: name, kind, soul: soulOf(agentDir), ...(notes ? { notes } : {}) };
|
|
5159
5205
|
}
|
|
5160
5206
|
|
|
5161
5207
|
/** Upsert a local agent soul (from raw instructions or a Claude-style def file).
|
|
@@ -5182,13 +5228,13 @@ export function upsertLocalAgent(root, o) {
|
|
|
5182
5228
|
const existing = findAgent(root, name);
|
|
5183
5229
|
if (existing && existing.kind !== "local") throw new Error(`"${name}" is a persistent agent — spawn it instead`);
|
|
5184
5230
|
if (!existing && instructions === undefined) throw new Error(`local agent "${name}" needs instructions (none on disk yet)`);
|
|
5185
|
-
writeSoul(root, {
|
|
5186
|
-
name, kind: "local",
|
|
5231
|
+
const { notes } = writeSoul(root, {
|
|
5232
|
+
name, kind: "local", oatsCore: o.oatsCore,
|
|
5187
5233
|
repo: repo ?? existing?.repo, work: work ?? existing?.work,
|
|
5188
5234
|
runtime: runtime ?? existing?.runtime, model: model ?? existing?.model, yolo: yolo ?? existing?.yolo,
|
|
5189
5235
|
description: description ?? existing?.description, instructions,
|
|
5190
5236
|
});
|
|
5191
|
-
return findAgent(root, name);
|
|
5237
|
+
return { ...findAgent(root, name), ...(notes ? { notes } : {}) };
|
|
5192
5238
|
}
|
|
5193
5239
|
/** Back-compat alias: older installed capabilities (oats-okf ≤1.3.x) call this. */
|
|
5194
5240
|
export const upsertTmpAgent = upsertLocalAgent;
|
|
@@ -6136,7 +6182,7 @@ export function spawnInstance(root, agent, o = {}) {
|
|
|
6136
6182
|
symlinkSync("AGENTS.md", join(home, "CLAUDE.md"));
|
|
6137
6183
|
|
|
6138
6184
|
// Runtime-neutral exact skill materialization. No harness receives ambient workspace/package skills.
|
|
6139
|
-
const sources =
|
|
6185
|
+
const sources = legacyOperationalSkills(soulDir);
|
|
6140
6186
|
const soulSkills = join(soulDir, "skills");
|
|
6141
6187
|
if (existsSync(soulSkills)) sources.push({ id: "soul", path: soulSkills });
|
|
6142
6188
|
for (const cap of resolvedCfg.capabilities) for (const path of cap.skills || []) sources.push({ id: cap.id, path });
|
|
@@ -108,7 +108,7 @@ export function preflightFreshDeployment({ deployment, maxEntries = 4096 }) {
|
|
|
108
108
|
return result;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
function
|
|
111
|
+
export function inspectWorkTarget(path) {
|
|
112
112
|
const canonical = canonicalExistingDirectory(path, "work target"), marker = present(join(canonical, ".git"));
|
|
113
113
|
return { path: canonical, state: "existing", git: marker ? { present: true, kind: marker.isDirectory() ? "directory" : marker.isFile() ? "file" : "other" } : { present: false, kind: null } };
|
|
114
114
|
}
|
|
@@ -146,7 +146,7 @@ export function inspectPortableOnboarding(input, { repositories } = {}) {
|
|
|
146
146
|
validateOrigin(input.origin);
|
|
147
147
|
const standalone = explicitContext(input);
|
|
148
148
|
const deployment = preflightFreshDeployment({ deployment: input.deployment });
|
|
149
|
-
const target =
|
|
149
|
+
const target = inspectWorkTarget(input.workTarget), discovery = createWorkspaceDiscovery(repositories);
|
|
150
150
|
const witness = { deployment: preflightWitnesses.get(deployment), work: directoryIdentity(target.path) };
|
|
151
151
|
const workspace = Object.hasOwn(input, "workspace") ? discovery.readWorkspace(input.workspace) : null;
|
|
152
152
|
const selected = typeof input.source === "string" ? sourceOrigin(workspace, input.source) : { reference: input.source, origin: input.origin };
|
|
@@ -236,7 +236,7 @@ export function buildFreshPreparationRequest(inspection, options = {}) {
|
|
|
236
236
|
const { operator, mode, allowLocalPaths = false } = options;
|
|
237
237
|
if (typeof allowLocalPaths !== "boolean") throw oatsError("invalid-declaration", "allowLocalPaths must be boolean");
|
|
238
238
|
if (mode !== undefined && (typeof mode !== "string" || !mode.trim())) throw oatsError("invalid-declaration", "preparation mode must be non-empty text");
|
|
239
|
-
const input = { deployment: inspection.deployment.deployment.path,
|
|
239
|
+
const input = { deployment: inspection.deployment.deployment.path, workTarget: inspection.workTarget.path,
|
|
240
240
|
source: inspection.source.reference,
|
|
241
241
|
origin: inspection.source.revision.provenance[0], allowLocalPaths,
|
|
242
242
|
...(inspection.workspace ? { workspace: inspection.workspace.request } : { standaloneContextKey: inspection.context.key }),
|