@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.
- package/README.md +8 -6
- package/bin/oats.mjs +648 -1755
- package/capabilities/oats-authoring/oats-package.json +2 -2
- package/capabilities/oats-authoring/oats.json +2 -2
- package/capabilities/oats-authoring/skills/integration-authoring/SKILL.md +46 -25
- package/capabilities/oats-authoring/skills/soul-craft/SKILL.md +13 -6
- package/capabilities/oats-aweb/bin/oats-aweb.mjs +279 -93
- package/capabilities/oats-aweb/injects/aweb.md +7 -2
- package/capabilities/oats-aweb/lib/binding-wire.mjs +89 -13
- package/capabilities/oats-aweb/lib/captured-native.mjs +1 -1
- package/capabilities/oats-aweb/lib/grant-custody.mjs +38 -0
- package/capabilities/oats-aweb/oats.json +8 -4
- package/capabilities/oats-jira/bin/oats-jira.mjs +4 -4
- package/capabilities/oats-jira/oats.json +2 -2
- package/capabilities/oats-jira/skills/jira-tasks/SKILL.md +6 -3
- package/capabilities/oats-linear/bin/oats-linear-hook.mjs +6 -4
- package/capabilities/oats-linear/oats.json +2 -2
- package/capabilities/oats-linear/skills/linear-tasks/SKILL.md +6 -0
- package/capabilities/oats-review/oats.json +3 -2
- package/docs/capabilities.md +229 -58
- package/docs/capability-manifest.schema.json +29 -9
- package/docs/configuration.md +17 -5
- package/docs/conventions.md +18 -28
- package/docs/design/2026-09-08-expert-assisted-deployment-proposal.md +1 -1
- package/docs/design/2026-09-13-knowledge-and-memory-direction.md +3 -3
- package/docs/design/2026-09-14-portable-souls-and-git-workspaces.md +2 -2
- package/docs/design/2026-09-15-portable-souls-handoff.md +2 -2
- package/docs/design/2026-09-15-portable-souls-implementation.md +1 -1
- package/docs/design/2026-09-20-redesign-program-board.md +2 -2
- package/docs/design/2026-09-23-workspace-module-contracts.md +1 -1
- package/docs/design/2026-09-23-workspace-v2-implementation-plan.md +1 -1
- package/docs/design/2026-09-24-desktop-phase-f-boundary.md +34 -1
- package/docs/design/2026-09-24-phase-d-plan.md +57 -0
- package/docs/design/2026-09-25-teams-contract.md +226 -0
- package/docs/design/README.md +3 -3
- package/docs/design/launch-configurations.md +20 -16
- package/docs/design/operations-contract.md +27 -10
- package/docs/desktop-cli-api.md +604 -271
- package/docs/desktop-instance-start.md +3 -3
- package/docs/desktop.md +7 -13
- package/docs/execution-targets.md +16 -18
- package/docs/first-team.md +15 -18
- package/docs/implementation.md +31 -62
- package/docs/integrations.md +64 -33
- package/docs/knowledge-capability-authoring.md +1 -1
- package/docs/knowledge-reference/package-craft.md +10 -8
- package/docs/knowledge-theory.md +1 -1
- package/docs/knowledge.md +10 -11
- package/docs/layers.md +16 -17
- package/docs/oats-local.schema.json +30 -1
- package/docs/oats-membership.schema.json +5 -3
- package/docs/oats-package.schema.json +2 -2
- package/docs/oats-workspace.schema.json +1 -1
- package/docs/{official-marketplace.md → official-catalog.md} +15 -16
- package/docs/packages.md +76 -53
- package/docs/release-notes/v0.22.0.md +1 -1
- package/docs/release-notes/v0.23.1.md +1 -1
- package/docs/release-notes/v0.26.0.md +670 -0
- package/docs/release-notes/v0.27.0.md +100 -0
- package/docs/schedules.md +54 -132
- package/docs/servers.md +4 -4
- package/docs/soul.schema.json +11 -4
- package/docs/souls-and-instances.md +60 -47
- package/docs/workspaces.md +80 -58
- package/injects/instance-boundary.md +2 -2
- package/injects/work-attached.md +1 -1
- package/injects/work-workspace.md +2 -2
- package/lib/{portable-files.mjs → bounded-read.mjs} +6 -6
- package/lib/{portable-values.mjs → canonical-json.mjs} +3 -12
- package/lib/capability-contract.mjs +110 -0
- package/lib/config-data.mjs +2 -2
- package/lib/core.mjs +947 -5023
- package/lib/deprecation.mjs +24 -0
- package/lib/digest.mjs +12 -0
- package/lib/instance-inspect.mjs +397 -0
- package/lib/instance-lifecycle.mjs +3 -4
- package/lib/instance-resolution.mjs +212 -26
- package/lib/instruction-composition.mjs +0 -20
- package/lib/materialize.mjs +6 -4
- package/lib/operator-dispatch.mjs +33 -13
- package/lib/packages.mjs +25 -190
- package/lib/process-group.mjs +1 -1
- package/lib/provider-binding.mjs +4 -2
- package/lib/provider-reasons.mjs +3 -68
- package/lib/remote.mjs +1 -1
- package/lib/resolve.mjs +204 -68
- package/lib/schedule.mjs +136 -292
- package/lib/servers.mjs +70 -38
- package/lib/{portable-shape.mjs → shape.mjs} +4 -3
- package/lib/tree-copy.mjs +44 -0
- package/lib/workspace.mjs +132 -20
- package/package-catalog.json +6 -6
- package/package.json +1 -1
- package/packages/record/lib/session-roots.mjs +8 -6
- package/skills/integration-authoring/SKILL.md +48 -40
- package/skills/oats-getting-started/SKILL.md +105 -110
- package/skills/oats-support/SKILL.md +2 -2
- package/skills/soul-craft/SKILL.md +13 -6
- package/bin/oats-pi-sdk-host.mjs +0 -17
- package/docs/2026-09-03-architecture-proposal.md +0 -642
- package/docs/artifact-approvals.schema.json +0 -7
- package/docs/captured-invocation-context.schema.json +0 -7
- package/docs/captured-resolution.schema.json +0 -7
- package/docs/design/package-engine-contract.md +0 -813
- package/docs/design/package-runtime-api.md +0 -588
- package/docs/desktop-succession.md +0 -57
- package/docs/execution-capsule.schema.json +0 -108
- package/docs/first-team-demo.md +0 -92
- package/docs/knowledge-migration.md +0 -147
- package/docs/migration-from-oas.md +0 -103
- package/docs/oats-config.schema.json +0 -172
- package/docs/oats-lock-v3.schema.json +0 -7
- package/docs/oats-lock.schema.json +0 -175
- package/docs/operating-team-migration.md +0 -470
- package/docs/portable.schema.json +0 -2512
- package/docs/provider-check-input.schema.json +0 -7
- package/docs/rebuild-to-v2.md +0 -511
- package/docs/workspace-adoption.md +0 -74
- package/injects/framework-workspace.md +0 -7
- package/injects/local-soul.md +0 -19
- package/injects/oats-portable.md +0 -20
- package/injects/oats.md +0 -11
- package/injects/portable-instance-boundary.md +0 -39
- package/injects/portable-work-directory.md +0 -29
- package/lib/artifact-approvals.mjs +0 -120
- package/lib/artifact-tree.mjs +0 -141
- package/lib/capability-artifacts.mjs +0 -179
- package/lib/capability-execution.mjs +0 -15
- package/lib/capability-inputs.mjs +0 -39
- package/lib/capability-provenance.mjs +0 -231
- package/lib/captured-action-shape.mjs +0 -21
- package/lib/captured-admission-shape.mjs +0 -20
- package/lib/captured-binding-file.mjs +0 -36
- package/lib/captured-dispatch.mjs +0 -66
- package/lib/captured-instance-index.mjs +0 -277
- package/lib/captured-invocation-context.mjs +0 -130
- package/lib/captured-launch-request.mjs +0 -66
- package/lib/captured-operation-process.mjs +0 -15
- package/lib/captured-pi-custody.mjs +0 -29
- package/lib/captured-pi-host.mjs +0 -167
- package/lib/captured-pi-outcome.mjs +0 -172
- package/lib/captured-resolutions.mjs +0 -275
- package/lib/captured-scaffold.mjs +0 -87
- package/lib/captured-selector.mjs +0 -28
- package/lib/captured-session-backend.mjs +0 -52
- package/lib/captured-source-receipt-file.mjs +0 -72
- package/lib/helper-injection-policy.mjs +0 -104
- package/lib/legacy-lock-codec.mjs +0 -106
- package/lib/manifest-settings.mjs +0 -84
- package/lib/package-closure.mjs +0 -48
- package/lib/package-materialization.mjs +0 -83
- package/lib/pi-sdk-host.mjs +0 -229
- package/lib/portable-artifacts.mjs +0 -115
- package/lib/portable-choices.mjs +0 -82
- package/lib/portable-composition.mjs +0 -136
- package/lib/portable-digest.mjs +0 -105
- package/lib/portable-identity.mjs +0 -40
- package/lib/portable-lock.mjs +0 -117
- package/lib/portable-onboarding-request.mjs +0 -49
- package/lib/portable-onboarding.mjs +0 -256
- package/lib/portable-package-preparation.mjs +0 -188
- package/lib/portable-policy.mjs +0 -44
- package/lib/portable-soul.mjs +0 -42
- package/lib/portable-state.mjs +0 -80
- package/lib/prepare-composition.mjs +0 -170
- package/lib/prepared-bindings.mjs +0 -92
- package/lib/prepared-resources.mjs +0 -127
- package/lib/provider-binding-broker.mjs +0 -65
- package/lib/provider-binding-wire.mjs +0 -116
- package/lib/readiness.mjs +0 -225
- package/lib/repository-observation.mjs +0 -226
- package/lib/resolution-shape.mjs +0 -393
- package/lib/schedule-capsule.mjs +0 -206
- package/lib/soul-constraints.mjs +0 -40
- package/lib/source-projection.mjs +0 -84
- package/lib/source-spec.mjs +0 -189
- package/lib/workspace-definition.mjs +0 -126
- package/lib/workspace-discovery.mjs +0 -146
- package/skills/oats/SKILL.md +0 -162
- package/skills/oats-config/SKILL.md +0 -164
- package/skills/oats-packages/SKILL.md +0 -184
- package/skills/oats-portable/SKILL.md +0 -115
- 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
|
+
}
|
package/lib/config-data.mjs
CHANGED
|
@@ -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 "./
|
|
6
|
-
import { byteView, canonicalJson, dataLimits, decodeUtf8, parseStrictJson } from "./
|
|
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");
|