{
  "$comment": "webGCP bundle contract per spec §5.3 — https://webgcp.org/spec/v0.1/. Authored 2026-05-16. Validates against https://webgcp.org/schemas/bundle/v0.1.json (reserved URL, stub-published in the spec authoring repo).",
  "contract_uri": "urn:webgcp:news.energypager.com:news-article-retrieval/v0.1",
  "contract_version": "0.1.0",
  "$schema_canonical": "https://webgcp.org/schemas/bundle/v0.1.json",
  "name": "news-article-retrieval",
  "human_name": "News Article Retrieval — typed fields with provenance",
  "purpose": "An agent issuing a query about AI news receives 1..max_results articles, each with title, AI-generated summary, source URL, topic, source feed, timestamps, authority class, and confidence. Designed for the common reading-agent pattern where the agent needs provenance on every field, not a free-text blob. Pairs with the news-kb manifest at urn:webgcp:news.energypager.com:news-kb.",
  "preferred_source_kb": "urn:webgcp:news.energypager.com:news-kb",
  "input_schema": {
    "type": "object",
    "required": ["query"],
    "properties": {
      "query": {
        "type": "string",
        "minLength": 1,
        "maxLength": 500,
        "description": "Natural-language query or topic name"
      },
      "category": {
        "type": "string",
        "enum": [
          "ai-research",
          "machine-learning",
          "llms",
          "computer-vision",
          "robotics",
          "ai-ethics",
          "industry",
          "startups"
        ]
      },
      "max_age_days": {
        "type": "integer",
        "minimum": 1,
        "maximum": 90,
        "default": 30
      },
      "max_results": {
        "type": "integer",
        "minimum": 1,
        "maximum": 50,
        "default": 10
      }
    }
  },
  "fields": [
    {
      "name": "articles",
      "type": "array",
      "items_type": "Article",
      "required": true,
      "preferred_source_kb": "urn:webgcp:news.energypager.com:news-kb",
      "primitive_hint": "vector_hybrid",
      "freshness_sla": "PT15M",
      "authority_required": "derived",
      "on_failure": "hard_fail",
      "acl_class": "public_read",
      "pii_class": "none",
      "max_length": 50,
      "description": "Array of Article objects matching the query, sorted by relevance descending."
    }
  ],
  "type_definitions": {
    "Article": {
      "fields": [
        {
          "name": "id",
          "type": "string",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "canonical",
          "description": "Firestore document ID; stable across queries; safe to use as a cache key."
        },
        {
          "name": "title",
          "type": "string",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "canonical",
          "description": "Article title as published by the originating RSS source."
        },
        {
          "name": "summary",
          "type": "string",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "derived",
          "description": "Gemini Flash Lite generated summary (low thinking mode). authority=derived because it is a model output, not the canonical article body.",
          "max_length": 2000
        },
        {
          "name": "source_url",
          "type": "string",
          "format": "uri",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "canonical",
          "description": "Canonical URL of the article on the originating site. Agents SHOULD link to this for any user-facing citation."
        },
        {
          "name": "source_feed_id",
          "type": "string",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "canonical",
          "enum_from_manifest": "authority.canonical_sources",
          "description": "Stable identifier of the RSS feed this article came from."
        },
        {
          "name": "topic",
          "type": "string",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "derived",
          "enum": [
            "ai-research",
            "machine-learning",
            "llms",
            "computer-vision",
            "robotics",
            "ai-ethics",
            "industry",
            "startups"
          ],
          "description": "Topic classification (Gemini Flash Lite). authority=derived."
        },
        {
          "name": "published_at",
          "type": "string",
          "format": "date-time",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "canonical",
          "description": "ISO-8601 timestamp from the RSS source's pubDate field."
        },
        {
          "name": "retrieved_at",
          "type": "string",
          "format": "date-time",
          "required": true,
          "primitive_hint": "direct_lookup",
          "authority_required": "canonical",
          "description": "When this KB ingested the article. Governs the freshness_sla check at retrieval time."
        }
      ]
    }
  },
  "completeness_policy": {
    "all_required_present": "strict_satisfied",
    "any_required_missing": "degraded",
    "no_in_scope_kb": "out_of_scope_failure",
    "rationale": "Per spec §6.4 and §6.7 — typed failures rather than partial blanks."
  },
  "spec_pin": {
    "spec_url": "https://webgcp.org/spec/v0.1/",
    "spec_version": "0.1.0-draft.2026-05-16",
    "spec_section_references": [
      "§5.3 bundle contract schema",
      "§5.5 provenance (_meta on every field)",
      "§5.6 authority tagging",
      "§6.4 success response shape"
    ]
  },
  "$status_2026_05_16": "Contract authored statically. The query endpoint that fulfills this contract is Phase 2 work. L0 conformance currently asserts contract correctness only; runtime conformance gates on Phase 2 completion."
}
