The problem nobody is naming
When you hire a development house to build something, you don't just describe the project in a Teams message and hope for the best. You produce a Statement of Work. It specifies the stack, the constraints, the security requirements, the definition of done. Both parties sign it. If the delivered work diverges from the spec, you have grounds to reject it.
When you use an AI coding agent, you describe the task in a chat window.
That's the entire governance model. A chat window.
The output might be excellent. It might also use Secrets Manager instead of SSM Parameter Store, introduce a NAT Gateway, skip type hints on every function, and write except: pass in three places. Not because the agent is malicious — because nobody told it not to. The chat message said "build me a Lambda function". It built one.
This isn't a complaint about AI quality. It's a structural problem. The mechanism that professional software development uses to constrain contractor behaviour — the contract — doesn't exist in the AI development loop. We've imported the capability (AI can code) without importing the governance framework that makes professional engagement possible.
What a DevContract actually is
A DevContract is a machine-readable Statement of Work. A JSON document you place at .tickety/devcontract.json in your repository. It specifies, in a format that both humans and AI agents can read, the constraints that apply to every task in the engagement.
Eight clause families cover the domains where AI agents most commonly produce non-compliant output:
| Clause family | What it constrains |
|---|---|
stack |
Language, runtime, cloud provider, deployment target, primary region |
architecture |
Permitted patterns, forbidden patterns (no NAT Gateways, no Elastic IPs) |
cost |
Monthly budget ceiling, secret store requirement, free-tier-only flag |
security |
Auth mechanism, secret store, forbidden patterns (no credentials in code) |
quality |
Test coverage floor, type hint requirement, docstring requirement, linting rules |
compliance |
Applicable standards (GDPR, SOC 2, ISO 27001), data classification, retention policy |
audit |
Trail destination, SIEM integration, required event types |
definition_of_done |
Required scan gates, blocking severities, quality thresholds |
A minimal contract looks like this:
{
"contract_id": "ticketyboo-2026-01",
"contract_version": "1.0.0",
"stack": {
"language": "python",
"runtime": "python3.12",
"cloud_provider": "aws",
"deployment_target": "aws_lambda",
"primary_region": "eu-north-1"
},
"cost": {
"monthly_budget_gbp": 5.0,
"secret_store": "ssm_parameter_store",
"free_tier_only": true
},
"security": {
"secret_store": "ssm_parameter_store",
"forbidden_patterns": ["credentials_in_code", "hardcoded_secrets", "nat_gateway"]
},
"quality": {
"min_test_coverage_pct": 80,
"type_hints": "required",
"docstrings": "public_functions"
}
}
This is not a config file. It's a contract. The distinction matters: a config file configures tooling. A contract specifies the obligations of a working relationship. The agent is party to it.
The three-phase model
Phase 1 — Contract phase (before the first line of code)
The contract is written, reviewed, and placed in the repository. The AI agent is handed the contract as the first thing in its system prompt — before any task description, before any steering file, before anything else.
tickety-ai does this automatically. When you open a project containing .tickety/devcontract.json, the extension reads the contract, renders it as a compact plain-text steering block, and prepends it to every system prompt. The agent knows the rules before you've typed a single request.
== ACTIVE DEVCONTRACT ==
CONTRACT: ticketyboo-2026-01 v1.0.0
PARTIES: ticketyboo-dev (client) → Claude (contractor)
STACK: python python3.12 | aws aws_lambda eu-north-1
COST ENVELOPE: budget £5.00/mo | secret-store ssm_parameter_store | free-tier-only
SECURITY: auth cognito_jwt | secrets ssm_parameter_store
FORBIDDEN: credentials_in_code, hardcoded_secrets, nat_gateway
QUALITY: coverage ≥80% | type-hints required | docstrings public_functions | lint ruff
COMPLIANCE: GDPR | data-class personal | retention 7yr | legal-basis consent
DEFINITION OF DONE:
scan-gates: secret(critical,blocking) sast(high,blocking) dependency(high,blocking)
iac(high,blocking) governance(high,blocking)
== END CONTRACT ==
The agent has acknowledged the contract. Not in a legal sense — in a functional one. Every response it generates is now constrained by these clauses. The contract is the first thing in its context window on every turn.
Phase 2 — Execution phase (during the work)
While the agent works, the contract shapes every decision. Should I use SSM or Secrets Manager? The contract says ssm_parameter_store. Should I add a NAT Gateway? The contract says nat_gateway is in forbidden_patterns. What's the minimum test coverage? The contract says 80%.
These aren't post-hoc checks. They're pre-decision constraints, embedded in the context the agent is working from. When the agent encounters a situation the contract doesn't cover, it raises a ContractQuery — a logged record of the decision point and the clause it consulted. These queries become part of the evidence bundle.
Phase 3 — Delivery phase (at the end of the engagement)
When the work is complete, Gatekeep runs the scan gates specified in definition_of_done. Each gate produces a ClauseResult: the clause it evaluated, the status (passed, failed, skipped, blocked), and the findings.
If a violation is found — the agent used Secrets Manager when the contract requires SSM, or skipped type hints on a public function — a ContractViolation is raised:
{
"clause_category": "cost",
"clause_id": "cost.secret_store",
"clause_description": "secret_store must be ssm_parameter_store",
"violated_by": "api/config.py:14 — boto3.client('secretsmanager')",
"severity": "high",
"remediation": "Replace secretsmanager client with SSM Parameter Store. Use boto3.client('ssm').get_parameter(Name=..., WithDecryption=True).",
"auto_remediation_available": true
}
All clause results, violations, contract queries, and gate outputs are assembled into an EvidenceBundle — the signed delivery receipt. The bundle is SHA-256 signed against the contract hash. If the contract changes between signing and verification, the signature breaks. You know the evidence was produced against this version of the contract, not some earlier draft.
The overall_verdict field tells you the outcome:
| Verdict | Meaning |
|---|---|
contract_honoured | All clauses passed, all blocking scan gates cleared |
contract_honoured_with_warnings | All blocking clauses passed, non-blocking warnings present |
contract_breached | One or more blocking clauses failed |
contract_not_evaluated | Scan gates could not run (pipeline failure, timeout) |
Why this matters more as agents get more capable
The better AI coding agents get, the more autonomously they operate. An agent that produces a working Lambda function in 90 seconds is impressive. An agent that produces 40 Lambda functions across a sprint, each making independent architectural decisions, is a different governance problem entirely.
The chat-window model does not scale to autonomous agents. You cannot review 40 decision threads in Slack. You cannot audit a fortnight of agent output by reading message history. The governance mechanism has to be structural, not conversational.
The DevContract solves this at the right layer. The constraints are expressed once, in a machine-readable format, before the first task. They apply to every task, automatically, for the duration of the engagement. The evidence is machine-readable and cryptographically verifiable. The audit record is not a screenshot of a chat window.
The .clinerules file is already a proto-contract
If you've been using Roo Code or Cursor with a .clinerules or .cursorrules file, you've already discovered the pattern. You write down the rules in markdown. The agent reads it. The agent follows it — mostly.
A DevContract is the formalised, machine-readable version of what .clinerules is trying to be:
| .clinerules | DevContract | |
|---|---|---|
| Format | Markdown prose | Typed JSON with defined schema |
| Scope | General guidance | Eight specific clause families |
| Enforcement | Agent follows if it remembers | Rendered into every system prompt automatically |
| Verification | Manual review | Gatekeep scan gates |
| Audit trail | None | Signed EvidenceBundle |
| Violation detection | None | ContractViolation model |
You don't have to abandon .clinerules. tickety-ai loads both — the contract first, then the steering files. The contract provides the formal structure. The steering files provide the narrative context. They serve different purposes and complement each other.
What this is not
A DevContract is not a prompt injection defence. It's not a way to prevent a malicious agent from doing bad things. It's not a substitute for code review.
It's a governance mechanism for a professional working relationship. The same way a Statement of Work with a development house isn't a way to prevent fraud — it's the document that makes a professional engagement possible at all. It specifies what was agreed, what was delivered, and how to adjudicate a disagreement.
If you're using AI agents as professional development contractors, you need the governance infrastructure that professional development contracting uses. That's what a DevContract is.
Getting started
Three archetypes are available at /docs/contracts/archetypes/:
- free_tier_python — AWS Lambda, Python 3.12, SSM-only, 80% coverage, GDPR. Matches the ticketyboo.dev stack exactly.
- gdpr_saas — GDPR + ISO 27001 SaaS. Secrets Manager approved, DPO review gate, 7-year retention.
- iso27001_enterprise — Enterprise and government. HSM required, architecture board gate, pen test gate, WCAG compliance.
- Pick an archetype. Copy it to
.tickety/devcontract.jsonin your repository root. - Edit the fields that don't match your project. The schema reference documents every field.
- Install tickety-ai. The extension reads the contract automatically — no configuration required.
- Run Gatekeep at delivery. The scan gates in
definition_of_donespecify what gets checked. The EvidenceBundle is the signed receipt.
The contract model doesn't replace judgment. It gives the AI agent a stable, machine-readable frame within which to exercise it.
→ Full contract documentation → Live three-phase demo → Contract archetypes
ticketyboo makes AI-assisted software delivery legible, enforceable, and provable. Start free — no credit card, no install required.
See how it works →