@openwop/spec-artifacts 2.0.0-rc.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 (229) hide show
  1. package/CORPUS-STAMP.json +234 -0
  2. package/LICENSE +201 -0
  3. package/README.md +7 -0
  4. package/api/.redocly.lint-ignore.yaml +22 -0
  5. package/api/asyncapi.yaml +834 -0
  6. package/api/grpc/openwop.proto +251 -0
  7. package/api/openapi.yaml +2693 -0
  8. package/api/redocly.yaml +23 -0
  9. package/api/seams-v2.yaml +680 -0
  10. package/api/v2/asyncapi.yaml +528 -0
  11. package/api/v2/openapi.yaml +3139 -0
  12. package/api/v2/redocly.yaml +16 -0
  13. package/package.json +10 -0
  14. package/schemas/README.md +144 -0
  15. package/schemas/a2a-task-state.schema.json +78 -0
  16. package/schemas/a2ui-surface-delta-frame.schema.json +48 -0
  17. package/schemas/agent-deployment-transition.schema.json +49 -0
  18. package/schemas/agent-deployment.schema.json +54 -0
  19. package/schemas/agent-eval-suite.schema.json +140 -0
  20. package/schemas/agent-inventory-response.schema.json +115 -0
  21. package/schemas/agent-manifest.schema.json +156 -0
  22. package/schemas/agent-org-chart.schema.json +82 -0
  23. package/schemas/agent-ref.schema.json +63 -0
  24. package/schemas/agent-roster-entry.schema.json +81 -0
  25. package/schemas/agent-roster-response.schema.json +21 -0
  26. package/schemas/ai-envelope.schema.json +134 -0
  27. package/schemas/annotation-create.schema.json +37 -0
  28. package/schemas/annotation.schema.json +56 -0
  29. package/schemas/artifact-type-pack-manifest.schema.json +244 -0
  30. package/schemas/audit-verify-result.schema.json +90 -0
  31. package/schemas/budget-policy.schema.json +18 -0
  32. package/schemas/capabilities.schema.json +4160 -0
  33. package/schemas/certification-bundle-v2.schema.json +118 -0
  34. package/schemas/channel-presence-payload.schema.json +41 -0
  35. package/schemas/channel-written-payload.schema.json +55 -0
  36. package/schemas/chat-card-pack-manifest.schema.json +253 -0
  37. package/schemas/compact-tool-descriptor.schema.json +51 -0
  38. package/schemas/compensation-policy.schema.json +64 -0
  39. package/schemas/conformance-certification-bundle.schema.json +86 -0
  40. package/schemas/connection-pack-manifest.schema.json +353 -0
  41. package/schemas/conversation-event.schema.json +168 -0
  42. package/schemas/conversation-turn.schema.json +117 -0
  43. package/schemas/core-conformance-mock-agent-config.schema.json +152 -0
  44. package/schemas/credential-provenance.schema.json +18 -0
  45. package/schemas/credential-reference.schema.json +21 -0
  46. package/schemas/debug-bundle.schema.json +196 -0
  47. package/schemas/dispatch-config.schema.json +112 -0
  48. package/schemas/envelopes/clarification.request.schema.json +52 -0
  49. package/schemas/envelopes/error.schema.json +30 -0
  50. package/schemas/envelopes/media.audio.schema.json +38 -0
  51. package/schemas/envelopes/media.file.schema.json +37 -0
  52. package/schemas/envelopes/media.image.schema.json +33 -0
  53. package/schemas/envelopes/schema.request.schema.json +26 -0
  54. package/schemas/envelopes/schema.response.schema.json +22 -0
  55. package/schemas/envelopes/ui.a2ui-surface.schema.json +154 -0
  56. package/schemas/error-envelope.schema.json +25 -0
  57. package/schemas/eval-summary.schema.json +92 -0
  58. package/schemas/export-bundle.schema.json +66 -0
  59. package/schemas/form-content-pack-manifest.schema.json +243 -0
  60. package/schemas/frontend-plugin-manifest.schema.json +109 -0
  61. package/schemas/goal.schema.json +104 -0
  62. package/schemas/heartbeat-evaluated.schema.json +14 -0
  63. package/schemas/heartbeat-state-changed.schema.json +14 -0
  64. package/schemas/localized-content-language-settings.schema.json +26 -0
  65. package/schemas/localized-content-page-response.schema.json +60 -0
  66. package/schemas/localized-content-page.schema.json +62 -0
  67. package/schemas/localized-content-section.schema.json +51 -0
  68. package/schemas/memory-entry.schema.json +36 -0
  69. package/schemas/memory-list-options.schema.json +37 -0
  70. package/schemas/node-pack-manifest.schema.json +654 -0
  71. package/schemas/orchestrator-decision.schema.json +90 -0
  72. package/schemas/org-chart-responsibility-view.schema.json +26 -0
  73. package/schemas/pack-lockfile.schema.json +108 -0
  74. package/schemas/prompt-kind.schema.json +8 -0
  75. package/schemas/prompt-pack-manifest.schema.json +117 -0
  76. package/schemas/prompt-ref.schema.json +40 -0
  77. package/schemas/prompt-template.schema.json +149 -0
  78. package/schemas/proposal.schema.json +84 -0
  79. package/schemas/registry-version-manifest.schema.json +208 -0
  80. package/schemas/residency.schema.json +16 -0
  81. package/schemas/run-ancestry-response.schema.json +54 -0
  82. package/schemas/run-diff-response.schema.json +64 -0
  83. package/schemas/run-event-payloads.schema.json +4452 -0
  84. package/schemas/run-event.schema.json +211 -0
  85. package/schemas/run-options.schema.json +80 -0
  86. package/schemas/run-orchestrator-decided-event.schema.json +20 -0
  87. package/schemas/run-snapshot.schema.json +148 -0
  88. package/schemas/security-advisory.schema.json +109 -0
  89. package/schemas/self-hosted-runner-dispatch-frame.schema.json +79 -0
  90. package/schemas/self-hosted-runner-registration.schema.json +53 -0
  91. package/schemas/self-hosted-runner-result-frame.schema.json +38 -0
  92. package/schemas/subject.schema.json +56 -0
  93. package/schemas/suspend-request.schema.json +207 -0
  94. package/schemas/tool-descriptor.schema.json +63 -0
  95. package/schemas/trigger-event.schema.json +222 -0
  96. package/schemas/trigger-subscription-registration.schema.json +67 -0
  97. package/schemas/trigger-subscription.schema.json +26 -0
  98. package/schemas/ui-plugin-message.schema.json +90 -0
  99. package/schemas/v2/a2a-task-state.schema.json +102 -0
  100. package/schemas/v2/a2ui-surface-delta-frame.schema.json +62 -0
  101. package/schemas/v2/agent-deployment-transition.schema.json +67 -0
  102. package/schemas/v2/agent-deployment.schema.json +68 -0
  103. package/schemas/v2/agent-eval-suite.schema.json +214 -0
  104. package/schemas/v2/agent-inventory-response.schema.json +172 -0
  105. package/schemas/v2/agent-manifest.schema.json +218 -0
  106. package/schemas/v2/agent-org-chart.schema.json +149 -0
  107. package/schemas/v2/agent-ref.schema.json +67 -0
  108. package/schemas/v2/agent-roster-entry.schema.json +104 -0
  109. package/schemas/v2/agent-roster-response.schema.json +27 -0
  110. package/schemas/v2/ai-envelope.schema.json +167 -0
  111. package/schemas/v2/annotation-create.schema.json +109 -0
  112. package/schemas/v2/annotation.schema.json +142 -0
  113. package/schemas/v2/artifact-type-pack-manifest.schema.json +245 -0
  114. package/schemas/v2/audit-verify-result.schema.json +110 -0
  115. package/schemas/v2/budget-policy.schema.json +61 -0
  116. package/schemas/v2/capabilities.schema.json +7644 -0
  117. package/schemas/v2/certification-bundle.schema.json +401 -0
  118. package/schemas/v2/channel-presence-payload.schema.json +60 -0
  119. package/schemas/v2/channel-written-payload.schema.json +64 -0
  120. package/schemas/v2/chat-card-pack-manifest.schema.json +254 -0
  121. package/schemas/v2/compact-tool-descriptor.schema.json +108 -0
  122. package/schemas/v2/compensation-policy.schema.json +91 -0
  123. package/schemas/v2/compensation-projection.schema.json +95 -0
  124. package/schemas/v2/configurable.schema.json +110 -0
  125. package/schemas/v2/connection-pack-manifest.schema.json +354 -0
  126. package/schemas/v2/conversation-event.schema.json +281 -0
  127. package/schemas/v2/conversation-turn.schema.json +165 -0
  128. package/schemas/v2/credential-provenance.schema.json +62 -0
  129. package/schemas/v2/credential-reference.schema.json +28 -0
  130. package/schemas/v2/debug-bundle.schema.json +312 -0
  131. package/schemas/v2/dispatch-config.schema.json +147 -0
  132. package/schemas/v2/effect-ledger-projection.schema.json +71 -0
  133. package/schemas/v2/effect-seam-manifest.schema.json +98 -0
  134. package/schemas/v2/envelopes/clarification.request.schema.json +59 -0
  135. package/schemas/v2/envelopes/error.schema.json +35 -0
  136. package/schemas/v2/envelopes/media.audio.schema.json +41 -0
  137. package/schemas/v2/envelopes/media.file.schema.json +40 -0
  138. package/schemas/v2/envelopes/media.image.schema.json +36 -0
  139. package/schemas/v2/envelopes/schema.request.schema.json +29 -0
  140. package/schemas/v2/envelopes/schema.response.schema.json +26 -0
  141. package/schemas/v2/envelopes/ui.a2ui-surface.schema.json +292 -0
  142. package/schemas/v2/error-envelope.schema.json +229 -0
  143. package/schemas/v2/eval-summary.schema.json +166 -0
  144. package/schemas/v2/export-bundle.schema.json +94 -0
  145. package/schemas/v2/form-content-pack-manifest.schema.json +241 -0
  146. package/schemas/v2/frontend-plugin-manifest.schema.json +152 -0
  147. package/schemas/v2/goal.schema.json +188 -0
  148. package/schemas/v2/heartbeat-evaluated.schema.json +34 -0
  149. package/schemas/v2/heartbeat-state-changed.schema.json +31 -0
  150. package/schemas/v2/ids.schema.json +31 -0
  151. package/schemas/v2/localized-content-language-settings.schema.json +34 -0
  152. package/schemas/v2/localized-content-page-response.schema.json +94 -0
  153. package/schemas/v2/localized-content-page.schema.json +87 -0
  154. package/schemas/v2/localized-content-section.schema.json +63 -0
  155. package/schemas/v2/memory-entry.schema.json +45 -0
  156. package/schemas/v2/memory-list-options.schema.json +41 -0
  157. package/schemas/v2/node-pack-manifest.schema.json +657 -0
  158. package/schemas/v2/orchestrator-decision.schema.json +120 -0
  159. package/schemas/v2/org-chart-responsibility-view.schema.json +36 -0
  160. package/schemas/v2/pack-lockfile.schema.json +139 -0
  161. package/schemas/v2/prompt-kind.schema.json +14 -0
  162. package/schemas/v2/prompt-pack-manifest.schema.json +118 -0
  163. package/schemas/v2/prompt-ref.schema.json +42 -0
  164. package/schemas/v2/prompt-template.schema.json +209 -0
  165. package/schemas/v2/proposal.schema.json +145 -0
  166. package/schemas/v2/registry-version-manifest.schema.json +292 -0
  167. package/schemas/v2/residency.schema.json +19 -0
  168. package/schemas/v2/run-ancestry-response.schema.json +68 -0
  169. package/schemas/v2/run-diff-response.schema.json +80 -0
  170. package/schemas/v2/run-event-payloads.schema.json +4588 -0
  171. package/schemas/v2/run-event.schema.json +324 -0
  172. package/schemas/v2/run-options.schema.json +90 -0
  173. package/schemas/v2/run-orchestrator-decided-event.schema.json +22 -0
  174. package/schemas/v2/run-snapshot.schema.json +207 -0
  175. package/schemas/v2/security-advisory.schema.json +138 -0
  176. package/schemas/v2/self-hosted-runner-dispatch-frame.schema.json +119 -0
  177. package/schemas/v2/self-hosted-runner-registration.schema.json +74 -0
  178. package/schemas/v2/self-hosted-runner-result-frame.schema.json +47 -0
  179. package/schemas/v2/subject-link.schema.json +69 -0
  180. package/schemas/v2/subject.schema.json +597 -0
  181. package/schemas/v2/suspend-request.schema.json +370 -0
  182. package/schemas/v2/tool-descriptor.schema.json +150 -0
  183. package/schemas/v2/trigger-event.schema.json +508 -0
  184. package/schemas/v2/trigger-subscription-registration.schema.json +99 -0
  185. package/schemas/v2/trigger-subscription.schema.json +79 -0
  186. package/schemas/v2/ui-plugin-message.schema.json +149 -0
  187. package/schemas/v2/workflow-chain-pack-manifest.schema.json +610 -0
  188. package/schemas/v2/workflow-definition.schema.json +864 -0
  189. package/schemas/v2/workload-identity.schema.json +115 -0
  190. package/schemas/v2/workspace-file-create.schema.json +23 -0
  191. package/schemas/v2/workspace-file.schema.json +45 -0
  192. package/schemas/workflow-chain-pack-manifest.schema.json +615 -0
  193. package/schemas/workflow-definition.schema.json +850 -0
  194. package/schemas/workload-identity.schema.json +79 -0
  195. package/schemas/workspace-file-create.schema.json +20 -0
  196. package/schemas/workspace-file.schema.json +39 -0
  197. package/spec/v1/alias-detectors.json +283 -0
  198. package/spec/v1/capability-declaration-classes.json +176 -0
  199. package/spec/v1/core-standard-manifest.json +423 -0
  200. package/spec/v1/deprecations.json +854 -0
  201. package/spec/v1/deprecations.schema.json +187 -0
  202. package/spec/v1/event-codemap.json +1089 -0
  203. package/spec/v1/event-codemap.schema.json +41 -0
  204. package/spec/v1/extensions.json +1273 -0
  205. package/spec/v1/gaps.json +14581 -0
  206. package/spec/v1/gaps.schema.json +55 -0
  207. package/spec/v1/migrations.json +1822 -0
  208. package/spec/v1/migrations.schema.json +44 -0
  209. package/spec/v1/operation-path-manifest.json +462 -0
  210. package/spec/v1/spec-gaps.json +4823 -0
  211. package/spec/v2/declaration.json +1862 -0
  212. package/spec/v2/declaration.schema.json +305 -0
  213. package/spec/v2/errors.json +837 -0
  214. package/spec/v2/event-codemap.json +1099 -0
  215. package/spec/v2/event-codemap.schema.json +114 -0
  216. package/spec/v2/ext/provider-idempotency/registry.json +6 -0
  217. package/spec/v2/facets/a2a.schema.json +51 -0
  218. package/spec/v2/facets/aiProviders.schema.json +56 -0
  219. package/spec/v2/facets/auth.schema.json +91 -0
  220. package/spec/v2/facets/heartbeat.schema.json +20 -0
  221. package/spec/v2/facets/interrupt.schema.json +29 -0
  222. package/spec/v2/facets/mcp.schema.json +81 -0
  223. package/spec/v2/facets/replay.schema.json +34 -0
  224. package/spec/v2/facets/sandbox.schema.json +31 -0
  225. package/spec/v2/facets/webhooks.schema.json +18 -0
  226. package/spec/v2/path-manifest.json +279 -0
  227. package/spec/v2/peer-dependency-aliases.json +165 -0
  228. package/spec/v2/profiles.json +45 -0
  229. package/spec/v2/release.json +6 -0
@@ -0,0 +1,90 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/orchestrator-decision.schema.json",
4
+ "title": "OrchestratorDecision",
5
+ "description": "Routing decision emitted by an orchestrator-supervisor node. Carried in the `runOrchestrator.decided` event payload's `decision` field (run-orchestrator-decided-event.schema.json). Three canonical kinds form a closed canonical enum at the protocol layer: `'next-worker'` (continue dispatch), `'ask-user'` (route a question to the human party), `'terminate'` (clean run completion). Vendor-extension decision kinds MAY ship under `vendor.<host>.<kind>` per host-extensions.md but conformance MUST validate against the closed canonical set. See RFC 0006 §C.",
6
+ "type": "object",
7
+ "required": ["kind"],
8
+ "oneOf": [
9
+ {
10
+ "title": "NextWorkerDecision",
11
+ "description": "Dispatch one or more next workers. Phase-5 hosts MAY treat the `nextWorkerIds` array as length-1 only and ignore the tail; Phase-6 hosts (RFC 0007 / `core.dispatch`) SHOULD honor full fan-out semantics. The interpretation of array entries (node-id vs agent-id) is left to host capability advertisement; see RFC 0006 §C unresolved-question 1.",
12
+ "type": "object",
13
+ "required": ["kind", "nextWorkerIds"],
14
+ "properties": {
15
+ "kind": { "const": "next-worker" },
16
+ "nextWorkerIds": {
17
+ "type": "array",
18
+ "minItems": 1,
19
+ "items": {
20
+ "type": "string",
21
+ "minLength": 1,
22
+ "maxLength": 256
23
+ },
24
+ "description": "Ordered list of worker node-ids OR agent-ids to dispatch. Hosts that interpret entries as node-ids dispatch in DAG order; hosts that interpret as agent-ids resolve to nodes via the run's static DAG."
25
+ },
26
+ "nextWorkerInputs": {
27
+ "type": "array",
28
+ "items": { "type": "object" },
29
+ "description": "RFC 0126 (data-parallel fan-out). OPTIONAL, index-aligned with `nextWorkerIds`: `nextWorkerInputs[i]` is a per-child input object (child input variable names → values) projected into the child dispatched for `nextWorkerIds[i]`, over the RFC 0022 `inputMapping`/`perWorkerInputMappings` projection (per-item value WINS on key collision). Enables fanning ONE `childWorkflowId` over N runtime items with distinct inputs (the map-over-collection pattern). When present, `nextWorkerInputs.length` MUST equal `nextWorkerIds.length` (a host MUST fail the dispatch node with `validation_error` and dispatch NO child otherwise — length is not JSON-Schema-enforceable, so this is a runtime MUST). Gated on `capabilities.dispatch.perItemInput`: a host NOT advertising it, upon receiving a non-empty `nextWorkerInputs`, MUST fail closed with `validation_error` and MUST NOT silently drop-and-dispatch N identical children (the correctness/spend hazard this closes). Replay-safe: rides the recorded `runOrchestrator.decided` event, re-read verbatim on `:fork`, never recomputed (frozen at decision time). A `sensitive`/secret per-item value MUST NOT appear here in plaintext (use the secret channel). See `node-packs.md` §core.dispatch."
30
+ },
31
+ "confidence": {
32
+ "type": "number",
33
+ "minimum": 0,
34
+ "maximum": 1,
35
+ "description": "RFC 0039 §A — supervisor's stated confidence in this decision, in [0, 1]. Optional; absent means 'no opinion stated' (NOT low confidence). Hosts advertising `capabilities.multiAgent.executionModel.version >= 2` MUST honor a confidence floor (spec floor 0.5; operator-stricter via `confidenceEscalationFloor`): a decision with `confidence` below the floor MUST escalate via clarify-or-escalate interrupt instead of executing. Pre-Phase-2 hosts ignore the field per forward-compat."
36
+ }
37
+ },
38
+ "additionalProperties": false
39
+ },
40
+ {
41
+ "title": "AskUserDecision",
42
+ "description": "Route a human-targeted question. Hosts that adopted RFC 0005 (Phase 4) SHOULD route through `conversation.exchange`; pre-RFC-0005 hosts MAY surface as a `'clarification'` interrupt. The transport is host-policy; the protocol-layer decision shape is the same.",
43
+ "type": "object",
44
+ "required": ["kind", "prompt"],
45
+ "properties": {
46
+ "kind": { "const": "ask-user" },
47
+ "prompt": {
48
+ "type": "string",
49
+ "minLength": 1,
50
+ "description": "Human-targeted question. Free-form text; the protocol does NOT structure the prompt further."
51
+ }
52
+ },
53
+ "additionalProperties": false
54
+ },
55
+ {
56
+ "title": "TerminateDecision",
57
+ "description": "Clean run termination driven by orchestrator judgement. Distinct from `run.failed` (uncaught executor error) and `run.cancelled` (operator cancellation) — see RFC 0006 §H. The terminate `reason?` is informational; the protocol does NOT close the value enum.",
58
+ "type": "object",
59
+ "required": ["kind"],
60
+ "properties": {
61
+ "kind": { "const": "terminate" },
62
+ "reason": {
63
+ "type": "string",
64
+ "description": "Optional free-form rationale captured for audit/debug. Common values: `'goal-reached'`, `'max-iterations'`, `'unrecoverable-error'`. Spec does NOT close this enum.",
65
+ "minLength": 1
66
+ },
67
+ "confidence": {
68
+ "type": "number",
69
+ "minimum": 0,
70
+ "maximum": 1,
71
+ "description": "RFC 0039 §A — supervisor's stated confidence in this termination decision, in [0, 1]. Optional; absent means 'no opinion stated' (NOT low confidence). Hosts advertising `capabilities.multiAgent.executionModel.version >= 2` MUST honor a confidence floor as documented on NextWorkerDecision.confidence above; the same MUST applies to TerminateDecision because a confidently-wrong terminate is the same class of failure as a confidently-wrong dispatch."
72
+ },
73
+ "successCriteria": {
74
+ "type": "array",
75
+ "description": "RFC 0090 (`multiAgent.executionModel.version >= 6`). Optional structured convergence record — the conditions the supervisor judged when terminating. Content-free: criterion keys + booleans only, never result content. When present, a terminate with any `met: false` entry signals a give-up (NOT goal-satisfied); consumers MUST NOT treat such a run as a success. Absent ⇒ today's free-text `reason` semantics, unchanged.",
76
+ "items": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["key", "met"],
80
+ "properties": {
81
+ "key": { "type": "string", "minLength": 1, "description": "Criterion identifier (e.g. `goal-answered`)." },
82
+ "met": { "type": "boolean", "description": "Whether the supervisor judged this criterion satisfied." }
83
+ }
84
+ }
85
+ }
86
+ },
87
+ "additionalProperties": false
88
+ }
89
+ ]
90
+ }
@@ -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
+ }
@@ -0,0 +1,108 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/pack-lockfile.schema.json",
4
+ "title": "PackLockfile",
5
+ "description": "Reproducible-build lockfile pinning resolved versions of every pack a workspace depends on. Per spec/v1/node-packs.md §\"Dependency resolution + lockfile\". A workspace records its lockfile alongside its workflow definitions; on subsequent installs the registry resolver MUST honor the lockfile's exact versions rather than re-running semver resolution. This guarantees that a workflow that ran against `vendor.openwop.rust-hello@1.0.0` will still run against `1.0.0` even after `1.0.1` is published.",
6
+ "type": "object",
7
+ "required": ["lockfileVersion", "generatedAt", "packs"],
8
+ "properties": {
9
+ "lockfileVersion": {
10
+ "type": "integer",
11
+ "minimum": 1,
12
+ "description": "Lockfile schema version. Bumped when the lockfile structure changes incompatibly. v1.0 ships at lockfileVersion 1."
13
+ },
14
+ "generatedAt": {
15
+ "type": "string",
16
+ "format": "date-time",
17
+ "description": "ISO 8601 timestamp the lockfile was written. Used for audit + cache-bust diagnostics; resolvers MUST NOT use this for resolution decisions."
18
+ },
19
+ "registry": {
20
+ "type": "string",
21
+ "format": "uri",
22
+ "description": "Optional source-of-truth registry URL the resolved versions were fetched from (e.g., `https://packs.openwop.dev`). Multi-registry workspaces include this for audit. Single-registry workspaces MAY omit."
23
+ },
24
+ "packs": {
25
+ "type": "array",
26
+ "description": "Resolved pack records, one per pack referenced (transitively) by the workspace's workflow definitions. Order is informational only; resolvers MUST NOT rely on order. Empty arrays are allowed (a workspace with no packs).",
27
+ "items": { "$ref": "#/$defs/ResolvedPack" }
28
+ },
29
+ "overrides": {
30
+ "type": "object",
31
+ "description": "Optional override map per `node-packs.md` §\"Transitive dependency resolution\" §\"Override pinning\". Keys are pack names; values are exact pinned versions that resolvers MUST honor ahead of normal range resolution. The override version MUST still satisfy at least one parent's declared range — silently breaking the contract fails with `pack_dependency_conflict`. Use sparingly: security patches, conflict resolution, supply-chain pinning.",
32
+ "additionalProperties": {
33
+ "type": "string",
34
+ "minLength": 1,
35
+ "maxLength": 64,
36
+ "description": "Exact pinned version that overrides this pack's normal range resolution."
37
+ }
38
+ },
39
+ "fallbackRegistries": {
40
+ "type": "array",
41
+ "items": { "type": "string", "format": "uri" },
42
+ "uniqueItems": true,
43
+ "description": "Optional ordered list of fallback registry base URLs per `registry-operations.md` §\"Registry mirror + federation\". When a pack is not found in the primary `registry`, resolvers MUST consult each fallback in order. The first registry returning a 200 for the version manifest wins. Trust roots are per-registry — a fallback being listed here does NOT imply trust transitivity. Each pack's signature is verified against the issuing registry's `signingKeys[]` allow-list."
44
+ }
45
+ },
46
+ "additionalProperties": false,
47
+ "$defs": {
48
+ "ResolvedPack": {
49
+ "type": "object",
50
+ "required": ["name", "version", "integrity"],
51
+ "properties": {
52
+ "name": {
53
+ "type": "string",
54
+ "minLength": 3,
55
+ "maxLength": 256,
56
+ "pattern": "^(core|vendor|community|private|local)\\.[a-z0-9][a-z0-9.-]*$",
57
+ "description": "Pack name per node-packs.md §\"Manifest format\" `name`. Reverse-DNS-style; namespace prefix is one of the canonical tiers."
58
+ },
59
+ "version": {
60
+ "type": "string",
61
+ "minLength": 1,
62
+ "maxLength": 64,
63
+ "description": "Resolved exact version (no ranges). Semver MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]. The resolver MUST pin to this exact version on subsequent installs."
64
+ },
65
+ "resolved": {
66
+ "type": "string",
67
+ "format": "uri",
68
+ "description": "Optional canonical URL the tarball was fetched from. Audit aid; resolvers MUST verify the `integrity` field even if this URL is present."
69
+ },
70
+ "integrity": {
71
+ "type": "string",
72
+ "pattern": "^sha256-[A-Za-z0-9+/]{43}=$",
73
+ "description": "Subresource-integrity-style hash of the tarball: literal `sha256-` followed by 43-char base64-encoded SHA-256 digest with trailing `=` padding. Resolvers MUST verify the downloaded tarball's SHA-256 matches before extraction. Hash mismatch MUST fail the install with `pack_integrity_mismatch`."
74
+ },
75
+ "signature": {
76
+ "type": "object",
77
+ "description": "Optional pack signature material (Ed25519 per node-packs.md §Signing). When present, resolvers MUST verify the signature against the publisher's advertised public key.",
78
+ "required": ["algorithm", "publicKey", "value"],
79
+ "properties": {
80
+ "algorithm": { "type": "string", "enum": ["ed25519"] },
81
+ "publicKey": { "type": "string", "minLength": 1, "description": "Base64-encoded Ed25519 public key bytes." },
82
+ "value": { "type": "string", "minLength": 1, "description": "Base64-encoded Ed25519 signature over the tarball." }
83
+ },
84
+ "additionalProperties": false
85
+ },
86
+ "dependencies": {
87
+ "type": "object",
88
+ "additionalProperties": {
89
+ "type": "string",
90
+ "minLength": 1,
91
+ "maxLength": 64
92
+ },
93
+ "description": "Pinned versions for this pack's `dependencies` (per its manifest). Each key is a pack name; each value is the resolved exact version. Pinned recursively — a transitively-installed pack appears once in the top-level `packs[]` array AND as a value in each parent's `dependencies` map."
94
+ },
95
+ "peerDependencies": {
96
+ "type": "object",
97
+ "additionalProperties": {
98
+ "type": "string",
99
+ "minLength": 1,
100
+ "maxLength": 64
101
+ },
102
+ "description": "Echo of this pack's manifest `peerDependencies` for audit. Resolvers MUST verify that the host's `/.well-known/openwop` advertises every key listed here (per host-capabilities.md §\"Capability negotiation\"). Lockfile records the host-capability values the workspace committed to at lockfile-write time; mismatches at install time MAY warn (host advertises richer set) but MUST fail if a peer-dep is missing."
103
+ }
104
+ },
105
+ "additionalProperties": false
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/prompt-kind.schema.json",
4
+ "title": "PromptKind",
5
+ "description": "Role a PromptTemplate plays when composed into an LLM call. Shared $def referenced by every schema that names a prompt kind. Adding a kind here is the single edit needed to introduce one across the corpus. See spec/v1/prompts.md §\"PromptKind\" for the canonical semantics of each value, and RFC 0027 for the rationale behind the four-value choice (vs. an open-ended string).\n\nKind semantics:\n- system: behavior + output discipline; composed as the LLM's system message.\n- user: per-call task prompt; composed as the LLM's user message; the surface variable substitution targets.\n- few-shot: example bodies prepended to the user message OR injected as alternating user/assistant turns per host policy.\n- schema-hint: structured-output schema description injected into the system or user message at compose time.",
6
+ "type": "string",
7
+ "enum": ["system", "user", "few-shot", "schema-hint"]
8
+ }
@@ -0,0 +1,117 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/prompt-pack-manifest.schema.json",
4
+ "title": "PromptPackManifest",
5
+ "description": "Manifest for a published OpenWOP prompt pack — `pack.json` at the pack root with `kind: \"prompt\"`. Peer to `node-pack-manifest.schema.json` (RFC 0003) and `workflow-chain-pack-manifest.schema.json` (RFC 0013); disjoint from both via the `kind` discriminator. See `spec/v1/prompts.md` §\"Discovery & distribution\" for the canonical contract and RFC 0028 §B for the rationale.\n\nPrompt packs distribute curated PromptTemplate collections via the same signed-tarball + Ed25519 + SRI pipeline that already serves node and workflow-chain packs. When a host installs a prompt pack and advertises `capabilities.prompts.packsSupported: true`, the templates appear in `GET /v1/prompts` with `meta.source: \"pack\"` + `meta.packName` + `meta.packVersion`.",
6
+ "type": "object",
7
+ "required": [
8
+ "name",
9
+ "version",
10
+ "kind",
11
+ "engines",
12
+ "prompts"
13
+ ],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "name": {
17
+ "type": "string",
18
+ "description": "Reverse-DNS pack name per `node-packs.md` §Naming. Reserved scopes are identical (`core.*` / `vendor.<org>.*` / `community.<author>.*` / `private.<host>.*`). Mirror of `workflow-chain-pack-manifest.schema.json#/properties/name`.",
19
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
20
+ "minLength": 1,
21
+ "maxLength": 256
22
+ },
23
+ "version": {
24
+ "type": "string",
25
+ "description": "Pack-level SemVer 2.0.0.",
26
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
27
+ },
28
+ "kind": {
29
+ "type": "string",
30
+ "const": "prompt",
31
+ "description": "Pack kind discriminator. MUST be the literal string `\"prompt\"` for this schema. Manifests carrying `kind: \"node\"` validate against `node-pack-manifest.schema.json`; `kind: \"workflow-chain\"` against `workflow-chain-pack-manifest.schema.json`."
32
+ },
33
+ "description": {
34
+ "type": "string",
35
+ "maxLength": 1024
36
+ },
37
+ "author": {
38
+ "type": "string"
39
+ },
40
+ "license": {
41
+ "type": "string",
42
+ "description": "SPDX license identifier (e.g., `Apache-2.0`)."
43
+ },
44
+ "homepage": {
45
+ "type": "string",
46
+ "format": "uri"
47
+ },
48
+ "repository": {
49
+ "type": "string",
50
+ "format": "uri"
51
+ },
52
+ "keywords": {
53
+ "type": "array",
54
+ "items": {
55
+ "type": "string",
56
+ "maxLength": 64
57
+ },
58
+ "maxItems": 50
59
+ },
60
+ "engines": {
61
+ "type": "object",
62
+ "required": [
63
+ "openwop"
64
+ ],
65
+ "properties": {
66
+ "openwop": {
67
+ "type": "string",
68
+ "description": "SemVer range — which openwop protocol versions this pack works against (e.g., `>=1.1.0 <2.0.0`)."
69
+ }
70
+ },
71
+ "additionalProperties": true,
72
+ "$comment": "Open by design — packs MAY advertise extra engine constraints (`node`, `python`, etc.) that consumer hosts ignore but operator tooling consumes. Mirrors workflow-chain-pack-manifest."
73
+ },
74
+ "dependencies": {
75
+ "type": "object",
76
+ "additionalProperties": {
77
+ "type": "string"
78
+ },
79
+ "description": "Other packs whose templates this pack's templates reference (e.g., via cross-pack `PromptRef.libraryId` lookups, or via a future `extends:` inheritance syntax). Map of pack name → SemVer range. Install-time validation MUST resolve every entry before accepting the install; an unresolvable entry rejects with `prompt_pack_dependency_unresolvable`. The *semantics* of cross-pack composition (template inheritance, transitive `dependencies` closure) are out of scope for RFC 0028 and defer to a follow-up RFC; this RFC ships the field + the install-time resolve MUST only. Shape mirrors `workflow-chain-pack-manifest.schema.json#/properties/dependencies` (RFC 0013)."
80
+ },
81
+ "prompts": {
82
+ "type": "array",
83
+ "minItems": 1,
84
+ "items": {
85
+ "$ref": "./prompt-template.schema.json"
86
+ },
87
+ "description": "PromptTemplate entries per RFC 0027 §A. Each MUST have a unique `(templateId, version)` pair within the pack. Hosts installing this pack expose the templates at `GET /v1/prompts` with `meta.source: \"pack\"` + `meta.packName: <this pack's name>` + `meta.packVersion: <this pack's version>` populated automatically (RFC 0028 §C)."
88
+ },
89
+ "signing": {
90
+ "type": "object",
91
+ "additionalProperties": false,
92
+ "description": "Optional signing metadata. Reuses the Ed25519 + SRI flow from `node-packs.md §Signing` unchanged. Hosts installing this pack MUST verify the signature before accepting any of `prompts[]` per `registry-operations.md §\"Signature verification\"`.",
93
+ "properties": {
94
+ "publicKeyRef": {
95
+ "type": "string",
96
+ "description": "Path inside the tarball to the Ed25519 public key (PEM-encoded)."
97
+ },
98
+ "signatureRef": {
99
+ "type": "string",
100
+ "description": "Path to the detached signature over `pack.json`."
101
+ },
102
+ "method": {
103
+ "type": "string",
104
+ "enum": [
105
+ "manual",
106
+ "sigstore"
107
+ ]
108
+ }
109
+ }
110
+ }
111
+ },
112
+ "patternProperties": {
113
+ "^(x-|vendor\\.)": {
114
+ "description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
115
+ }
116
+ }
117
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/prompt-ref.schema.json",
4
+ "title": "PromptRef",
5
+ "description": "Reference to a PromptTemplate. Two equivalent forms are accepted: a compact stringy URI (`prompt:templateId[@version]`) and a structured object form. The stringy form is canonical for inline use in WorkflowNode.config and AgentManifest.promptOverrides; the object form is canonical when libraryId disambiguation, variable overrides, or pinned versions need to be expressed explicitly. See spec/v1/prompts.md §\"PromptRef\" for the canonical contract and RFC 0027 §B for the rationale.\n\nResolution semantics (host responsibility): the host looks up the referenced template in its library (host built-ins + installed packs + user templates, gated by capabilities.prompts.*). When no `version` is given, the latest version wins. When two installed packs ship the same templateId, the stringy form is rejected with `prompt_ref_ambiguous` and consumers MUST use the object form with `libraryId` to disambiguate (RFC 0028 §B \"Conflict resolution\").",
6
+ "oneOf": [
7
+ {
8
+ "type": "string",
9
+ "pattern": "^prompt:[a-z0-9][a-z0-9._-]{0,127}(@\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?)?$",
10
+ "description": "Compact stringy form: `prompt:<templateId>[@<version>]`. Examples: `prompt:writer`, `prompt:writer@1.2.0`, `prompt:vendor.acme.writer.v2@2.0.0`."
11
+ },
12
+ {
13
+ "type": "object",
14
+ "additionalProperties": false,
15
+ "required": ["templateId"],
16
+ "description": "Structured object form. Use when `libraryId` disambiguation, per-reference variable overrides, or version pinning is needed.",
17
+ "properties": {
18
+ "libraryId": {
19
+ "type": "string",
20
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$",
21
+ "description": "Library scope. Per RFC 0028, the host's default library is identified by `capabilities.prompts.library.id`; pack-sourced templates resolve via the installed pack's `name`."
22
+ },
23
+ "templateId": {
24
+ "type": "string",
25
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$",
26
+ "description": "Same pattern as PromptTemplate.templateId."
27
+ },
28
+ "version": {
29
+ "type": "string",
30
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$",
31
+ "description": "Pinned SemVer. When omitted, the host resolves the latest version available in the named library."
32
+ },
33
+ "variableOverrides": {
34
+ "type": "object",
35
+ "description": "Per-reference variable bindings, applied at composition time. Take precedence over node-input bindings (matching the four-layer resolution chain in RFC 0029 §A). Bindings are validated against PromptTemplate.variables before composition."
36
+ }
37
+ }
38
+ }
39
+ ]
40
+ }
@@ -0,0 +1,149 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/prompt-template.schema.json",
4
+ "title": "PromptTemplate",
5
+ "description": "Canonical wire shape for a named, versioned, variable-bound prompt body referenced by workflow nodes and agent manifests. See spec/v1/prompts.md §\"PromptTemplate\" for the canonical contract, RFC 0027 for the rationale, and prompt-ref.schema.json for the reference type that points at instances of this shape. Variable interpolation MUST use Mustache-compatible `{{varName}}` placeholders; unresolved required variables MUST cause the node to fail with `prompt_variable_unresolved`; unresolved optional variables render as the empty string per RFC 0027 §A.\n\nThe `text` field MAY contain `<UNTRUSTED>...</UNTRUSTED>` markers verbatim — hosts MUST preserve them through composition per SECURITY/threat-model-prompt-injection.md. Variables sourced from `secret` MUST be replaced with `[REDACTED:<secretId>]` markers in any observability output (e.g., `prompt.composed` events) per SECURITY/threat-model-secret-leakage.md §SR-1.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["templateId", "version", "kind", "text"],
9
+ "properties": {
10
+ "templateId": {
11
+ "type": "string",
12
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$",
13
+ "description": "Stable identifier. Convention: vendor-prefixed for portable templates (`vendor.acme.writer.v2`) or unprefixed for host-resident templates (`writer`). Same naming discipline as node-pack typeIds (host-extensions.md §\"Canonical-prefix table\")."
14
+ },
15
+ "version": {
16
+ "type": "string",
17
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$",
18
+ "description": "Semantic Versioning 2.0.0. Bumping major implies a breaking variable-schema or text change; consumers MUST pin to a specific version via PromptRef.version if they care about exact bodies."
19
+ },
20
+ "kind": {
21
+ "$ref": "./prompt-kind.schema.json",
22
+ "description": "Role this template plays when composed into an LLM call. A node MAY reference one template of each kind. Relative $ref resolves to the shared enum file for redocly's local-file walker; Ajv resolves it equivalently via the schema registry."
23
+ },
24
+ "text": {
25
+ "type": "string",
26
+ "maxLength": 65536,
27
+ "description": "Template body. Mustache-compatible `{{varName}}` placeholders are substituted at compose time using bindings from PromptVariable.source + variableOverrides. Hosts MAY cap below 65536 via capabilities.prompts.maxTemplateBytes, but MUST NOT exceed it."
28
+ },
29
+ "name": {
30
+ "type": "string",
31
+ "maxLength": 200,
32
+ "description": "Human-readable display name surfaced in authoring UIs and template pickers."
33
+ },
34
+ "description": {
35
+ "type": "string",
36
+ "maxLength": 2000,
37
+ "description": "One-paragraph description of what the template is for. Surfaced in authoring UI hover-text and library-list cards."
38
+ },
39
+ "variables": {
40
+ "type": "array",
41
+ "items": { "$ref": "#/$defs/PromptVariable" },
42
+ "description": "Typed interpolation slots. Hosts MUST validate runtime bindings against this array before composing. A `{{varName}}` placeholder that has no matching entry in `variables[]` MAY appear (treated as an optional variable with source `input` and no default) — hosts SHOULD warn at install time."
43
+ },
44
+ "modelHints": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "description": "Non-normative authoring hints. Hosts MAY surface these in editor UI (default temperature, suggested model class). They do NOT override per-node config or per-run RunOptions.configurable values.",
48
+ "properties": {
49
+ "modelClass": {
50
+ "type": "string",
51
+ "description": "Per AgentRef.modelClass enum + vendor extensions (e.g., `reasoning`, `writing`, `vendor.openwop.creative-writing`)."
52
+ },
53
+ "temperature": {
54
+ "type": "number",
55
+ "minimum": 0,
56
+ "maximum": 2,
57
+ "description": "Suggested sampling temperature."
58
+ },
59
+ "maxTokens": {
60
+ "type": "integer",
61
+ "minimum": 1,
62
+ "description": "Suggested max-tokens ceiling."
63
+ },
64
+ "envelopeType": {
65
+ "type": "string",
66
+ "description": "Suggested AI Envelope kind to use with this template, per RFC 0021. Opaque string in v1.x; future RFC MAY cross-validate against capabilities.supportedEnvelopes."
67
+ }
68
+ }
69
+ },
70
+ "tags": {
71
+ "type": "array",
72
+ "items": { "type": "string", "minLength": 1, "maxLength": 64 },
73
+ "maxItems": 32,
74
+ "description": "Free-form classification labels. Used by authoring UIs to group templates; not normative."
75
+ },
76
+ "meta": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "description": "Provenance + lifecycle metadata. Optional; hosts SHOULD populate it for any persistent storage. When `source: \"pack\"`, the host MUST populate `packName` + `packVersion` so clients can disambiguate templates that share a `templateId` across multiple installed packs (per RFC 0028 §B \"Conflict resolution\").",
80
+ "properties": {
81
+ "author": { "type": "string", "description": "Free-form author identifier (handle, email, etc.)." },
82
+ "createdAt": { "type": "string", "format": "date-time", "description": "ISO 8601 UTC timestamp of initial creation." },
83
+ "updatedAt": { "type": "string", "format": "date-time", "description": "ISO 8601 UTC timestamp of most recent update." },
84
+ "source": {
85
+ "type": "string",
86
+ "enum": ["host", "pack", "user"],
87
+ "description": "Provenance discriminator. `host`: ships with the host's built-in library; immutable. `pack`: installed via RFC 0028 prompt pack; immutable; MUST carry `packName` + `packVersion`. `user`: created at run time via mutating endpoints; mutable iff `capabilities.prompts.mutableLibrary: true`."
88
+ },
89
+ "packName": {
90
+ "type": "string",
91
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
92
+ "description": "RFC 0028 §C. When `source: \"pack\"`, the installed pack's `name` (matches `PromptPackManifest.name`). Required when `source: \"pack\"`; absent otherwise. Lets clients pass a structured `PromptRef` with `libraryId` set to this value to disambiguate templates that share a `templateId` across packs."
93
+ },
94
+ "packVersion": {
95
+ "type": "string",
96
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$",
97
+ "description": "RFC 0028 §C. When `source: \"pack\"`, the installed pack's `version`. Required when `source: \"pack\"`; absent otherwise."
98
+ }
99
+ },
100
+ "allOf": [
101
+ {
102
+ "if": { "properties": { "source": { "const": "pack" } }, "required": ["source"] },
103
+ "then": { "required": ["source", "packName", "packVersion"] }
104
+ }
105
+ ]
106
+ }
107
+ },
108
+ "$defs": {
109
+ "PromptVariable": {
110
+ "type": "object",
111
+ "additionalProperties": false,
112
+ "required": ["name", "type", "required"],
113
+ "description": "Typed interpolation slot. Bindings are validated against this declaration before composition; unresolved required slots MUST fail the node with `prompt_variable_unresolved`. Variables sourced from `secret` MUST be redacted to `[REDACTED:<secretId>]` markers in observability output per SECURITY/threat-model-secret-leakage.md §SR-1.",
114
+ "properties": {
115
+ "name": {
116
+ "type": "string",
117
+ "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,63}$",
118
+ "description": "Variable identifier. MUST match the `{{name}}` placeholder pattern in `text`. Pattern aligns with common templating engines (Mustache, Handlebars, Liquid) — no dashes, no dotted paths."
119
+ },
120
+ "type": {
121
+ "type": "string",
122
+ "enum": ["string", "number", "boolean", "array", "object"],
123
+ "description": "JSON-Schema-style type hint. Hosts SHOULD validate the bound value's type against this declaration; type-mismatch MAY warn or fail per host policy (no normative MUST yet — see RFC 0027 §A)."
124
+ },
125
+ "required": {
126
+ "type": "boolean",
127
+ "description": "When true, an absent binding fails the node with `prompt_variable_unresolved`. When false, the variable renders as `defaultValue` (if present) or the empty string."
128
+ },
129
+ "source": {
130
+ "type": "string",
131
+ "enum": ["input", "variable", "secret", "context"],
132
+ "description": "Where the binding comes from. `input`: node input port. `variable`: run-scoped variable (`ctx.variables.get`). `secret`: BYOK secret reference — MUST be redacted in observability events per RFC 0027 §E. `context`: host-provided implicit context (current user id, run id, etc.). Default when omitted: `input`."
133
+ },
134
+ "extractPath": {
135
+ "type": "string",
136
+ "description": "JSONPath into the source. When omitted, the entire source value binds to `name`. Hosts that don't support JSONPath MAY treat this as opaque dotted-path and surface an `unsupported_extract_path` warning."
137
+ },
138
+ "defaultValue": {
139
+ "description": "Used when `required: false` and the source resolves to undefined. Any JSON-serializable value."
140
+ },
141
+ "description": {
142
+ "type": "string",
143
+ "maxLength": 500,
144
+ "description": "Human-readable explanation. Surfaced in authoring UIs."
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/proposal.schema.json",
4
+ "title": "Proposal",
5
+ "description": "RFC 0096 §B. A reviewable-learning proposal — an INERT, draft-state reusable artifact (skill/pack/template/automation) the host synthesized from run/tool traces, that MUST NOT influence the resolution, planning, or execution of any run while in any state other than `applied`. Activation is delegated to RFC 0051 approval-gate or RFC 0049 RBAC (no new authorization path). On `apply` the installed artifact MUST byte-match the last-persisted `artifact` (no silent re-synthesis). `rationale` and `provenance.sourceRunIds` are SR-1 redaction-safe (no secrets/PII). Gated on the `agents.proposals` capability.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["id", "kind", "state", "artifact", "provenance", "owner", "createdAt"],
9
+ "properties": {
10
+ "id": {
11
+ "type": "string",
12
+ "minLength": 1,
13
+ "description": "Host-assigned identifier, stable across revisions."
14
+ },
15
+ "kind": {
16
+ "type": "string",
17
+ "enum": ["agent-pack", "workflow-chain-pack", "prompt-template", "automation"],
18
+ "description": "The reusable artifact kind. `agent-pack` (RFC 0003), `workflow-chain-pack` (RFC 0013), `prompt-template` (RFC 0027), `automation` (RFC 0052 scheduled job)."
19
+ },
20
+ "state": {
21
+ "type": "string",
22
+ "enum": ["draft", "revised", "applied", "rejected", "archived"],
23
+ "description": "Lifecycle state. Only `applied` may influence a run. `draft`/`revised` are inert; `rejected`/`archived` are terminal-inert."
24
+ },
25
+ "title": {
26
+ "type": "string",
27
+ "description": "Human-facing label. SR-1 redaction-safe."
28
+ },
29
+ "rationale": {
30
+ "type": "string",
31
+ "description": "Plain-language justification. SR-1 redaction-safe — no secrets/PII."
32
+ },
33
+ "artifact": {
34
+ "type": "object",
35
+ "description": "The proposed artifact, shaped by `kind` (an RFC 0003 pack manifest, an RFC 0013 chain pack, an RFC 0027 template, an RFC 0052 job spec). Inert until applied. Deliberately open (`additionalProperties` not constrained here) because the payload conforms to the kind's own existing schema, validated by the host at `apply` (malformed-for-kind ⇒ 422).",
36
+ "$comment": "Intentionally open object — the artifact body is validated against the kind's own schema, not this envelope."
37
+ },
38
+ "provenance": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "required": ["sourceRunIds"],
42
+ "description": "Where the proposal came from.",
43
+ "properties": {
44
+ "sourceRunIds": {
45
+ "type": "array",
46
+ "items": { "type": "string", "minLength": 1 },
47
+ "description": "Runs whose traces produced this proposal (RFC 0040 causation-compatible). SR-1 redaction-safe."
48
+ },
49
+ "synthesizerModel": {
50
+ "type": "string",
51
+ "description": "Opaque identifier of the model/process that synthesized the draft."
52
+ }
53
+ }
54
+ },
55
+ "duplicateOf": {
56
+ "type": ["string", "null"],
57
+ "default": null,
58
+ "description": "Existing artifact ref this proposal restates/overlaps, when `agents.proposals.duplicationDetection` is on. `null` when unknown or detection is off."
59
+ },
60
+ "owner": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["tenant"],
64
+ "description": "RFC 0048 identity triple that owns this proposal. Redaction-safe — `principal` is an opaque id, never PII or credential material. Single-tenant hosts populate at least `tenant`.",
65
+ "properties": {
66
+ "tenant": { "type": "string", "minLength": 1, "description": "Top-level isolation boundary." },
67
+ "workspace": { "type": "string", "minLength": 1, "description": "Optional sub-tenant within the tenant (RFC 0048 workspace)." },
68
+ "principal": { "type": "string", "minLength": 1, "description": "Acting identity (user or agent) — opaque id, never PII." }
69
+ }
70
+ },
71
+ "activation": {
72
+ "type": ["object", "null"],
73
+ "default": null,
74
+ "description": "Populated only when `state: applied`: the RFC 0051 approval reference (if `activation = approval-gate`) and the resulting installed artifact ref.",
75
+ "additionalProperties": false,
76
+ "properties": {
77
+ "approvalId": { "type": ["string", "null"], "description": "RFC 0051 approval/gate id when activation routed through an approval gate." },
78
+ "installedArtifactRef": { "type": "string", "description": "Ref of the artifact installed on `apply` (RFC 0043 install path)." }
79
+ }
80
+ },
81
+ "createdAt": { "type": "string", "format": "date-time" },
82
+ "updatedAt": { "type": "string", "format": "date-time" }
83
+ }
84
+ }