@clowder-ai/plugin-contract 0.1.0-beta.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 (74) hide show
  1. package/dist/codegen/generate-contract.d.ts +24 -0
  2. package/dist/codegen/generate-contract.d.ts.map +1 -0
  3. package/dist/codegen/generate-contract.js +328 -0
  4. package/dist/codegen/generate-contract.js.map +1 -0
  5. package/dist/conformance/index.d.ts +13 -0
  6. package/dist/conformance/index.d.ts.map +1 -0
  7. package/dist/conformance/index.js +13 -0
  8. package/dist/conformance/index.js.map +1 -0
  9. package/dist/conformance/runner.d.ts +18 -0
  10. package/dist/conformance/runner.d.ts.map +1 -0
  11. package/dist/conformance/runner.js +252 -0
  12. package/dist/conformance/runner.js.map +1 -0
  13. package/dist/generated/contract.generated.d.ts +282 -0
  14. package/dist/generated/contract.generated.d.ts.map +1 -0
  15. package/dist/generated/contract.generated.js +37 -0
  16. package/dist/generated/contract.generated.js.map +1 -0
  17. package/dist/index.d.ts +35 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +36 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/types/capability.d.ts +4 -0
  22. package/dist/types/capability.d.ts.map +1 -0
  23. package/dist/types/capability.js +11 -0
  24. package/dist/types/capability.js.map +1 -0
  25. package/dist/types/data-class.d.ts +3 -0
  26. package/dist/types/data-class.d.ts.map +1 -0
  27. package/dist/types/data-class.js +12 -0
  28. package/dist/types/data-class.js.map +1 -0
  29. package/dist/types/index.d.ts +5 -0
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/dist/types/index.js +5 -0
  32. package/dist/types/index.js.map +1 -0
  33. package/dist/validation/index.d.ts +2 -0
  34. package/dist/validation/index.d.ts.map +1 -0
  35. package/dist/validation/index.js +2 -0
  36. package/dist/validation/index.js.map +1 -0
  37. package/dist/validation/messaging-semantic.d.ts +10 -0
  38. package/dist/validation/messaging-semantic.d.ts.map +1 -0
  39. package/dist/validation/messaging-semantic.js +99 -0
  40. package/dist/validation/messaging-semantic.js.map +1 -0
  41. package/fixtures/behavior/messaging/adversarial-invariants.json +475 -0
  42. package/fixtures/manifest/invalid/.gitkeep +0 -0
  43. package/fixtures/manifest/invalid/contract-version-leading-zero-prerelease.json +17 -0
  44. package/fixtures/manifest/invalid/contract-version-range.json +17 -0
  45. package/fixtures/manifest/invalid/ipc-empty-entrypoint.json +18 -0
  46. package/fixtures/manifest/invalid/plugin-version-leading-zero-prerelease.json +17 -0
  47. package/fixtures/manifest/invalid/plugin-version-not-semver.json +17 -0
  48. package/fixtures/manifest/invalid/semver-empty-build-metadata.json +17 -0
  49. package/fixtures/manifest/invalid/stdio-missing-entrypoint.json +17 -0
  50. package/fixtures/manifest/invalid/unknown-capability.json +19 -0
  51. package/fixtures/manifest/invalid/user-authored-lifecycle.json +24 -0
  52. package/fixtures/manifest/valid/.gitkeep +0 -0
  53. package/fixtures/manifest/valid/minimal-builtin.json +17 -0
  54. package/fixtures/manifest/valid/protocol-intrinsic-lifecycle.json +18 -0
  55. package/fixtures/manifest/valid/semver-build-metadata.json +17 -0
  56. package/fixtures/manifest/valid/stdio-entrypoint.json +18 -0
  57. package/fixtures/messaging/invalid/.gitkeep +0 -0
  58. package/fixtures/messaging/invalid/non-rfc3339-occurred-at.json +34 -0
  59. package/fixtures/messaging/invalid/non-utc-occurred-at.json +34 -0
  60. package/fixtures/messaging/invalid/raw-message-id-append.json +16 -0
  61. package/fixtures/messaging/invalid/raw-thread-id.json +28 -0
  62. package/fixtures/messaging/invalid/stale-read-with-ack-token.json +8 -0
  63. package/fixtures/messaging/invalid/system-draft-audience.json +31 -0
  64. package/fixtures/messaging/invalid/text-payload-missing-text.json +10 -0
  65. package/fixtures/messaging/invalid/untyped-root-document.json +3 -0
  66. package/fixtures/messaging/valid/.gitkeep +0 -0
  67. package/fixtures/messaging/valid/append-elements-with-handle.json +21 -0
  68. package/fixtures/messaging/valid/message-draft.json +28 -0
  69. package/fixtures/messaging/valid/root-message-draft.json +25 -0
  70. package/fixtures/messaging/valid/subscription-delivery.json +45 -0
  71. package/package.json +59 -0
  72. package/src/schemas/behavior-fixture.schema.json +370 -0
  73. package/src/schemas/manifest.schema.json +186 -0
  74. package/src/schemas/messaging.schema.json +473 -0
@@ -0,0 +1,370 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://clowder-ai.dev/schemas/behavior-fixture/v0.1",
4
+ "title": "Clowder AI Contract Behavior Fixture",
5
+ "type": "object",
6
+ "properties": {
7
+ "_meta": { "$ref": "#/$defs/FixtureMetadata" },
8
+ "cases": {
9
+ "type": "array",
10
+ "items": { "$ref": "#/$defs/BehaviorCase" },
11
+ "minItems": 1
12
+ }
13
+ },
14
+ "required": ["_meta", "cases"],
15
+ "additionalProperties": false,
16
+ "$defs": {
17
+ "FixtureMetadata": {
18
+ "type": "object",
19
+ "properties": {
20
+ "executor": { "const": "loopback" },
21
+ "domain": { "const": "messaging" },
22
+ "contractVersion": {
23
+ "type": "string",
24
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?$"
25
+ },
26
+ "source": { "type": "string", "minLength": 1 },
27
+ "description": { "type": "string", "minLength": 1 }
28
+ },
29
+ "required": ["executor", "domain", "contractVersion", "source", "description"],
30
+ "additionalProperties": false
31
+ },
32
+ "FixtureCaller": {
33
+ "type": "object",
34
+ "properties": {
35
+ "pluginInstanceId": { "type": "string", "minLength": 1 }
36
+ },
37
+ "required": ["pluginInstanceId"],
38
+ "additionalProperties": false
39
+ },
40
+ "FixtureHandle": {
41
+ "type": "object",
42
+ "properties": {
43
+ "kind": {
44
+ "type": "string",
45
+ "enum": ["thread_handle", "connector_binding", "message_handle", "subscription"]
46
+ },
47
+ "token": { "type": "string", "minLength": 1 },
48
+ "ownerPluginInstanceId": { "type": "string", "minLength": 1 },
49
+ "threadId": { "type": "string", "minLength": 1 },
50
+ "messageId": { "type": "string", "minLength": 1 },
51
+ "connectorId": { "type": "string", "minLength": 1 },
52
+ "subscriptionId": { "type": "string", "minLength": 1 }
53
+ },
54
+ "required": ["kind", "token", "ownerPluginInstanceId"],
55
+ "additionalProperties": false
56
+ },
57
+ "FixtureSetup": {
58
+ "type": "object",
59
+ "properties": {
60
+ "caller": { "$ref": "#/$defs/FixtureCaller" },
61
+ "grants": {
62
+ "type": "array",
63
+ "items": { "$ref": "#/$defs/CapabilityName" },
64
+ "uniqueItems": true
65
+ },
66
+ "handles": {
67
+ "type": "object",
68
+ "additionalProperties": { "$ref": "#/$defs/FixtureHandle" }
69
+ },
70
+ "state": {
71
+ "type": "object",
72
+ "additionalProperties": true
73
+ }
74
+ },
75
+ "required": ["caller", "grants", "handles", "state"],
76
+ "additionalProperties": false
77
+ },
78
+ "FixtureOperation": {
79
+ "oneOf": [
80
+ {
81
+ "type": "object",
82
+ "properties": {
83
+ "operation": { "const": "send" },
84
+ "input": { "$ref": "#/$defs/SendOperationInput" }
85
+ },
86
+ "required": ["operation", "input"],
87
+ "additionalProperties": false
88
+ },
89
+ {
90
+ "type": "object",
91
+ "properties": {
92
+ "operation": { "const": "appendElements" },
93
+ "input": { "$ref": "#/$defs/AppendOperationInput" }
94
+ },
95
+ "required": ["operation", "input"],
96
+ "additionalProperties": false
97
+ },
98
+ {
99
+ "type": "object",
100
+ "properties": {
101
+ "operation": { "const": "subscribe" },
102
+ "input": { "$ref": "#/$defs/SubscribeOperationInput" }
103
+ },
104
+ "required": ["operation", "input"],
105
+ "additionalProperties": false
106
+ },
107
+ {
108
+ "type": "object",
109
+ "properties": {
110
+ "operation": { "const": "read" },
111
+ "input": { "$ref": "#/$defs/ReadOperationInput" }
112
+ },
113
+ "required": ["operation", "input"],
114
+ "additionalProperties": false
115
+ },
116
+ {
117
+ "type": "object",
118
+ "properties": {
119
+ "operation": { "const": "ack" },
120
+ "input": { "$ref": "#/$defs/AckOperationInput" }
121
+ },
122
+ "required": ["operation", "input"],
123
+ "additionalProperties": false
124
+ },
125
+ {
126
+ "type": "object",
127
+ "properties": {
128
+ "operation": { "const": "snapshot" },
129
+ "input": { "$ref": "#/$defs/SnapshotOperationInput" }
130
+ },
131
+ "required": ["operation", "input"],
132
+ "additionalProperties": false
133
+ },
134
+ {
135
+ "type": "object",
136
+ "properties": {
137
+ "operation": { "const": "applyGrantPreset" },
138
+ "input": { "$ref": "#/$defs/GrantPresetInput" }
139
+ },
140
+ "required": ["operation", "input"],
141
+ "additionalProperties": false
142
+ },
143
+ {
144
+ "type": "object",
145
+ "properties": {
146
+ "operation": { "const": "revokeGrant" },
147
+ "input": { "$ref": "#/$defs/RevokeGrantInput" }
148
+ },
149
+ "required": ["operation", "input"],
150
+ "additionalProperties": false
151
+ },
152
+ {
153
+ "type": "object",
154
+ "properties": {
155
+ "operation": { "const": "deliverOnMessage" },
156
+ "input": { "$ref": "#/$defs/OnMessageDeliveryInput" }
157
+ },
158
+ "required": ["operation", "input"],
159
+ "additionalProperties": false
160
+ },
161
+ {
162
+ "type": "object",
163
+ "properties": {
164
+ "operation": { "const": "checkPermissionMatrix" },
165
+ "input": { "$ref": "#/$defs/PermissionMatrixInput" }
166
+ },
167
+ "required": ["operation", "input"],
168
+ "additionalProperties": false
169
+ },
170
+ {
171
+ "type": "object",
172
+ "properties": {
173
+ "operation": { "const": "deleteReplayEvents" },
174
+ "input": { "$ref": "#/$defs/DeleteReplayEventsInput" }
175
+ },
176
+ "required": ["operation", "input"],
177
+ "additionalProperties": false
178
+ }
179
+ ]
180
+ },
181
+ "SendOperationInput": {
182
+ "type": "object",
183
+ "properties": {
184
+ "address": { "type": "object" },
185
+ "idempotencyKey": { "type": "string", "minLength": 1 },
186
+ "payload": { "type": "object" }
187
+ },
188
+ "required": ["address", "idempotencyKey", "payload"],
189
+ "additionalProperties": true
190
+ },
191
+ "AppendOperationInput": {
192
+ "type": "object",
193
+ "properties": {
194
+ "handle": { "type": "object" },
195
+ "operationId": { "type": "string", "minLength": 1 },
196
+ "elements": { "type": "array", "minItems": 1 }
197
+ },
198
+ "required": ["handle", "operationId", "elements"],
199
+ "additionalProperties": true
200
+ },
201
+ "SubscribeOperationInput": {
202
+ "type": "object",
203
+ "properties": {
204
+ "handleId": { "type": "string", "minLength": 1 }
205
+ },
206
+ "required": ["handleId"],
207
+ "additionalProperties": false
208
+ },
209
+ "ReadOperationInput": {
210
+ "type": "object",
211
+ "properties": {
212
+ "subscriptionId": { "type": "string", "minLength": 1 },
213
+ "limit": { "type": "integer", "minimum": 1, "maximum": 32 }
214
+ },
215
+ "required": ["subscriptionId"],
216
+ "additionalProperties": false
217
+ },
218
+ "AckOperationInput": {
219
+ "type": "object",
220
+ "properties": {
221
+ "subscriptionId": { "type": "string", "minLength": 1 },
222
+ "ackToken": { "type": "string", "minLength": 1 }
223
+ },
224
+ "required": ["subscriptionId", "ackToken"],
225
+ "additionalProperties": false
226
+ },
227
+ "SnapshotOperationInput": {
228
+ "type": "object",
229
+ "properties": {
230
+ "subscriptionId": { "type": "string", "minLength": 1 }
231
+ },
232
+ "required": ["subscriptionId"],
233
+ "additionalProperties": false
234
+ },
235
+ "CapabilityName": {
236
+ "$ref": "https://clowder-ai.dev/schemas/manifest/v0.1#/$defs/Capability"
237
+ },
238
+ "GrantPresetInput": {
239
+ "type": "object",
240
+ "properties": {
241
+ "presetKind": { "const": "first_party" },
242
+ "capabilities": {
243
+ "type": "array",
244
+ "items": { "$ref": "#/$defs/CapabilityName" },
245
+ "minItems": 1,
246
+ "uniqueItems": true
247
+ }
248
+ },
249
+ "required": ["presetKind", "capabilities"],
250
+ "additionalProperties": false
251
+ },
252
+ "RevokeGrantInput": {
253
+ "type": "object",
254
+ "properties": {
255
+ "capability": { "$ref": "#/$defs/CapabilityName" }
256
+ },
257
+ "required": ["capability"],
258
+ "additionalProperties": false
259
+ },
260
+ "OnMessageDeliveryInput": {
261
+ "type": "object",
262
+ "properties": {
263
+ "threadHandle": { "type": "string", "minLength": 1 },
264
+ "envelope": { "type": "object" }
265
+ },
266
+ "required": ["threadHandle", "envelope"],
267
+ "additionalProperties": false
268
+ },
269
+ "PermissionMatrixEntry": {
270
+ "type": "object",
271
+ "properties": {
272
+ "capability": { "$ref": "#/$defs/CapabilityName" },
273
+ "layer": { "type": "string", "enum": ["L0", "L1", "L2"] },
274
+ "firstPartyPreset": { "type": "boolean" }
275
+ },
276
+ "required": ["capability", "layer", "firstPartyPreset"],
277
+ "additionalProperties": false
278
+ },
279
+ "PermissionMatrixInput": {
280
+ "type": "object",
281
+ "properties": {
282
+ "entries": {
283
+ "type": "array",
284
+ "items": { "$ref": "#/$defs/PermissionMatrixEntry" },
285
+ "minItems": 17,
286
+ "maxItems": 17
287
+ }
288
+ },
289
+ "required": ["entries"],
290
+ "additionalProperties": false
291
+ },
292
+ "DeleteReplayEventsInput": {
293
+ "type": "object",
294
+ "properties": {
295
+ "subscriptionId": { "type": "string", "minLength": 1 },
296
+ "throughSequence": { "type": "integer", "minimum": 0 }
297
+ },
298
+ "required": ["subscriptionId", "throughSequence"],
299
+ "additionalProperties": false
300
+ },
301
+ "MessagingErrorCode": {
302
+ "type": "string",
303
+ "enum": ["VALIDATION", "PERMISSION", "NOT_FOUND", "CONFLICT", "RETRYABLE_INFLIGHT", "STALE_CURSOR"]
304
+ },
305
+ "SideEffectAssertion": {
306
+ "type": "object",
307
+ "properties": {
308
+ "target": {
309
+ "type": "string",
310
+ "enum": ["messages", "output_events", "idempotency_ledger", "subscription", "snapshot", "reply_preview", "provenance", "grant_state", "permission_matrix", "replay_events"]
311
+ },
312
+ "assertion": {
313
+ "type": "string",
314
+ "enum": ["unchanged", "none", "state_equals", "round_trip", "matches"]
315
+ },
316
+ "value": true
317
+ },
318
+ "required": ["target", "assertion"],
319
+ "additionalProperties": false,
320
+ "allOf": [
321
+ {
322
+ "if": {
323
+ "properties": {
324
+ "assertion": { "enum": ["state_equals", "round_trip", "matches"] }
325
+ },
326
+ "required": ["assertion"]
327
+ },
328
+ "then": { "required": ["value"] },
329
+ "else": { "not": { "required": ["value"] } }
330
+ }
331
+ ]
332
+ },
333
+ "ExpectedVerdict": {
334
+ "type": "object",
335
+ "properties": {
336
+ "status": { "type": "string", "enum": ["success", "error"] },
337
+ "errorCode": { "$ref": "#/$defs/MessagingErrorCode" },
338
+ "sideEffects": {
339
+ "type": "array",
340
+ "items": { "$ref": "#/$defs/SideEffectAssertion" },
341
+ "minItems": 1
342
+ }
343
+ },
344
+ "required": ["status", "sideEffects"],
345
+ "additionalProperties": false,
346
+ "allOf": [
347
+ {
348
+ "if": {
349
+ "properties": { "status": { "const": "error" } },
350
+ "required": ["status"]
351
+ },
352
+ "then": { "required": ["errorCode"] },
353
+ "else": { "not": { "required": ["errorCode"] } }
354
+ }
355
+ ]
356
+ },
357
+ "BehaviorCase": {
358
+ "type": "object",
359
+ "properties": {
360
+ "id": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
361
+ "invariant": { "type": "string", "minLength": 1 },
362
+ "given": { "$ref": "#/$defs/FixtureSetup" },
363
+ "when": { "$ref": "#/$defs/FixtureOperation" },
364
+ "expect": { "$ref": "#/$defs/ExpectedVerdict" }
365
+ },
366
+ "required": ["id", "invariant", "given", "when", "expect"],
367
+ "additionalProperties": false
368
+ }
369
+ }
370
+ }
@@ -0,0 +1,186 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://clowder-ai.dev/schemas/manifest/v0.1",
4
+ "title": "Clowder AI Plugin Manifest (v0.1)",
5
+ "description": "Machine-readable truth source for plugin manifest (§3.4/§3.5). v0.1 covers core manifest + features + data classification. Signals/events (C-2) and schedule/state (C-3) are schema deltas in future contract versions.",
6
+ "x-clowder-capability-layers": {
7
+ "L0": ["plugin.config.read", "plugin.state.get", "plugin.state.set"],
8
+ "L1": ["messaging.send", "schedule.register", "events.publish", "messaging.appendElements"],
9
+ "L2": ["onMessage", "message.event.subscribe", "secret.read", "thread.listMetadata", "thread.readContent", "memory.query", "memory.append", "memory.retrieve", "windows.create", "whisper.extend"]
10
+ },
11
+ "x-clowder-data-class-strategies": {
12
+ "cache": ["lifecycle", "retained", "ask-on-uninstall"],
13
+ "ephemeral": ["lifecycle", "retained", "ask-on-uninstall"],
14
+ "user-authored": ["retained", "ask-on-uninstall"],
15
+ "derived-user-visible": ["retained", "ask-on-uninstall"],
16
+ "relationship": ["retained", "ask-on-uninstall"],
17
+ "interaction-history": ["retained", "ask-on-uninstall"]
18
+ },
19
+
20
+ "$defs": {
21
+ "SemVer": {
22
+ "type": "string",
23
+ "minLength": 1,
24
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$",
25
+ "description": "SemVer 2.0.0 including optional prerelease and build metadata."
26
+ },
27
+
28
+ "DataClass": {
29
+ "type": "string",
30
+ "enum": ["cache", "ephemeral", "user-authored", "derived-user-visible", "relationship", "interaction-history"]
31
+ },
32
+
33
+ "DataStrategy": {
34
+ "type": "string",
35
+ "enum": ["lifecycle", "retained", "ask-on-uninstall"]
36
+ },
37
+
38
+ "Capability": {
39
+ "type": "string",
40
+ "enum": [
41
+ "plugin.config.read",
42
+ "plugin.state.get",
43
+ "plugin.state.set",
44
+ "messaging.send",
45
+ "schedule.register",
46
+ "events.publish",
47
+ "messaging.appendElements",
48
+ "onMessage",
49
+ "message.event.subscribe",
50
+ "secret.read",
51
+ "thread.listMetadata",
52
+ "thread.readContent",
53
+ "memory.query",
54
+ "memory.append",
55
+ "memory.retrieve",
56
+ "windows.create",
57
+ "whisper.extend"
58
+ ]
59
+ },
60
+
61
+ "DataDeclaration": {
62
+ "type": "object",
63
+ "properties": {
64
+ "name": { "type": "string", "minLength": 1 },
65
+ "dataClass": { "$ref": "#/$defs/DataClass" },
66
+ "strategy": { "$ref": "#/$defs/DataStrategy" },
67
+ "schemaVersion": { "type": "string" }
68
+ },
69
+ "required": ["name", "dataClass", "strategy"],
70
+ "additionalProperties": false,
71
+ "allOf": [
72
+ {
73
+ "if": {
74
+ "properties": {
75
+ "dataClass": {
76
+ "enum": ["user-authored", "derived-user-visible", "relationship", "interaction-history"]
77
+ }
78
+ },
79
+ "required": ["dataClass"]
80
+ },
81
+ "then": {
82
+ "properties": {
83
+ "strategy": {
84
+ "enum": ["retained", "ask-on-uninstall"],
85
+ "description": "User-visible/relationship data MUST be retained or ask-on-uninstall. lifecycle is structurally forbidden (铁律 #5: user state defaults to persistent)."
86
+ }
87
+ }
88
+ }
89
+ }
90
+ ]
91
+ },
92
+
93
+ "ResourceReference": {
94
+ "type": "object",
95
+ "properties": {
96
+ "type": { "type": "string", "minLength": 1 },
97
+ "id": { "type": "string", "minLength": 1 }
98
+ },
99
+ "required": ["type", "id"],
100
+ "additionalProperties": false
101
+ },
102
+
103
+ "PluginFeature": {
104
+ "type": "object",
105
+ "properties": {
106
+ "id": { "type": "string", "minLength": 1 },
107
+ "name": { "type": "string", "minLength": 1 },
108
+ "resources": {
109
+ "type": "array",
110
+ "items": { "$ref": "#/$defs/ResourceReference" }
111
+ },
112
+ "capabilities": {
113
+ "type": "array",
114
+ "items": { "$ref": "#/$defs/Capability" },
115
+ "description": "@signed(G-0 2026-07-15) — capability vocabulary is contract-versioned (P15). Adding a new capability = new contract version. Unknown strings are structurally rejected at schema level; authorization is a separate host runtime layer. Lifecycle callbacks are protocol-intrinsic baseline behavior, so they are not grantable or revocable capability IDs."
116
+ }
117
+ },
118
+ "required": ["id", "name", "resources", "capabilities"],
119
+ "additionalProperties": false
120
+ },
121
+
122
+ "RuntimeTransport": {
123
+ "type": "string",
124
+ "enum": ["stdio", "ipc", "builtin"]
125
+ },
126
+
127
+ "ExternalRuntimeTransport": {
128
+ "type": "string",
129
+ "enum": ["stdio", "ipc"]
130
+ },
131
+
132
+ "ExternalRuntimeDeclaration": {
133
+ "type": "object",
134
+ "properties": {
135
+ "transport": { "$ref": "#/$defs/ExternalRuntimeTransport" },
136
+ "entrypoint": { "type": "string", "minLength": 1 }
137
+ },
138
+ "required": ["transport", "entrypoint"],
139
+ "additionalProperties": false
140
+ },
141
+
142
+ "BuiltinRuntimeDeclaration": {
143
+ "type": "object",
144
+ "properties": {
145
+ "transport": { "const": "builtin" },
146
+ "entrypoint": { "type": "string", "minLength": 1 }
147
+ },
148
+ "required": ["transport"],
149
+ "additionalProperties": false
150
+ },
151
+
152
+ "RuntimeDeclaration": {
153
+ "oneOf": [
154
+ { "$ref": "#/$defs/ExternalRuntimeDeclaration" },
155
+ { "$ref": "#/$defs/BuiltinRuntimeDeclaration" }
156
+ ]
157
+ }
158
+ },
159
+
160
+ "type": "object",
161
+ "properties": {
162
+ "pluginId": { "type": "string", "minLength": 1 },
163
+ "version": {
164
+ "$ref": "#/$defs/SemVer",
165
+ "description": "Plugin version — must be valid semver (§9: numeric prerelease identifiers MUST NOT have leading zeroes)."
166
+ },
167
+ "contractVersion": {
168
+ "$ref": "#/$defs/SemVer",
169
+ "description": "Must be an exact published semver version — no ranges, wildcards, or operator prefixes (five-step freeze: pin exact version). §9: numeric prerelease identifiers MUST NOT have leading zeroes."
170
+ },
171
+ "name": { "type": "string", "minLength": 1 },
172
+ "description": { "type": "string" },
173
+ "features": {
174
+ "type": "array",
175
+ "items": { "$ref": "#/$defs/PluginFeature" },
176
+ "minItems": 1
177
+ },
178
+ "data": {
179
+ "type": "array",
180
+ "items": { "$ref": "#/$defs/DataDeclaration" }
181
+ },
182
+ "runtime": { "$ref": "#/$defs/RuntimeDeclaration" }
183
+ },
184
+ "required": ["pluginId", "version", "contractVersion", "name", "features", "runtime"],
185
+ "additionalProperties": false
186
+ }