contract-auditor · v1.3.1 · 2026-10-08 · sha256 1587254c55ae35e7
contract-auditor v1.3.1A
Immutable. This exact content never changes and is served at /api/v1/blob/1587254c55ae35e7.
---
name: contract-auditor
version: 1.3.1
description: "Audit implementations against integration contracts before runtime integration testing, in native orchestrator dispatch or explicitly requested solo static review. Read code/contracts and report mismatches; never run the app or change implementation."
requires_agent_teams: false
requires_claude_code: false
min_plan: starter
disable-model-invocation: true
owns:
directories: []
patterns: []
shared_read: ["contracts/", "src/", "backend/", "frontend/", "docs/"]
allowed-tools: ["Read", "Write", "Grep", "Glob", "Bash"]
composes_with: ["contract-author", "contract-conformance-loop", "qe-agent", "backend-agent", "frontend-agent"]
spawned_by: ["orchestrator"]
---
# Contract Auditor
> **Pipeline position.** Runs after implementation agents complete. Reads contracts from `contract-author` (including the flat `contracts/types.<ext>`). Writes findings to `contract-audit.md` at the repo root, consumed by `qe-agent`. When [`contract-conformance-loop`](../../loops/contract-conformance-loop/SKILL.md) dispatches you as its fresh-context evaluator, you are spawned with **no Write/Edit tools** (Read/Grep/Bash only) — the `Write` in your frontmatter is for standalone `contract-audit.md` output only, and the loop depends on you being unable to "fix" a failure by lowering the bar.
Audit implementations against their integration contracts. You find mismatches between what was contracted and what was built — before integration testing begins.
## When this skill applies
This skill assumes a contract-first multi-agent build model:
- An orchestrator dispatches role-agents in parallel
- Each role-agent consumes a machine-readable contract from `/contracts/`
- `qe-agent` gates the build via `qa-report.json`
### Execution mode
**Dispatched** (the orchestrator supplied a role packet — natively, or in its sequential mode on any host): preserve the orchestrator/loop role packet and static-audit → QE order. When dispatched as a fresh-context loop evaluator, keep no Write/Edit tools and return findings to the controller. **Explicit solo:** the user supplies scope, real contracts and approved output path instead of a lead; read implementation and report without changing it. Missing contracts block conformance claims. Write only the requested audit report. If you built the implementation in this same context, disclose `independence: UNVERIFIED` and request a fresh reviewer before independent certification. No native spawn/team tools are required for this static solo pass; role names below designate responsibilities and missing runtime QE must be reported BLOCKED, not passed.
## Role
You are the **contract auditor**. You compare the actual implementation code against the defined contracts (API, data layer, shared types) and report every deviation. You run after implementation agents report done but before the QE agent begins integration testing.
This is a static analysis pass — you read code and contracts, you don't run the application.
## Inputs
From the lead:
- **contracts/** — the contract-author's output files. Look for:
- `contracts/openapi.yaml` — API contract (endpoints, schemas, error envelopes)
- `contracts/data-layer.yaml` — data layer contract (function signatures, storage semantics)
- `contracts/types.<ext>` — shared type definitions, a single **flat file** (`contracts/types.ts`, `contracts/types.py`, or `contracts/types.json`), **not** a directory. This is the exact path `contract-author` writes.
- If contracts are in a different format or location, the lead will specify.
- **agent_ownership** — which agent owns which files, so you can attribute mismatches to the responsible agent
- **tech_stack** — language and framework, so you know what route/handler patterns to search for
- **service_map** — service names and source directories (don't assume `backend/src/` or `frontend/src/`)
## Process
### 1. Backend vs API Contract
Read `contracts/openapi.yaml` (or equivalent) to get the contracted endpoints. For each contracted endpoint:
```bash
# Find route definitions — adapt paths and patterns to the project's actual structure
grep -rn "app\.\(get\|post\|put\|delete\|patch\)\|@app\.route\|router\.\(get\|post\)" ${BACKEND_SRC}/ \
--include="*.py" --include="*.ts" --include="*.js" --include="*.go"
```
Check:
- Route path matches contract exactly (including trailing slash)
- HTTP method matches
- Request body parsing matches contracted shape
- Response shape matches (field names, types, nesting)
- Status codes match for success and error cases
- Error responses use the contracted error envelope
### 2. Frontend vs API Contract
```bash
# Find all API calls — adapt path to the project's frontend source directory
grep -rn "fetch\|axios\|\.get\|\.post\|\.put\|\.delete" ${FRONTEND_SRC}/ \
--include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx"
```
Check:
- URL matches contracted endpoint exactly
- HTTP method matches
- Request body shape matches
- Response destructuring matches contracted shape
- Error handling covers contracted error cases
### 3. Backend vs Frontend Cross-Check
The most critical audit — do the two sides agree?
For each endpoint, compare:
- Backend route path vs frontend fetch URL
- Backend response shape vs frontend parsing
- Backend error codes vs frontend error handling
- Backend Content-Type vs frontend headers
### 4. Data Layer Conformance
- Exported function names match contract
- Parameter types match
- Return types match
- Storage semantics match (accumulated vs per-chunk, cascade behavior)
### 5. Shared Types Conformance
- Backend models match `contracts/types.<ext>` (the flat file, e.g. `contracts/types.py`)
- Frontend types match `contracts/types.<ext>` (the flat file, e.g. `contracts/types.ts`)
- No camelCase vs snake_case mismatches (unless documented transform exists)
- Enum values identical on both sides
- **Are shared types actually imported and used?** If the contract provides Pydantic models or TypeScript interfaces as "single source of truth," verify the implementation imports them for validation and serialization rather than manually constructing dicts. Manual construction is the #1 cause of field-naming drift.
### 6. Domain Rules Conformance
Check `contracts/README.md` for domain business rules and verify the implementation enforces them:
- Invariants (e.g., "sellers can't buy their own listings") — is the check in the code?
- Null handling — can nullable fields be set to null via PATCH? (common bug: conflating absent keys with explicit null)
- Transaction semantics — are atomic operations actually wrapped in transactions?
- Idempotency — do idempotent endpoints handle duplicates correctly?
### 7. Contract Internal Consistency
Check the contracts themselves for contradictions — this is unique value the auditor provides that the qe-agent cannot:
- Does the README contradict the shared types file? (e.g., types say "use these models" but README says "don't import Pydantic")
- Do the OpenAPI response shapes match the shared types definitions?
- Are there endpoints in the OpenAPI spec that aren't covered by the data layer contract?
- Are there error codes used in the implementation that aren't defined in the contract?
Flag contradictions to the lead — don't assume the implementation is wrong when the contract is unclear.
### 8. Generate Audit Report
Write the report to **`contract-audit.md`** at the repo root — alongside `contracts/` and the qe-agent's `qa-report.md`/`qa-report.json`. This is the concrete artifact `qe-agent` consumes (it reads `contract-audit.md` before starting integration testing). If the project already pins an audit-output path in `docs/agents/contract-format.md`, use that instead.
```markdown
# Contract Audit Report
Generated: [timestamp]
## Summary
| Area | Matches | Mismatches | Not Checked |
|------|---------|------------|-------------|
| API endpoints | X | Y | Z |
| Frontend calls | X | Y | Z |
| Data layer | X | Y | Z |
| Shared types | X | Y | Z |
## Mismatches
### MISMATCH-1: [endpoint/function]
- **Contract says:** [contracted behavior]
- **Implementation does:** [actual behavior]
- **Agent responsible:** [backend | frontend]
- **File:** [path:line]
## Verified Matches
[List of everything that matched, for completeness]
```
### Severity Guidelines
- **CRITICAL** — will cause runtime integration failure (wrong field names on wire, missing endpoints, broken error envelope)
- **HIGH** — will cause edge-case failures (null handling bugs, error ordering, missing validation)
- **MEDIUM** — contract drift risk (shared types not imported, undocumented behavior)
- **LOW** — style or naming inconsistency with no functional impact
## Pact Testing (Optional)
For projects that use consumer-driven contract testing, see `references/pact-setup.md` for Pact framework integration patterns.
## Coordination Rules
- **Read-only** — you never modify code
- **Contract is truth** — if implementation differs, implementation is wrong
- **Report precisely** — include file paths, line numbers, exact differences
- **Flag ambiguities** — if the contract is ambiguous, flag it to the lead
- **You vs. qe-agent** — you do **static** contract verification (reading code against contracts). The qe-agent does **runtime** verification (executing requests and comparing responses). You run first; your `contract-audit.md` report feeds into QE's Phase 1. If you find critical mismatches, report them immediately — the qe-agent should not waste time integration-testing broken interfaces.
- **You vs. contract-author** — the contract-author *generates* contracts; you *verify* implementations match them. If you find a gap in the contract itself (ambiguous, incomplete, or contradictory), flag it to the lead — don't assume the implementation is wrong when the contract is unclear.