@awebai/oats 0.25.9 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +8 -6
  2. package/bin/oats.mjs +648 -1755
  3. package/capabilities/oats-authoring/oats-package.json +2 -2
  4. package/capabilities/oats-authoring/oats.json +2 -2
  5. package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +46 -25
  6. package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +13 -6
  7. package/capabilities/oats-aweb/bin/oats-aweb.mjs +279 -93
  8. package/capabilities/oats-aweb/injects/aweb.md +7 -2
  9. package/capabilities/oats-aweb/lib/binding-wire.mjs +89 -13
  10. package/capabilities/oats-aweb/lib/captured-native.mjs +1 -1
  11. package/capabilities/oats-aweb/lib/grant-custody.mjs +38 -0
  12. package/capabilities/oats-aweb/oats.json +8 -4
  13. package/capabilities/oats-jira/bin/oats-jira.mjs +4 -4
  14. package/capabilities/oats-jira/oats.json +2 -2
  15. package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +6 -3
  16. package/capabilities/oats-linear/bin/oats-linear-hook.mjs +6 -4
  17. package/capabilities/oats-linear/oats.json +2 -2
  18. package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +6 -0
  19. package/capabilities/oats-review/oats.json +3 -2
  20. package/docs/capabilities.md +229 -58
  21. package/docs/capability-manifest.schema.json +29 -9
  22. package/docs/configuration.md +17 -5
  23. package/docs/conventions.md +18 -28
  24. package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +1 -1
  25. package/docs/design/2026-09-13-knowledge-and-memory-direction.md +3 -3
  26. package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +2 -2
  27. package/docs/design/2026-09-15-portable-souls-handoff.md +2 -2
  28. package/docs/design/2026-09-15-portable-souls-implementation.md +1 -1
  29. package/docs/design/2026-09-20-redesign-program-board.md +2 -2
  30. package/docs/design/2026-09-23-workspace-module-contracts.md +1 -1
  31. package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +1 -1
  32. package/docs/design/2026-09-24-desktop-phase-f-boundary.md +34 -1
  33. package/docs/design/2026-09-24-phase-d-plan.md +57 -0
  34. package/docs/design/2026-09-25-teams-contract.md +226 -0
  35. package/docs/design/README.md +3 -3
  36. package/docs/design/launch-configurations.md +20 -16
  37. package/docs/design/operations-contract.md +27 -10
  38. package/docs/desktop-cli-api.md +604 -271
  39. package/docs/desktop-instance-start.md +3 -3
  40. package/docs/desktop.md +7 -13
  41. package/docs/execution-targets.md +16 -18
  42. package/docs/first-team.md +15 -18
  43. package/docs/implementation.md +31 -62
  44. package/docs/integrations.md +64 -33
  45. package/docs/knowledge-capability-authoring.md +1 -1
  46. package/docs/knowledge-reference/package-craft.md +10 -8
  47. package/docs/knowledge-theory.md +1 -1
  48. package/docs/knowledge.md +10 -11
  49. package/docs/layers.md +16 -17
  50. package/docs/oats-local.schema.json +30 -1
  51. package/docs/oats-membership.schema.json +5 -3
  52. package/docs/oats-package.schema.json +2 -2
  53. package/docs/oats-workspace.schema.json +1 -1
  54. package/docs/{official-marketplace.md → official-catalog.md} +15 -16
  55. package/docs/packages.md +76 -53
  56. package/docs/release-notes/v0.22.0.md +1 -1
  57. package/docs/release-notes/v0.23.1.md +1 -1
  58. package/docs/release-notes/v0.26.0.md +670 -0
  59. package/docs/release-notes/v0.27.0.md +100 -0
  60. package/docs/schedules.md +54 -132
  61. package/docs/servers.md +4 -4
  62. package/docs/soul.schema.json +11 -4
  63. package/docs/souls-and-instances.md +60 -47
  64. package/docs/workspaces.md +80 -58
  65. package/injects/instance-boundary.md +2 -2
  66. package/injects/work-attached.md +1 -1
  67. package/injects/work-workspace.md +2 -2
  68. package/lib/{portable-files.mjs → bounded-read.mjs} +6 -6
  69. package/lib/{portable-values.mjs → canonical-json.mjs} +3 -12
  70. package/lib/capability-contract.mjs +110 -0
  71. package/lib/config-data.mjs +2 -2
  72. package/lib/core.mjs +947 -5023
  73. package/lib/deprecation.mjs +24 -0
  74. package/lib/digest.mjs +12 -0
  75. package/lib/instance-inspect.mjs +397 -0
  76. package/lib/instance-lifecycle.mjs +3 -4
  77. package/lib/instance-resolution.mjs +212 -26
  78. package/lib/instruction-composition.mjs +0 -20
  79. package/lib/materialize.mjs +6 -4
  80. package/lib/operator-dispatch.mjs +33 -13
  81. package/lib/packages.mjs +25 -190
  82. package/lib/process-group.mjs +1 -1
  83. package/lib/provider-binding.mjs +4 -2
  84. package/lib/provider-reasons.mjs +3 -68
  85. package/lib/remote.mjs +1 -1
  86. package/lib/resolve.mjs +204 -68
  87. package/lib/schedule.mjs +136 -292
  88. package/lib/servers.mjs +70 -38
  89. package/lib/{portable-shape.mjs → shape.mjs} +4 -3
  90. package/lib/tree-copy.mjs +44 -0
  91. package/lib/workspace.mjs +132 -20
  92. package/package-catalog.json +6 -6
  93. package/package.json +1 -1
  94. package/packages/record/lib/session-roots.mjs +8 -6
  95. package/skills/integration-authoring/SKILL.md +48 -40
  96. package/skills/oats-getting-started/SKILL.md +105 -110
  97. package/skills/oats-support/SKILL.md +2 -2
  98. package/skills/soul-craft/SKILL.md +13 -6
  99. package/bin/oats-pi-sdk-host.mjs +0 -17
  100. package/docs/2026-09-03-architecture-proposal.md +0 -642
  101. package/docs/artifact-approvals.schema.json +0 -7
  102. package/docs/captured-invocation-context.schema.json +0 -7
  103. package/docs/captured-resolution.schema.json +0 -7
  104. package/docs/design/package-engine-contract.md +0 -813
  105. package/docs/design/package-runtime-api.md +0 -588
  106. package/docs/desktop-succession.md +0 -57
  107. package/docs/execution-capsule.schema.json +0 -108
  108. package/docs/first-team-demo.md +0 -92
  109. package/docs/knowledge-migration.md +0 -147
  110. package/docs/migration-from-oas.md +0 -103
  111. package/docs/oats-config.schema.json +0 -172
  112. package/docs/oats-lock-v3.schema.json +0 -7
  113. package/docs/oats-lock.schema.json +0 -175
  114. package/docs/operating-team-migration.md +0 -470
  115. package/docs/portable.schema.json +0 -2512
  116. package/docs/provider-check-input.schema.json +0 -7
  117. package/docs/rebuild-to-v2.md +0 -511
  118. package/docs/workspace-adoption.md +0 -74
  119. package/injects/framework-workspace.md +0 -7
  120. package/injects/local-soul.md +0 -19
  121. package/injects/oats-portable.md +0 -20
  122. package/injects/oats.md +0 -11
  123. package/injects/portable-instance-boundary.md +0 -39
  124. package/injects/portable-work-directory.md +0 -29
  125. package/lib/artifact-approvals.mjs +0 -120
  126. package/lib/artifact-tree.mjs +0 -141
  127. package/lib/capability-artifacts.mjs +0 -179
  128. package/lib/capability-execution.mjs +0 -15
  129. package/lib/capability-inputs.mjs +0 -39
  130. package/lib/capability-provenance.mjs +0 -231
  131. package/lib/captured-action-shape.mjs +0 -21
  132. package/lib/captured-admission-shape.mjs +0 -20
  133. package/lib/captured-binding-file.mjs +0 -36
  134. package/lib/captured-dispatch.mjs +0 -66
  135. package/lib/captured-instance-index.mjs +0 -277
  136. package/lib/captured-invocation-context.mjs +0 -130
  137. package/lib/captured-launch-request.mjs +0 -66
  138. package/lib/captured-operation-process.mjs +0 -15
  139. package/lib/captured-pi-custody.mjs +0 -29
  140. package/lib/captured-pi-host.mjs +0 -167
  141. package/lib/captured-pi-outcome.mjs +0 -172
  142. package/lib/captured-resolutions.mjs +0 -275
  143. package/lib/captured-scaffold.mjs +0 -87
  144. package/lib/captured-selector.mjs +0 -28
  145. package/lib/captured-session-backend.mjs +0 -52
  146. package/lib/captured-source-receipt-file.mjs +0 -72
  147. package/lib/helper-injection-policy.mjs +0 -104
  148. package/lib/legacy-lock-codec.mjs +0 -106
  149. package/lib/manifest-settings.mjs +0 -84
  150. package/lib/package-closure.mjs +0 -48
  151. package/lib/package-materialization.mjs +0 -83
  152. package/lib/pi-sdk-host.mjs +0 -229
  153. package/lib/portable-artifacts.mjs +0 -115
  154. package/lib/portable-choices.mjs +0 -82
  155. package/lib/portable-composition.mjs +0 -136
  156. package/lib/portable-digest.mjs +0 -105
  157. package/lib/portable-identity.mjs +0 -40
  158. package/lib/portable-lock.mjs +0 -117
  159. package/lib/portable-onboarding-request.mjs +0 -49
  160. package/lib/portable-onboarding.mjs +0 -256
  161. package/lib/portable-package-preparation.mjs +0 -188
  162. package/lib/portable-policy.mjs +0 -44
  163. package/lib/portable-soul.mjs +0 -42
  164. package/lib/portable-state.mjs +0 -80
  165. package/lib/prepare-composition.mjs +0 -170
  166. package/lib/prepared-bindings.mjs +0 -92
  167. package/lib/prepared-resources.mjs +0 -127
  168. package/lib/provider-binding-broker.mjs +0 -65
  169. package/lib/provider-binding-wire.mjs +0 -116
  170. package/lib/readiness.mjs +0 -225
  171. package/lib/repository-observation.mjs +0 -226
  172. package/lib/resolution-shape.mjs +0 -393
  173. package/lib/schedule-capsule.mjs +0 -206
  174. package/lib/soul-constraints.mjs +0 -40
  175. package/lib/source-projection.mjs +0 -84
  176. package/lib/source-spec.mjs +0 -189
  177. package/lib/workspace-definition.mjs +0 -126
  178. package/lib/workspace-discovery.mjs +0 -146
  179. package/skills/oats/SKILL.md +0 -162
  180. package/skills/oats-config/SKILL.md +0 -164
  181. package/skills/oats-packages/SKILL.md +0 -184
  182. package/skills/oats-portable/SKILL.md +0 -115
  183. package/skills/oats-portable-artifacts/SKILL.md +0 -63
@@ -0,0 +1,110 @@
1
+ /** The capability manifest's kernel contract, shared by every reader: workspace
2
+ * discovery (member capabilities, E_WORKSPACE_SCHEMA), package manifests
3
+ * (E_PACKAGE_MANIFEST), the resolver (payload values) and the kernel's own
4
+ * manifest loader. One rule set, so a manifest a workspace accepts is one the
5
+ * kernel can run.
6
+ *
7
+ * Covers what the kernel enforces when it RUNS a capability, checked where the
8
+ * manifest is READ instead: the launch environment a capability may declare
9
+ * (names, namespaces), its hooks (approved events, declaration shape, `required`
10
+ * only on spawn, the script inside the capability), and a provider payload's
11
+ * value against the manifest's `settings.<key>.values`. Dependency-free. */
12
+
13
+ export const APPROVED_HOOKS = new Set(["soul-scaffold", "spawn", "retire", "launch"]);
14
+ export const PORTABLE_ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
15
+ export const CAPABILITY_ENV_ID_RE = /^[a-z][a-z0-9]*\.[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
16
+ export const CORE_LAUNCH_ENV = new Set(["OATS_INSTANCE", "OATS_INSTANCE_HOME", "PI_AGENT_INSTANCE", "PI_AGENT_HOME"]);
17
+ export const PROCESS_BOOTSTRAP_ENV = new Set([
18
+ "PATH", "HOME", "SHELL", "TMPDIR", "TMP", "TEMP", "PWD", "OLDPWD", "SHLVL", "_",
19
+ "ENV", "BASH_ENV", "BASHOPTS", "SHELLOPTS", "CDPATH", "IFS", "PROMPT_COMMAND", "PS4", "ZDOTDIR",
20
+ "NODE_OPTIONS", "NODE_PATH", "_JAVA_OPTIONS", "GCONV_PATH", "GLIBC_TUNABLES", "ELECTRON_RUN_AS_NODE",
21
+ ]);
22
+ export const PROCESS_BOOTSTRAP_PREFIXES = [
23
+ "NODE_", "LD_", "DYLD_", "PYTHON", "PERL", "RUBY", "JAVA_", "JDK_JAVA_",
24
+ "DOTNET_", "COMPlus_", "COREHOST_", "LUA_", "PHP_", "ELECTRON_", "GLIBC_",
25
+ ];
26
+
27
+ const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
28
+ const pointerKey = (k) => String(k).replace(/~/g, "~0").replace(/\//g, "~1");
29
+
30
+ /** A hook's script, the first word of its command: relative to the capability root and inside it. */
31
+ export function hookScriptEscapes(command) {
32
+ const script = String(command).trim().split(/\s+/)[0] || "";
33
+ return script.startsWith("/") || script.startsWith("~") || /^[A-Za-z]:[\\/]/.test(script) || script.split(/[\\/]/).includes("..");
34
+ }
35
+
36
+ /** Every contract problem of one manifest → [{ pointer, message }] (empty when it is sound).
37
+ * Messages name the capability; `pointer` is the JSON pointer inside oats.json. */
38
+ export function manifestContractProblems(m) {
39
+ const problems = [];
40
+ const id = m?.capability;
41
+ const bad = (pointer, message) => problems.push({ pointer, message: `capability ${id} ${message}` });
42
+
43
+ if (m.environmentNamespaces !== undefined && (!Array.isArray(m.environmentNamespaces) || m.environmentNamespaces.some((ns) => typeof ns !== "string"))) {
44
+ bad("/environmentNamespaces", "manifest environmentNamespaces must be an array of prefixes");
45
+ }
46
+ if (m.environment !== undefined) {
47
+ if (!Array.isArray(m.environment) || m.environment.some((name) => typeof name !== "string")) {
48
+ bad("/environment", "manifest environment must be an array of exact variable names");
49
+ } else if (new Set(m.environment).size !== m.environment.length) {
50
+ bad("/environment", "manifest environment contains duplicate names");
51
+ } else if (m.environment.length) {
52
+ const vendor = CAPABILITY_ENV_ID_RE.test(id) ? id.match(/^([a-z][a-z0-9]*)\./)?.[1] : undefined;
53
+ if (!vendor) bad("/capability", "must use a lowercase dotted ID (vendor.name) without package or path syntax to declare launch environment");
54
+ else {
55
+ const extra = Array.isArray(m.environmentNamespaces) ? m.environmentNamespaces.filter((ns) => typeof ns === "string") : [];
56
+ extra.forEach((ns, i) => {
57
+ if (!/^[A-Z][A-Z0-9]*_$/.test(ns)) bad(`/environmentNamespaces/${i}`, `manifest environmentNamespaces entry ${JSON.stringify(ns)} must be an uppercase prefix ending in an underscore`);
58
+ else if (ns === "OATS_" || ns === "PI_AGENT_" || PROCESS_BOOTSTRAP_PREFIXES.some((reserved) => ns.startsWith(reserved) || reserved.startsWith(ns))) bad(`/environmentNamespaces/${i}`, `manifest environmentNamespaces entry ${ns} is a reserved namespace`);
59
+ });
60
+ const allowed = [`${vendor.toUpperCase()}_`, ...extra];
61
+ m.environment.forEach((name, i) => {
62
+ const at = `/environment/${i}`;
63
+ if (!PORTABLE_ENV_NAME_RE.test(name)) bad(at, `manifest environment name ${JSON.stringify(name)} is invalid`);
64
+ else if (CORE_LAUNCH_ENV.has(name) || name.startsWith("OATS_") || name.startsWith("PI_AGENT_")) bad(at, `manifest environment name ${name} collides with a reserved core variable`);
65
+ else if (PROCESS_BOOTSTRAP_ENV.has(name) || PROCESS_BOOTSTRAP_PREFIXES.some((reserved) => name.startsWith(reserved))) bad(at, `manifest environment name ${name} collides with a reserved process bootstrap variable`);
66
+ else if (!allowed.some((ns) => name.startsWith(ns))) bad(at, `manifest environment name ${name} is outside its ${allowed.join(", ")} namespace${allowed.length > 1 ? "s" : ""} (declare another in environmentNamespaces)`);
67
+ });
68
+ }
69
+ }
70
+ }
71
+
72
+ if (m.hooks !== undefined && !isObject(m.hooks)) bad("/hooks", "manifest hooks must be an object of event → command");
73
+ const hooks = isObject(m.hooks) ? Object.entries(m.hooks) : [];
74
+ // A hook's launch environment is claimed under the capability's dotted vendor
75
+ // component; an undotted id has none, so its hooks cannot run.
76
+ if (hooks.length && !/^[a-z][a-z0-9]*\./.test(String(id))) bad("/hooks", "declares hooks but its id has no dotted lowercase vendor component (e.g. acme.tool); only a dotted id can carry hooks");
77
+ for (const [event, value] of hooks) {
78
+ const at = `/hooks/${pointerKey(event)}`;
79
+ if (!APPROVED_HOOKS.has(event)) { bad(at, `declares unsupported hook "${event}" (${[...APPROVED_HOOKS].join(", ")})`); continue; }
80
+ const extraKeys = isObject(value) ? Object.keys(value).filter((k) => !["command", "required", "inputs"].includes(k)) : [];
81
+ const command = typeof value === "string" ? value : isObject(value) && typeof value.command === "string" ? value.command : undefined;
82
+ if (command === undefined || !command.trim() || extraKeys.length) { bad(at, `hook "${event}" must be a command string or { command, required, inputs }${extraKeys.length ? ` (unknown: ${extraKeys.join(", ")})` : ""}`); continue; }
83
+ if (isObject(value) && value.required !== undefined && typeof value.required !== "boolean") bad(`${at}/required`, `hook "${event}": "required" must be a boolean`);
84
+ // Only a spawn hook can fail a spawn; marking others required would promise
85
+ // an enforcement that has no defined moment to act.
86
+ else if (isObject(value) && value.required === true && event !== "spawn") bad(`${at}/required`, `hook "${event}" cannot be required — only the spawn hook is enforced (retire, launch and soul-scaffold run outside a spawn transaction)`);
87
+ if (hookScriptEscapes(command)) bad(isObject(value) ? `${at}/command` : at, `hook "${event}" script ${JSON.stringify(command.trim().split(/\s+/)[0])} escapes the capability directory; a hook script is a path inside it`);
88
+ }
89
+ return problems;
90
+ }
91
+
92
+ /** The setting keys a manifest declares (`settings.<key>`), sorted: names only, never their
93
+ * descriptions or defaults. The spawn preview and inspect expose them so a client can gate
94
+ * a choice on a declared key (e.g. a messaging provider's `join`). */
95
+ export function declaredSettings(manifest) {
96
+ return isObject(manifest?.settings) ? Object.keys(manifest.settings).sort() : [];
97
+ }
98
+
99
+ /** Top-level payload keys whose value is outside the manifest's `settings.<key>.values`
100
+ * → [{ key, value, values }]. A conditional `requires` row reads these values, so a
101
+ * misspelled one would silently skip every row instead of failing. */
102
+ export function settingValueProblems(manifest, payload) {
103
+ const out = [];
104
+ if (!isObject(manifest?.settings) || !isObject(payload)) return out;
105
+ for (const [key, decl] of Object.entries(manifest.settings)) {
106
+ if (!isObject(decl) || !Array.isArray(decl.values) || !Object.hasOwn(payload, key) || payload[key] === undefined) continue;
107
+ if (!decl.values.some((v) => String(v) === String(payload[key]))) out.push({ key, value: payload[key], values: decl.values });
108
+ }
109
+ return out;
110
+ }
@@ -2,8 +2,8 @@
2
2
  * object-construction language: no tags, anchors, aliases, merges or coercive keys.
3
3
  * Legacy core readers are unchanged until the explicit consumer migration. */
4
4
  import { Composer, CST, Lexer, Parser, isAlias, isMap, isScalar, isSeq } from "yaml";
5
- import { bytesIntegrity } from "./portable-digest.mjs";
6
- import { byteView, canonicalJson, dataLimits, decodeUtf8, parseStrictJson } from "./portable-values.mjs";
5
+ import { bytesIntegrity } from "./digest.mjs";
6
+ import { byteView, canonicalJson, dataLimits, decodeUtf8, parseStrictJson } from "./canonical-json.mjs";
7
7
  import { oatsError } from "./errors.mjs";
8
8
 
9
9
  const pointerKey = (key) => key.replace(/~/g, "~0").replace(/\//g, "~1");