Skip to content

[upstream-cq] cli/v0.9.0: Go discovery library + FooList/FooPage wire-shape convention — untracked compat surface vs #282 / #288 #289

@dwinter3

Description

@dwinter3

Triggering event

https://github.com/mozilla-ai/cq/releases/tag/cli/v0.9.0
Upstream PRs: mozilla-ai#372 (API envelope unification), mozilla-ai#373 (node discovery Go SDK)

What changed

1. Go discovery library (sdk/go/discovery/) — NOT covered by #282

While #282 tracks node discovery in the Python SDK, cli/v0.9.0 ships a parallel Go implementation with distinct concerns:

  • Functional-options Resolver (WithCacheDir, WithHTTPClient, WithLogger) wired into the Go SDK Client and CLI in place of all hardcoded /api/v1 prefixes.
  • XDG-compliant disk cache with mtime-TTL, atomic writes, re-validation on every read, and schema-invalid entry eviction.
  • Strict validation: JSON-Schema-conformant document, url.Parse-validated api_base_url, rejected unknown fields, rejected unsupported document/API versions.
  • cq.WithLogger(*slog.Logger) added to Go SDK Client — defaults to slog.DiscardHandler to protect MCP-over-stdio stdout (JSONRPC channel). Cache-write failures emit structured Warn only when a logger is wired.
  • Reference server explicitly returns 404 for /.well-known/cq-node.json so the SPA catch-all does not intercept it.

2. HTTP API wire-shape convention (FooList / FooPage) — NOT covered by #288

PR #372 doesn't just fix {data} envelope decoding — it codifies a documented architectural convention in docs/architecture.md §6 "HTTP API Conventions":

  • Unpaginated list endpoints → FooList = {data: [...]} (no count).
  • Cursor-paginated endpoints → FooPage shape (not yet shipped, but reserved).
  • Contract tests pin the shape; any stray top-level field (e.g. count) is now a test failure upstream.

Why it matters for 8th-layer

Surface Risk
Go SDK / AIGRP / DSN client code Any 8th-layer Go code that calls /api/v1/knowledge or /api/v1/users/me/api-keys and parses the raw JSON (not via updated SDK) will break — count is gone, top-level shape is now {data:[...]}.
8th-layer node split-origin deployments The Go discovery library's strict unknown-field rejection means a cq-node.json that 8th-layer extended (e.g. with AIGRP/DSN fields) will be rejected by upstream SDK consumers. FORK_DELTA position needed.
MCP-over-stdio (slog.DiscardHandler default) 8th-layer's MCP adapter must verify it does NOT wire a stdout-writing logger into cq.WithLogger — upstream explicitly chose DiscardHandler to avoid polluting the JSONRPC channel.
Future list endpoints Any new 8th-layer list endpoint must follow FooList/FooPage convention or it becomes a compat deviation the moment upstream clients consume it.

Recommended actions

  1. Audit all 8th-layer Go code (agent, core) for direct JSON parsing of /api/v1/knowledge or /api/v1/api-keys responses — migrate to updated SDK envelope decoder.
  2. Assess cq-node.json extension strategy: if 8th-layer's /.well-known/cq-node.json carries extra fields (AIGRP, DSN metadata), upstream Go SDK will reject it as unknown fields. Decide: contribute extension proposal upstream, or maintain a FORK_DELTA shim in the Go discovery client.
  3. Review MCP adapter logger wiring — confirm cq.WithLogger is called with a file/structured logger, never a stdout logger, in the MCP-over-stdio path.
  4. Update FORK_DELTA registry to reflect the Go discovery library as a parallel tracked surface alongside [upstream-cq] Node discovery protocol lands in Python SDK (/.well-known/cq-node.json) — evaluate fork compat + FORK_DELTA position #282 (Python).

Related issues

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions