feat(adagents): directory inverse-lookup + divergence detector (Parts 2+3 of #749)#752
Draft
bokelley wants to merge 3 commits into
Draft
feat(adagents): directory inverse-lookup + divergence detector (Parts 2+3 of #749)#752bokelley wants to merge 3 commits into
bokelley wants to merge 3 commits into
Conversation
…r (Parts 2+3 of #749) Part 2 — fetch_agent_authorizations_from_directory: New async function wrapping GET /api/v1/agents/{agent_url}/publishers on the AAO directory. Returns AgentDirectoryLookup (paged) with one AgentPublisherEntry per authorized publisher. Provenance fields (discovery_method, manager_domain) align with AdAgentsValidationResult so callers can route directory-sourced and per-domain results through the same code path. Mutable status default avoided (uses None → ["authorized"]). Part 3 — detect_publisher_properties_divergence: New async verifier that compares the directory's property counts (inline resolution) against direct per-child adagents.json fetches (federated resolution). Returns a DivergenceReport (list of PublisherDivergence dataclasses) — empty means no divergence. Per adcp#4827, federated wins on disagreement; this function surfaces the signal for operator monitoring. sample_size caps sweeps over large managed networks (cafemedia = ~6,800 child fetches without a cap). Refs #749 https://claude.ai/code/session_01RDYrywLhVbd4crrAHkTnsH
…(Parts 2+3 of #749) BLOCKER 1 — missing_in_inline/missing_in_federated were always []; changed to list[str] | None where None signals count-only mode (directory doesn't return property IDs). Callers can now branch on None vs [] correctly. Docstring updated to call out the count-only limitation explicitly. BLOCKER 2 — Count-equality was silently treated as "no divergence" even though set divergence (same-count property replacement) is undetectable without IDs. Docstring now documents this false-negative path; fields are None not [] to prevent callers from treating empty lists as "diff computed, no gaps". NIT — status query param now uses repeated keys (?status=a&status=b) via a list-of-tuples param_list, not comma-joined (?status=a%2Cb). Tests updated to assert the repeated-key form. Refs #749 https://claude.ai/code/session_01RDYrywLhVbd4crrAHkTnsH
- Docstring Example in detect_publisher_properties_divergence branches on missing_in_inline is None (count-only mode) so copy-paste doesn't raise TypeError on None. - Export AgentDirectoryLookup, AgentPublisherEntry, PublisherDivergence, DivergenceReport, fetch_agent_authorizations_from_directory, and detect_publisher_properties_divergence from adcp.__init__. - Add isinstance guard on directory response so a non-dict body raises AdagentsValidationError instead of bare AttributeError. - Use row.get() + skip-on-empty for publisher_domain instead of bare KeyError-raising access; use 'or' chain to avoid None fallback. - Assert caller-provided client is not closed in two tests. Refs #749 https://claude.ai/code/session_01RDYrywLhVbd4crrAHkTnsH
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #749
Implements Parts 2 and 3 of #749, following the spec PRs adcp#4828 (directory endpoint) and adcp#4827 (divergence rule). Part 1 (bug fix) shipped as #750.
Part 2 —
fetch_agent_authorizations_from_directoryNew async wrapper for
GET /api/v1/agents/{agent_url}/publisherson the AAO directory (endpoint path confirmed by @bokelley in #749's comments;%-encodesagent_urlin the path per RFC 3986).Returns
AgentDirectoryLookup(paged) with oneAgentPublisherEntryper publisher.AgentPublisherEntrycarries the samediscovery_method/manager_domainprovenance vocabulary asAdAgentsValidationResultso callers can route directory-sourced and per-domain results through the same code path.statususes repeated query params (?status=authorized&status=revoked) rather than a comma-joined string.Part 3 —
detect_publisher_properties_divergenceNew async verifier that compares the directory's
properties_authorizedcount (inline resolution) against a per-child direct adagents.json fetch (federated resolution). ReturnsDivergenceReport— an empty list means no count divergence detected.Per adcp#4827 §Resolution-paths, the federated result is authoritative.
sample_sizecaps sweeps against large managed networks (cafemedia = ~6,800 child fetches without a cap).Known limitation (documented in type + docstring): The AAO directory currently returns
properties_authorizedcounts, not property-ID lists. Count-equality is a necessary but not sufficient condition for set-equality (same-count property replacement is undetectable).missing_in_inlineandmissing_in_federatedarelist[str] | NonewhereNonesignals count-only mode — callers must NOT treatNoneas "empty diff computed." A future?include=propertiesdirectory parameter will enable full(publisher_domain, property_id)set-diff.New public exports
All six new symbols are exported from
adcp.__init__:AgentDirectoryLookup,AgentPublisherEntry,PublisherDivergence,DivergenceReport,fetch_agent_authorizations_from_directory,detect_publisher_properties_divergenceWhat was tested
ruff check src/adcp/adagents.py src/adcp/__init__.py— cleanpython -m mypy src/adcp/adagents.py— clean (0 errors)pytest tests/test_adagents.py— 131 passed, 0 failedfetch_agent_authorizations_from_directory: field deserialization, URL encoding, cursor pagination, default-status repeated-key encoding, custom directory URL, caller-client not-closed assertiondetect_publisher_properties_divergence: no-divergence (count match), count divergence (missing_in_* areNonein count-only mode), child fetch error, sample_size cap, caller-client not-closed assertionPre-PR review
Two review→fix rounds (within the 2-iteration cap):
Round 1:
len()onNonefields after BLOCKER 1 fix); fixed in round 2missing_in_inline/missing_in_federatedalways[]— fields useless and misleading), BLOCKER 2 (count-equality silently swallows set divergence), NIT (status comma-joining vs repeated keys); all three addressedRound 2:
AgentPublisherEntry.discovery_methodtypedstrnotDiscoveryMethod— correct given"adagents_authoritative"is outside the existing Literal; docstring claim of alignment clarified)None-sentinel designNits (not fixed):
AgentPublisherEntry.discovery_method: stris a wider type thanDiscoveryMethodbecause the directory uses"adagents_authoritative"which is not in the existing Literal; typed asstrintentionallydata.get("publishers") or data.get("results")fallback will silently return[]if the directory adds an"items"key — acceptable for now, documented in the response-parsing commentSession: https://claude.ai/code/session_01RDYrywLhVbd4crrAHkTnsH
Generated by Claude Code