@uppercut-labs/agent-native 0.0.0-stage → 1.1.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 (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +164 -2
  3. package/agent/agent-prompt-short.md +1 -0
  4. package/agent/agent-prompt.md +26 -0
  5. package/bin/agent-native-site.mjs +269 -0
  6. package/bin/discover-routes.mjs +162 -0
  7. package/bin/verify-publication.mjs +317 -0
  8. package/dist/adapters/zod.d.ts +4 -0
  9. package/dist/adapters/zod.d.ts.map +1 -0
  10. package/dist/adapters/zod.js +20 -0
  11. package/dist/adapters/zod.js.map +1 -0
  12. package/dist/astro.d.ts +13 -0
  13. package/dist/astro.d.ts.map +1 -0
  14. package/dist/astro.js +41 -0
  15. package/dist/astro.js.map +1 -0
  16. package/dist/auth.d.ts +52 -0
  17. package/dist/auth.d.ts.map +1 -0
  18. package/dist/auth.js +128 -0
  19. package/dist/auth.js.map +1 -0
  20. package/dist/browser.d.ts +47 -0
  21. package/dist/browser.d.ts.map +1 -0
  22. package/dist/browser.js +219 -0
  23. package/dist/browser.js.map +1 -0
  24. package/dist/cli.d.ts +80 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +484 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/core/assert-never.d.ts +2 -0
  29. package/dist/core/assert-never.d.ts.map +1 -0
  30. package/dist/core/assert-never.js +5 -0
  31. package/dist/core/assert-never.js.map +1 -0
  32. package/dist/core/binding-internal.d.ts +10 -0
  33. package/dist/core/binding-internal.d.ts.map +1 -0
  34. package/dist/core/binding-internal.js +15 -0
  35. package/dist/core/binding-internal.js.map +1 -0
  36. package/dist/core/composition.d.ts +119 -0
  37. package/dist/core/composition.d.ts.map +1 -0
  38. package/dist/core/composition.js +545 -0
  39. package/dist/core/composition.js.map +1 -0
  40. package/dist/core/contracts.d.ts +55 -0
  41. package/dist/core/contracts.d.ts.map +1 -0
  42. package/dist/core/contracts.js +271 -0
  43. package/dist/core/contracts.js.map +1 -0
  44. package/dist/core/diagnostics.d.ts +14 -0
  45. package/dist/core/diagnostics.d.ts.map +1 -0
  46. package/dist/core/diagnostics.js +29 -0
  47. package/dist/core/diagnostics.js.map +1 -0
  48. package/dist/core/executor.d.ts +52 -0
  49. package/dist/core/executor.d.ts.map +1 -0
  50. package/dist/core/executor.js +98 -0
  51. package/dist/core/executor.js.map +1 -0
  52. package/dist/core/registry.d.ts +37 -0
  53. package/dist/core/registry.d.ts.map +1 -0
  54. package/dist/core/registry.js +75 -0
  55. package/dist/core/registry.js.map +1 -0
  56. package/dist/core/schema.d.ts +9 -0
  57. package/dist/core/schema.d.ts.map +1 -0
  58. package/dist/core/schema.js +36 -0
  59. package/dist/core/schema.js.map +1 -0
  60. package/dist/discovery.d.ts +16 -0
  61. package/dist/discovery.d.ts.map +1 -0
  62. package/dist/discovery.js +23 -0
  63. package/dist/discovery.js.map +1 -0
  64. package/dist/doctor.d.ts +200 -0
  65. package/dist/doctor.d.ts.map +1 -0
  66. package/dist/doctor.js +287 -0
  67. package/dist/doctor.js.map +1 -0
  68. package/dist/harness-codex.d.ts +17 -0
  69. package/dist/harness-codex.d.ts.map +1 -0
  70. package/dist/harness-codex.js +485 -0
  71. package/dist/harness-codex.js.map +1 -0
  72. package/dist/harness-mcp-bridge.d.ts +14 -0
  73. package/dist/harness-mcp-bridge.d.ts.map +1 -0
  74. package/dist/harness-mcp-bridge.js +159 -0
  75. package/dist/harness-mcp-bridge.js.map +1 -0
  76. package/dist/harness.d.ts +72 -0
  77. package/dist/harness.d.ts.map +1 -0
  78. package/dist/harness.js +101 -0
  79. package/dist/harness.js.map +1 -0
  80. package/dist/http.d.ts +20 -0
  81. package/dist/http.d.ts.map +1 -0
  82. package/dist/http.js +537 -0
  83. package/dist/http.js.map +1 -0
  84. package/dist/index.d.ts +16 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +8 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/init.d.ts +73 -0
  89. package/dist/init.d.ts.map +1 -0
  90. package/dist/init.js +1039 -0
  91. package/dist/init.js.map +1 -0
  92. package/dist/mcp-apps.d.ts +9 -0
  93. package/dist/mcp-apps.d.ts.map +1 -0
  94. package/dist/mcp-apps.js +171 -0
  95. package/dist/mcp-apps.js.map +1 -0
  96. package/dist/mcp-core.d.ts +64 -0
  97. package/dist/mcp-core.d.ts.map +1 -0
  98. package/dist/mcp-core.js +358 -0
  99. package/dist/mcp-core.js.map +1 -0
  100. package/dist/mcp.d.ts +3 -0
  101. package/dist/mcp.d.ts.map +1 -0
  102. package/dist/mcp.js +2 -0
  103. package/dist/mcp.js.map +1 -0
  104. package/dist/next-browser.d.ts +14 -0
  105. package/dist/next-browser.d.ts.map +1 -0
  106. package/dist/next-browser.js +14 -0
  107. package/dist/next-browser.js.map +1 -0
  108. package/dist/next.d.ts +24 -0
  109. package/dist/next.d.ts.map +1 -0
  110. package/dist/next.js +28 -0
  111. package/dist/next.js.map +1 -0
  112. package/dist/package-version.d.ts +2 -0
  113. package/dist/package-version.d.ts.map +1 -0
  114. package/dist/package-version.js +3 -0
  115. package/dist/package-version.js.map +1 -0
  116. package/dist/publication.d.ts +115 -0
  117. package/dist/publication.d.ts.map +1 -0
  118. package/dist/publication.js +441 -0
  119. package/dist/publication.js.map +1 -0
  120. package/dist/registry.d.ts +3 -0
  121. package/dist/registry.d.ts.map +1 -0
  122. package/dist/registry.js +2 -0
  123. package/dist/registry.js.map +1 -0
  124. package/docs/adopt-existing-site.md +189 -0
  125. package/docs/browser.md +70 -0
  126. package/docs/capabilities-and-bindings.md +141 -0
  127. package/docs/cli.md +88 -0
  128. package/docs/compatibility.md +32 -0
  129. package/docs/composition-and-versioning.md +113 -0
  130. package/docs/doctor-and-troubleshooting.md +58 -0
  131. package/docs/evidence/GHSA-ch52-4w7c-c8xp-2026-10-03.md +17 -0
  132. package/docs/evidence/GHSA-ch52-4w7c-c8xp-2026-10-10.md +30 -0
  133. package/docs/evidence/GHSA-ch52-4w7c-c8xp-2026-10-12.md +10 -0
  134. package/docs/evidence/UAN-002-house-style-review.md +29 -0
  135. package/docs/evidence/UAN-007-astro.md +43 -0
  136. package/docs/evidence/UAN-008-worker-sidecar.md +56 -0
  137. package/docs/evidence/UAN-009-init.md +43 -0
  138. package/docs/evidence/UAN-010-auth.md +17 -0
  139. package/docs/evidence/UAN-011-discovery.md +18 -0
  140. package/docs/evidence/UAN-012-mcp-apps.md +14 -0
  141. package/docs/evidence/UAN-013-astro-on-demand.md +47 -0
  142. package/docs/evidence/UAN-014-next.md +57 -0
  143. package/docs/evidence/UAN-015-node-hono.md +69 -0
  144. package/docs/evidence/UAN-016-composition.md +52 -0
  145. package/docs/evidence/UAN-017-version-migrations.md +50 -0
  146. package/docs/evidence/UAN-018-surface-overrides.md +30 -0
  147. package/docs/evidence/UAN-019-doctor.md +19 -0
  148. package/docs/evidence/UAN-020-negative-security-fixtures.md +61 -0
  149. package/docs/evidence/UAN-020-operational-failure-safety.md +49 -0
  150. package/docs/evidence/UAN-021-docs-coverage.md +30 -0
  151. package/docs/evidence/UAN-022-cross-platform-license-notices.md +39 -0
  152. package/docs/evidence/UAN-022-overhead-license-audit.md +233 -0
  153. package/docs/evidence/UAN-022-package-portability.md +54 -0
  154. package/docs/evidence/UAN-023-commercial-agent-hosts.md +36 -0
  155. package/docs/evidence/UAN-023-inspector-host-probe.md +37 -0
  156. package/docs/evidence/UAN-023-inspector-web-and-astro-adoption.md +44 -0
  157. package/docs/evidence/UAN-023-native-webmcp-chrome.md +44 -0
  158. package/docs/evidence/UAN-024-release-readiness-2026-10-10.md +33 -0
  159. package/docs/evidence/UAN-024-release-readiness.md +41 -0
  160. package/docs/evidence/codex-harness.md +56 -0
  161. package/docs/evidence/gate-2-domain-expansion.md +35 -0
  162. package/docs/evidence/recovery-and-selection-recipes-2026-10-15.md +63 -0
  163. package/docs/for-agents.md +50 -0
  164. package/docs/frameworks.md +62 -0
  165. package/docs/getting-started.md +109 -0
  166. package/docs/harness-codex.md +117 -0
  167. package/docs/harness-mcp-bridge.md +30 -0
  168. package/docs/http.md +80 -0
  169. package/docs/installation.md +95 -0
  170. package/docs/mcp-apps.md +57 -0
  171. package/docs/mcp.md +178 -0
  172. package/docs/next.md +73 -0
  173. package/docs/permissions-and-discovery.md +58 -0
  174. package/docs/programmatic-harness.md +88 -0
  175. package/docs/readability-frameworks.md +18 -0
  176. package/docs/reference.md +161 -0
  177. package/docs/release-handoff.md +41 -0
  178. package/docs/site-publication.md +85 -0
  179. package/docs/stability.md +53 -0
  180. package/docs/static-sites.md +141 -0
  181. package/docs/support-and-limitations.md +20 -0
  182. package/docs/surfaces.md +27 -0
  183. package/docs/upgrading-to-1.0.md +26 -0
  184. package/package.json +188 -4
  185. package/skill/agent-native/SKILL.md +54 -0
  186. package/skill/agent-native/references/adapter-decision.md +19 -0
  187. package/skill/agent-native/references/verification.md +25 -0
@@ -0,0 +1,119 @@
1
+ import { type CapabilityDefinition, type CapabilityIdentity } from './contracts.js';
2
+ export type CapabilityPackIdentity = {
3
+ readonly authority: string;
4
+ readonly namespace: string;
5
+ };
6
+ export type CapabilityPack = {
7
+ readonly identity: CapabilityPackIdentity;
8
+ readonly source: string;
9
+ readonly definitions: readonly CapabilityDefinition<unknown, unknown>[];
10
+ readonly migrations?: readonly CapabilityMigration[];
11
+ readonly lifecycle?: CapabilityLifecyclePolicy;
12
+ };
13
+ export type CapabilityPackOptions = CapabilityPack;
14
+ export type CapabilityAlias = {
15
+ readonly name: string;
16
+ readonly capabilityId: string;
17
+ readonly source?: string;
18
+ };
19
+ export type CapabilityAliasPolicy = {
20
+ readonly kind: 'none';
21
+ } | {
22
+ readonly kind: 'explicit';
23
+ readonly aliases: readonly CapabilityAlias[];
24
+ };
25
+ export type CapabilityPackImport = {
26
+ readonly pack: CapabilityPack;
27
+ readonly source: string;
28
+ readonly aliasPolicy: CapabilityAliasPolicy;
29
+ };
30
+ export type CapabilitySurfaceNames = {
31
+ readonly cli: string;
32
+ readonly http: string;
33
+ readonly mcp: string;
34
+ readonly openApiOperation: string;
35
+ };
36
+ export type CapabilityComposition = {
37
+ readonly definitions: readonly CapabilityDefinition<unknown, unknown>[];
38
+ readonly aliases: ReadonlyMap<string, string>;
39
+ readonly surfaceNames: ReadonlyMap<string, CapabilitySurfaceNames>;
40
+ resolve(name: string): CapabilityDefinition<unknown, unknown> | undefined;
41
+ select(identity: CapabilityIdentity): CapabilityDefinition<unknown, unknown> | undefined;
42
+ };
43
+ export type CapabilityContractChange = {
44
+ readonly area: 'input' | 'output' | 'risk' | 'access' | 'surface';
45
+ readonly kind: 'property-added' | 'property-removed' | 'property-renamed' | 'required-added' | 'required-removed' | 'value-changed';
46
+ readonly path: string;
47
+ readonly before?: unknown;
48
+ readonly after?: unknown;
49
+ readonly breaking: boolean;
50
+ };
51
+ export type CapabilityContractChangeReport = {
52
+ readonly fromId: string;
53
+ readonly toId: string;
54
+ readonly schemaEquivalent: boolean;
55
+ readonly changes: readonly CapabilityContractChange[];
56
+ readonly breaking: boolean;
57
+ };
58
+ export type CapabilitySemanticReview = {
59
+ readonly note: string;
60
+ readonly reviewedBy: string;
61
+ };
62
+ export type CapabilityMigration = {
63
+ readonly fromId: string;
64
+ readonly toId: string;
65
+ readonly semanticReview: CapabilitySemanticReview;
66
+ readonly contract: CapabilityContractChangeReport;
67
+ };
68
+ export type CapabilityMigrationOptions = {
69
+ readonly previous: CapabilityDefinition<unknown, unknown>;
70
+ readonly next: CapabilityDefinition<unknown, unknown>;
71
+ readonly semanticReview: CapabilitySemanticReview;
72
+ };
73
+ export type CapabilityLifecycleEntry = {
74
+ readonly capabilityId: string;
75
+ readonly state: 'supported';
76
+ } | {
77
+ readonly capabilityId: string;
78
+ readonly state: 'deprecated';
79
+ readonly note: string;
80
+ } | {
81
+ readonly capabilityId: string;
82
+ readonly state: 'removed';
83
+ readonly note: string;
84
+ readonly reviewedBy: string;
85
+ };
86
+ export type CapabilityLifecyclePolicy = {
87
+ readonly entries: readonly CapabilityLifecycleEntry[];
88
+ get(capabilityId: string): CapabilityLifecycleEntry | undefined;
89
+ };
90
+ export type CapabilityPackMigrationOptions = {
91
+ readonly previous: CapabilityPack;
92
+ readonly next: CapabilityPack;
93
+ readonly migrations: readonly CapabilityMigration[];
94
+ readonly previousLifecycle: CapabilityLifecyclePolicy;
95
+ readonly nextLifecycle: CapabilityLifecyclePolicy;
96
+ };
97
+ export type CapabilityPackMigrationReport = {
98
+ readonly contractChanges: readonly CapabilityContractChangeReport[];
99
+ readonly added: readonly string[];
100
+ readonly removed: readonly string[];
101
+ };
102
+ export declare class CapabilityCompositionError extends Error {
103
+ readonly kind: 'invalid-pack' | 'duplicate-identity' | 'alias-collision' | 'surface-collision';
104
+ constructor(kind: CapabilityCompositionError['kind'], message: string);
105
+ }
106
+ export declare class CapabilityMigrationError extends Error {
107
+ readonly kind: 'breaking-replacement' | 'invalid-migration' | 'missing-semantic-review' | 'implicit-removal' | 'invalid-lifecycle';
108
+ constructor(kind: CapabilityMigrationError['kind'], message: string);
109
+ }
110
+ export declare function defineCapabilityPack(options: CapabilityPackOptions): CapabilityPack;
111
+ export declare function compareCapabilityDefinitions(previous: CapabilityDefinition<unknown, unknown>, next: CapabilityDefinition<unknown, unknown>): CapabilityContractChangeReport;
112
+ export declare function defineCapabilityMigration(options: CapabilityMigrationOptions): CapabilityMigration;
113
+ export declare function assertCompatibleCapabilityReplacement(previous: CapabilityDefinition<unknown, unknown>, next: CapabilityDefinition<unknown, unknown>): CapabilityContractChangeReport;
114
+ export declare function defineCapabilityLifecyclePolicy(entries: readonly CapabilityLifecycleEntry[]): CapabilityLifecyclePolicy;
115
+ export declare function validateCapabilityPackMigration(options: CapabilityPackMigrationOptions): CapabilityPackMigrationReport;
116
+ export declare function capabilitySurfaceNames(identity: CapabilityIdentity): CapabilitySurfaceNames;
117
+ export declare function createCapabilitySurfaceMap(definitions: readonly CapabilityDefinition<unknown, unknown>[]): ReadonlyMap<string, CapabilitySurfaceNames>;
118
+ export declare function composeCapabilityPacks(imports: readonly CapabilityPackImport[]): CapabilityComposition;
119
+ //# sourceMappingURL=composition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../../src/core/composition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,545 @@
1
+ import { canonicalCapabilityId, } from './contracts.js';
2
+ const SLUG_PATTERN = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
3
+ const MCP_NAME_LIMIT = 128;
4
+ export class CapabilityCompositionError extends Error {
5
+ kind;
6
+ constructor(kind, message) {
7
+ super(message);
8
+ this.name = 'CapabilityCompositionError';
9
+ this.kind = kind;
10
+ }
11
+ }
12
+ export class CapabilityMigrationError extends Error {
13
+ kind;
14
+ constructor(kind, message) {
15
+ super(message);
16
+ this.name = 'CapabilityMigrationError';
17
+ this.kind = kind;
18
+ }
19
+ }
20
+ function assertSource(source, label) {
21
+ if (source.trim().length === 0)
22
+ throw new TypeError(`${label} must identify a source location`);
23
+ }
24
+ function packNamespace(identity) {
25
+ if (!SLUG_PATTERN.test(identity.authority) || !SLUG_PATTERN.test(identity.namespace)) {
26
+ throw new TypeError('pack authority and namespace must be lowercase capability slugs');
27
+ }
28
+ return `${identity.authority}.${identity.namespace}`;
29
+ }
30
+ function assertPackOwnership(identity, definitions, source) {
31
+ const namespace = packNamespace(identity);
32
+ for (const definition of definitions) {
33
+ if (definition.identity.namespace !== namespace) {
34
+ throw new CapabilityCompositionError('invalid-pack', `pack ${source} owns namespace ${namespace}, but ${canonicalCapabilityId(definition.identity)} uses ${definition.identity.namespace}`);
35
+ }
36
+ }
37
+ }
38
+ function verifiedLifecyclePolicy(policy) {
39
+ if (!Array.isArray(policy?.entries)) {
40
+ throw new CapabilityMigrationError('invalid-lifecycle', 'lifecycle entries must be an array');
41
+ }
42
+ return defineCapabilityLifecyclePolicy(policy.entries);
43
+ }
44
+ export function defineCapabilityPack(options) {
45
+ assertSource(options.source, 'pack source');
46
+ assertPackOwnership(options.identity, options.definitions, options.source);
47
+ const lifecycle = options.lifecycle === undefined ? undefined : verifiedLifecyclePolicy(options.lifecycle);
48
+ let reviewedMigrations = [];
49
+ let families = new Map();
50
+ for (const definition of options.definitions) {
51
+ const key = `${definition.identity.namespace}:${definition.identity.name}`;
52
+ let family = families.get(key) ?? [];
53
+ family.push(definition);
54
+ families.set(key, family);
55
+ }
56
+ for (const family of families.values()) {
57
+ if (family.length < 2)
58
+ continue;
59
+ const ordered = family.sort((left, right) => left.identity.majorVersion - right.identity.majorVersion);
60
+ for (let index = 1; index < ordered.length; index += 1) {
61
+ const previous = ordered[index - 1];
62
+ const next = ordered[index];
63
+ if (previous === undefined || next === undefined)
64
+ continue;
65
+ const fromId = canonicalCapabilityId(previous.identity);
66
+ const toId = canonicalCapabilityId(next.identity);
67
+ const migration = options.migrations?.find((entry) => entry.fromId === fromId && entry.toId === toId);
68
+ if (migration === undefined) {
69
+ throw new CapabilityMigrationError('missing-semantic-review', `pack ${options.source} requires a reviewed migration for ${fromId} -> ${toId}`);
70
+ }
71
+ const reviewed = defineCapabilityMigration({
72
+ previous,
73
+ next,
74
+ semanticReview: migration.semanticReview,
75
+ });
76
+ if (stableValue(migration.contract) !== stableValue(reviewed.contract)) {
77
+ throw new CapabilityMigrationError('invalid-migration', `migration ${fromId} -> ${toId} contains a contract report that does not match its definitions`);
78
+ }
79
+ reviewedMigrations.push(reviewed);
80
+ }
81
+ for (const definition of ordered) {
82
+ const id = canonicalCapabilityId(definition.identity);
83
+ const state = lifecycle?.get(id);
84
+ if (state === undefined || state.state === 'removed') {
85
+ throw new CapabilityMigrationError('invalid-lifecycle', `versioned pack ${options.source} requires an explicit supported or deprecated state for ${id}`);
86
+ }
87
+ }
88
+ }
89
+ if ((options.migrations?.length ?? 0) !== reviewedMigrations.length) {
90
+ throw new CapabilityMigrationError('invalid-migration', `pack ${options.source} contains an unmatched or duplicate migration record`);
91
+ }
92
+ return Object.freeze({
93
+ identity: Object.freeze({ ...options.identity }),
94
+ source: options.source.trim(),
95
+ definitions: Object.freeze([...options.definitions]),
96
+ ...(options.migrations === undefined ? {} : { migrations: Object.freeze(reviewedMigrations) }),
97
+ ...(lifecycle === undefined ? {} : { lifecycle }),
98
+ });
99
+ }
100
+ function fnv1a64(value) {
101
+ let hash = 0xcbf29ce484222325n;
102
+ for (let index = 0; index < value.length; index += 1) {
103
+ hash ^= BigInt(value.charCodeAt(index));
104
+ hash = BigInt.asUintN(64, hash * 0x100000001b3n);
105
+ }
106
+ return hash.toString(16).padStart(16, '0');
107
+ }
108
+ function lengthEncoded(identity) {
109
+ return `${identity.namespace.length}_${identity.namespace}_${identity.name.length}_${identity.name}_v${identity.majorVersion}`;
110
+ }
111
+ function readonlyMap(source) {
112
+ let view;
113
+ view = Object.freeze({
114
+ size: source.size,
115
+ get(key) {
116
+ return source.get(key);
117
+ },
118
+ has(key) {
119
+ return source.has(key);
120
+ },
121
+ entries() {
122
+ return source.entries();
123
+ },
124
+ keys() {
125
+ return source.keys();
126
+ },
127
+ values() {
128
+ return source.values();
129
+ },
130
+ forEach(callback, thisArg) {
131
+ source.forEach((value, key) => {
132
+ callback.call(thisArg, value, key, view);
133
+ });
134
+ },
135
+ [Symbol.iterator]() {
136
+ return source[Symbol.iterator]();
137
+ },
138
+ });
139
+ return view;
140
+ }
141
+ function isRecord(value) {
142
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
143
+ }
144
+ function stableValue(value) {
145
+ if (Array.isArray(value))
146
+ return `[${value.map(stableValue).join(',')}]`;
147
+ if (!isRecord(value))
148
+ return JSON.stringify(value) ?? 'undefined';
149
+ return `{${Object.keys(value)
150
+ .sort()
151
+ .map((key) => `${JSON.stringify(key)}:${stableValue(value[key])}`)
152
+ .join(',')}}`;
153
+ }
154
+ function schemaChanges(area, before, after, path = '$') {
155
+ let changes = [];
156
+ const beforeProperties = isRecord(before['properties'])
157
+ ? before['properties']
158
+ : {};
159
+ const afterProperties = isRecord(after['properties'])
160
+ ? after['properties']
161
+ : {};
162
+ const removed = Object.keys(beforeProperties).filter((key) => !(key in afterProperties));
163
+ const added = Object.keys(afterProperties).filter((key) => !(key in beforeProperties));
164
+ let pairedAdded = new Set();
165
+ let pairedRemoved = new Set();
166
+ for (const oldName of removed) {
167
+ const candidates = added.filter((newName) => !pairedAdded.has(newName) &&
168
+ stableValue(beforeProperties[oldName]) === stableValue(afterProperties[newName]));
169
+ if (candidates.length === 1) {
170
+ const newName = candidates[0];
171
+ if (newName !== undefined) {
172
+ pairedRemoved.add(oldName);
173
+ pairedAdded.add(newName);
174
+ changes.push({
175
+ area,
176
+ kind: 'property-renamed',
177
+ path: `${path}.properties.${oldName}`,
178
+ before: oldName,
179
+ after: newName,
180
+ breaking: true,
181
+ });
182
+ }
183
+ }
184
+ }
185
+ for (const name of removed) {
186
+ if (!pairedRemoved.has(name)) {
187
+ changes.push({
188
+ area,
189
+ kind: 'property-removed',
190
+ path: `${path}.properties.${name}`,
191
+ before: beforeProperties[name],
192
+ breaking: true,
193
+ });
194
+ }
195
+ }
196
+ for (const name of added) {
197
+ if (!pairedAdded.has(name)) {
198
+ changes.push({
199
+ area,
200
+ kind: 'property-added',
201
+ path: `${path}.properties.${name}`,
202
+ after: afterProperties[name],
203
+ breaking: area === 'input' ||
204
+ (area === 'output' &&
205
+ (('additionalProperties' in before && before['additionalProperties'] !== true) ||
206
+ ('unevaluatedProperties' in before && before['unevaluatedProperties'] !== true))),
207
+ });
208
+ }
209
+ }
210
+ const beforeRequired = new Set(Array.isArray(before['required'])
211
+ ? before['required'].filter((value) => typeof value === 'string')
212
+ : []);
213
+ const afterRequired = new Set(Array.isArray(after['required'])
214
+ ? after['required'].filter((value) => typeof value === 'string')
215
+ : []);
216
+ for (const name of afterRequired) {
217
+ if (!beforeRequired.has(name)) {
218
+ changes.push({
219
+ area,
220
+ kind: 'required-added',
221
+ path: `${path}.required`,
222
+ after: name,
223
+ breaking: area === 'input',
224
+ });
225
+ }
226
+ }
227
+ for (const name of beforeRequired) {
228
+ if (!afterRequired.has(name)) {
229
+ changes.push({
230
+ area,
231
+ kind: 'required-removed',
232
+ path: `${path}.required`,
233
+ before: name,
234
+ breaking: area === 'output',
235
+ });
236
+ }
237
+ }
238
+ for (const name of Object.keys(beforeProperties)) {
239
+ if (!(name in afterProperties) ||
240
+ !isRecord(beforeProperties[name]) ||
241
+ !isRecord(afterProperties[name])) {
242
+ continue;
243
+ }
244
+ changes.push(...schemaChanges(area, beforeProperties[name], afterProperties[name], `${path}.properties.${name}`));
245
+ }
246
+ const handled = new Set([
247
+ 'properties',
248
+ 'required',
249
+ 'title',
250
+ 'description',
251
+ '$schema',
252
+ ]);
253
+ for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {
254
+ if (handled.has(key) || stableValue(before[key]) === stableValue(after[key]))
255
+ continue;
256
+ changes.push({
257
+ area,
258
+ kind: 'value-changed',
259
+ path: `${path}.${key}`,
260
+ ...(key in before ? { before: before[key] } : {}),
261
+ ...(key in after ? { after: after[key] } : {}),
262
+ breaking: true,
263
+ });
264
+ }
265
+ return changes;
266
+ }
267
+ export function compareCapabilityDefinitions(previous, next) {
268
+ const fromId = canonicalCapabilityId(previous.identity);
269
+ const toId = canonicalCapabilityId(next.identity);
270
+ let changes = [
271
+ ...schemaChanges('input', previous.input.toJSONSchema(), next.input.toJSONSchema()),
272
+ ...schemaChanges('output', previous.output.toJSONSchema(), next.output.toJSONSchema()),
273
+ ];
274
+ if (previous.risk !== next.risk) {
275
+ changes.push({
276
+ area: 'risk',
277
+ kind: 'value-changed',
278
+ path: '$.risk',
279
+ before: previous.risk,
280
+ after: next.risk,
281
+ breaking: true,
282
+ });
283
+ }
284
+ if (stableValue(previous.access) !== stableValue(next.access)) {
285
+ changes.push({
286
+ area: 'access',
287
+ kind: 'value-changed',
288
+ path: '$.access',
289
+ before: previous.access,
290
+ after: next.access,
291
+ breaking: true,
292
+ });
293
+ }
294
+ if (stableValue(previous.surfaces) !== stableValue(next.surfaces)) {
295
+ changes.push({
296
+ area: 'surface',
297
+ kind: 'value-changed',
298
+ path: '$.surfaces',
299
+ ...(previous.surfaces === undefined ? {} : { before: previous.surfaces }),
300
+ ...(next.surfaces === undefined ? {} : { after: next.surfaces }),
301
+ breaking: true,
302
+ });
303
+ }
304
+ return Object.freeze({
305
+ fromId,
306
+ toId,
307
+ schemaEquivalent: changes.every((change) => change.area === 'risk' || change.area === 'access' || change.area === 'surface'),
308
+ changes: Object.freeze(changes),
309
+ breaking: changes.some((change) => change.breaking),
310
+ });
311
+ }
312
+ function assertSemanticReview(review) {
313
+ if (typeof review !== 'object' || review === null) {
314
+ throw new CapabilityMigrationError('missing-semantic-review', 'a major migration requires a substantive semantic note and named reviewer');
315
+ }
316
+ const note = typeof review.note === 'string' ? review.note.trim() : '';
317
+ const reviewedBy = typeof review.reviewedBy === 'string' ? review.reviewedBy.trim() : '';
318
+ if (note.length < 12 ||
319
+ reviewedBy.length < 3 ||
320
+ /^(?:tbd|todo|n\/?a|none|no change|same)$/i.test(note)) {
321
+ throw new CapabilityMigrationError('missing-semantic-review', 'a major migration requires a substantive semantic note and named reviewer');
322
+ }
323
+ return Object.freeze({ note, reviewedBy });
324
+ }
325
+ export function defineCapabilityMigration(options) {
326
+ const { previous, next } = options;
327
+ if (previous.identity.namespace !== next.identity.namespace ||
328
+ previous.identity.name !== next.identity.name ||
329
+ previous.identity.majorVersion >= next.identity.majorVersion) {
330
+ throw new CapabilityMigrationError('invalid-migration', 'a major migration must connect an older major to a newer major of the same namespace and name');
331
+ }
332
+ const semanticReview = assertSemanticReview(options.semanticReview);
333
+ const contract = compareCapabilityDefinitions(previous, next);
334
+ return Object.freeze({
335
+ fromId: contract.fromId,
336
+ toId: contract.toId,
337
+ semanticReview,
338
+ contract,
339
+ });
340
+ }
341
+ export function assertCompatibleCapabilityReplacement(previous, next) {
342
+ const report = compareCapabilityDefinitions(previous, next);
343
+ if (report.fromId !== report.toId) {
344
+ throw new CapabilityMigrationError('invalid-migration', 'replacement validation requires an unchanged canonical identity');
345
+ }
346
+ if (report.breaking) {
347
+ throw new CapabilityMigrationError('breaking-replacement', `breaking contract changes cannot replace ${report.fromId} without a new major identity`);
348
+ }
349
+ return report;
350
+ }
351
+ export function defineCapabilityLifecyclePolicy(entries) {
352
+ let byId = new Map();
353
+ for (const entry of entries) {
354
+ if (!isRecord(entry) ||
355
+ typeof entry.capabilityId !== 'string' ||
356
+ (entry.state !== 'supported' && entry.state !== 'deprecated' && entry.state !== 'removed')) {
357
+ throw new CapabilityMigrationError('invalid-lifecycle', 'invalid lifecycle entry');
358
+ }
359
+ if (byId.has(entry.capabilityId)) {
360
+ throw new CapabilityMigrationError('invalid-lifecycle', `duplicate lifecycle state for ${entry.capabilityId}`);
361
+ }
362
+ if (entry.state !== 'supported') {
363
+ const note = typeof entry.note === 'string' ? entry.note.trim() : '';
364
+ const reviewedBy = entry.state === 'removed' && typeof entry.reviewedBy === 'string'
365
+ ? entry.reviewedBy.trim()
366
+ : '';
367
+ if (note.length < 12 || (entry.state === 'removed' && reviewedBy.length < 3)) {
368
+ throw new CapabilityMigrationError('invalid-lifecycle', `${entry.state} lifecycle state for ${entry.capabilityId} requires an explicit note${entry.state === 'removed' ? ' and reviewer' : ''}`);
369
+ }
370
+ }
371
+ byId.set(entry.capabilityId, Object.freeze({ ...entry }));
372
+ }
373
+ const frozenEntries = Object.freeze([...byId.values()]);
374
+ return Object.freeze({
375
+ entries: frozenEntries,
376
+ get(capabilityId) {
377
+ return byId.get(capabilityId);
378
+ },
379
+ });
380
+ }
381
+ export function validateCapabilityPackMigration(options) {
382
+ if (options.previous.identity.authority !== options.next.identity.authority ||
383
+ options.previous.identity.namespace !== options.next.identity.namespace) {
384
+ throw new CapabilityMigrationError('invalid-migration', 'pack migration must compare the same authority and namespace');
385
+ }
386
+ const previousLifecycle = verifiedLifecyclePolicy(options.previousLifecycle);
387
+ const nextLifecycle = verifiedLifecyclePolicy(options.nextLifecycle);
388
+ const previous = new Map(options.previous.definitions.map((definition) => [
389
+ canonicalCapabilityId(definition.identity),
390
+ definition,
391
+ ]));
392
+ const next = new Map(options.next.definitions.map((definition) => [
393
+ canonicalCapabilityId(definition.identity),
394
+ definition,
395
+ ]));
396
+ const migrations = new Map(options.migrations.map((migration) => [
397
+ `${migration.fromId}->${migration.toId}`,
398
+ migration,
399
+ ]));
400
+ let contractChanges = [];
401
+ let added = [];
402
+ let removed = [];
403
+ for (const [id, definition] of previous) {
404
+ const priorState = previousLifecycle.get(id);
405
+ if (priorState === undefined || priorState.state === 'removed') {
406
+ throw new CapabilityMigrationError('invalid-lifecycle', `previous definition ${id} requires an explicit supported or deprecated lifecycle state`);
407
+ }
408
+ const replacement = next.get(id);
409
+ if (replacement !== undefined) {
410
+ contractChanges.push(assertCompatibleCapabilityReplacement(definition, replacement));
411
+ continue;
412
+ }
413
+ const nextState = nextLifecycle.get(id);
414
+ if (priorState?.state !== 'deprecated' || nextState?.state !== 'removed') {
415
+ throw new CapabilityMigrationError('implicit-removal', `cannot remove supported major ${id}; deprecate it in an earlier policy and record an explicit reviewed removal`);
416
+ }
417
+ removed.push(id);
418
+ }
419
+ for (const [id, definition] of next) {
420
+ const state = nextLifecycle.get(id);
421
+ if (state === undefined || state.state === 'removed') {
422
+ throw new CapabilityMigrationError('invalid-lifecycle', `current definition ${id} requires an explicit supported or deprecated lifecycle state`);
423
+ }
424
+ if (previous.has(id))
425
+ continue;
426
+ added.push(id);
427
+ const candidate = [
428
+ ...previous.entries(),
429
+ ]
430
+ .filter(([, old]) => old.identity.namespace === definition.identity.namespace &&
431
+ old.identity.name === definition.identity.name &&
432
+ old.identity.majorVersion < definition.identity.majorVersion)
433
+ .sort(([, left], [, right]) => right.identity.majorVersion - left.identity.majorVersion)[0];
434
+ if (candidate !== undefined) {
435
+ const [oldId, oldDefinition] = candidate;
436
+ const migration = migrations.get(`${oldId}->${id}`);
437
+ if (migration === undefined) {
438
+ throw new CapabilityMigrationError('missing-semantic-review', `major migration ${oldId} -> ${id} requires an explicit semantic review`);
439
+ }
440
+ const reviewed = defineCapabilityMigration({
441
+ previous: oldDefinition,
442
+ next: definition,
443
+ semanticReview: migration.semanticReview,
444
+ });
445
+ contractChanges.push(reviewed.contract);
446
+ }
447
+ }
448
+ return Object.freeze({
449
+ contractChanges: Object.freeze(contractChanges),
450
+ added: Object.freeze(added),
451
+ removed: Object.freeze(removed),
452
+ });
453
+ }
454
+ export function capabilitySurfaceNames(identity) {
455
+ const canonical = canonicalCapabilityId(identity);
456
+ const encoded = lengthEncoded(identity);
457
+ const fullMcpName = `cap_${encoded}`;
458
+ const mcp = fullMcpName.length <= MCP_NAME_LIMIT
459
+ ? fullMcpName
460
+ : `cap_${fullMcpName.slice(4, 101)}_fnv1a64_${fnv1a64(canonical)}`;
461
+ return Object.freeze({
462
+ cli: canonical,
463
+ http: `/capabilities/${encodeURIComponent(identity.namespace)}/${encodeURIComponent(identity.name)}/v${identity.majorVersion}/invoke`,
464
+ mcp,
465
+ openApiOperation: `invoke_${encoded}`,
466
+ });
467
+ }
468
+ function surfaceMap(definitions, sources) {
469
+ let result = new Map();
470
+ let owners = new Map();
471
+ for (const definition of definitions) {
472
+ const id = canonicalCapabilityId(definition.identity);
473
+ const names = capabilitySurfaceNames(definition.identity);
474
+ for (const [surface, name] of Object.entries(names)) {
475
+ const key = `${surface}:${name}`;
476
+ const previous = owners.get(key);
477
+ if (previous !== undefined && previous.id !== id) {
478
+ throw new CapabilityCompositionError('surface-collision', `${surface} name ${name} maps both ${previous.id} from ${previous.source} and ${id} from ${sources.get(id) ?? 'unknown source'}`);
479
+ }
480
+ owners.set(key, { id, source: sources.get(id) ?? 'unknown source' });
481
+ }
482
+ result.set(id, names);
483
+ }
484
+ return result;
485
+ }
486
+ export function createCapabilitySurfaceMap(definitions) {
487
+ return readonlyMap(new Map(surfaceMap(definitions, new Map())));
488
+ }
489
+ export function composeCapabilityPacks(imports) {
490
+ let definitions = [];
491
+ let byId = new Map();
492
+ let sources = new Map();
493
+ let aliases = new Map();
494
+ let aliasSources = new Map();
495
+ for (const imported of imports) {
496
+ assertSource(imported.source, 'import source');
497
+ assertPackOwnership(imported.pack.identity, imported.pack.definitions, imported.source);
498
+ defineCapabilityPack(imported.pack);
499
+ if (imported.aliasPolicy?.kind !== 'none' && imported.aliasPolicy?.kind !== 'explicit') {
500
+ throw new CapabilityCompositionError('invalid-pack', `pack import ${imported.source} must declare aliasPolicy as none or explicit`);
501
+ }
502
+ for (const definition of imported.pack.definitions) {
503
+ const id = canonicalCapabilityId(definition.identity);
504
+ const previousSource = sources.get(id);
505
+ if (previousSource !== undefined) {
506
+ throw new CapabilityCompositionError('duplicate-identity', `duplicate capability identity ${id}: ${previousSource} conflicts with ${imported.source}`);
507
+ }
508
+ sources.set(id, imported.source);
509
+ byId.set(id, definition);
510
+ definitions.push(definition);
511
+ }
512
+ }
513
+ for (const imported of imports) {
514
+ if (imported.aliasPolicy.kind === 'none')
515
+ continue;
516
+ for (const alias of imported.aliasPolicy.aliases) {
517
+ const source = alias.source?.trim() || imported.source;
518
+ if (!SLUG_PATTERN.test(alias.name)) {
519
+ throw new CapabilityCompositionError('alias-collision', `alias ${alias.name} from ${source} must be a lowercase capability slug`);
520
+ }
521
+ if (!byId.has(alias.capabilityId)) {
522
+ throw new CapabilityCompositionError('alias-collision', `alias ${alias.name} from ${source} targets missing capability ${alias.capabilityId}`);
523
+ }
524
+ const previousSource = aliasSources.get(alias.name);
525
+ if (previousSource !== undefined) {
526
+ throw new CapabilityCompositionError('alias-collision', `duplicate alias ${alias.name}: ${previousSource} conflicts with ${source}`);
527
+ }
528
+ aliases.set(alias.name, alias.capabilityId);
529
+ aliasSources.set(alias.name, source);
530
+ }
531
+ }
532
+ const names = surfaceMap(definitions, sources);
533
+ return Object.freeze({
534
+ definitions: Object.freeze(definitions),
535
+ aliases: readonlyMap(aliases),
536
+ surfaceNames: readonlyMap(new Map(names)),
537
+ resolve(name) {
538
+ return byId.get(aliases.get(name) ?? name);
539
+ },
540
+ select(identity) {
541
+ return byId.get(canonicalCapabilityId(identity));
542
+ },
543
+ });
544
+ }
545
+ //# sourceMappingURL=composition.js.map