UNMAPPED markers
The specification marks with UNMAPPED each rule of A2A it does not hold, in a YAML comment beside the place the rule belongs. ess/ has 41 markers: 40 name a construct ESS lacks (an ESS gap), 1 an open question. Each row links the marker's line and shows its first sentence; the comment there carries the source quote and, for an ESS gap, the refusal ESS gave.
The HTTP+JSON routes ESS cannot serve at A2A's path are on HTTP+JSON routes.
ess/components.yaml
| Line | Kind | Marker |
|---|---|---|
| 10 | ESS gap | the binding itself. ESS 0.67.0 binds a command to an HTTP route (ess-http/1), one method and path each, while JSON-RPC sends every method to one endpoint and dispatches on the body's method. |
| 33 | ESS gap | no authored scenario holds -32601 or -32602. An act expects one refusal, refused: not_granted; there is none for an input the declaration rejects or for an unknown command, and a scenario naming an undeclared command is refused by name. |
| 59 | ESS gap | push delivery. Section 4.3.3: "When a task update occurs, the agent sends an HTTP POST request to the configured webhook URL", and the same section: "Agents MUST attempt delivery at least once for each configured webhook". |
| 74 | ESS gap | the stream transport. Section 11.7: "REST streaming uses Server-Sent Events", answering Content-Type: text/event-stream with one data: line per StreamResponse; JSON-RPC streams over SSE too (section 9.4.2), gRPC as a server stream (10.7). |
More columns: swipe horizontally, or focus the table and use the arrow keys.
ess/domains/discovery.yaml
| Line | Kind | Marker |
|---|---|---|
| 229 | ESS gap | the exactly-one rule of the oneof. ESS 0.67.0 has no externally tagged union (a union without tag: is refused: "missing field tag"). |
| 292 | ESS gap | the exactly-one rule of the oneof, as for OAuthFlows above. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
ess/domains/tasks.yaml
| Line | Kind | Marker |
|---|---|---|
| 58 | ESS gap | the exactly-one rule. ESS 0.67.0 validates it as a type invariant (any: [all: [defined(text), not defined(raw), …], …]), but Part is reachable from the typed responses of GetTask, CancelTask, SubscribeToTask and SendMessage, and synthesis then refuses each returning outcome: "ESS-SYNTH-001: … … |
| 120 | ESS gap | a2a.proto, Artifact.artifact_id: "It must be unique within a task", and Artifact.parts: "Must contain at least one part." The second validates as a type invariant (parts.count >= 1), but synthesis refuses it: "record invariant on a response type a2a.tasks.Artifact has no executable observer". |
| 363 | ESS gap | the natural identity is the struct (task_id, config_id). ESS 0.67.0 refuses both ways to create one: instance: {task_id: input.task_id, id: input.id} gives "invalid type: map, expected a string", and a struct identity published by the creating event gives SYNTH-001 "a struct held by reference has … |
| 404 | ESS gap | the per-row boundary (which tasks and configurations this client may see); ESS 0.67.0 grants a whole view to an actor. |
| 428 | ESS gap | the summary is the only place ESS 0.67.0 carries the code, and nothing reads it. |
| 579 | ESS gap | ESS 0.67.0 answers a command when its outcome commits. Missing construct: an answer deferred until later commands (StartWorking, Complete, RequireInput, …) move the created row into a named set of states. |
| 604 | ESS gap | task-not-found, task-terminal, context-mismatch and continued depend on message.taskId, a member of the message input. |
| 656 | ESS gap | a2a.proto, SendMessageConfiguration.task_push_notification_config: "Configuration for the agent to send push notifications for task updates. |
| 714 | ESS gap | task-not-found, task-terminal, context-mismatch and continued depend on message.taskId, a member of the message input. |
| 785 | ESS gap | a2a.proto, SendMessageConfiguration.task_push_notification_config: "Configuration for the agent to send push notifications for task updates. |
| 826 | ESS gap | a2a.proto, GetTaskRequest.history_length: "The server MUST NOT return more messages than the provided value, but MAY apply a lower limit." Nothing below bounds the returned task.history by it. |
| 984 | ESS gap | nothing emits a2a.tasks.TaskSubscriptionResponse. Subscribing changes no task, and a preserving outcome that emits is refused: "ESS-COMMAND-004: a preserving outcome declares no assignment, event or error". |
| 1025 | open question | A2A v1.0.1 is silent on a second create with an id a configuration of the same task already carries; created then adds a second row with that pair. |
| 1029 | ESS gap | assigned writes row and config_id as two independent {generated: true} values; ESS 0.67.0 has no construct to generate the id once and reuse it in the stored field and the event payload, so nothing checks they agree. |
| 1057 | ESS gap | a task of another tenant, or of one when the request has none (and the reverse), answers TaskNotFound, as GetTask other-tenant says. |
| 1150 | ESS gap | the rule is on the configuration's tenant, not the task's. ESS 0.67.0 refuses a when_subject: guard beside this row-set guard: "ESS-COMMAND-009: a2a.tasks.GetTaskPushNotificationConfig selects on a row set (when_related: {entity, where, …}) and on a when_subject guard; one command reads one … |
| 1161 | ESS gap | the config answered is not bound to the matched row; a typed response is opaque to ESS 0.67.0, as on ListTaskPushNotificationConfigs. |
| 1200 | ESS gap | which rows configs holds. Section 3.1.9: "The operation MUST return all active push notification configurations for the specified task and MAY support pagination". |
| 1275 | ESS gap | a task of another tenant, or of one when the request has none (and the reverse), answers TaskNotFound, as GetTask other-tenant says. |
| 1283 | ESS gap | a no-op delete emits PushNotificationConfigDeleted; a separate no-op branch (when_related exists: false) is refused, ESS-SYNTH-001 "a step of the scenario changes rows of the selector's entity in a way synthesis does not follow". |
| 1374 | ESS gap | section 7.6.1, the agent "MUST include a TaskStatus message explaining the required authorization, unless the details of the authorization have been negotiated out-of-band or via an extension". |
| 1525 | ESS gap | the task's stored artifacts should gain input.artifact, or, with append, the parts of the artifact with the same artifact_id should grow (a2a.proto, TaskArtifactUpdateEvent.append: "the content of this artifact should be appended to a previously sent artifact with the same ID"). |
| 1596 | ESS gap | the exactly-one rule of the oneof. ESS 0.67.0 has no externally tagged union (a union without tag: is refused: "missing field tag"), and an emitting outcome must source every member, the absent ones included: leaving message out of the payload is refused, "ESS-COMMAND-005: emitted payload … |
| 1605 | ESS gap | the elements after the first. Section 3.1.2 follows the first Task with "zero or more TaskStatusUpdateEvent or TaskArtifactUpdateEvent objects", and section 3.5.2: "Events MUST be broadcast to all active streams for that task" and "Each stream MUST receive the same events in the same order". |
| 1663 | ESS gap | row has no A2A source; dropping it is refused, ESS-COMMAND-001 "acts on the instance named by row, which is no field of an emitted event of it". |
| 1683 | ESS gap | "Implementations MUST return tasks sorted by their status timestamp time in descending order". |
| 1689 | ESS gap | the cursor paging (page_size, page_token, next_page_token, "MUST use cursor-based pagination"). |
| 1698 | ESS gap | a view answers no error, so the protocol-negotiation refusals (VersionNotSupportedError -32009, ExtensionSupportRequiredError -32008; section 3.6.2 "agents MUST return a VersionNotSupportedError") are not declared for ListTasks. |
| 1711 | ESS gap | wire type is TaskState (TASK_STATE_*); ESS 0.67.0 has no map from it to the lifecycle states the filter compares. |
| 1742 | ESS gap | the wire spells the state TASK_STATE_*. ESS 0.67.0 gives a lifecycle state no wire spelling: states: [{name: Submitted, wire: TASK_STATE_SUBMITTED}, …] is refused "invalid type: map, expected a string", so the row carries the lifecycle name. |
| 1766 | ESS gap | the per-row boundary within the Agent's reads (which tasks one authenticated caller may see); ESS 0.67.0 grants a whole view to an actor, no subset of rows. |
| 1840 | ESS gap | row has no A2A source; dropping it is refused, ESS-SYNTH-001 on DeleteTaskPushNotificationConfig/deleted "published by no immediate, unfiltered, unparameterised, unpaged view carrying its identity". |
More columns: swipe horizontally, or focus the table and use the arrow keys.
ess/http.yaml
| Line | Kind | Marker |
|---|---|---|
| 8 | ESS gap | the /{tenant}/... additional binding of every operation, for example post: "/{tenant}/message:send" beside post: "/message:send". |
| 31 | ESS gap | DELETE carries its inputs outside the path in a JSON body, where section 11.5 says "HTTP methods that do not support request bodies (GET, DELETE) MUST transmit operation request parameters as path parameters or query parameters": query encoding is admitted on get only (ESS-HTTP-020). |
| 56 | ESS gap | a2a.proto CancelTask, post "/tasks/{id=*}:cancel", body "*", and SubscribeToTask, get "/tasks/{id=*}:subscribe" (section 11.3.2 writes POST /tasks/{id}:subscribe), keep their derived routes, post /tasks/commands/tasks:cancel and post /tasks/commands/tasks:subscribe. |
More columns: swipe horizontally, or focus the table and use the arrow keys.