Contracts
Contracts are the primary artifact in lexicon. A contract declares the stable behavioral specification for a component — what it must do, what it must not do, and what is explicitly out of scope.
The core idea: make stable contracts explicit. Contracts govern what the API exposes. They are not documentation — they are enforceable declarations that the verification pipeline checks against.
The contract system clearly distinguishes between:
- stable contract — behavior that is committed and enforced
- draft contract — behavior being defined but not yet enforced
- advisory notes — implementation hints and non-goals that inform but do not constrain
- speculative ideas — explicitly separated from stable requirements
Do not blur these together. This separation is what makes contracts safe for AI-assisted workflows — an AI tool can read a contract and immediately understand what can and cannot change.
Contracts are stored as TOML files at specs/contracts/<id>.toml.
Contract Structure
Section titled “Contract Structure”Every contract has these fields:
| Field | Type | Description |
|---|---|---|
schema_version | string | Schema version for forward compatibility |
id | string | Unique slug identifier (e.g., key-value-store) |
title | string | Human-readable name |
status | enum | Lifecycle status (see below) |
stability | enum | Stability level (see below) |
scope | string | High-level scope description |
capabilities | string[] | What the component provides |
invariants | Invariant[] | Conditions that must always hold |
required_semantics | Semantic[] | Behavior that is required |
forbidden_semantics | Semantic[] | Behavior that is explicitly forbidden |
edge_cases | EdgeCase[] | Edge cases with expected behavior |
examples | Example[] | Usage examples |
non_goals | string[] | What this component explicitly does not do |
implementation_notes | string[] | Notes not part of the contract |
test_expectations | string[] | Expected tests for this contract |
history | HistoryEntry[] | Version history of contract changes |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
Status Lifecycle
Section titled “Status Lifecycle”Contracts move through four statuses:
draft— Being drafted, not yet enforcedactive— Active and enforceddeprecated— Still enforced but expected to be replacedretired— No longer enforced
Stability Levels
Section titled “Stability Levels”Contracts have a stability level that controls how changes are handled:
experimental— May change or be removed at any timeunstable— Expected to stabilize but may still changestable— Changes require versioned migrationfrozen— Must not change without extraordinary justification
New contracts default to experimental stability and draft status.
Invariants
Section titled “Invariants”Invariants are conditions that must always hold. Each invariant has an id, description, and severity:
required(default) — Failure blocks verificationadvisory— Contributes to score but does not block
Required and Forbidden Semantics
Section titled “Required and Forbidden Semantics”Required semantics declare behavior the implementation must provide. Forbidden semantics declare behavior that must never occur. Each has an id, description, and optional test_tags for linking to conformance tests.
Forbidden semantics are especially important for AI safety. They make it explicit what an AI assistant must not introduce, even if it seems “locally clever.”
Edge Cases
Section titled “Edge Cases”Edge cases describe specific scenarios with expected behavior. Each has an id, scenario description, and expected_behavior.
Examples
Section titled “Examples”Examples have a title, description, and optional code snippet.
Version History
Section titled “Version History”The history array tracks contract changes with version, date, description, and author fields. Rewriting contract semantics without updating contract status and history is a policy violation that lexicon detects and flags.
TOML Example
Section titled “TOML Example”schema_version = "1.0"id = "key-value-store"title = "Key-Value Store Contract"status = "active"stability = "stable"scope = "Defines the behavior of a basic key-value store"capabilities = ["get/set/delete operations"]non_goals = ["persistence", "network access"]implementation_notes = ["Consider using a HashMap internally"]test_expectations = ["All invariants covered by conformance tests"]created_at = "2025-01-15T00:00:00Z"updated_at = "2025-01-15T00:00:00Z"
[[invariants]]id = "inv-001"description = "A key set with a value must return that value on get"severity = "required"
[[required_semantics]]id = "req-001"description = "get(key) returns None for missing keys"test_tags = ["conformance", "basic"]
[[forbidden_semantics]]id = "forbid-001"description = "Must not panic on missing key lookup"test_tags = ["safety"]
[[edge_cases]]id = "edge-001"scenario = "Setting the same key twice"expected_behavior = "The second value overwrites the first"
[[examples]]title = "Basic usage"description = "Set and get a value"code = "store.set(\"key\", \"value\"); assert_eq!(store.get(\"key\"), Some(\"value\"));"
[[history]]version = "1.0"date = "2025-01-15T00:00:00Z"description = "Initial contract"author = "team"Creating Contracts
Section titled “Creating Contracts”Start a lexicon chat session and describe what you want to build. The AI will create contracts using the CREATE_CONTRACT directive:
- Inspects the repo and infers likely public API shape
- Asks structured questions about scope, capabilities, and invariants
- Proposes an initial contract draft
- Lets you refine it conversationally
- Validates the result and writes the final contract
You can also infer contracts from existing code using the INFER_CONTRACT directive, which scans your public API source code and generates contracts automatically.