@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,177 @@
1
+ # Portable fresh onboarding and source discovery
2
+
3
+ 16 September 2026. This module supports a controlled fresh setup path while
4
+ historical in-place migration is deferred. It does not alter the Portable Souls
5
+ architecture or weaken the existing partial/unknown evidence safeguards.
6
+
7
+ ## Responsibilities remain separate
8
+
9
+ A fresh setup request carries four independent facts:
10
+
11
+ 1. **Source location** — an explicit four-field soul reference, or an alias from
12
+ one explicit workspace observation.
13
+ 2. **Deployment/install location** — an explicit absolute path that passes fresh
14
+ state preflight.
15
+ 3. **Work target** — an explicit existing directory, independently reported as a
16
+ Git or non-Git target. It never identifies the soul or deployment.
17
+ 4. **Context/membership** — an explicit workspace plus optional reciprocal member
18
+ request, or an explicit standalone context key. Declared messaging teams are
19
+ reported separately; inspection performs no enrollment and makes no privacy
20
+ claim.
21
+
22
+ `lib/portable-onboarding.mjs` reuses `createWorkspaceDiscovery`, the repository
23
+ transaction issued by the caller, and the existing workspace/member/soul parsers.
24
+ It contains no source/config parser, resolver, network adapter, package installer,
25
+ provider codec, credential handler or team operation.
26
+
27
+ ## Fresh deployment preflight
28
+
29
+ `preflightFreshDeployment({deployment,maxEntries?})` is read-only. A missing child
30
+ of one real canonical parent is a valid fresh destination. An existing directory
31
+ may contain arbitrary project files, a Git repository, authored souls, and authored
32
+ capability source. Those do not make it dirty.
33
+
34
+ The preflight reports `separate-deployment-required` for fixed deployment-owned
35
+ state: configuration or selection locks, schedules, portable state, captured
36
+ resolutions or migration evidence, retained/installed artifacts, installed package
37
+ state, native history, and bounded discovered instance/retirement directories.
38
+ The scan is shallow and incrementally bounded. It never recursively inventories
39
+ project contents and never deletes, moves, repairs or rewrites a conflict. Advice
40
+ is always to preserve the existing path and choose a separate fresh deployment.
41
+
42
+ Issued inspections also keep ephemeral directory identity witnesses in memory:
43
+ the existing deployment, or the parent of an absent deployment, and the work
44
+ target. `recheckFreshOnboarding` rechecks those selected roots and managed state
45
+ after source inspection and immediately before the fresh mutation adapter. Root
46
+ replacement, disappearance or provisioning after an absent-path inspection
47
+ requires a new inspection (`selection-changed`); ordinary project-file edits are
48
+ allowed. No witness is added to public preparation JSON, written to disk or made
49
+ into an identity registry. This is a local point-in-time check, not a lock against
50
+ hostile concurrent writers; core retains its own action-boundary custody checks.
51
+
52
+ ## Explicit source/workspace/export/catalog inspection
53
+
54
+ `inspectPortableOnboarding` requires an explicit deployment, work target, source
55
+ and origin. A string source is accepted only as an alias in an explicit workspace;
56
+ otherwise the caller supplies the ordinary four-field source reference. Workspace
57
+ and `standaloneContextKey` are mutually exclusive. Presence means an own field:
58
+ any supplied workspace value must pass the existing workspace discovery/schema
59
+ validator; `null`, `false`, `0` and empty text are not omission or a standalone
60
+ shortcut. Without a workspace, the key
61
+ must be explicitly supplied as opaque text of at most 256 UTF-8 bytes or explicit
62
+ `null`; it is never
63
+ derived from source/work paths, OS identity or repository metadata. `null` records
64
+ an explicit lack of standalone private context and is suitable only when later
65
+ preparation resolves messaging disabled. The
66
+ existing discovery adapter qualifies source identity, observes exact revisions,
67
+ validates the advertised export and parses the exported soul.
68
+
69
+ An optional explicit member request performs the existing reciprocal membership
70
+ check. Without it, repository membership is `not-requested`; import does not follow
71
+ the publisher's workspace backlink. Messaging team declarations are data only and
72
+ always report `enrollment:"not-performed"` and
73
+ `privateTeamQualification:"not-evaluated"`.
74
+
75
+ Catalog inspection is opt-in by unique declared workspace indexes. It observes the
76
+ catalog source/revision and exact explicit descriptor path through the same
77
+ repository transaction, returning only the source and document witnesses. There is
78
+ no guessed catalog filename and no kernel-owned catalog payload parser.
79
+
80
+ The result is `ready-for-preparation`, `needs-configuration`, or
81
+ `separate-deployment-required`, with all four responsibilities represented in
82
+ separate fields. `effects` reports no deployment writes, installs, activation,
83
+ credential, team or job operations while honestly recording repository reads and
84
+ caller-owned repository-transaction scratch use.
85
+
86
+ ## Preparation handoff
87
+
88
+ `buildFreshPreparationRequest` accepts only an inspection object issued by this
89
+ module and only when its status is `ready-for-preparation`. It accepts public
90
+ operator/mode/local-input choices only; the public preparation wrapper owns its
91
+ private scratch directory, so `directory` is rejected rather than leaked from the
92
+ private `prepareComposition` contract. It returns:
93
+
94
+ ```text
95
+ { schemaVersion: 1, operation: "prepare", persisted: false,
96
+ preparation: <existing prepareCapturedComposition input>,
97
+ workTarget: <the separately inspected target>,
98
+ effects: {writes:false, installs:false, activation:false, enrollment:false} }
99
+ ```
100
+
101
+ It does not invoke preparation. A thin core/CLI adapter may pass `preparation`
102
+ unchanged to public `prepareCapturedComposition` only at an explicit mutating
103
+ boundary. The handoff forwards the exact standalone key for standalone contexts;
104
+ core at `c5c6a3c9171e424a36a1bdbf3932b9319a3c6c72` now admits and stores that field.
105
+ No adapter may rediscover targets, infer the key, read ambient config to fill
106
+ omissions, adopt a publisher workspace, or reinterpret work and team fields.
107
+ The public JavaScript bridge is implemented at that source pin; a complete fresh
108
+ onboarding CLI is still separate integration work.
109
+
110
+ ## Fresh acceptance driver
111
+
112
+ `lib/portable-onboarding-acceptance.mjs` keeps acceptance above the same facade:
113
+
114
+ - `compareFreshSourceAcceptance({organization,standalone})` accepts only issued,
115
+ ready inspections and proves qualified identity, exact commit, export and
116
+ definition equality. The organization side must have workspace context; the
117
+ standalone side must have standalone context and an explicit non-Git work target.
118
+ - `prepareFreshOnboarding(inspection, options, adapters)` builds the exact public
119
+ request, rechecks the issued deployment/work-root witnesses and fresh managed
120
+ state immediately before any mutation, and
121
+ calls only an explicitly supplied `prepareCapturedComposition` adapter. An
122
+ absent deployment returns `fresh-deployment-provisioning-required`; a missing
123
+ core bridge returns `onboarding-integration-required`; both are `pending` with
124
+ `mutationAttempted:false`.
125
+ - A supplied preparation result exposes explicit requested write bindings and
126
+ exact artifact approval requests. The driver never approves them or converts an
127
+ approval-required result into success.
128
+
129
+ The deterministic fixture uses one unchanged source in an explicit organization
130
+ workspace/member context and a standalone non-Git target. It verifies explicit
131
+ bindings and approval requests, publisher-backlink non-follow, and a positive
132
+ control where newly appeared managed state refuses before the mutating adapter.
133
+ That deterministic fixture uses no production provider, install, team, identity,
134
+ timer or job operation.
135
+
136
+ ## Request-file transport
137
+
138
+ `readPortablePreparationRequest` in `lib/portable-onboarding-request.mjs` is the
139
+ thin bounded file reader for the proposed lifecycle-owned `prepare --request`
140
+ route. It accepts parsed transport forms, uses shared no-follow/strict JSON
141
+ readers and returns the entire public request unchanged. It rejects competing
142
+ input flags and explicit captured selectors before file access, does not inherit
143
+ old resolution authority, and adds no preparation schema/resolver/defaults.
144
+ Unknown fields remain present for public core to reject. See the
145
+ [request transport contract](2026-09-17-public-prepare-request.md); implementing
146
+ the helper does not claim CLI router availability.
147
+
148
+ ## Pinned real public consumer
149
+
150
+ `test/portable-onboarding-public.acceptance.mjs` additionally executes the real
151
+ public preparation/approval/retained-inspection APIs archived from exact core
152
+ `c5c6a3c9171e424a36a1bdbf3932b9319a3c6c72`, without merging its branch. It uses
153
+ isolated local Git transport, temporary deployments and a declared inert fixture
154
+ knowledge capability—not OKF or a live service. The unchanged builder output
155
+ crosses the public boundary with no added private `directory` and no stripped
156
+ standalone/operator fields. Source identity, exact revision, explicit destinations,
157
+ string/null contexts, approval-before-code and retained full-subject authority are
158
+ checked. A newly appeared legacy lock still refuses before preparation.
159
+
160
+ A separate case in the same explicit driver pins
161
+ `257c4b96b67001fa2bcf38436e57106c44aa797b` for the actual public CLI
162
+ `spawn --no-launch`. It uses the real producer, not hand-written instance metadata,
163
+ to mint distinct incarnations and index admitted/completed fixture spawn-hook
164
+ intents. It verifies exact retained subject/context/binding, private snapshot
165
+ cleanup, and refusal of both repeated and occupied homes without overwrite.
166
+ The result is still `launched:false`, `launchPending:true`; actual runtime launch
167
+ and live provider behavior are not qualified.
168
+
169
+ See the [fresh operator walkthrough](2026-09-16-fresh-operator-walkthrough.md) for
170
+ exact reproduction, implemented public no-launch steps and the pending lifecycle-
171
+ owned request-file router versus actual launch/provider qualification. The earlier standalone key limit mismatch is corrected: onboarding
172
+ uses core's 256 UTF-8-byte bound, with no silent conversion. The pinned public
173
+ consumer checks preservation of a non-ASCII key exactly at that boundary.
174
+
175
+ Fresh setup is not permission to remove existing work, knowledge, native history,
176
+ identities or credentials. It is also not release, provider/privacy qualification,
177
+ instance launch, team creation or schedule activation.
@@ -0,0 +1,26 @@
1
+ # Public preparation request-file transport
2
+
3
+ ```
4
+ oats prepare --request <absolute-regular-json-file> [--json]
5
+ ```
6
+
7
+ The JSON file is the **whole public `prepareCapturedComposition` input**—for fresh onboarding, only `buildFreshPreparationRequest(...).preparation`. It is not the onboarding result/ready-inspection wrapper, captured resolution/execution binding, private preparation scratch `directory`, or instance/work placement. No fields are filtered or inferred: the existing closed public validator rejects unknown fields. Preparation distinguishes workspace field presence from truthiness: every supplied workspace is validated, including null/false/zero/empty-string values, and it conflicts with any explicit standalone key. An absent workspace plus an explicit standalone null remains valid.
8
+
9
+ The CLI delegates to `readPortablePreparationRequest` in `lib/portable-onboarding-request.mjs`, the same leaf used by onboarding consumers. It uses `readPortableBytes` and `parseStrictJson` once, with their existing bounds: regular/no-follow descriptor read, at most 8 MiB, strict UTF-8/JSON, duplicate-key rejection, depth 64 and 100000 entries. The full decoded object is frozen without filtering/defaulting. There is no new JSON/global argument parser, resolver, recursive include syntax, stdin/eval mode or private scratch API. Diagnostic errors are sanitized and do not echo raw provider values. Requests must contain nonsecret declarations and credential references, never credential values.
10
+
11
+ `--request` is mutually exclusive with all other preparation input flags. Exclusivity and normalized absolute-path checks precede opening the file. Missing/nonregular/symlink files and invalid path arguments report `E_BAD_ARGS`; malformed UTF-8/JSON reports `invalid-declaration`, while byte/depth/entry excess remains `resource-limit` and observed read drift remains `integrity-drift`. This aligns the unreleased inline CLI prototype with the shared helper rather than maintaining competing error contracts. Explicit captured `--deployment`, `--resolution`, or `--artifact-set` selectors—including equals spelling and selectors before the command—are rejected before reading/preparing a request. Partial/malformed selectors retain the existing typed refusal.
12
+
13
+ The shared routing boundary first uses `capturedSelector(args,{})` to inspect explicit selectors without inherited authority. Prepare then handles explicit new work; even malformed inherited OATS deployment/resolution/instance variables cannot select its source or context. Other commands retain their existing explicit/inherited capture rules. No global environment reset is performed.
14
+
15
+ Existing forms remain supported:
16
+
17
+ ```
18
+ oats prepare --dir ABS --source GIT --revision REF --export PATH --alias NAME [--work MODE] [--json]
19
+ oats prepare --dir ABS --workspace GIT [--workspace-revision REF] --alias NAME [--work MODE] [--json]
20
+ ```
21
+
22
+ All forms share the existing result renderer. Incomplete preparation preserves problems and exact approval requests in error details. A returned resolution is not enrollment, privacy, executable approval or actual launch success.
23
+
24
+ This transport represents explicit **new-work input**, not a reusable ready-inspection permission. Fresh onboarding must still enforce its own preflight at the mutation boundary. After a first prepare writes managed state, explicit approved continuation uses ordinary public preparation; the CLI neither deletes that state nor imposes fresh-only restrictions on legitimate continuation.
25
+
26
+ Focused tests cover complete native-transport requests with provider-owned operator bindings and explicit standalone string/null contexts; exact 256-byte Unicode key preservation; poisoned inherited selectors; source/workspace flag compatibility; mixed/duplicate/relative/malformed/symlink/oversized/unknown-field refusals; and before/after-command explicit selector refusal. These are isolated fixture preparation tests, not real provider privacy or managed-runtime launch qualification.
@@ -0,0 +1,98 @@
1
+ # Provider-owned binding codecs — implementation boundary
2
+
3
+ This implements the accepted provider-neutral binding direction, not a new policy
4
+ engine or an OKF data model in the kernel. Current preparation deliberately returns
5
+ `provider-not-qualified`; the following handshake is the next integration step.
6
+
7
+ ## One provider, three bounded commands
8
+
9
+ A fundamental capability may declare an optional versioned `binding` interface:
10
+
11
+ ```json
12
+ {
13
+ "binding": {
14
+ "version": 1,
15
+ "normalize": "binding-normalize",
16
+ "bind": "binding-bind",
17
+ "check": "binding-check"
18
+ }
19
+ }
20
+ ```
21
+
22
+ Each value names an EXISTING command in that same capability manifest. It is not a
23
+ second script/operation table. Those commands therefore already participate in
24
+ self-containment, exact executable approval and retained resource inventory.
25
+ Missing/unknown versions or references refuse. The interface belongs only to the
26
+ manifest's fundamental slot.
27
+
28
+ 1. **normalize** receives already parsed source/workspace/operator inputs with their
29
+ origins and captured effective capability settings. It emits equality/presence
30
+ requirements and bounded candidates for its own `/bindings/<slot>/…` fields.
31
+ It must not select capability sources or rewrite another provider's fields.
32
+ 2. The kernel combines these with existing requirements/candidates through the SAME
33
+ `resolveChoices` engine. A conflict/incomplete result is not a usable binding.
34
+ 3. **bind** receives the selected field values and emits the effective, NONSECRET
35
+ ProviderBinding envelope plus credential references. Messaging additionally emits
36
+ the responsible-human/private/wider choice envelope. Output does not certify
37
+ membership, authorization or privacy. It cannot change the selected software.
38
+ 4. **check** receives a captured binding at the requested action boundary and checks
39
+ mutable credentials/host/provider readiness using native facilities. It does not
40
+ rewrite the immutable binding or silently enroll/create a replacement team.
41
+
42
+ Separating normalization from binding avoids constructing a payload before operator
43
+ choices have passed the common resolver, or letting a provider carry its own hidden
44
+ precedence implementation. The default OKF provider owns its node/store/schema rules;
45
+ an alternate provider need not contain OKF reads/owns/stateDir fields.
46
+
47
+ ## Execution and custody
48
+
49
+ No codec executes merely because it was downloaded. Preparation reads current exact
50
+ artifact approval first; missing approval exposes the prospective artifact set for
51
+ explicit `oats trust --artifact-set`, not a fabricated partial resolution. Commands
52
+ run from their verified retained root with bounded JSON stdin/stdout and duration,
53
+ not imports from a current source directory. Errors handling malformed provider
54
+ output must not quote possibly sensitive raw stdout/stderr.
55
+
56
+ Preparation commands are normalization/rendering, not enrollment or lifecycle hooks.
57
+ Approved provider implementations must keep those phases free of external mutations.
58
+ Actual setup/identity/team lifecycle occurs only at its explicit later action boundary.
59
+ This is a provider contract, not a claimed filesystem/network sandbox.
60
+
61
+ Provider output is structurally validated, field ownership checked, and no complete
62
+ record is published until binding/resource/helper preparation succeeds. Credential
63
+ values are never copied into a record or notes; only supported lookup references are
64
+ retained. A check's current result is not cached as permanent authority in the record.
65
+
66
+ ## Delivery status
67
+
68
+ The optional manifest field has a shared validator wired into the complete kernel
69
+ manifest loader and its public structural schema. The [wire v1](2026-09-16-provider-binding-wire.md)
70
+ now has a bounded codec and native invocation broker, exposed through core
71
+ `runCapturedProviderBinding({deployment,artifacts,capability,phase,settings,input})`.
72
+ It loads the complete retained manifest, verifies artifact/provenance, checks current
73
+ exact approval before execution, and validates/sanitizes provider output. Shared
74
+ ProviderBinding, MessagingChoice and captured-choice codecs are reused, not copied.
75
+ A native fixture proves no unapproved child runs and all phases work after source
76
+ deletion/current-config poison; that is transport evidence, not provider qualification.
77
+
78
+ Preparation now supplies frozen decoded declarations/origins to the broker, merges
79
+ provider-owned fields through the same resolver, and captures complete nonsecret
80
+ bindings only after conflicts and provenance checks pass. Missing approval/interface
81
+ or unresolved fields still expose prospective software without a fabricated record.
82
+ Operator preparation input may include a provider-owned `bindings` map alongside its
83
+ existing software `policy`; it does not introduce another precedence engine. Adoption
84
+ origin-map keys are made subtree-relative while original document pointers/spans stay
85
+ intact. A real standalone-OKF consumer probe at a pinned source commit verifies the
86
+ cross-repository payload and source-deleted, non-ready check (an absent base is not ready).
87
+
88
+ Captured action loading now runs read-only provider readiness against its exact
89
+ binding; non-ready refuses before execution and is not cached in the immutable record.
90
+ Synchronous captured CLI commands receive a private `OATS_BINDING_FILE` snapshot,
91
+ not live configuration, with owned cleanup after success/failure. A real pinned OKF
92
+ consumer fixture verifies its native snapshot loader against an initialized temporary
93
+ base after source/config deletion. That is integration evidence, not production
94
+ provider or privacy qualification.
95
+
96
+ Captured lifecycle/registration consumers and full helper policy remain unfinished.
97
+ Default-provider work remains in its own source repository. No live provider,
98
+ private-team behavior, new release or deployment was qualified here.
@@ -0,0 +1,247 @@
1
+ # Provider binding wire v1
2
+
3
+ Concrete child/parent integration contract for [provider-owned codecs](2026-09-16-provider-binding-codecs.md).
4
+ This is a bounded JSON protocol, not a second resolver or sandbox. Source commands
5
+ must already have exact artifact approval before any phase runs.
6
+
7
+ ## Transport
8
+
9
+ Invoke the manifest-owned phase command with its declared arguments, no shell and
10
+ no extra implicit flags. Write ONE UTF-8 JSON request to stdin and close stdin.
11
+ Stdout is ONE JSON response; logs belong on stderr. Maximum request/response size
12
+ is 1 MiB, depth 32, 16384 entries; execution timeout is at most 30 seconds. The
13
+ native broker may accept a shorter explicit `timeoutMs` (1–30000). Timeout terminates
14
+ only the spawned codec process with SIGKILL, not an ignorable SIGTERM; no existing
15
+ session or unrelated process is targeted. Duplicate keys,
16
+ trailing output, malformed UTF-8 and unknown envelope fields/versions refuse.
17
+ Kernel diagnostics never echo provider stdout/stderr or free-form error messages.
18
+ The command runs from its verified retained capability root. Ambient OATS/PI
19
+ instance identity is scrubbed; kernel supplies only this capability's identity,
20
+ root and effective settings. Native host facilities remain host-owned. This is
21
+ not filesystem/network isolation, and normalization/binding must not enroll,
22
+ write stores, publish knowledge or start workers.
23
+
24
+ Every request has exactly:
25
+
26
+ ```json
27
+ {"schemaVersion":1,"phase":"normalize","slot":"knowledge","capability":"oats.okf","settings":{},"input":{}}
28
+ ```
29
+
30
+ `phase` is normalize/bind/check; slot is knowledge/messaging/tasks. Both must match
31
+ the retained manifest. Settings are already selected and schema-validated.
32
+
33
+ Success echoes the identity fields and contains `ok:true,result:{...}`. Failure
34
+ echoes them and contains `ok:false,error:{code:"needs-configuration"}`. It has no
35
+ result. All structured responses exit 0: transport completed, while `ok` is the
36
+ semantic outcome. Nonzero exit/signal/timeout is transport failure. Allowed error/problem codes are needs-configuration, requirement-conflict,
37
+ invalid-binding, authorization-required, host-requirement-missing,
38
+ provider-unavailable and provider-not-qualified. Optional provider error/problem
39
+ `message` is permitted but never forwarded by the kernel.
40
+
41
+ Knowledge providers and harvesters follow the same separation: the
42
+ [knowledge capability boundary](2026-09-16-knowledge-capability-contract.md) keeps
43
+ models, retrieval, evidence selection, judgment and delivery in the capability.
44
+ Shared invocation/evidence/helper execution is infrastructure, not a kernel harvester.
45
+
46
+ ## Normalize
47
+
48
+ `input` is `{declarations,context}`. Context is the captured workspace/standalone
49
+ context, not a cwd to inspect. Each declaration has exactly
50
+ `{kind,value,origin,origins}`:
51
+
52
+ - kind: soul/workspace/adoption/operator;
53
+ - value: the already-decoded soul declaration, workspace declaration, adoption
54
+ object, or operator input respectively (not YAML bytes or a filename);
55
+ - origin: its root Origin1; origins: JSON-pointer map of supplied Origin1 locators.
56
+
57
+ The provider interprets only its domain. It must not reread live source/config.
58
+ Returned origins must refer to supplied document/pointer witnesses. Soul hard
59
+ constraints use soul-requirement, soul defaults use soul-default; candidates from
60
+ other inputs use workspace-default/import-adoption/operator respectively. The
61
+ kernel checks origin authority as well as its structure; a source cannot mint an
62
+ operator candidate.
63
+
64
+ Result is exactly `{requirements,candidates,model}`. Requirements/candidates use
65
+ the existing resolveChoices wire entries. Every key must be a canonical JSON
66
+ pointer strictly below `/bindings/<slot>/`. Only the kernel selects winners by
67
+ combining these with the existing plan in the SAME resolver. Model is bounded
68
+ opaque nonsecret provider data, passed unchanged into bind in this transaction.
69
+
70
+ For default OKF, source `value.knowledge` is oats.okf.locations@1 with its existing
71
+ owner/stores/reads/owns payload. A workspace `knowledge.stores[]` entry for that
72
+ contract has `payload:{bindings:{"write.default":<portable locator>,...}}`.
73
+ Adoption/operator `value.bindings` is the already-authored provider binding map.
74
+ Several workspace envelopes remain separate same-authority inputs, not a merge
75
+ that silently chooses a winner. Explicit selected settings may supply host-owned
76
+ state placement; no stateDir or publication destination is inferred from a home.
77
+ Other providers own their payload contracts; the kernel does not parse these OKF
78
+ fields. Unknown/incompatible payload contracts must be reported, not reinterpreted.
79
+
80
+ ## Bind
81
+
82
+ `input` is exactly `{model,choices,context}`. Choices contains ONLY this provider's
83
+ resolved `/bindings/<slot>/...` choices, including selectedBy/constraints/considered.
84
+ Result is `{payloadContract,payloadVersion,payload,credentialRefs,provenance}` plus
85
+ `messagingChoice` ONLY for messaging. Kernel adds schemaVersion/capability to form
86
+ ProviderBinding1. Credential references use the EXISTING env or provider-reference
87
+ shapes; values, keys and tokens are never copied. Payload is opaque NONSECRET data;
88
+ providers are responsible for their domain's nonsecret validation.
89
+
90
+ Messaging must return the existing enabled MessagingChoice1 with provider-resolvable
91
+ responsible human and exact context, plus explicit wider-team consent. A populated
92
+ binding is not evidence of enrollment/privacy/readiness. Non-messaging providers
93
+ cannot set messagingChoice. Disabled messaging is represented by no messaging
94
+ provider and `{schemaVersion:1,enabled:false}`, not an invented private team.
95
+
96
+ For messaging lifecycle integration, the [capability contract boundary](2026-09-16-messaging-capability-contract.md)
97
+ assigns generic intent/invocation to the kernel and native identity/team/transport
98
+ behavior to the capability. Missing additional invocation fields need one reviewed
99
+ versioned projection, not aweb-specific kernel behavior.
100
+
101
+ ## Check
102
+
103
+ `input` is `{binding,context,action,invocation?}` with no other fields. Binding is
104
+ the complete immutable ProviderBinding1. Action is the requested captured action,
105
+ not a new launch recipe. Optional `invocation` is the same bounded
106
+ CapturedInvocationContext1 projected for execution below; if present, its capability,
107
+ context and action must match this request. It is not nullable: omit it for an explicit
108
+ scope check without invocation data. Identity-dependent provider actions must refuse
109
+ missing instance context. Normalize/bind do not accept this field.
110
+ Result is exactly `{status,problems}`; status is ready/needs-configuration/
111
+ authorization-required/unavailable. Problems is an array of code + optional message
112
+ objects using the error-code set above. Ready requires an empty problems array.
113
+
114
+ Check performs provider-owned READ-ONLY mutable readiness/credential/store/member
115
+ checks through existing native/provider mechanisms. Bounded private temporary Git
116
+ staging for fetch/checkout/read is allowed with owned cleanup; accepted stores,
117
+ operator checkouts and remotes must not be mutated. It does not change binding,
118
+ initialize a base, enroll an identity, create a team, or schedule/publish work.
119
+ Unsupported/unqualified checks return non-ready. Results are evaluated at each
120
+ action boundary and never persisted as permanent authority in the resolution.
121
+ A real provider acceptance is still required; fixture success is not certification.
122
+
123
+ ## Captured command invocation
124
+
125
+ The captured action loader runs the provider's check against the verified record at
126
+ each command/operation/hook load; non-ready blocks before the action. Inspection and
127
+ instruction composition do not enroll or claim readiness. Captured hook dispatch and public captured native start/restart are implemented.
128
+ Public captured retirement remains unimplemented; managed-runtime/Pi adoption and
129
+ real-host readiness remain separate qualification steps.
130
+
131
+ For synchronous captured CLI commands, core writes the exact ProviderBinding1 to a
132
+ fresh private invocation directory outside the home and retained artifacts. It
133
+ passes only its absolute path in `OATS_BINDING_FILE`; the selected capability's
134
+ retained root and effective settings are supplied separately. The file is owner-only
135
+ mode `0600` and removed with its owned directory after success or failure. A pre-existing
136
+ ambient snapshot variable is scrubbed. The caller must not exit before cleanup.
137
+
138
+ This is an ephemeral invocation input, never the operator's live `bindings-file`
139
+ or a durable worker pointer. A provider must distinguish absent (legacy) from
140
+ present-but-invalid (refuse, no fallback). Independent work must freeze its needed
141
+ binding/runtime data under existing durable source/attempt custody before returning;
142
+ no async worker may rely on the invocation file remaining. No credential value is
143
+ part of the ProviderBinding contract. Abrupt process death can leave private scratch;
144
+ it does not make that scratch selectable authority or justify unsafe cleanup.
145
+
146
+ ### Current paired execution transport versus explicit old ingress
147
+
148
+ Current captured commands, operations and hooks with an actual selected provider binding receive BOTH `OATS_INVOCATION_CONTEXT_FILE` and `OATS_BINDING_FILE`. Generic invocation is universal; an additive/unbound capability legitimately has no binding snapshot. The supplemental source receipt is not a substitute for either input. Checks still use the existing stdin contract and optional inline invocation, not an additional file channel.
149
+
150
+ The raw namespace-command route does not nominate an instance or admit an action. Source-independent existing-run completion therefore receives `instance:null`, `intent:null` and no instance-derived prior receipt, even after source-home deletion. The [existing-run completion boundary](2026-09-16-captured-admission.md#existing-provider-run-completion-after-source-home-deletion) keeps qualified retained provider-run custody separate from a new kernel mutation grant. No helper binding or invented live source identity substitutes for that authority.
151
+
152
+ Binding/source-receipt-only fixtures represent explicitly OLD transport, not positives for the current paired reader. Missing, malformed or invalid-present current snapshots must not cause synthesized projections or silent fallback. Any deliberate old-ingress compatibility path is separately explicit and qualified against exact producer/provider pins; it does not silently upgrade old fixtures or alter the selected supplemental-input/registered-replay policy.
153
+
154
+ ## Captured lifecycle registration input
155
+
156
+ The kernel also has a bounded private `OATS_SOURCE_RECEIPT_FILE` projection for a
157
+ synchronous captured lifecycle hook that explicitly selects
158
+ `inputs.sourceReceipt:{version:1}` in its retained object-form declaration. No
159
+ opt-in means no source snapshot, regardless of layer; generic invocation remains
160
+ universal. See the [selected input contract](2026-09-17-capability-helper-input-contract.md). Its exact v1 payload is the agreed
161
+ `{schemaVersion,kind,home,work,context,agent,instance,sourceIdentity,role,executionBinding,responsibleHuman,binding}`
162
+ receipt. Persistent sources require their qualified captured soul identity; helper
163
+ receipts require `sourceIdentity:null`. The context equals the durable execution
164
+ deployment, the role is the retained canonical source instructions (bounded to
165
+ 128 KiB), and the provider binding contains no credential values.
166
+
167
+ The file uses the same owner-only mode `0600`, outside-home/retained-artifact custody
168
+ and normal success/failure cleanup posture as `OATS_BINDING_FILE`. The home argument
169
+ must match the receipt. Captured lifecycle hook loading preflights every applicable
170
+ retained hook, exact approval, host requirement and provider readiness before the
171
+ first lifecycle side effect, then preserves the existing hook metadata, warning,
172
+ environment and required-hook result contract. Each selected receipt is derived only for its actual binding owner, from the
173
+ verified canonical body and owned generic instance/action facts, before provider
174
+ readiness/effects. Multiple opting providers get separate same-owner snapshots;
175
+ unsolicited/contradictory explicit receipts refuse and caller extraEnv cannot
176
+ nominate snapshot paths. No knowledge-slot dependency or automatic receipt is
177
+ inferred. This supplemental input is not a generic messaging identity contract
178
+ or permission for new registration through an absent-input fallback.
179
+
180
+ ## Provider-neutral captured invocation context
181
+
182
+ Captured commands, hooks and operations receive one private mode-`0600`
183
+ `OATS_INVOCATION_CONTEXT_FILE`. Read-only checks receive that same validated data in
184
+ `input.invocation` instead, NOT via a second file/environment source of authority.
185
+ This enables setup-specific admission without requiring already-completed enrollment.
186
+ The unreleased v1 payload is:
187
+
188
+ ```text
189
+ {schemaVersion:1, executionBinding,
190
+ subject: <exact captured record subject>,
191
+ instance:null|{home,work,name,agent,incarnationId},
192
+ intent:null|{schemaVersion:1,executionId,incarnationId,attempt},
193
+ context, responsibleHuman, messagingChoice,
194
+ capability, action, priorReceipt}
195
+ ```
196
+
197
+ The subject is the existing closed union: `{kind:'persistent',soul: SoulSelection}`
198
+ or `{kind:'helper',provider: CapabilityArtifactRef,definition: ResourceRef,name}`.
199
+ Helpers retain their exact provider artifact and definition, not an alias-derived
200
+ identity. The shared subject/context codecs and structural schemas are reused.
201
+ Overall limits are 512 KiB, depth 32 and 16384 entries; `priorReceipt` separately has
202
+ 128 KiB, depth 24 and 8192 entries. Its JSON is opaque and nullable, never credentials.
203
+
204
+ The kernel derives it from the verified record, explicit target and that capability's
205
+ current stored metadata/index before provider readiness or execution. Non-null instance
206
+ facts and any supplied prior receipt must match the captured home's owned incarnation,
207
+ record and indexed receipts; a scope action has instance:null and no invented home. A public broker check
208
+ with invocation re-verifies the referenced record and matches the entire binding,
209
+ artifact set and effective settings, not merely the request's syntactic shape.
210
+ `action` is the
211
+ existing exact loader action (`command` with capability/namespace and name, `hook`
212
+ with capability/name, or `operation` with slot/name), not a new action table.
213
+ `messagingChoice`
214
+ carries the requested private floor and explicit wider set; it is intent, never proof
215
+ of privacy/enrollment. `priorReceipt` is bounded opaque JSON owned by the selected
216
+ capability. Credential values remain outside all three snapshots. Providers must use
217
+ the exact execution/source/instance/context/human/action facts and reconcile retries
218
+ against their prior receipt; they must not infer replacements from cwd, OS user,
219
+ display name, source alias or ambient configuration.
220
+
221
+ The file uses the same owned scratch, success/failure cleanup and observed-result
222
+ preservation boundary as the binding/source snapshots. Captured hook dispatch recovers
223
+ an observed opaque provider receipt even if several nested snapshot cleanups fail,
224
+ including after a nonzero child exit. It records a required, unconfirmed cleanup
225
+ failure rather than treating the hook as clean or discarding receipt-owned effects.
226
+ This accounting is provider-neutral and does not interpret knowledge or messaging data.
227
+ Existing
228
+ `OATS_SOURCE_RECEIPT_FILE` remains a selected supplemental source-context input,
229
+ not a messaging-specific or general identity mechanism. Provider registration,
230
+ helper skipping/recursion policy and qualified existing-descriptor replay stay
231
+ provider-owned; absence alone does not identify a dependent/non-ready provider. Captured hook dispatch and public captured
232
+ start/restart are implemented; public captured retirement remains unimplemented.
233
+ Managed-runtime/Pi adoption and real-host qualification remain outstanding. These
234
+ captured paths must not fall back to current source or configuration.
235
+
236
+ This addition is an unreleased coordinated wire change: both provider validators
237
+ must accept optional `check.input.invocation` and the exact subject union before a
238
+ new compatible provider pin is used. The new incarnation/intent fields also need
239
+ coordinated successor consumers; earlier pins are not silently patched or claimed
240
+ compatible. [Captured admission](2026-09-16-captured-admission.md) records opaque fresh
241
+ incarnations and logical request IDs before effects using the existing home index.
242
+ An explicit retry reuses its ID/receipt; identical distinct requests get distinct IDs.
243
+ Composition/home/alias values are never replacement identities. Actual captured native dispatch is implemented under indexed incarnation/intent
244
+ custody. Stable scheduler execution-ID propagation and broader managed-runtime/Pi
245
+ and real-host qualification remain outstanding; inert fixture dispatch does not
246
+ prove model health or task completion. Admission
247
+ authorizes an attempt/reconciliation, not duplicate native effects, enrollment or privacy.