Skip to content

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.

Every contract has these fields:

FieldTypeDescription
schema_versionstringSchema version for forward compatibility
idstringUnique slug identifier (e.g., key-value-store)
titlestringHuman-readable name
statusenumLifecycle status (see below)
stabilityenumStability level (see below)
scopestringHigh-level scope description
capabilitiesstring[]What the component provides
invariantsInvariant[]Conditions that must always hold
required_semanticsSemantic[]Behavior that is required
forbidden_semanticsSemantic[]Behavior that is explicitly forbidden
edge_casesEdgeCase[]Edge cases with expected behavior
examplesExample[]Usage examples
non_goalsstring[]What this component explicitly does not do
implementation_notesstring[]Notes not part of the contract
test_expectationsstring[]Expected tests for this contract
historyHistoryEntry[]Version history of contract changes
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp

Contracts move through four statuses:

  • draft — Being drafted, not yet enforced
  • active — Active and enforced
  • deprecated — Still enforced but expected to be replaced
  • retired — No longer enforced

Contracts have a stability level that controls how changes are handled:

  • experimental — May change or be removed at any time
  • unstable — Expected to stabilize but may still change
  • stable — Changes require versioned migration
  • frozen — Must not change without extraordinary justification

New contracts default to experimental stability and draft status.

Invariants are conditions that must always hold. Each invariant has an id, description, and severity:

  • required (default) — Failure blocks verification
  • advisory — Contributes to score but does not block

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 describe specific scenarios with expected behavior. Each has an id, scenario description, and expected_behavior.

Examples have a title, description, and optional code snippet.

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.

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"

Start a lexicon chat session and describe what you want to build. The AI will create contracts using the CREATE_CONTRACT directive:

  1. Inspects the repo and infers likely public API shape
  2. Asks structured questions about scope, capabilities, and invariants
  3. Proposes an initial contract draft
  4. Lets you refine it conversationally
  5. 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.