@openwop/openwop-conformance 1.6.1 → 1.11.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 (200) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +2 -2
  3. package/api/asyncapi.yaml +127 -0
  4. package/api/openapi.yaml +518 -1
  5. package/coverage.md +44 -2
  6. package/fixtures/conformance-run-duration-breach.json +33 -0
  7. package/fixtures/oauth-providers/synthetic.json +38 -0
  8. package/fixtures.md +29 -0
  9. package/package.json +1 -1
  10. package/schemas/README.md +22 -0
  11. package/schemas/agent-deployment-transition.schema.json +49 -0
  12. package/schemas/agent-deployment.schema.json +54 -0
  13. package/schemas/agent-eval-suite.schema.json +140 -0
  14. package/schemas/agent-inventory-response.schema.json +115 -0
  15. package/schemas/agent-manifest.schema.json +5 -0
  16. package/schemas/agent-org-chart.schema.json +82 -0
  17. package/schemas/agent-ref.schema.json +12 -2
  18. package/schemas/agent-roster-entry.schema.json +81 -0
  19. package/schemas/agent-roster-response.schema.json +21 -0
  20. package/schemas/ai-envelope.schema.json +28 -0
  21. package/schemas/artifact-type-pack-manifest.schema.json +160 -0
  22. package/schemas/budget-policy.schema.json +18 -0
  23. package/schemas/capabilities.schema.json +448 -4
  24. package/schemas/chat-card-pack-manifest.schema.json +158 -0
  25. package/schemas/credential-provenance.schema.json +18 -0
  26. package/schemas/envelopes/media.audio.schema.json +38 -0
  27. package/schemas/envelopes/media.file.schema.json +37 -0
  28. package/schemas/envelopes/media.image.schema.json +33 -0
  29. package/schemas/eval-summary.schema.json +92 -0
  30. package/schemas/heartbeat-evaluated.schema.json +14 -0
  31. package/schemas/heartbeat-state-changed.schema.json +14 -0
  32. package/schemas/node-pack-manifest.schema.json +33 -1
  33. package/schemas/org-chart-responsibility-view.schema.json +26 -0
  34. package/schemas/run-event-payloads.schema.json +380 -6
  35. package/schemas/run-event.schema.json +23 -0
  36. package/schemas/tool-descriptor.schema.json +63 -0
  37. package/schemas/trigger-subscription.schema.json +26 -0
  38. package/schemas/workflow-definition.schema.json +5 -0
  39. package/schemas/workspace-file-create.schema.json +20 -0
  40. package/schemas/workspace-file.schema.json +39 -0
  41. package/src/lib/agentLoop.ts +44 -0
  42. package/src/lib/agentRoster.ts +76 -0
  43. package/src/lib/agentRuntime.ts +45 -0
  44. package/src/lib/artifactTypes.ts +96 -0
  45. package/src/lib/cardPacks.ts +52 -0
  46. package/src/lib/discovery-capabilities.ts +50 -0
  47. package/src/lib/distillation.ts +38 -0
  48. package/src/lib/feedback.ts +3 -3
  49. package/src/lib/heartbeat.ts +31 -0
  50. package/src/lib/liveRuntime.ts +59 -0
  51. package/src/lib/memoryAttribution.ts +48 -0
  52. package/src/lib/profiles.ts +157 -0
  53. package/src/lib/runtimeRequires.ts +38 -0
  54. package/src/lib/safeFetch.ts +87 -0
  55. package/src/lib/subRunAttestation.ts +35 -0
  56. package/src/lib/toolHooks.ts +33 -0
  57. package/src/scenarios/agent-deployment-shape.test.ts +139 -0
  58. package/src/scenarios/agent-eval-suite-shape.test.ts +167 -0
  59. package/src/scenarios/agent-live-allowlist-enforced.test.ts +53 -0
  60. package/src/scenarios/agent-live-invocation-bracket.test.ts +98 -0
  61. package/src/scenarios/agent-live-runtime-shape.test.ts +98 -0
  62. package/src/scenarios/agent-live-structured-output.test.ts +58 -0
  63. package/src/scenarios/agent-loop-iteration-monotonic.test.ts +33 -0
  64. package/src/scenarios/agent-loop-stateful-resume.test.ts +28 -0
  65. package/src/scenarios/agent-loop-version5-shape.test.ts +41 -0
  66. package/src/scenarios/agent-loop-workspace-snapshot.test.ts +33 -0
  67. package/src/scenarios/agent-manifest-runtime.test.ts +85 -0
  68. package/src/scenarios/agent-org-chart-shape.test.ts +127 -0
  69. package/src/scenarios/agent-platform-profile.test.ts +158 -0
  70. package/src/scenarios/agent-roster-attribution.test.ts +179 -0
  71. package/src/scenarios/agent-roster-shape.test.ts +146 -0
  72. package/src/scenarios/ai-envelope-shape.test.ts +14 -18
  73. package/src/scenarios/aiEnvelope.capBreached.test.ts +2 -1
  74. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +2 -1
  75. package/src/scenarios/aiEnvelope.universalKinds.test.ts +2 -1
  76. package/src/scenarios/approval-gate-flow.test.ts +4 -6
  77. package/src/scenarios/artifact-schema-compile-bounded.test.ts +126 -0
  78. package/src/scenarios/artifact-type-pack-install.test.ts +78 -0
  79. package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +140 -0
  80. package/src/scenarios/artifact-type-store-without-render.test.ts +54 -0
  81. package/src/scenarios/audit-log-integrity.test.ts +3 -2
  82. package/src/scenarios/auth-api-key-rotation.test.ts +2 -1
  83. package/src/scenarios/auth-mtls.test.ts +2 -1
  84. package/src/scenarios/auth-oauth2-client-credentials.test.ts +2 -1
  85. package/src/scenarios/auth-oidc-user-bearer.test.ts +2 -1
  86. package/src/scenarios/auth-saml-profile.test.ts +2 -1
  87. package/src/scenarios/auth-scim-profile.test.ts +2 -1
  88. package/src/scenarios/authorization-fail-closed.test.ts +2 -1
  89. package/src/scenarios/authorization-roles-shape.test.ts +2 -1
  90. package/src/scenarios/budget-policy-shape.test.ts +136 -0
  91. package/src/scenarios/byok-auth-modes.test.ts +141 -0
  92. package/src/scenarios/chat-card-pack-execution.test.ts +56 -0
  93. package/src/scenarios/chat-card-pack-manifest-validation.test.ts +128 -0
  94. package/src/scenarios/commitment-fired.test.ts +83 -0
  95. package/src/scenarios/credential-payload-redaction.test.ts +2 -1
  96. package/src/scenarios/credentials-capability-shape.test.ts +2 -1
  97. package/src/scenarios/cross-engine-append-ordering.test.ts +2 -1
  98. package/src/scenarios/cross-host-ancestry-endpoint.test.ts +3 -2
  99. package/src/scenarios/cross-host-causation-shape.test.ts +3 -2
  100. package/src/scenarios/deadletter-capability-shape.test.ts +2 -1
  101. package/src/scenarios/deadletter-retry-exhaustion.test.ts +2 -1
  102. package/src/scenarios/distillation-index-roundtrip.test.ts +35 -0
  103. package/src/scenarios/distillation-secret-carryforward.test.ts +35 -0
  104. package/src/scenarios/distillation-shape.test.ts +41 -0
  105. package/src/scenarios/distillation-stable-archive.test.ts +37 -0
  106. package/src/scenarios/distillation-token-budget.test.ts +45 -0
  107. package/src/scenarios/egress-provenance-shape.test.ts +137 -0
  108. package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +4 -3
  109. package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +5 -4
  110. package/src/scenarios/envelope-reasoning-shape.test.ts +3 -2
  111. package/src/scenarios/envelope-refusal-shape.test.ts +3 -2
  112. package/src/scenarios/envelope-rendering-hint.test.ts +95 -0
  113. package/src/scenarios/envelope-retry-attempted.test.ts +2 -1
  114. package/src/scenarios/envelope-tier-one-subset-static.test.ts +3 -2
  115. package/src/scenarios/exec-not-protocol-tier.test.ts +137 -0
  116. package/src/scenarios/experimental-tier-shape.test.ts +5 -4
  117. package/src/scenarios/fs-path-traversal.test.ts +2 -1
  118. package/src/scenarios/heartbeat-capability-shape.test.ts +35 -0
  119. package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +28 -0
  120. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +43 -0
  121. package/src/scenarios/heartbeat-runtime-bound.test.ts +30 -0
  122. package/src/scenarios/http-client-ssrf.test.ts +10 -13
  123. package/src/scenarios/mcp-toolcall-redaction.test.ts +3 -2
  124. package/src/scenarios/media-url-inline-cap.test.ts +167 -0
  125. package/src/scenarios/memory-attribution-emits-on-write.test.ts +54 -0
  126. package/src/scenarios/memory-attribution-no-content.test.ts +45 -0
  127. package/src/scenarios/memory-attribution-replay-stable.test.ts +60 -0
  128. package/src/scenarios/memory-attribution-shape.test.ts +28 -0
  129. package/src/scenarios/memory-attribution-tenant-scoped.test.ts +44 -0
  130. package/src/scenarios/memory-capability-model-shape.test.ts +186 -0
  131. package/src/scenarios/memory-compaction-event-emitted.test.ts +2 -1
  132. package/src/scenarios/memory-compaction-provenance-tag.test.ts +2 -1
  133. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +2 -1
  134. package/src/scenarios/memory-consolidation-idempotent.test.ts +77 -0
  135. package/src/scenarios/memory-consolidation-shape.test.ts +90 -0
  136. package/src/scenarios/model-capability-substituted.test.ts +2 -1
  137. package/src/scenarios/multi-agent-confidence-escalation.test.ts +5 -4
  138. package/src/scenarios/multi-agent-handoff-state-machine.test.ts +6 -5
  139. package/src/scenarios/multi-agent-memory-lifecycle.test.ts +4 -3
  140. package/src/scenarios/multi-region-idempotency.test.ts +10 -10
  141. package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +145 -0
  142. package/src/scenarios/oauth-capability-shape.test.ts +2 -1
  143. package/src/scenarios/oauth-connector-redaction.test.ts +2 -1
  144. package/src/scenarios/pause-resume.test.ts +3 -3
  145. package/src/scenarios/production-backpressure.test.ts +2 -2
  146. package/src/scenarios/production-retention-expiry.test.ts +2 -2
  147. package/src/scenarios/prompt-all-four-kinds-events.test.ts +2 -1
  148. package/src/scenarios/prompt-composed-secret-redaction.test.ts +2 -1
  149. package/src/scenarios/prompt-composed-trust-marker.test.ts +2 -1
  150. package/src/scenarios/prompt-end-to-end-events.test.ts +2 -1
  151. package/src/scenarios/prompt-list-and-fetch.test.ts +2 -1
  152. package/src/scenarios/prompt-mutable-lifecycle.test.ts +2 -1
  153. package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +2 -1
  154. package/src/scenarios/prompt-pack-install.test.ts +2 -1
  155. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +2 -1
  156. package/src/scenarios/prompt-render-deterministic.test.ts +2 -1
  157. package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +2 -1
  158. package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +2 -1
  159. package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +2 -1
  160. package/src/scenarios/prompt-template-shape.test.ts +2 -1
  161. package/src/scenarios/provider-usage.test.ts +2 -1
  162. package/src/scenarios/replay-divergence-at-refusal.test.ts +4 -3
  163. package/src/scenarios/replay-fork-arbitrary.test.ts +3 -1
  164. package/src/scenarios/replay-llm-cache-key-portable.test.ts +2 -1
  165. package/src/scenarios/replayDeterminism.test.ts +3 -1
  166. package/src/scenarios/run-execution-bounds-shape.test.ts +133 -0
  167. package/src/scenarios/runtime-requires-install-gate.test.ts +92 -0
  168. package/src/scenarios/runtime-requires-shape.test.ts +134 -0
  169. package/src/scenarios/safefetch-behavior.test.ts +99 -0
  170. package/src/scenarios/safefetch-live-audit.test.ts +175 -0
  171. package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
  172. package/src/scenarios/sandbox-mvp-behavior.test.ts +2 -1
  173. package/src/scenarios/sandbox-no-host-fs-escape.test.ts +2 -1
  174. package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
  175. package/src/scenarios/scheduling-capability-shape.test.ts +2 -1
  176. package/src/scenarios/scheduling-cron-fires-once.test.ts +2 -1
  177. package/src/scenarios/secret-leakage-otel-attribute.test.ts +7 -6
  178. package/src/scenarios/spec-corpus-validity.test.ts +20 -4
  179. package/src/scenarios/subrun-approval-fail-closed.test.ts +33 -0
  180. package/src/scenarios/subrun-approval-gate.test.ts +35 -0
  181. package/src/scenarios/subrun-attestation-shape.test.ts +30 -0
  182. package/src/scenarios/subrun-checksum-stable.test.ts +43 -0
  183. package/src/scenarios/tool-descriptor-shape.test.ts +133 -0
  184. package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +39 -0
  185. package/src/scenarios/tool-hooks-content-free.test.ts +40 -0
  186. package/src/scenarios/tool-hooks-rate-limit.test.ts +32 -0
  187. package/src/scenarios/tool-hooks-secret-redaction.test.ts +34 -0
  188. package/src/scenarios/tool-hooks-shape.test.ts +34 -0
  189. package/src/scenarios/trigger-bridge-shape.test.ts +135 -0
  190. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -10
  191. package/src/scenarios/wasm-pack-invoke-completed.test.ts +2 -2
  192. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +2 -2
  193. package/src/scenarios/wasm-pack-load.test.ts +2 -2
  194. package/src/scenarios/wasm-pack-memory-cap.test.ts +3 -6
  195. package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -2
  196. package/src/scenarios/workflow-primary-output-annotation.test.ts +142 -0
  197. package/src/scenarios/workspace-behavior.test.ts +134 -0
  198. package/src/scenarios/workspace-capability-shape.test.ts +73 -0
  199. package/src/scenarios/workspace-cross-tenant-isolation.test.ts +84 -0
  200. package/src/scenarios/x-openwop-form-pack-manifest.test.ts +155 -0
@@ -0,0 +1,158 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/chat-card-pack-manifest.schema.json",
4
+ "title": "ChatCardPackManifest",
5
+ "description": "Manifest for a published OpenWOP AI chat card pack — `pack.json` at the pack root with `kind: \"card\"`. Peer to the node / workflow-chain / prompt / artifact-type pack manifests; disjoint via the `kind` discriminator. See `spec/v1/chat-card-packs.md` for the canonical contract and RFC 0071 Phase 2 for the rationale.\n\nA chat card pack distributes AI step cards: each card binds a prompt template (with typed input slots) to a typed output artifact. When a host advertises `host.chat.cardPacks: supported` and a registered card is invoked, the host substitutes inputs into the prompt, routes the call through `ctx.aiEnvelope.generate`, and (when `outputArtifactType` is set) validates the result against the referenced artifact-type pack's schema before emitting `artifact.created`.",
6
+ "type": "object",
7
+ "required": ["name", "version", "kind", "engines", "cards"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "kind": {
11
+ "type": "string",
12
+ "const": "card",
13
+ "description": "Pack kind discriminator. MUST be the literal string `\"card\"`."
14
+ },
15
+ "name": {
16
+ "type": "string",
17
+ "description": "Reverse-DNS pack name per `node-packs.md` §Naming. Reserved scopes are identical (`core.*` / `vendor.<org>.*` / `community.<author>.*` / `private.<host>.*`).",
18
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
19
+ "minLength": 1,
20
+ "maxLength": 256
21
+ },
22
+ "version": {
23
+ "type": "string",
24
+ "description": "Pack-level SemVer 2.0.0.",
25
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
26
+ },
27
+ "description": { "type": "string", "maxLength": 1024 },
28
+ "author": { "type": "string" },
29
+ "license": { "type": "string", "description": "SPDX license identifier (e.g., `Apache-2.0`, `MIT`)." },
30
+ "homepage": { "type": "string", "format": "uri" },
31
+ "repository": { "type": "string", "format": "uri" },
32
+ "keywords": {
33
+ "type": "array",
34
+ "items": { "type": "string", "maxLength": 64 },
35
+ "maxItems": 50
36
+ },
37
+ "engines": {
38
+ "type": "object",
39
+ "required": ["openwop"],
40
+ "properties": {
41
+ "openwop": { "type": "string", "description": "Semver range — which openwop protocol versions this pack works against." }
42
+ },
43
+ "additionalProperties": true
44
+ },
45
+ "dependencies": {
46
+ "type": "object",
47
+ "additionalProperties": { "type": "string" },
48
+ "description": "Other packs this pack depends on (e.g., the artifact-type pack declaring this card's `outputArtifactType`). Map of pack name → semver range."
49
+ },
50
+ "peerDependencies": {
51
+ "type": "object",
52
+ "additionalProperties": { "type": "string" },
53
+ "description": "Engine-supplied capabilities the pack consumes (e.g., `{ \"host.aiEnvelope\": \"supported\", \"host.chat.cards\": \"supported\" }`). Resolved against the host's advertised capabilities at register time."
54
+ },
55
+ "cards": {
56
+ "type": "array",
57
+ "minItems": 1,
58
+ "items": { "$ref": "#/$defs/Card" },
59
+ "description": "AI chat card definitions this pack contributes. Each MUST have a unique `cardTypeId` within the pack."
60
+ },
61
+ "signing": { "$ref": "#/$defs/Signing" }
62
+ },
63
+ "$defs": {
64
+ "Card": {
65
+ "type": "object",
66
+ "required": ["cardTypeId", "prompt"],
67
+ "additionalProperties": false,
68
+ "properties": {
69
+ "cardTypeId": {
70
+ "type": "string",
71
+ "description": "Reverse-DNS card identifier. Same pattern and reserved scopes as a pack `name`. The value `WorkflowNode.cardType` / `ctx.chat.emitCard` MAY reference. Third parties MUST NOT publish under `core.*`.",
72
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
73
+ "minLength": 1,
74
+ "maxLength": 256
75
+ },
76
+ "schemaVersion": {
77
+ "type": "integer",
78
+ "minimum": 0,
79
+ "description": "Non-negative integer card-schema version (the envelope/artifact integer-version axis). Absent ⇒ treated as 0."
80
+ },
81
+ "prompt": { "$ref": "#/$defs/PromptSpec" },
82
+ "inputs": {
83
+ "type": "array",
84
+ "items": { "$ref": "#/$defs/InputField" },
85
+ "description": "Typed input fields the card collects. The portable subset only; host-specific widget kinds extend via `vendor.*`/`x-` prefixed `type` values."
86
+ },
87
+ "outputArtifactType": {
88
+ "type": "string",
89
+ "description": "A registered `artifactTypeId` (RFC 0071 Phase 1) the card produces. When present, the host MUST validate the LLM output against that artifact type's schema and emit `artifact.created`. Registered-only by design: unlike a bare node `WorkflowNode.artifactType` (where the unregistered free-string tier is permanently valid), a card's product is always a contract-bound artifact, so this MUST be a reverse-DNS registered id. Omit the field for a prompt-only card that produces no durable artifact.",
90
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$"
91
+ },
92
+ "outputSchemaRef": {
93
+ "type": "string",
94
+ "minLength": 1,
95
+ "description": "Path inside the pack tarball to the JSON Schema (Draft 2020-12) the LLM output MUST conform to. SHOULD be consistent with the referenced artifact type's schema. MUST set top-level `additionalProperties: false`."
96
+ },
97
+ "requiredModelCapabilities": {
98
+ "type": "array",
99
+ "items": {
100
+ "type": "string",
101
+ "pattern": "^([a-z][a-z0-9-]*|x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*)$"
102
+ },
103
+ "uniqueItems": true,
104
+ "maxItems": 32,
105
+ "description": "Model capabilities the card requires the active model to advertise. Reuses the `requiredModelCapabilities` registry in `host-capabilities.md` (spec-reserved: `structured-output`, `discriminator-enum`, `long-context`, `reasoning`, `function-calling`; host extensions `x-host-<host>-`)."
106
+ }
107
+ }
108
+ },
109
+ "PromptSpec": {
110
+ "type": "object",
111
+ "required": ["template", "placeholderMapping"],
112
+ "additionalProperties": false,
113
+ "description": "The prompt the card composes. The host substitutes mapped input values into `template`/`systemPrompt` before dispatch; segments derived from card inputs are `untrusted` (RFC 0071 Trust boundary).",
114
+ "properties": {
115
+ "template": { "type": "string", "minLength": 1, "description": "Prompt body with `{{placeholder}}` slots." },
116
+ "systemPrompt": { "type": "string", "description": "Optional system prompt." },
117
+ "placeholderMapping": {
118
+ "type": "object",
119
+ "additionalProperties": { "type": "string" },
120
+ "description": "Map of `{{placeholder}}` name → input path (e.g. `\"spec\": \"inputs.spec\"`)."
121
+ },
122
+ "temperature": { "type": "number", "minimum": 0, "maximum": 2 },
123
+ "maxTokens": { "type": "integer", "minimum": 1 }
124
+ }
125
+ },
126
+ "InputField": {
127
+ "type": "object",
128
+ "required": ["id", "type"],
129
+ "additionalProperties": false,
130
+ "properties": {
131
+ "id": { "type": "string", "minLength": 1, "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" },
132
+ "type": {
133
+ "type": "string",
134
+ "description": "Closed portable subset OR a `vendor.<org>.<kind>` / `x-<kind>` host extension other hosts ignore. The portable subset (G9, resolved 2026-05-27 against MyndHyve's `CardFieldType`): `text`, `longtext`, `number`, `boolean`, `select`, `multiselect`, `file`, `artifact-ref`. MyndHyve maps `textarea`→`longtext` and `toggle`→`boolean`; its product-specific kinds (`canvas-reference`, `collection-reference`, `color`) are host extensions (`vendor.myndhyve.*`), not portable.",
135
+ "pattern": "^(text|longtext|number|boolean|select|multiselect|file|artifact-ref|vendor\\.[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*|x-[a-z][a-z0-9-]*)$"
136
+ },
137
+ "label": { "type": "string" },
138
+ "required": { "type": "boolean" },
139
+ "default": {},
140
+ "options": {
141
+ "type": "array",
142
+ "items": { "type": "string" },
143
+ "description": "Choices for `type: \"select\"`."
144
+ }
145
+ }
146
+ },
147
+ "Signing": {
148
+ "type": "object",
149
+ "description": "Optional signing metadata. See node-packs.md §signing.",
150
+ "additionalProperties": false,
151
+ "properties": {
152
+ "publicKeyRef": { "type": "string" },
153
+ "signatureRef": { "type": "string" },
154
+ "method": { "type": "string", "enum": ["manual", "sigstore"] }
155
+ }
156
+ }
157
+ }
158
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/credential-provenance.schema.json",
4
+ "title": "CredentialProvenance",
5
+ "description": "RFC 0079 §A. Metadata ABOUT a host-issued credential (an RFC 0046 stored reference or an RFC 0047 OAuth token) attached at the tool/egress boundary — never the secret value (SR-1; reuses the RFC 0046 `credential-payload-redaction` posture). Travels with the egress decision, not the credential material. The §C audience-binding MUST is evaluated against `audiences`.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["credentialId", "issuer", "audiences"],
9
+ "properties": {
10
+ "credentialId": { "type": "string", "minLength": 1, "description": "Stable host-issued id for the credential (the RFC 0046 `ref`, or an OAuth-grant id). Correlates audit + the Keys-page view. NOT the secret value." },
11
+ "issuer": { "type": "string", "minLength": 1, "description": "Who minted/owns the credential — the host itself (`host`), an RFC 0047 OAuth provider id, or a BYOK principal (RFC 0046). Lets a consumer distinguish host-managed from caller-supplied credentials." },
12
+ "audiences": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "REQUIRED. The destination hosts/domains (or destination-class ids) the credential is valid for. The §C binding MUST is evaluated against this list — a credential MUST NOT be attached to an egress outside its audiences. Matching is exact host or an explicit `*.domain` suffix form (no arbitrary regex — injection risk; RFC 0079 §UQ1)." },
13
+ "scopes": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "description": "MAY — RFC 0049 scopes the credential grants (e.g. `egress:stripe:charge`)." },
14
+ "expiresAt": { "type": "string", "format": "date-time", "description": "MAY — credential expiry; an expired credential MUST NOT be attached (deny, `reason: \"expired\"`)." },
15
+ "redactionPolicy": { "type": "string", "enum": ["always", "hash", "host-policy"], "description": "MAY — how the credential surfaces in logs/events. `always`: never appears (default posture, SR-1); `hash`: an SR-1-redacted digest MAY appear; `host-policy`: host-defined. The secret value itself is NEVER on the wire regardless." },
16
+ "auditCorrelationId": { "type": "string", "minLength": 1, "description": "MAY — id correlating this credential's egress decisions across the run's `egress.decided` events + the host audit log." }
17
+ }
18
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/envelopes/media.audio.schema.json",
4
+ "title": "MediaAudioPayload",
5
+ "description": "Payload for the OPTIONAL `media.audio` AI Envelope kind (RFC 0055 §C). Carries a host-served URL reference (preferred) or, below the host's `aiProviders.maxInlineMediaBytes` cap, inline base64 audio data. Pairs with the `meta.rendering.display: \"audio\"` hint. Advertised, opt-in kind — not a MUST-recognize universal kind.",
6
+ "type": "object",
7
+ "required": ["bytes"],
8
+ "properties": {
9
+ "url": {
10
+ "type": "string",
11
+ "format": "uri",
12
+ "description": "Tenant-scoped, non-guessable host-served asset URL (RFC 0055 §C rule 1). SHOULD be used above `aiProviders.maxInlineMediaBytes`. Enforced by the `media-asset-url-tenant-scoped` SECURITY invariant."
13
+ },
14
+ "base64": {
15
+ "type": "string",
16
+ "description": "Inline base64-encoded audio, permitted only at or below `aiProviders.maxInlineMediaBytes` (RFC 0055 §C rule 2). Above the cap the host MUST use `url`."
17
+ },
18
+ "bytes": {
19
+ "type": "integer",
20
+ "minimum": 0,
21
+ "description": "Byte size of the asset."
22
+ },
23
+ "mimeType": {
24
+ "type": "string",
25
+ "description": "IANA media type (e.g. `audio/mpeg`, `audio/wav`, `audio/ogg`). SHOULD match `meta.rendering.mimeType`."
26
+ },
27
+ "durationSeconds": {
28
+ "type": "number",
29
+ "minimum": 0,
30
+ "description": "Optional clip duration in seconds, for a consumer's player UI."
31
+ },
32
+ "alt": {
33
+ "type": "string",
34
+ "description": "Text alternative / label for accessibility (RFC 0055 §B); mirrors `meta.rendering.alt` when the producer also sets the rendering hint."
35
+ }
36
+ },
37
+ "additionalProperties": false
38
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/envelopes/media.file.schema.json",
4
+ "title": "MediaFilePayload",
5
+ "description": "Payload for the OPTIONAL `media.file` AI Envelope kind (RFC 0055 §C). A downloadable, non-inline-rendered asset (document, archive, dataset). Carries a host-served URL reference (preferred) or, below the host's `aiProviders.maxInlineMediaBytes` cap, inline base64. Pairs with the `meta.rendering.display: \"file\"` hint. Advertised, opt-in kind — not a MUST-recognize universal kind.",
6
+ "type": "object",
7
+ "required": ["bytes"],
8
+ "properties": {
9
+ "url": {
10
+ "type": "string",
11
+ "format": "uri",
12
+ "description": "Tenant-scoped, non-guessable host-served asset URL (RFC 0055 §C rule 1). SHOULD be used above `aiProviders.maxInlineMediaBytes`. Enforced by the `media-asset-url-tenant-scoped` SECURITY invariant."
13
+ },
14
+ "base64": {
15
+ "type": "string",
16
+ "description": "Inline base64-encoded file bytes, permitted only at or below `aiProviders.maxInlineMediaBytes` (RFC 0055 §C rule 2). Above the cap the host MUST use `url`."
17
+ },
18
+ "bytes": {
19
+ "type": "integer",
20
+ "minimum": 0,
21
+ "description": "Byte size of the asset."
22
+ },
23
+ "mimeType": {
24
+ "type": "string",
25
+ "description": "IANA media type (e.g. `application/pdf`, `text/csv`, `application/zip`). SHOULD match `meta.rendering.mimeType`."
26
+ },
27
+ "name": {
28
+ "type": "string",
29
+ "description": "Optional suggested filename for download (e.g. `q3-report.pdf`)."
30
+ },
31
+ "alt": {
32
+ "type": "string",
33
+ "description": "Text alternative / label for accessibility (RFC 0055 §B); mirrors `meta.rendering.alt` when the producer also sets the rendering hint."
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/envelopes/media.image.schema.json",
4
+ "title": "MediaImagePayload",
5
+ "description": "Payload for the OPTIONAL `media.image` AI Envelope kind (RFC 0055 §C). Carries a host-served URL reference (preferred) or, below the host's `aiProviders.maxInlineMediaBytes` cap, inline base64 image data. Pairs with the `meta.rendering.display: \"image\"` hint. This is an advertised, opt-in kind — not one of the four MUST-recognize universal kinds; a host that emits no `media.*` kind is unaffected.",
6
+ "type": "object",
7
+ "required": ["bytes"],
8
+ "properties": {
9
+ "url": {
10
+ "type": "string",
11
+ "format": "uri",
12
+ "description": "Tenant-scoped, non-guessable host-served asset URL (RFC 0055 §C rule 1 — signed-token / capability-token discipline). SHOULD be used when the asset exceeds `capabilities.aiProviders.maxInlineMediaBytes`. Enforced by the `media-asset-url-tenant-scoped` SECURITY invariant."
13
+ },
14
+ "base64": {
15
+ "type": "string",
16
+ "description": "Inline base64-encoded image, permitted only when the asset is at or below `aiProviders.maxInlineMediaBytes` (default 256 KiB, RFC 0055 §C rule 2). Above the cap the host MUST use `url`. Mutually exclusive with `url` in practice — a single envelope carries one or the other."
17
+ },
18
+ "bytes": {
19
+ "type": "integer",
20
+ "minimum": 0,
21
+ "description": "Byte size of the asset. Required so a consumer can decide whether to inline-render or defer-fetch, and so the cap rule is checkable."
22
+ },
23
+ "mimeType": {
24
+ "type": "string",
25
+ "description": "IANA media type (e.g. `image/png`, `image/jpeg`, `image/webp`). SHOULD match `meta.rendering.mimeType`."
26
+ },
27
+ "alt": {
28
+ "type": "string",
29
+ "description": "Text alternative for accessibility (RFC 0055 §B). SHOULD be present so a consumer can describe the image to assistive technology; mirrors `meta.rendering.alt` when the producer also sets the rendering hint."
30
+ }
31
+ },
32
+ "additionalProperties": false
33
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/eval-summary.schema.json",
4
+ "title": "EvalSummary",
5
+ "description": "RFC 0081 §C. The terminal scorecard of an eval run (the `mode: \"eval\"` projection over `POST /v1/runs`, RFC 0081 §B): the aggregate + per-task scores, cost, latency, schema-validity, and safety findings, plus the suite provenance and (for `regression` mode) the score delta vs a baseline. Set as the eval run's output and served by `GET /v1/runs/{runId}/eval-summary`. SECURITY invariant `eval-summary-no-content-leak`: the summary carries scores, ids, counts, and redaction-safe safety descriptors only — NEVER task output bodies, rubric prose, model completions, prompts, or credential material (SR-1). A consumer reads the run's normal projection for any body.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["suiteId", "suiteVersion", "aggregateScore", "passed", "taskCount", "passedCount", "tasks"],
9
+ "properties": {
10
+ "suiteId": {
11
+ "type": "string",
12
+ "pattern": "^[a-z0-9.-]+\\.evals\\.[a-z0-9-]+$",
13
+ "description": "The `agent-eval-suite.schema.json#suiteId` this summary scores."
14
+ },
15
+ "suiteVersion": {
16
+ "type": "string",
17
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
18
+ "description": "The pinned suite version the run executed (mirrors `eval.started.suiteVersion`)."
19
+ },
20
+ "evaluatedModelClass": {
21
+ "type": "string",
22
+ "enum": ["reasoning", "writing", "coding", "research", "classification", "general"],
23
+ "description": "MAY. The `AgentManifest.modelClass` (RFC 0002) the run was evaluated against, so a score is read against its model. Present when the host resolves a concrete class."
24
+ },
25
+ "aggregateScore": {
26
+ "type": "number",
27
+ "minimum": 0,
28
+ "maximum": 1,
29
+ "description": "The suite-level score (0.0–1.0): the aggregation (host-defined, typically the mean) of per-task scores."
30
+ },
31
+ "passed": {
32
+ "type": "boolean",
33
+ "description": "Whether the run cleared the suite's `thresholds` (RFC 0081 §A) — `aggregateScore >= passScore` AND, when declared, `totalCostUsd <= maxCostUsd` AND the p95 latency bar. The load-bearing flag an RFC 0082 deployment gate may require (`requiredEval`)."
34
+ },
35
+ "taskCount": {
36
+ "type": "integer",
37
+ "minimum": 0,
38
+ "description": "Number of tasks executed."
39
+ },
40
+ "passedCount": {
41
+ "type": "integer",
42
+ "minimum": 0,
43
+ "description": "Number of tasks that individually passed."
44
+ },
45
+ "totalCostUsd": {
46
+ "type": "number",
47
+ "minimum": 0,
48
+ "description": "MAY. Total cost of the run, summed from the per-task RFC 0026 `provider.usage` events (the scalar only — never a pricing breakdown or rate card; `eval-summary-no-content-leak`)."
49
+ },
50
+ "tasks": {
51
+ "type": "array",
52
+ "description": "Per-task results, in suite order. Each entry is content-free: scores, scalars, ids, and redaction-safe safety descriptors only.",
53
+ "items": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["taskId", "score", "passed"],
57
+ "properties": {
58
+ "taskId": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$", "description": "The `agent-eval-suite` task id." },
59
+ "score": { "type": "number", "minimum": 0, "maximum": 1, "description": "Task score (0.0–1.0)." },
60
+ "passed": { "type": "boolean", "description": "Whether this task individually met its bar." },
61
+ "costUsd": { "type": "number", "minimum": 0, "description": "MAY. Task cost (scalar)." },
62
+ "latencyMs": { "type": "integer", "minimum": 0, "description": "MAY. Task wall-clock latency." },
63
+ "schemaValid": { "type": "boolean", "description": "MAY. Whether the task output validated against the agent's `handoff.returnSchemaRef` (when structured-output enforcement is in effect)." },
64
+ "safetyFindings": {
65
+ "type": "array",
66
+ "description": "MAY. Redaction-safe safety findings (primarily `adversarial` mode). Each is a `{kind, severity}` descriptor — NO excerpted content, prompt, or completion text (`eval-summary-no-content-leak`).",
67
+ "items": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "required": ["kind", "severity"],
71
+ "properties": {
72
+ "kind": { "type": "string", "minLength": 1, "description": "Finding category (e.g. `jailbreak`, `pii-leak`, `unsafe-tool-call`) — a category label, not excerpted content." },
73
+ "severity": { "type": "string", "enum": ["low", "medium", "high", "critical"], "description": "Finding severity." }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ },
80
+ "regression": {
81
+ "type": "object",
82
+ "additionalProperties": false,
83
+ "description": "MAY. Present for `regression` mode. The score delta vs a baseline eval run, plus a pointer to the RFC 0054 `:diff` for the structural divergence. Content-free.",
84
+ "required": ["baselineRunId", "scoreDelta"],
85
+ "properties": {
86
+ "baselineRunId": { "type": "string", "minLength": 1, "description": "The prior eval run this run is compared against." },
87
+ "scoreDelta": { "type": "number", "minimum": -1, "maximum": 1, "description": "`aggregateScore` minus the baseline's (negative ⇒ regression)." },
88
+ "diffRef": { "type": "string", "description": "MAY. A pointer to `GET /v1/runs/{runId}:diff?against={baselineRunId}` (RFC 0054) for the structural delta." }
89
+ }
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/heartbeat-evaluated.schema.json",
4
+ "title": "HeartbeatEvaluated",
5
+ "description": "RFC 0060. Emitted every tick by a host advertising `capabilities.heartbeat.supported: true` — the observability record of a heartbeat predicate evaluation. Heartbeat-scoped (NOT a replayable run-event-log entry). Carries no external state or secret material; `changed` gates whether a `heartbeat.stateChanged` + enqueued run follow.",
6
+ "type": "object",
7
+ "required": ["heartbeatId", "status", "changed"],
8
+ "properties": {
9
+ "heartbeatId": { "type": "string", "minLength": 1, "description": "Host-assigned identifier for the heartbeat whose tick this records." },
10
+ "status": { "type": "string", "enum": ["ok", "timeout", "error"], "description": "`ok` — predicate evaluated within `maxRuntimeMs`. `timeout` — terminated at the budget (RFC 0060 §B.2). `error` — the predicate threw." },
11
+ "changed": { "type": "boolean", "description": "Whether the predicate's state transitioned vs. the prior tick. `true` is the only path that may emit `heartbeat.stateChanged` and enqueue a run." }
12
+ },
13
+ "additionalProperties": false
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/heartbeat-state-changed.schema.json",
4
+ "title": "HeartbeatStateChanged",
5
+ "description": "RFC 0060. Emitted ONLY on a predicate-state transition — an unchanged tick MUST NOT emit it (this is what prevents notification spam). Heartbeat-scoped (NOT a replayable run-event-log entry). `from`/`to` are opaque host-persisted predicate-state tokens; they MUST NOT carry secret or external-content material beyond the minimal state needed to detect a transition.",
6
+ "type": "object",
7
+ "required": ["heartbeatId", "from", "to"],
8
+ "properties": {
9
+ "heartbeatId": { "type": "string", "minLength": 1, "description": "Host-assigned identifier for the heartbeat that transitioned." },
10
+ "from": { "type": "object", "additionalProperties": true, "description": "Prior tick's predicate state (opaque, host-defined)." },
11
+ "to": { "type": "object", "additionalProperties": true, "description": "Current tick's predicate state — the transition target (opaque, host-defined)." }
12
+ },
13
+ "additionalProperties": false
14
+ }
@@ -56,7 +56,22 @@
56
56
  "peerDependencies": {
57
57
  "type": "object",
58
58
  "additionalProperties": { "type": "string" },
59
- "description": "Engine-supplied capabilities the pack consumes (e.g., a particular AI provider extension). Resolved against `Capabilities` at register time."
59
+ "description": "Engine-supplied capabilities the pack consumes (e.g., a particular AI provider extension). Resolved against `Capabilities` at register time. Each entry is REQUIRED by default — an unmet entry fails install with `pack_peer_dependency_missing` — unless marked optional in `peerDependenciesMeta` (RFC 0072 §C)."
60
+ },
61
+ "peerDependenciesMeta": {
62
+ "type": "object",
63
+ "description": "Per-peer-dependency metadata (RFC 0072 §C). Keys mirror `peerDependencies` keys. Marking an entry `optional: true` makes it degrade-if-unmet instead of refuse-if-unmet: a host that does not satisfy it MUST install the pack with that capability inert AND surface it in the affected agents' inventory `degraded[]` (RFC 0072 §A); it MUST NOT silently ignore the declared dependency. Default (absent entry) is required. Packs published before RFC 0072 validate unchanged.",
64
+ "additionalProperties": {
65
+ "type": "object",
66
+ "additionalProperties": false,
67
+ "properties": {
68
+ "optional": {
69
+ "type": "boolean",
70
+ "default": false,
71
+ "description": "When true, an unmet peer dependency degrades (inert + surfaced in `degraded[]`) rather than failing install."
72
+ }
73
+ }
74
+ }
60
75
  },
61
76
  "nodes": {
62
77
  "type": "array",
@@ -351,6 +366,23 @@
351
366
  "minRuntimeVersion": {
352
367
  "type": "string",
353
368
  "description": "Minimum host runtime version (e.g., `node>=20`, `python>=3.10`, `go>=1.22`)."
369
+ },
370
+ "requires": {
371
+ "type": "array",
372
+ "uniqueItems": true,
373
+ "description": "RFC 0076. Abstract platform primitives the pack's runtime code exercises, for install-time sandbox gating. Runtime-agnostic (not language builtin names). Absent or [] ⇒ no elevated platform needs. A sandbox host MUST evaluate this at install time and refuse (`pack_runtime_requirement_unmet`) any primitive it will not grant; see node-packs.md §\"Runtime platform requirements\".",
374
+ "items": {
375
+ "oneOf": [
376
+ { "const": "net.dns", "description": "Resolves hostnames (e.g., SSRF pre-flight)." },
377
+ { "const": "net.outbound", "description": "Opens outbound network connections / fetch." },
378
+ { "const": "crypto", "description": "Primitives beyond the standard hashing the host already provides." },
379
+ { "const": "subprocess", "description": "Spawns a child process (composes with the RFC 0069 exec-class contract when the host advertises it)." },
380
+ { "const": "fs.read", "description": "Reads the local filesystem." },
381
+ { "const": "fs.write", "description": "Writes the local filesystem." },
382
+ { "const": "env.read", "description": "Reads the process environment (may expose deployment secrets if the host does not scrub it)." },
383
+ { "const": "clock", "description": "Reads wall-clock time as a behavioral input — gated for REPLAY determinism, not access control. A pack that branches on the clock is non-deterministic on replay (replay.md)." }
384
+ ]
385
+ }
354
386
  }
355
387
  },
356
388
  "additionalProperties": false
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/org-chart-responsibility-view.schema.json",
4
+ "title": "OrgChartResponsibilityView",
5
+ "description": "RFC 0087 §D. Response body for `GET /v1/agents/org-chart/{departmentId}` — one department's subtree + the derived responsibility roll-up (the union of its members' RFC 0086 workflow portfolios, recursively through sub-departments unless `?recursive=false`). A read-only VIEW computed from live roster entries: it grants nothing (§B `org-position-no-authority-escalation`) and stores nothing. Tenant-scoped per RFC 0074.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["department", "members", "responsibilities"],
9
+ "properties": {
10
+ "department": {
11
+ "$ref": "./agent-org-chart.schema.json#/$defs/Department",
12
+ "description": "The department this view is rooted at."
13
+ },
14
+ "members": {
15
+ "type": "array",
16
+ "items": { "$ref": "./agent-org-chart.schema.json#/$defs/Member" },
17
+ "description": "The department's members (and, by default, its sub-departments' members)."
18
+ },
19
+ "responsibilities": {
20
+ "type": "array",
21
+ "items": { "type": "string", "minLength": 1 },
22
+ "uniqueItems": true,
23
+ "description": "The union of the members' RFC 0086 `workflows[]` portfolios — 'what this department is collectively responsible for'. Deduped; descriptive only."
24
+ }
25
+ }
26
+ }