Context
Filed as the AC5 follow-up of #16334. The handler-signature census (ai/scripts/diagnostics/mcpHandlerSignatureCensus.mjs) answered "is this mechanically checkable?" with yes, by construction: the classification IS mechanical, and the instrument already carries a --fail-on-defects lint mode. What does not exist yet is the gate that runs it on every PR.
Receipts from the census lane (both reproducible with --root <worktree>):
- Pre-fix tree (
dfdb0fc4dc, parent of the #16330 merge): defect set = 2 — get_ingestion_progress (class 2, destructure-under-positional) and get_pull_request_diff (class 3, truncation: 1 param for 4 contract args); starting set = 9 (independently reproduces the contributor's contract-side count from #16250).
- Current dev: defect set = 0, starting set = 7 (9 − the 2 now-annotated), suspects = 0, unresolved = 0, class 1 = 159.
--fail-on-defects exits 1 on the pre-fix tree, 0 on current dev.
The Problem
The bug class #16250 proved is re-fileable today: a contributor adds an operation to any of the six MCP servers whose handler destructures an object (or declares fewer params than the contract) without x-pass-as-object, and every existing check stays green — the contract validates, the tool lists, calls that pass only the first argument "work" (defaults win, extras dropped). The two production instances were found by hand, weeks apart. The census makes the class mechanically detectable; without a gate, detection stays a manual ritual that must be remembered.
The Architectural Reality
- Dispatcher:
ai/mcp/ToolService.mjs:107-112 — positional spread of argNames unless x-pass-as-object: true.
- Instrument:
ai/scripts/diagnostics/mcpHandlerSignatureCensus.mjs — census(root) returns classified rows for all 159 operations; --fail-on-defects is the CLI tripwire. Pure static analysis (yaml + acorn), no server boot, no network — unit-suite-priced.
- The named home (from #16334):
test/playwright/unit/ai/mcp/validation/OpenApiValidatorCompliance.spec.mjs — the existing contract-vs-implementation compliance spec. A sibling spec file in the same directory is equally in-pattern (GuideToolParity.spec.mjs precedent).
The Fix
Add a unit spec under test/playwright/unit/ai/mcp/validation/ that executes census(repoRoot) and asserts the gate conditions (ACs below). The standard unit config (playwright.config.unit.mjs) already runs in CI, so the gate inherits enforcement with no new workflow surface.
Gold standard rejected: a dedicated CI workflow step invoking the script's CLI. Heavier (new workflow file, new failure surface outside the suite agents already run locally), and it splits "did the contracts validate" (suite) from "do the handlers match the dispatch" (workflow) across two places a contributor must check. The suite is the existing home for contract-vs-implementation checks; keep the family together.
Acceptance Criteria
Out of Scope
- Repairing any operation a future red gate names — each repair is a live tool-surface behavior change with its own ticket and review (per #16334's Out of Scope).
- Changing the dispatcher, the contracts, or any handler.
- Extending the census taxonomy (suspects stay human-judged; the gate fires on classes 2 / 2M / 3 and unresolved only).
Related
- #16334 — the census (delivers the instrument; this ticket is its AC5 follow-up)
- #16250 / PR #16330 — the two proven defect instances and their fix
- #16231 — established that a missing annotation can break a call
Live latest-open sweep at 2026-08-02T11:46Z (20 newest open issues) + A2A in-flight claim scan (30 newest): no equivalent found.
Origin Session ID: session_5c970912-b750-4835-ad51-fbb3d2bc4ebe
Retrieval Hint: query_raw_memories("handler signature census lint gate fail-on-defects six servers")
Context
Filed as the AC5 follow-up of #16334. The handler-signature census (
ai/scripts/diagnostics/mcpHandlerSignatureCensus.mjs) answered "is this mechanically checkable?" with yes, by construction: the classification IS mechanical, and the instrument already carries a--fail-on-defectslint mode. What does not exist yet is the gate that runs it on every PR.Receipts from the census lane (both reproducible with
--root <worktree>):dfdb0fc4dc, parent of the #16330 merge): defect set = 2 —get_ingestion_progress(class 2, destructure-under-positional) andget_pull_request_diff(class 3, truncation: 1 param for 4 contract args); starting set = 9 (independently reproduces the contributor's contract-side count from #16250).--fail-on-defectsexits 1 on the pre-fix tree, 0 on current dev.The Problem
The bug class #16250 proved is re-fileable today: a contributor adds an operation to any of the six MCP servers whose handler destructures an object (or declares fewer params than the contract) without
x-pass-as-object, and every existing check stays green — the contract validates, the tool lists, calls that pass only the first argument "work" (defaults win, extras dropped). The two production instances were found by hand, weeks apart. The census makes the class mechanically detectable; without a gate, detection stays a manual ritual that must be remembered.The Architectural Reality
ai/mcp/ToolService.mjs:107-112— positional spread ofargNamesunlessx-pass-as-object: true.ai/scripts/diagnostics/mcpHandlerSignatureCensus.mjs—census(root)returns classified rows for all 159 operations;--fail-on-defectsis the CLI tripwire. Pure static analysis (yaml + acorn), no server boot, no network — unit-suite-priced.test/playwright/unit/ai/mcp/validation/OpenApiValidatorCompliance.spec.mjs— the existing contract-vs-implementation compliance spec. A sibling spec file in the same directory is equally in-pattern (GuideToolParity.spec.mjsprecedent).The Fix
Add a unit spec under
test/playwright/unit/ai/mcp/validation/that executescensus(repoRoot)and asserts the gate conditions (ACs below). The standard unit config (playwright.config.unit.mjs) already runs in CI, so the gate inherits enforcement with no new workflow surface.Gold standard rejected: a dedicated CI workflow step invoking the script's CLI. Heavier (new workflow file, new failure surface outside the suite agents already run locally), and it splits "did the contracts validate" (suite) from "do the handlers match the dispatch" (workflow) across two places a contributor must check. The suite is the existing home for contract-vs-implementation checks; keep the family together.
Acceptance Criteria
test/playwright/unit/ai/mcp/validation/runscensus()over all six servers and fails when the defect set (classes 2, 2M, 3) is non-empty, printing the defect rows as the failure message.unresolved > 0— a census that cannot see a binding is not a green census.mcpHandlerSignatureCensus.spec.mjs) already pins both shapes; this AC is about the GATE firing, not the classifier.UNIT_TEST_MODE=true npx playwright test -c test/playwright/playwright.config.unit.mjs.Out of Scope
Related
Live latest-open sweep at 2026-08-02T11:46Z (20 newest open issues) + A2A in-flight claim scan (30 newest): no equivalent found.
Origin Session ID: session_5c970912-b750-4835-ad51-fbb3d2bc4ebe
Retrieval Hint:
query_raw_memories("handler signature census lint gate fail-on-defects six servers")