fix(registry): flip 5 buying-vs-sales inversions missed by #3540 sweep — closes #3774#3776
Merged
Merged
Conversation
Closes #3774. Surfaced by Brian-style red-team of #3766. Same inversion class as #3540 swept across filter sites, but 5 sites slipped through because they had a different shape — function-call arguments and local- inference re-implementations rather than equality comparisons against stored type. ## listAgents("buying") -> listAgents("sales") at 3 call sites - server/src/http.ts:2007 — POST /api/crawler/run - server/src/http.ts:8729 — periodic property crawler boot (variable also renamed buyingAgents -> salesAgents and the comment fixed) - server/src/mcp-tools.ts:831 — find_agents_for_property MCP tool These pass the agent set into property-crawl logic that semantically operates on sales agents (the ones with publisher authorizations and list_authorized_properties responses). Pre-fix the filter was a no-op because the crawler internally re-filters on agent.type !== "sales" at crawler.ts:420 — but the call sites were misleading and load-bearing on the defensive re-filter. ## Diagnostic-endpoint local inference consolidated + polarity flipped server/src/http.ts:8442 and server/src/routes/registry-api.ts:5802 had duplicated inline inference that returned 'buying' for agents exposing get_products / create_media_buy / create_media — exactly inverted vs the canonical CapabilityDiscovery.inferAgentType. Visible bug for any consumer of the public discovery diagnostic endpoints: every sales agent reported as type='buying'. Extracted into a single helper: server/src/lib/diagnostic-agent-type-inference.ts Both endpoints now call inferDiagnosticAgentType. Loose substring matching preserved (separate concern from polarity); canonical strict-match path in CapabilityDiscovery is unchanged. ## Missing 'sales' in resource handler server/src/mcp-tools.ts:2058 hard-coded ["creative", "signals", "buying"] in its agent-resource type filter — pre-#3540 'buying' was the (incorrectly) only sell-side type, so 'sales' was never added. Post-#3540 this means agents://sales returns "Unknown resource type". Added 'sales' to the list. 'buying' kept because per #3766 the type is now meaningful. ## Tests New: server/tests/unit/diagnostic-agent-type-inference.test.ts pins the 12-case polarity matrix, including an exhaustive "NEVER returns 'buying'" invariant assertion. If anyone reverts polarity back to 'buying', the cases marked `// pinning #3774` fail loudly. 12/12 pass. Typecheck clean. ## Out of scope - Tightening the diagnostic helper's loose substring matching to align with CapabilityDiscovery.inferAgentType's strict matching. Loose matching is preserved here intentionally — diagnostic endpoints serve pre-onboarding probes where tool-name conformance is incomplete. Worth a follow-up if the diagnostic endpoints' false-positive rate becomes a concern. - Replacing the diagnostic helper with the canonical CapabilityDiscovery inference helper (different match semantics — strict vs loose). Same follow-up.
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.
Closes #3774. Surfaced by Brian-style red-team of #3766.
Same inversion class as PR #3540 swept across filter sites — but 5 sites slipped through because they had a different shape (function-call arguments and local-inference re-implementations rather than equality comparisons against stored type). Two were visible bugs in the public discovery diagnostic endpoints; three were silently aligned with the registry's defensive re-filter and would become live bugs if the defensive filter ever changed.
Sites flipped
http.ts:2007listAgents("buying")filter"sales"http.ts:8729listAgents("buying")filter +buyingAgentsvarsalesAgentsmcp-tools.ts:831listAgents("buying")filter"sales"http.ts:8442type: 'buying'returned for sales agentsregistry-api.ts:5802mcp-tools.ts:2058'sales'agents://salesreturns "Unknown resource type"'sales'What changed structurally
The two duplicated local-inference blocks at
http.ts:8442andregistry-api.ts:5802are now consolidated into a single helper:Both diagnostic endpoints call it. Polarity is now in one place — future polarity changes need exactly one fix, not two. Loose substring matching preserved as-is (separate concern from polarity; the canonical strict-match inference at
CapabilityDiscovery.inferAgentTypeis unchanged).Why this wasn't caught in #3540
#3540's sweep used
grep -E 'type [!=]==? \"buying\"'for filter-site inversions on stored agent.type. These 5 sites are different:listAgents("buying")— function-call argument, not a comparison'buying'based on tool surface, not compare against stored typeA wider sweep at the time (or a smell-test for "any string literal
'buying'") would have caught them.Test plan
server/tests/unit/diagnostic-agent-type-inference.test.ts— 12/12 pass. Pins the polarity matrix including an exhaustiveNEVER returns 'buying'invariant assertion. If anyone reverts polarity, cases marked// pinning #3774fail loudly.npx tsc --noEmit -p server/tsconfig.json— clean.Backwards compatibility
Non-breaking on the wire. Only behavior change: the public discovery diagnostic endpoints now return
type: 'sales'for sales-tool-exposing agents instead oftype: 'buying'. Any consumer that was relying on the broken'buying'response was already wrong —'sales'is the correct AdCP polarity per #3540 and #3495.Pairs with
This sweep makes the registry's
agent.typepolarity consistent across the filter sites, the inference paths, the resource handler, and the diagnostic endpoints. No remaining'buying'references except the deliberateby_typestat tallies (which correctly countbuying-typed agents).Out of scope
CapabilityDiscovery.inferAgentType's strict matching. Loose matching preserved here intentionally — diagnostic endpoints serve pre-onboarding probes where tool-name conformance is incomplete. Worth a follow-up if false-positive rate becomes a concern.