@clowder-ai/plugin-contract 0.1.0-beta.1 → 0.1.0-beta.10

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 (157) hide show
  1. package/dist/codegen/generate-contract.d.ts +5 -0
  2. package/dist/codegen/generate-contract.d.ts.map +1 -1
  3. package/dist/codegen/generate-contract.js +45 -4
  4. package/dist/codegen/generate-contract.js.map +1 -1
  5. package/dist/conformance/behavior-executor.d.ts +18 -0
  6. package/dist/conformance/behavior-executor.d.ts.map +1 -0
  7. package/dist/conformance/behavior-executor.js +52 -0
  8. package/dist/conformance/behavior-executor.js.map +1 -0
  9. package/dist/conformance/fixtures.d.ts +9 -0
  10. package/dist/conformance/fixtures.d.ts.map +1 -0
  11. package/dist/conformance/fixtures.js +8 -0
  12. package/dist/conformance/fixtures.js.map +1 -0
  13. package/dist/conformance/index.d.ts +5 -0
  14. package/dist/conformance/index.d.ts.map +1 -1
  15. package/dist/conformance/index.js +4 -0
  16. package/dist/conformance/index.js.map +1 -1
  17. package/dist/conformance/messaging-loopback-adapter.d.ts +23 -0
  18. package/dist/conformance/messaging-loopback-adapter.d.ts.map +1 -0
  19. package/dist/conformance/messaging-loopback-adapter.js +389 -0
  20. package/dist/conformance/messaging-loopback-adapter.js.map +1 -0
  21. package/dist/conformance/messaging-loopback-state.d.ts +22 -0
  22. package/dist/conformance/messaging-loopback-state.d.ts.map +1 -0
  23. package/dist/conformance/messaging-loopback-state.js +101 -0
  24. package/dist/conformance/messaging-loopback-state.js.map +1 -0
  25. package/dist/conformance/runner.d.ts +18 -1
  26. package/dist/conformance/runner.d.ts.map +1 -1
  27. package/dist/conformance/runner.js +153 -66
  28. package/dist/conformance/runner.js.map +1 -1
  29. package/dist/conformance/stdio-harness/child-process-harness.d.ts +65 -0
  30. package/dist/conformance/stdio-harness/child-process-harness.d.ts.map +1 -0
  31. package/dist/conformance/stdio-harness/child-process-harness.js +296 -0
  32. package/dist/conformance/stdio-harness/child-process-harness.js.map +1 -0
  33. package/dist/conformance/stdio-harness/dual-transport-oracle.d.ts +26 -0
  34. package/dist/conformance/stdio-harness/dual-transport-oracle.d.ts.map +1 -0
  35. package/dist/conformance/stdio-harness/dual-transport-oracle.js +32 -0
  36. package/dist/conformance/stdio-harness/dual-transport-oracle.js.map +1 -0
  37. package/dist/conformance/stdio-harness/harness-process-spawn.d.ts +27 -0
  38. package/dist/conformance/stdio-harness/harness-process-spawn.d.ts.map +1 -0
  39. package/dist/conformance/stdio-harness/harness-process-spawn.js +43 -0
  40. package/dist/conformance/stdio-harness/harness-process-spawn.js.map +1 -0
  41. package/dist/conformance/stdio-harness/index.d.ts +5 -0
  42. package/dist/conformance/stdio-harness/index.d.ts.map +1 -0
  43. package/dist/conformance/stdio-harness/index.js +4 -0
  44. package/dist/conformance/stdio-harness/index.js.map +1 -0
  45. package/dist/conformance/stdio-harness/ndjson-frame.d.ts +31 -0
  46. package/dist/conformance/stdio-harness/ndjson-frame.d.ts.map +1 -0
  47. package/dist/conformance/stdio-harness/ndjson-frame.js +125 -0
  48. package/dist/conformance/stdio-harness/ndjson-frame.js.map +1 -0
  49. package/dist/conformance/stdio-harness/node-process-tree-runtime.d.ts +15 -0
  50. package/dist/conformance/stdio-harness/node-process-tree-runtime.d.ts.map +1 -0
  51. package/dist/conformance/stdio-harness/node-process-tree-runtime.js +78 -0
  52. package/dist/conformance/stdio-harness/node-process-tree-runtime.js.map +1 -0
  53. package/dist/conformance/stdio-harness/process-tree-controller.d.ts +51 -0
  54. package/dist/conformance/stdio-harness/process-tree-controller.d.ts.map +1 -0
  55. package/dist/conformance/stdio-harness/process-tree-controller.js +162 -0
  56. package/dist/conformance/stdio-harness/process-tree-controller.js.map +1 -0
  57. package/dist/conformance/stdio-harness/windows-sentinel.d.ts +15 -0
  58. package/dist/conformance/stdio-harness/windows-sentinel.d.ts.map +1 -0
  59. package/dist/conformance/stdio-harness/windows-sentinel.js +160 -0
  60. package/dist/conformance/stdio-harness/windows-sentinel.js.map +1 -0
  61. package/dist/conformance/stdio-harness/wire-shape.d.ts +18 -0
  62. package/dist/conformance/stdio-harness/wire-shape.d.ts.map +1 -0
  63. package/dist/conformance/stdio-harness/wire-shape.js +2 -0
  64. package/dist/conformance/stdio-harness/wire-shape.js.map +1 -0
  65. package/dist/generated/contract.generated.d.ts +305 -1
  66. package/dist/generated/contract.generated.d.ts.map +1 -1
  67. package/dist/generated/contract.generated.js +1 -1
  68. package/dist/generated/contract.generated.js.map +1 -1
  69. package/dist/index.d.ts +3 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +5 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/validation/index.d.ts +2 -0
  74. package/dist/validation/index.d.ts.map +1 -1
  75. package/dist/validation/index.js +2 -0
  76. package/dist/validation/index.js.map +1 -1
  77. package/dist/validation/manifest.d.ts +23 -0
  78. package/dist/validation/manifest.d.ts.map +1 -0
  79. package/dist/validation/manifest.js +53 -0
  80. package/dist/validation/manifest.js.map +1 -0
  81. package/dist/validation/signals.d.ts +26 -0
  82. package/dist/validation/signals.d.ts.map +1 -0
  83. package/dist/validation/signals.js +206 -0
  84. package/dist/validation/signals.js.map +1 -0
  85. package/dist/wire/constants.d.ts +36 -0
  86. package/dist/wire/constants.d.ts.map +1 -0
  87. package/dist/wire/constants.js +36 -0
  88. package/dist/wire/constants.js.map +1 -0
  89. package/dist/wire/disposition-fixtures.d.ts +110 -0
  90. package/dist/wire/disposition-fixtures.d.ts.map +1 -0
  91. package/dist/wire/disposition-fixtures.js +1462 -0
  92. package/dist/wire/disposition-fixtures.js.map +1 -0
  93. package/dist/wire/disposition.d.ts +102 -0
  94. package/dist/wire/disposition.d.ts.map +1 -0
  95. package/dist/wire/disposition.js +217 -0
  96. package/dist/wire/disposition.js.map +1 -0
  97. package/dist/wire/envelope.d.ts +253 -0
  98. package/dist/wire/envelope.d.ts.map +1 -0
  99. package/dist/wire/envelope.js +19 -0
  100. package/dist/wire/envelope.js.map +1 -0
  101. package/dist/wire/errors.d.ts +222 -0
  102. package/dist/wire/errors.d.ts.map +1 -0
  103. package/dist/wire/errors.js +153 -0
  104. package/dist/wire/errors.js.map +1 -0
  105. package/dist/wire/grants.d.ts +57 -0
  106. package/dist/wire/grants.d.ts.map +1 -0
  107. package/dist/wire/grants.js +59 -0
  108. package/dist/wire/grants.js.map +1 -0
  109. package/dist/wire/handshake-byte-bounds.d.ts +69 -0
  110. package/dist/wire/handshake-byte-bounds.d.ts.map +1 -0
  111. package/dist/wire/handshake-byte-bounds.js +173 -0
  112. package/dist/wire/handshake-byte-bounds.js.map +1 -0
  113. package/dist/wire/handshake.d.ts +146 -0
  114. package/dist/wire/handshake.d.ts.map +1 -0
  115. package/dist/wire/handshake.js +189 -0
  116. package/dist/wire/handshake.js.map +1 -0
  117. package/dist/wire/index.d.ts +35 -0
  118. package/dist/wire/index.d.ts.map +1 -0
  119. package/dist/wire/index.js +53 -0
  120. package/dist/wire/index.js.map +1 -0
  121. package/dist/wire/lifecycle-byte-bounds.d.ts +55 -0
  122. package/dist/wire/lifecycle-byte-bounds.d.ts.map +1 -0
  123. package/dist/wire/lifecycle-byte-bounds.js +209 -0
  124. package/dist/wire/lifecycle-byte-bounds.js.map +1 -0
  125. package/dist/wire/registry.d.ts +283 -0
  126. package/dist/wire/registry.d.ts.map +1 -0
  127. package/dist/wire/registry.js +258 -0
  128. package/dist/wire/registry.js.map +1 -0
  129. package/dist/wire/request-id.d.ts +34 -0
  130. package/dist/wire/request-id.d.ts.map +1 -0
  131. package/dist/wire/request-id.js +40 -0
  132. package/dist/wire/request-id.js.map +1 -0
  133. package/dist/wire/row-shapes.d.ts +212 -0
  134. package/dist/wire/row-shapes.d.ts.map +1 -0
  135. package/dist/wire/row-shapes.js +59 -0
  136. package/dist/wire/row-shapes.js.map +1 -0
  137. package/dist/wire/signal-byte-bounds.d.ts +97 -0
  138. package/dist/wire/signal-byte-bounds.d.ts.map +1 -0
  139. package/dist/wire/signal-byte-bounds.js +229 -0
  140. package/dist/wire/signal-byte-bounds.js.map +1 -0
  141. package/dist/wire/wire-uint53.d.ts +26 -0
  142. package/dist/wire/wire-uint53.d.ts.map +1 -0
  143. package/dist/wire/wire-uint53.js +32 -0
  144. package/dist/wire/wire-uint53.js.map +1 -0
  145. package/fixtures/behavior/messaging/adversarial-invariants.json +56 -5
  146. package/fixtures/manifest/invalid/duplicate-signal-type.json +33 -0
  147. package/fixtures/signals/invalid/destination-injection.json +15 -0
  148. package/fixtures/signals/invalid/dynamic-schema-url.json +10 -0
  149. package/fixtures/signals/invalid/forbidden-raw-privacy.json +10 -0
  150. package/fixtures/signals/invalid/non-utc-occurred-at.json +12 -0
  151. package/fixtures/signals/valid/feishu-meeting-artifact.json +18 -0
  152. package/fixtures/signals/valid/remote-service-declaration.json +10 -0
  153. package/package.json +13 -5
  154. package/src/schemas/manifest.schema.json +5 -2
  155. package/src/schemas/messaging.schema.json +1 -0
  156. package/src/schemas/physical-limb.schema.json +319 -0
  157. package/src/schemas/signal.schema.json +129 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clowder-ai/plugin-contract",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.10",
4
4
  "private": false,
5
5
  "description": "Clowder AI plugin contract — the single machine-readable truth source for plugin schema, types, capability table, and conformance fixtures (P15)",
6
6
  "license": "MIT",
@@ -10,8 +10,14 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js"
12
12
  },
13
+ "./conformance": {
14
+ "types": "./dist/conformance/index.d.ts",
15
+ "import": "./dist/conformance/index.js"
16
+ },
13
17
  "./schemas/messaging": "./src/schemas/messaging.schema.json",
14
18
  "./schemas/manifest": "./src/schemas/manifest.schema.json",
19
+ "./schemas/signals": "./src/schemas/signal.schema.json",
20
+ "./schemas/physical-limb": "./src/schemas/physical-limb.schema.json",
15
21
  "./schemas/behavior-fixture": "./src/schemas/behavior-fixture.schema.json"
16
22
  },
17
23
  "main": "./dist/index.js",
@@ -27,9 +33,9 @@
27
33
  "scripts": {
28
34
  "generate": "node --import tsx src/codegen/generate-contract.ts",
29
35
  "generate:check": "node --import tsx src/codegen/generate-contract.ts --check",
30
- "build": "pnpm clean && tsc -p tsconfig.build.json",
36
+ "build": "pnpm clean && tsc -p tsconfig.build.json && node --test scripts/conformance-public-boundary.test.mjs",
31
37
  "typecheck": "tsc --noEmit",
32
- "test": "node --import tsx --test src/**/*.test.ts",
38
+ "test": "node --import tsx --test src/**/*.test.ts src/**/**/*.test.ts",
33
39
  "conformance": "node --import tsx src/conformance/runner.ts",
34
40
  "lint": "tsc --noEmit",
35
41
  "clean": "rm -rf dist",
@@ -37,11 +43,13 @@
37
43
  },
38
44
  "devDependencies": {
39
45
  "@types/node": "^20.17.0",
40
- "ajv": "^8.17.0",
41
- "ajv-formats": "^3.0.0",
42
46
  "tsx": "^4.19.0",
43
47
  "typescript": "^5.7.0"
44
48
  },
49
+ "dependencies": {
50
+ "ajv": "^8.17.0",
51
+ "ajv-formats": "^3.0.0"
52
+ },
45
53
  "publishConfig": {
46
54
  "access": "public"
47
55
  },
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://clowder-ai.dev/schemas/manifest/v0.1",
4
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.",
5
+ "description": "Machine-readable truth source for plugin manifest (§3.4/§3.5). beta.9 adds the C-2 declared-signal contribution while schedule/state (C-3) remain future contract deltas.",
6
6
  "x-clowder-capability-layers": {
7
7
  "L0": ["plugin.config.read", "plugin.state.get", "plugin.state.set"],
8
8
  "L1": ["messaging.send", "schedule.register", "events.publish", "messaging.appendElements"],
@@ -179,7 +179,10 @@
179
179
  "type": "array",
180
180
  "items": { "$ref": "#/$defs/DataDeclaration" }
181
181
  },
182
- "runtime": { "$ref": "#/$defs/RuntimeDeclaration" }
182
+ "runtime": { "$ref": "#/$defs/RuntimeDeclaration" },
183
+ "signals": {
184
+ "$ref": "https://clowder-ai.dev/schemas/signals/v0.2#/$defs/SignalContribution"
185
+ }
183
186
  },
184
187
  "required": ["pluginId", "version", "contractVersion", "name", "features", "runtime"],
185
188
  "additionalProperties": false
@@ -354,6 +354,7 @@
354
354
  "messageId": { "type": "string", "minLength": 1 },
355
355
  "threadId": { "type": "string", "minLength": 1 },
356
356
  "revision": { "type": "integer", "minimum": 1 },
357
+ "handle": { "$ref": "#/$defs/MessageHandle" },
357
358
  "publishSequence": { "type": "integer", "minimum": 0 }
358
359
  },
359
360
  "required": ["messageId", "threadId", "revision"],
@@ -0,0 +1,319 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://clowder-ai.dev/schemas/physical-limb/v0.1",
4
+ "title": "Clowder AI Physical Limb Contribution (v0.1)",
5
+ "description": "Typed, bounded contract for a Host-governed physical limb contribution. Raw sensor media is intentionally absent.",
6
+ "x-clowder-physical-limb-grants": [
7
+ "limb.action.motion",
8
+ "limb.action.display",
9
+ "limb.action.light",
10
+ "limb.action.speaker",
11
+ "limb.observe.touch",
12
+ "limb.sensor.microphone",
13
+ "limb.sensor.camera"
14
+ ],
15
+ "x-clowder-physical-limb-bounds": {
16
+ "maxIdentifierLength": 128,
17
+ "maxTranscriptCodePoints": 4096,
18
+ "maxTouchDurationMs": 10000,
19
+ "minListenDurationMs": 100,
20
+ "maxListenDurationMs": 30000,
21
+ "maxActionTimeoutMs": 30000
22
+ },
23
+ "$defs": {
24
+ "PhysicalLimbIdentifier": {
25
+ "type": "string",
26
+ "minLength": 1,
27
+ "maxLength": 128
28
+ },
29
+ "PhysicalLimbGrant": {
30
+ "type": "string",
31
+ "enum": [
32
+ "limb.action.motion",
33
+ "limb.action.display",
34
+ "limb.action.light",
35
+ "limb.action.speaker",
36
+ "limb.observe.touch",
37
+ "limb.sensor.microphone",
38
+ "limb.sensor.camera"
39
+ ]
40
+ },
41
+ "PhysicalLimbSafePose": {
42
+ "type": "object",
43
+ "properties": {
44
+ "yawDeg": { "type": "number", "minimum": -90, "maximum": 90 },
45
+ "pitchDeg": { "type": "number", "minimum": -90, "maximum": 90 },
46
+ "timeoutMs": { "type": "integer", "minimum": 100, "maximum": 30000 }
47
+ },
48
+ "required": ["yawDeg", "pitchDeg", "timeoutMs"],
49
+ "additionalProperties": false
50
+ },
51
+ "PhysicalLimbContribution": {
52
+ "type": "object",
53
+ "properties": {
54
+ "contributionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
55
+ "nodeType": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
56
+ "displayName": { "type": "string", "minLength": 1, "maxLength": 128 },
57
+ "grants": {
58
+ "type": "array",
59
+ "items": { "$ref": "#/$defs/PhysicalLimbGrant" },
60
+ "minItems": 1,
61
+ "maxItems": 7,
62
+ "uniqueItems": true
63
+ },
64
+ "safePose": { "$ref": "#/$defs/PhysicalLimbSafePose" }
65
+ },
66
+ "required": ["contributionId", "nodeType", "displayName", "grants", "safePose"],
67
+ "additionalProperties": false
68
+ },
69
+ "PhysicalLimbExpressionSource": {
70
+ "type": "object",
71
+ "properties": {
72
+ "kind": { "type": "string", "enum": ["cat_state", "play", "degraded"] },
73
+ "ref": { "$ref": "#/$defs/PhysicalLimbIdentifier" }
74
+ },
75
+ "required": ["kind", "ref"],
76
+ "additionalProperties": false
77
+ },
78
+ "PhysicalLimbTouchPayload": {
79
+ "type": "object",
80
+ "properties": {
81
+ "gesture": { "type": "string", "enum": ["tap", "stroke"] },
82
+ "durationMs": { "type": "integer", "minimum": 0, "maximum": 10000 },
83
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 }
84
+ },
85
+ "required": ["gesture", "durationMs", "confidence"],
86
+ "additionalProperties": false
87
+ },
88
+ "PhysicalLimbTranscriptPayload": {
89
+ "type": "object",
90
+ "properties": {
91
+ "interactionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
92
+ "text": { "type": "string", "minLength": 1, "maxLength": 4096 },
93
+ "language": { "type": "string", "minLength": 1, "maxLength": 32 },
94
+ "captureDurationMs": { "type": "integer", "minimum": 100, "maximum": 30000 }
95
+ },
96
+ "required": ["interactionId", "text", "captureDurationMs"],
97
+ "additionalProperties": false
98
+ },
99
+ "PhysicalLimbTouchObservation": {
100
+ "type": "object",
101
+ "properties": {
102
+ "v": { "const": 1 },
103
+ "observationId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
104
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
105
+ "occurredAt": { "type": "string", "format": "date-time" },
106
+ "sessionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
107
+ "kind": { "const": "touch" },
108
+ "payload": { "$ref": "#/$defs/PhysicalLimbTouchPayload" }
109
+ },
110
+ "required": ["v", "observationId", "nodeId", "occurredAt", "sessionId", "kind", "payload"],
111
+ "additionalProperties": false
112
+ },
113
+ "PhysicalLimbTranscriptObservation": {
114
+ "type": "object",
115
+ "properties": {
116
+ "v": { "const": 1 },
117
+ "observationId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
118
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
119
+ "occurredAt": { "type": "string", "format": "date-time" },
120
+ "sessionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
121
+ "kind": { "const": "transcript" },
122
+ "payload": { "$ref": "#/$defs/PhysicalLimbTranscriptPayload" }
123
+ },
124
+ "required": ["v", "observationId", "nodeId", "occurredAt", "sessionId", "kind", "payload"],
125
+ "additionalProperties": false
126
+ },
127
+ "PhysicalLimbObservation": {
128
+ "oneOf": [
129
+ { "$ref": "#/$defs/PhysicalLimbTouchObservation" },
130
+ { "$ref": "#/$defs/PhysicalLimbTranscriptObservation" }
131
+ ]
132
+ },
133
+ "PhysicalLimbMotionPayload": {
134
+ "type": "object",
135
+ "properties": {
136
+ "yawDeg": { "type": "number", "minimum": -90, "maximum": 90 },
137
+ "pitchDeg": { "type": "number", "minimum": -90, "maximum": 90 },
138
+ "speedDps": { "type": "number", "exclusiveMinimum": 0, "maximum": 240 },
139
+ "accelerationDps2": { "type": "number", "exclusiveMinimum": 0, "maximum": 720 }
140
+ },
141
+ "required": ["yawDeg", "pitchDeg", "speedDps", "accelerationDps2"],
142
+ "additionalProperties": false
143
+ },
144
+ "PhysicalLimbDisplayPayload": {
145
+ "type": "object",
146
+ "properties": {
147
+ "expression": { "type": "string", "minLength": 1, "maxLength": 128 },
148
+ "expressionSource": { "$ref": "#/$defs/PhysicalLimbExpressionSource" }
149
+ },
150
+ "required": ["expression", "expressionSource"],
151
+ "additionalProperties": false
152
+ },
153
+ "PhysicalLimbRgb": {
154
+ "type": "array",
155
+ "items": { "type": "integer", "minimum": 0, "maximum": 255 },
156
+ "minItems": 3,
157
+ "maxItems": 3
158
+ },
159
+ "PhysicalLimbLightPayload": {
160
+ "type": "object",
161
+ "properties": {
162
+ "colors": {
163
+ "type": "array",
164
+ "items": { "$ref": "#/$defs/PhysicalLimbRgb" },
165
+ "minItems": 1,
166
+ "maxItems": 256
167
+ }
168
+ },
169
+ "required": ["colors"],
170
+ "additionalProperties": false
171
+ },
172
+ "PhysicalLimbSpeakerPayload": {
173
+ "type": "object",
174
+ "properties": {
175
+ "text": { "type": "string", "minLength": 1, "maxLength": 4096 },
176
+ "voiceProfileRef": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
177
+ "volumePercent": { "type": "integer", "minimum": 0, "maximum": 100 }
178
+ },
179
+ "required": ["text", "voiceProfileRef", "volumePercent"],
180
+ "additionalProperties": false
181
+ },
182
+ "PhysicalLimbMotionAction": {
183
+ "type": "object",
184
+ "properties": {
185
+ "v": { "const": 1 },
186
+ "actionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
187
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
188
+ "deadlineUnixMs": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
189
+ "timeoutMs": { "type": "integer", "minimum": 1, "maximum": 30000 },
190
+ "cancelToken": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
191
+ "kind": { "const": "motion" },
192
+ "payload": { "$ref": "#/$defs/PhysicalLimbMotionPayload" }
193
+ },
194
+ "required": ["v", "actionId", "nodeId", "deadlineUnixMs", "timeoutMs", "cancelToken", "kind", "payload"],
195
+ "additionalProperties": false
196
+ },
197
+ "PhysicalLimbDisplayAction": {
198
+ "type": "object",
199
+ "properties": {
200
+ "v": { "const": 1 },
201
+ "actionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
202
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
203
+ "deadlineUnixMs": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
204
+ "timeoutMs": { "type": "integer", "minimum": 1, "maximum": 30000 },
205
+ "cancelToken": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
206
+ "kind": { "const": "display" },
207
+ "payload": { "$ref": "#/$defs/PhysicalLimbDisplayPayload" }
208
+ },
209
+ "required": ["v", "actionId", "nodeId", "deadlineUnixMs", "timeoutMs", "cancelToken", "kind", "payload"],
210
+ "additionalProperties": false
211
+ },
212
+ "PhysicalLimbLightAction": {
213
+ "type": "object",
214
+ "properties": {
215
+ "v": { "const": 1 },
216
+ "actionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
217
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
218
+ "deadlineUnixMs": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
219
+ "timeoutMs": { "type": "integer", "minimum": 1, "maximum": 30000 },
220
+ "cancelToken": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
221
+ "kind": { "const": "light" },
222
+ "payload": { "$ref": "#/$defs/PhysicalLimbLightPayload" }
223
+ },
224
+ "required": ["v", "actionId", "nodeId", "deadlineUnixMs", "timeoutMs", "cancelToken", "kind", "payload"],
225
+ "additionalProperties": false
226
+ },
227
+ "PhysicalLimbSpeakerAction": {
228
+ "type": "object",
229
+ "properties": {
230
+ "v": { "const": 1 },
231
+ "actionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
232
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
233
+ "deadlineUnixMs": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
234
+ "timeoutMs": { "type": "integer", "minimum": 1, "maximum": 30000 },
235
+ "cancelToken": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
236
+ "kind": { "const": "speaker" },
237
+ "payload": { "$ref": "#/$defs/PhysicalLimbSpeakerPayload" }
238
+ },
239
+ "required": ["v", "actionId", "nodeId", "deadlineUnixMs", "timeoutMs", "cancelToken", "kind", "payload"],
240
+ "additionalProperties": false
241
+ },
242
+ "PhysicalLimbAction": {
243
+ "oneOf": [
244
+ { "$ref": "#/$defs/PhysicalLimbMotionAction" },
245
+ { "$ref": "#/$defs/PhysicalLimbDisplayAction" },
246
+ { "$ref": "#/$defs/PhysicalLimbLightAction" },
247
+ { "$ref": "#/$defs/PhysicalLimbSpeakerAction" }
248
+ ]
249
+ },
250
+ "PhysicalLimbCancel": {
251
+ "type": "object",
252
+ "properties": {
253
+ "v": { "const": 1 },
254
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
255
+ "actionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
256
+ "cancelToken": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
257
+ "reason": { "type": "string", "enum": ["user", "timeout", "lease_lost", "host_lost", "superseded"] }
258
+ },
259
+ "required": ["v", "nodeId", "actionId", "cancelToken", "reason"],
260
+ "additionalProperties": false
261
+ },
262
+ "PhysicalLimbActionResult": {
263
+ "type": "object",
264
+ "properties": {
265
+ "v": { "const": 1 },
266
+ "actionId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
267
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
268
+ "outcome": { "type": "string", "enum": ["succeeded", "refused", "failed", "canceled"] },
269
+ "reason": { "type": "string", "maxLength": 512 },
270
+ "observedAt": { "type": "string", "format": "date-time" }
271
+ },
272
+ "required": ["v", "actionId", "nodeId", "outcome", "observedAt"],
273
+ "additionalProperties": false
274
+ },
275
+ "PhysicalLimbReadinessReason": {
276
+ "type": "string",
277
+ "enum": [
278
+ "gateway_disconnected",
279
+ "device_disconnected",
280
+ "firmware_incompatible",
281
+ "sensor_unavailable",
282
+ "speech_dependency_missing",
283
+ "skin_unavailable",
284
+ "grant_revoked",
285
+ "host_unavailable"
286
+ ]
287
+ },
288
+ "PhysicalLimbReadyReadiness": {
289
+ "type": "object",
290
+ "properties": {
291
+ "v": { "const": 1 },
292
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
293
+ "status": { "const": "ready" },
294
+ "observedAt": { "type": "string", "format": "date-time" }
295
+ },
296
+ "required": ["v", "nodeId", "status", "observedAt"],
297
+ "additionalProperties": false
298
+ },
299
+ "PhysicalLimbUnavailableReadiness": {
300
+ "type": "object",
301
+ "properties": {
302
+ "v": { "const": 1 },
303
+ "nodeId": { "$ref": "#/$defs/PhysicalLimbIdentifier" },
304
+ "status": { "type": "string", "enum": ["degraded", "offline"] },
305
+ "reason": { "$ref": "#/$defs/PhysicalLimbReadinessReason" },
306
+ "observedAt": { "type": "string", "format": "date-time" }
307
+ },
308
+ "required": ["v", "nodeId", "status", "reason", "observedAt"],
309
+ "additionalProperties": false
310
+ },
311
+ "PhysicalLimbReadiness": {
312
+ "oneOf": [
313
+ { "$ref": "#/$defs/PhysicalLimbReadyReadiness" },
314
+ { "$ref": "#/$defs/PhysicalLimbUnavailableReadiness" }
315
+ ]
316
+ }
317
+ },
318
+ "$ref": "#/$defs/PhysicalLimbContribution"
319
+ }
@@ -0,0 +1,129 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://clowder-ai.dev/schemas/signals/v0.2",
4
+ "title": "Clowder AI Signal Ingress Contract (C-2)",
5
+ "description": "Declared external signals and the closed events.publish wire payload. Producer identity, provenance, grants, routing, and liveness are Host-bound and intentionally absent from plugin input.",
6
+ "x-clowder-payload-max-encoded-bytes": 65536,
7
+ "x-clowder-forbidden-privacy-classes": ["av-raw", "input-raw"],
8
+ "x-clowder-forbidden-source-classes": ["av-capture", "input-hardware"],
9
+ "$defs": {
10
+ "SignalType": {
11
+ "type": "string",
12
+ "minLength": 3,
13
+ "maxLength": 128,
14
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_-]*)+$"
15
+ },
16
+ "SignalSchemaRef": {
17
+ "type": "string",
18
+ "description": "Package-local schema applied to the {payload, source} signal content at publish admission.",
19
+ "minLength": 21,
20
+ "maxLength": 256,
21
+ "pattern": "^schemas/([A-Za-z0-9][A-Za-z0-9._-]*/)*[A-Za-z0-9][A-Za-z0-9._-]*\\.schema\\.json$"
22
+ },
23
+ "SignalEpistemicStatus": {
24
+ "type": "string",
25
+ "enum": ["observation", "inference"]
26
+ },
27
+ "SignalPrivacyClass": {
28
+ "type": "string",
29
+ "enum": ["behavioral", "content-adjacent", "content", "av-raw", "input-raw"]
30
+ },
31
+ "AdmissibleSignalPrivacyClass": {
32
+ "type": "string",
33
+ "enum": ["behavioral", "content-adjacent", "content"]
34
+ },
35
+ "SignalSourceClass": {
36
+ "type": "string",
37
+ "enum": ["os-metadata", "accessibility-api", "remote-service", "av-capture", "input-hardware"]
38
+ },
39
+ "AdmissibleSignalSourceClass": {
40
+ "type": "string",
41
+ "enum": ["os-metadata", "accessibility-api", "remote-service"]
42
+ },
43
+ "SignalDeclaration": {
44
+ "type": "object",
45
+ "properties": {
46
+ "type": { "$ref": "#/$defs/SignalType" },
47
+ "schemaRef": { "$ref": "#/$defs/SignalSchemaRef" },
48
+ "epistemicStatus": { "$ref": "#/$defs/SignalEpistemicStatus" },
49
+ "privacyClass": { "$ref": "#/$defs/AdmissibleSignalPrivacyClass" },
50
+ "sourceClass": { "$ref": "#/$defs/AdmissibleSignalSourceClass" }
51
+ },
52
+ "required": ["type", "schemaRef", "epistemicStatus", "privacyClass", "sourceClass"],
53
+ "additionalProperties": false
54
+ },
55
+ "SignalContribution": {
56
+ "type": "object",
57
+ "properties": {
58
+ "provides": {
59
+ "type": "array",
60
+ "items": { "$ref": "#/$defs/SignalDeclaration" },
61
+ "minItems": 1,
62
+ "maxItems": 64,
63
+ "uniqueItems": true
64
+ }
65
+ },
66
+ "required": ["provides"],
67
+ "additionalProperties": false
68
+ },
69
+ "SignalEventId": {
70
+ "type": "string",
71
+ "minLength": 1,
72
+ "maxLength": 128,
73
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
74
+ },
75
+ "SignalIdempotencyKey": {
76
+ "type": "string",
77
+ "minLength": 1,
78
+ "maxLength": 256,
79
+ "pattern": "^[^\\u0000-\\u001F\\u007F\\uD800-\\uDFFF]+$"
80
+ },
81
+ "OpaqueSourceHandle": {
82
+ "type": "string",
83
+ "minLength": 1,
84
+ "maxLength": 512,
85
+ "pattern": "^[^\\u0000-\\u001F\\u007F\\uD800-\\uDFFF]+$"
86
+ },
87
+ "SignalSourceRef": {
88
+ "type": "object",
89
+ "properties": {
90
+ "handle": { "$ref": "#/$defs/OpaqueSourceHandle" }
91
+ },
92
+ "required": ["handle"],
93
+ "additionalProperties": false
94
+ },
95
+ "EventsPublishInput": {
96
+ "type": "object",
97
+ "properties": {
98
+ "signalType": { "$ref": "#/$defs/SignalType" },
99
+ "eventId": { "$ref": "#/$defs/SignalEventId" },
100
+ "idempotencyKey": { "$ref": "#/$defs/SignalIdempotencyKey" },
101
+ "occurredAt": {
102
+ "type": "string",
103
+ "format": "date-time",
104
+ "minLength": 20,
105
+ "maxLength": 30,
106
+ "pattern": "Z$"
107
+ },
108
+ "payload": { "type": "object", "additionalProperties": true },
109
+ "source": { "$ref": "#/$defs/SignalSourceRef" }
110
+ },
111
+ "required": ["signalType", "eventId", "idempotencyKey", "occurredAt", "payload", "source"],
112
+ "additionalProperties": false
113
+ },
114
+ "EventsPublishDisposition": {
115
+ "type": "string",
116
+ "enum": ["accepted", "duplicate"]
117
+ },
118
+ "EventsPublishResult": {
119
+ "type": "object",
120
+ "properties": {
121
+ "publicationId": { "$ref": "#/$defs/SignalEventId" },
122
+ "disposition": { "$ref": "#/$defs/EventsPublishDisposition" }
123
+ },
124
+ "required": ["publicationId", "disposition"],
125
+ "additionalProperties": false
126
+ }
127
+ },
128
+ "$ref": "#/$defs/EventsPublishInput"
129
+ }