feat(a2a): Agent Card discovery endpoint #1123

Merged
HAL9000 merged 11 commits from feature/m9-agent-card into master 2026-06-12 04:12:49 +00:00

11 Commits

Author SHA1 Message Date
controller-ci-rerun aa082ced92 chore: re-trigger CI [controller]
CI / push-validation (pull_request) Successful in 27s
CI / lint (pull_request) Successful in 37s
CI / helm (pull_request) Successful in 45s
CI / quality (pull_request) Successful in 56s
CI / build (pull_request) Successful in 58s
CI / typecheck (pull_request) Successful in 1m11s
CI / security (pull_request) Successful in 1m24s
CI / unit_tests (pull_request) Successful in 4m50s
CI / docker (pull_request) Successful in 1m36s
CI / integration_tests (pull_request) Successful in 10m13s
CI / coverage (pull_request) Successful in 11m6s
CI / status-check (pull_request) Successful in 3s
2026-06-11 20:14:55 -04:00
controller-ci-rerun 010014398c chore: re-trigger CI [controller]
CI / lint (pull_request) Failing after 0s
CI / typecheck (pull_request) Failing after 1s
CI / security (pull_request) Failing after 0s
CI / quality (pull_request) Failing after 0s
CI / integration_tests (pull_request) Failing after 0s
CI / unit_tests (pull_request) Failing after 0s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / build (pull_request) Failing after 1s
CI / helm (pull_request) Failing after 1s
CI / push-validation (pull_request) Failing after 0s
CI / status-check (pull_request) Failing after 1s
2026-06-11 20:00:04 -04:00
controller-ci-rerun ff05f8ed35 chore: re-trigger CI [controller] 2026-06-11 20:00:04 -04:00
cleveragents-auto 432028b284 chore: worker ruff auto-fix (pre-push lint gate) 2026-06-11 20:00:04 -04:00
HAL9000 577820c8ba test(a2a): cover start() body and request_shutdown None branch; pragma diagnostics fallback
Add two BDD scenarios to server_lifecycle.feature that bring
previously unreachable code under coverage:

- "ServerLifecycle start runs uvicorn and marks lifecycle stopped":
  mocks uvicorn.Server so start() completes without binding a real
  port; covers the full start() body (lines 105-133) and the
  _install_signal_handlers() call path (lines 148-159). Signal
  handlers are saved and restored in a finally block so the test
  runner's SIGINT/SIGTERM handlers are not permanently clobbered.

- "ServerLifecycle request_shutdown is a no-op when server not
  started": calls request_shutdown() on a fresh lifecycle where
  _server is None; covers the False branch of the
  `if self._server is not None:` guard (previously only the True
  branch was exercised by the mock-server scenario).

Also marks the diagnostics-only skill fallback in agent_card.py
(lines 244-251) with # pragma: no cover — the current A2aLocalFacade
never surfaces _cleveragents/diagnostics/ operations, making this
branch structurally unreachable without a future facade extension.

ISSUES CLOSED: #867
2026-06-11 20:00:04 -04:00
HAL9000 5020f4c08b test(a2a): cover parse error and internal error paths; exclude run_server
Add BDD scenarios for two previously uncovered asgi_app.py paths:
- A2A endpoint returns -32700 for actual invalid JSON bytes (parse error)
- A2A endpoint returns -32603 when facade dispatch raises unexpectedly

The existing "malformed request" scenario sent valid JSON with bad schema,
exercising only the -32600 Invalid Request path. The parse error path
(await request.json() catching JSONDecodeError) and the catch-all
exception handler were never triggered, dropping coverage below 96.5%.

Also marks run_server() with # pragma: no cover — it is a blocking entry
point that wraps ServerLifecycle.start() and cannot be exercised in a
unit-test environment without starting a real server.

ISSUES CLOSED: #867
2026-06-11 20:00:04 -04:00
HAL9000 e92e83c590 fix(a2a): decouple A2aVersion from JSONRPC_VERSION
A2aVersion.CURRENT was incorrectly set equal to JSONRPC_VERSION ("2.0"),
conflating the CleverAgents A2A API version with the JSON-RPC protocol
version. The Agent Card `version` field represents the CleverAgents API
version ("1.0"), not the JSON-RPC wire protocol version ("2.0").

Restores A2aVersion.CURRENT = "1.0" and SUPPORTED = ("1.0",), fixing
4 failing BDD scenarios in agent_card.feature and the Robot integration
test "Build Agent Card From Facade".

ISSUES CLOSED: #867
2026-06-11 20:00:04 -04:00
controller-ci-rerun 83974f69a4 chore: re-trigger CI [controller] 2026-06-11 20:00:04 -04:00
HAL9000 9c3b0331a2 fix(a2a): align A2A endpoint with JSON-RPC 2.0 wire format changes
- Fix asgi_app.py: use a2a_request.method instead of a2a_request.operation
  (A2aRequest model was updated in master to use JSON-RPC 2.0 field names)
- Fix server_lifecycle_steps.py: send JSON-RPC 2.0 wire format with
  "method" field; check result.status instead of top-level status
- Fix server_lifecycle.feature: update step name to match new step
  definition (A2A response result status)
- Fix helper_server_lifecycle.py: use "method" field in JSON-RPC 2.0
  payload; check result.status in response
2026-06-11 20:00:04 -04:00
HAL9000 e4224eb8ec fix(a2a): resolve JSON-RPC protocol conformance and code quality issues
- Fix malformed JSON parse error: wrap request.json() in try/except,
  return -32700 Parse error instead of unhandled HTTP 500
- Fix JSON-RPC error responses: add required 'id' field to all error
  responses per JSON-RPC 2.0 Section 5
- Fix HTTP status codes: return HTTP 200 for all JSON-RPC responses
  (error codes expressed in JSON body per JSON-RPC 2.0 over HTTP)
- Fix error message leakage: return generic messages instead of raw
  Pydantic ValidationError internals (CWE-209)
- Add catch-all exception handler returning -32603 Internal error
- Fix Agent Card url field: use base server URL without /a2a suffix;
  interfaces[0].url correctly uses endpoint URL with /a2a suffix
- Fix 0.0.0.0 host: substitute 127.0.0.1 for Agent Card URL
- Fix context typing: replace context: Any with context: Context in
  all step files per project convention
- Fix inline imports: move all imports to top of step files
- Fix _COMMANDS typing: use dict[str, Callable[[], None]] to avoid
  type: ignore suppression in helper files
- Add BDD scenarios for entity-sync and namespace-mgmt skill enumeration
- Update server_lifecycle.feature: correct HTTP status assertions to 200

ISSUES CLOSED: #867
2026-06-11 19:58:52 -04:00
freemo d3b9b8c8b8 feat(a2a): Agent Card discovery endpoint
Implement A2A Agent Card discovery per ADR-047 and issue #867:

- AgentCard Pydantic model (agent_card.py) with nested models for
  skills, capabilities, extensions, security schemes, and interfaces.
- Factory function build_agent_card() enumerates supported operations
  from the facade and maps them to A2A skills (plan-lifecycle,
  registry-crud, context-mgmt, entity-sync, namespace-mgmt,
  health-diagnostics).
- Version negotiation: supportedVersions and version fields from
  A2aVersion constants.
- A2A conformance validation (validate_agent_card_conformance) checks
  required fields, version support, and structural integrity.
- Updated ASGI app to build the Agent Card from the facade model
  instead of a raw dict, with conformance validation at startup.
- Behave BDD tests: 34 scenarios covering model construction, field
  validation, conformance checks, serialization, endpoint responses,
  and skill enumeration from facade operations.
- Robot Framework integration tests: 6 test cases for build, conformance,
  endpoint, serialization, skill enumeration, and version info.
- Updated A2A package exports and CHANGELOG.

ISSUES CLOSED: #867
2026-06-11 19:57:39 -04:00