@awebai/oats 0.24.3 → 0.24.5

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.
@@ -0,0 +1,77 @@
1
+ /** Fixed provider-declared diagnostics, never a free-text transport. Values
2
+ * come from the verified selected manifest or reviewed kernel compatibility
3
+ * data, not from a codec response, operator input or today's configuration. */
4
+ import { invalidShape, stringAt, stringSetAt } from './portable-shape.mjs';
5
+
6
+ // Compatibility literals for manifests predating binding.reasons. These are
7
+ // data, never provider-name-dependent interpretation of payloads or settings.
8
+ // aweb: awebai/oats-aweb v1.11.0, 862f156c883ab39c69c9e83cdf3bab86be882867.
9
+ // oats-package/capabilities/oats-aweb/lib/{binding-wire,session-readiness}.mjs:
10
+ // complete safeReasons/fallback/overflow/check vocabulary (no hook warnings).
11
+ // OKF: awebai/oats-okf PR5, 0517a70a7158ebdf14ccb6e880b437c3d43cb1db,
12
+ // same capability-relative file, settingMessages (UNRELEASED 2.1.2 at selection).
13
+ // Released OKF 2.1.1 sends code-only; this table invents no reason for it.
14
+ const bundled = Object.freeze({
15
+ 'oats.aweb': Object.freeze([
16
+ 'messaging-enabled standalone preparation needs an explicit context key',
17
+ 'messaging binding needs one soul declaration',
18
+ 'messaging workspace must declare private: per-human',
19
+ 'an explicit responsible-human binding is required',
20
+ 'an explicit wider-membership consent list is required',
21
+ 'a selected wider-team binding is required',
22
+ 'a selected wider alias needs an explicit workspace team mapping',
23
+ 'multiple soul messaging declarations',
24
+ 'adoption team aliases have conflicting mappings',
25
+ 'messaging settings and explicit binding selections are required',
26
+ 'messaging declarations contain incompatible requirements',
27
+ 'messaging input must match the supported binding contract',
28
+ 'explicit native messaging authorization is required',
29
+ 'a required native messaging host resource is unavailable',
30
+ 'the selected messaging provider is unavailable',
31
+ 'the requested messaging configuration is not qualified',
32
+ 'messaging response exceeds the supported wire limits',
33
+ 'an admitted captured instance intent is required for execution',
34
+ 'an explicit private-team binding is required',
35
+ 'selected binding and inline captured invocation are required',
36
+ 'an explicit captured instance home is required',
37
+ 'captured messaging requires explicit delivery: session',
38
+ 'selected wider memberships need their explicitly qualified native setup; they were not omitted',
39
+ 'caller-owned OATS_CLI_BIN and readable kernel version are required',
40
+ 'oats >=0.24.2 is required for captured HOME custody and retained runtime inspection',
41
+ 'the exact retained runtime profile must be readable',
42
+ 'the kernel must report the exact retained resolution',
43
+ 'a retained launchSelection runtime/model observation is required',
44
+ 'Pi strict print does not support session input; retain messaging and configure an input-capable profile',
45
+ 'a supported input-capable ordinary Claude/Codex profile is required',
46
+ ]),
47
+ 'oats.okf': Object.freeze([
48
+ 'setting bindings-file is required (absolute host path)',
49
+ 'setting bindings-file must be a normalized absolute host path',
50
+ 'setting state-dir is required (absolute host path)',
51
+ 'setting state-dir must be a normalized absolute host path',
52
+ 'setting harvest-runtime is required (pi, claude or codex)',
53
+ 'setting harvest-runtime must be pi, claude or codex',
54
+ 'setting harvest-model must be null or a non-empty string',
55
+ ]),
56
+ });
57
+ const none = Object.freeze([]);
58
+
59
+ export function validateBindingReasons(reasons, { allowEmpty = false } = {}) {
60
+ stringSetAt(reasons, '/binding/reasons', (reason, pointer) => {
61
+ stringAt(reason, pointer);
62
+ if (reason.length > 200 || /[{}]|[^\x20-\x7e]/.test(reason)) invalidShape(pointer, 'reason must be printable ASCII of at most 200 characters without braces');
63
+ });
64
+ if (reasons.length > 64 || (!allowEmpty && reasons.length === 0)) invalidShape('/binding/reasons', 'expected 1 to 64 fixed reasons');
65
+ return reasons;
66
+ }
67
+
68
+ export function providerReasons(manifest) {
69
+ if (Object.hasOwn(manifest.binding ?? {}, 'reasons')) return validateBindingReasons(manifest.binding.reasons);
70
+ return Object.hasOwn(bundled, manifest.capability) ? bundled[manifest.capability] : none;
71
+ }
72
+
73
+ /** Exact Unicode scalar text is exact UTF-8 text; never trim, normalize,
74
+ * interpolate or accept a prefix/substring. Absence preserves template fallback. */
75
+ export function safeProviderReason(message, reasons) {
76
+ return typeof message === 'string' && reasons.includes(message) ? message : undefined;
77
+ }
@@ -37,11 +37,28 @@ function repositoryRequest(source) {
37
37
  }
38
38
  }
39
39
 
40
+ /** `packages["oats.framework"]` from the repository's own `package-catalog.json` at the observed
41
+ * revision, or null when the file or entry is absent. Data only; the acquisition still verifies
42
+ * bytes, and the edition/package integrity comparison still applies. */
43
+ function frameworkCatalogEntry(transaction, observation) {
44
+ const file = transaction.readFile(observation, 'package-catalog.json', { optional: true });
45
+ if (!file) return null;
46
+ let doc;
47
+ try { doc = JSON.parse(file.bytes.toString('utf8')); } catch { throw oatsError('invalid-source', 'workspace package-catalog.json is not valid JSON'); }
48
+ const entry = doc && typeof doc === 'object' && !Array.isArray(doc) && doc.packages && typeof doc.packages === 'object' && !Array.isArray(doc.packages)
49
+ ? doc.packages['oats.framework'] : undefined;
50
+ if (entry === undefined) return null;
51
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.url !== 'string' || typeof entry.ref !== 'string' || (entry.path !== undefined && typeof entry.path !== 'string')) {
52
+ throw oatsError('invalid-source', 'workspace package-catalog.json has an invalid oats.framework entry');
53
+ }
54
+ return { url: entry.url, ref: entry.ref, ...(entry.path === undefined ? {} : { path: entry.path }), revision: observation.source.commit };
55
+ }
56
+
40
57
  export function loadSetupExpertEdition(workspace, repositoryOptions = {}) {
41
58
  if (workspace === undefined) {
42
59
  const root = fileURLToPath(new URL(`../${EXPORT}/`, import.meta.url));
43
60
  return { declaration: validateEdition(readFileSync(join(root, 'soul.yaml'))), instructions: readFileSync(join(root, 'AGENTS.md'), 'utf8'),
44
- source: { kind: 'packaged-definition', captured: false }, packageIntegrity: null };
61
+ source: { kind: 'packaged-definition', captured: false }, packageIntegrity: null, catalogEntry: null };
45
62
  }
46
63
  const request = repositoryRequest(workspace), scratch = realpathSync(mkdtempSync(join(tmpdir(), 'oats-setup-source-'))), owned = lstatSync(scratch);
47
64
  let transaction;
@@ -64,7 +81,14 @@ export function loadSetupExpertEdition(workspace, repositoryOptions = {}) {
64
81
  || readdirSync(soulRoot).some(name => !['soul.yaml', 'AGENTS.md', 'CLAUDE.md'].includes(name))) {
65
82
  throw oatsError('source-incomplete', 'classic setup edition must have canonical AGENTS.md/CLAUDE.md and no omitted private skill or knowledge trees');
66
83
  }
84
+ // The workspace publishes the reviewed catalog: read the oats.framework entry at the WORKSPACE's
85
+ // observed revision (falling back to the edition's own revision when the source has no workspace
86
+ // document), so onboarding acquires the framework the workspace currently names instead of
87
+ // whatever the kernel tarball snapshotted at its own tag. The edition/package integrity check
88
+ // below still decides whether that acquisition matches the copied edition.
89
+ const catalogEntry = frameworkCatalogEntry(transaction, observed) ?? frameworkCatalogEntry(transaction, imported.observation);
67
90
  return { declaration, instructions: readFileSync(body, 'utf8'), packageIntegrity: packageIntegrity(join(projection, 'oats-package')),
91
+ catalogEntry,
68
92
  source: { kind: 'exported-edition-copy', source: imported.reference.source, revision: imported.observation.source.commit,
69
93
  path: imported.reference.soul, workspaceRevision: view?.source.commit ?? null, captured: false } };
70
94
  } finally {
@@ -3,12 +3,12 @@
3
3
  "packages": {
4
4
  "oats.okf": {
5
5
  "url": "https://github.com/awebai/oats-okf.git",
6
- "ref": "v2.1.1",
6
+ "ref": "v2.1.2",
7
7
  "path": "oats-package"
8
8
  },
9
9
  "oats.aweb": {
10
10
  "url": "https://github.com/awebai/oats-aweb.git",
11
- "ref": "v1.11.0",
11
+ "ref": "v1.11.2",
12
12
  "path": "oats-package"
13
13
  },
14
14
  "oats.jira": {
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "oats.framework": {
35
35
  "url": "https://github.com/awebai/oats.git",
36
- "ref": "oats-framework/v1.1.1",
36
+ "ref": "oats-framework/v1.1.3",
37
37
  "path": "oats-package"
38
38
  }
39
39
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awebai/oats",
3
- "version": "0.24.3",
3
+ "version": "0.24.5",
4
4
  "description": "OATS (Open Agent Team Specification) — durable souls, disposable instances, targetable capability packages, and the runtime-neutral oats CLI/kernel.",
5
5
  "keywords": [
6
6
  "agents",