DEV Community

tsing liu
tsing liu

Posted on

Cairness: Bringing Software Engineering Discipline to AI Coding Agents

Cairness gives Claude Code and Codex an executable, verifiable, and auditable software-development lifecycle.

architecture

AI coding assistants have become remarkably capable. They can inspect a codebase, propose a patch, write tests, and explain their reasoning in a few minutes.

But production engineering has a harder question than "can it write code?":

When an AI agent says, "Done. Tests pass," what evidence makes that claim trustworthy?

The answer cannot be another paragraph in a prompt. A CLAUDE.md, an AGENTS.md, and a carefully worded checklist are useful, but they remain prose. They depend on the model remembering and voluntarily following them. When the model takes a shortcut, prose alone neither stops it nor gives you a reliable way to prove what happened afterward.

That is the problem Cairness is designed to address. It is an open-source lifecycle governance framework for Claude Code and Codex that turns development conventions into executable contracts and verifies them with deterministic tooling.

Its core idea is simple:

Replace "please follow this process" with "this process can be verified."

At the time this article was written, Cairness v1.3.5 includes 14 lifecycle command contracts, 37 deterministic cc-* scripts, 17 JSON Schemas, 34 topic rules, and a repository test suite with 1,206 passing tests. Those numbers matter less than the design behind them: an AI agent should not be the sole judge of whether it followed the rules.

The Failure Mode Is Not Just Model Quality

If you use AI coding agents on real projects, the following situations are probably familiar:

  • You ask for a small login-timeout fix. The agent edits code before anyone has clarified the requirements, scope, or failure mode.
  • It reports that tests pass. You run them locally and discover a failure, then begin another repair loop.
  • You send several agents into different modules. They all touch the same shared file.
  • The context grows through dozens of turns, quality falls, and token cost climbs.
  • You wrote a long engineering guide. The agent read it, then ignored an important rule three turns later.
  • Your team accumulated hard-won operational knowledge, but neither people nor agents load it at the moment it matters.

None of these problems requires a bad model. They are what happens when an engineering workflow has only one executor: the model itself.

Prompt or prose guideline Cairness
Form of the agreement Natural-language instructions Structured YAML contract
Who executes it The model's judgment The model plus deterministic scripts
Who verifies it Usually nobody independent Schemas, CLI checks, CI, regression tests
Consequence of a violation It may go unnoticed Non-zero exit, hard gate, and audit trail
Context cost Re-send a large guide repeatedly Load the smallest declared set per command

The important distinction is independent execution. A structured contract has a second executor that does not get tired, forget rule 12, or decide that a shortcut is probably fine.

What Cairness Actually Is

Cairness organizes clarification, change proposal, implementation, review, testing, and archive steps as a lifecycle. Its architecture has three layers:

  1. Contracts: command manifests declare what is allowed, forbidden, required, and risky.
  2. Deterministic verification: scripts inspect whether those contracts and their results are valid.
  3. Project truth: .cairness/ stores specs, task plans, reviews, test evidence, audits, and knowledge.

Claude Code uses .claude/; Codex uses .codex/ and .agents/skills/cc-harness/. Both adapters consume the same runtime contracts and share the same .cairness/ state. The evidence written during a Change is fed back into verification, which is the practical meaning of the framework's Fresh Evidence principle.

The rest of this article explains the five ideas that make that system useful.

1. Commands Are Contracts, Not Suggestions

Each lifecycle command has a machine-readable manifest. Here is a representative excerpt from the implementation phase, cc-apply:

command: cc-apply

writes:
  - task_declared_code_files
  - test_files
  - .cairness/changes/<change-id>/spec.md
  - .cairness/context/dev-map.md

forbids:
  - silently_expand_implementation_beyond_spec_boundary
  - defer_minimum_verification_to_cc_test
  - mark_done_without_evidence
  - auto_push_or_merge
  - dispatch_tasks_across_waves_in_parallel

preconditions:
  - hard_gate_confirmed_for_current_revisions
  - depends_on_satisfied_verified_by_cc_deps_check
  - branch_matches_change_and_is_not_main
  - save_pre_apply_baseline_before_first_code_edit

red_flags:
  - baseline_delta_contains_new_failure
  - wave_contains_tasks_with_overlapping_write_sets
  - implementation_expanded_beyond_declared_scope_without_flag_or_user_choice
Enter fullscreen mode Exit fullscreen mode

writes, forbids, preconditions, red_flags, and stop_conditions are not documentation conventions. They are fields that schemas and runtime checks can inspect.

A hard gate that a language model cannot hand-wave away

lifecycle

The hard gate is central to the workflow. It is not a polite "please confirm" message. A user must explicitly choose confirm_scope, request_revision, or block_until_clarified. Until a confirmation for the current revision exists, cc-apply fails its hard_gate_confirmed_for_current_revisions precondition and implementation does not begin.

This is a small but important shift: "the agent said it was ready" is not a valid state transition.

Design for the excuses an agent will make

One especially useful manifest field is anti_rationalizations. It names common shortcuts before the agent takes them:

anti_rationalizations:
  - claim: "These changes are small, so they do not need a spec."
    reality: "Small does not mean unrecorded."
  - claim: "I can refine the task scope during implementation."
    reality: "cc-apply depends on frozen task scope and verification mapping."
  - claim: "Authorization is checked in the handler."
    reality: "A service or repository path may bypass the handler."
  - claim: "That value appears only in tests."
    reality: "Fixtures can still expose real credentials or personal data."
Enter fullscreen mode Exit fullscreen mode

This is more than prompt wording. The project contains 206 anti-rationalization entries across 45 runtime files. The broader lesson is reusable: instead of only describing the ideal behavior, enumerate predictable ways an agent may rationalize a shortcut and make the response explicit.

2. Completion Claims Need Fresh Evidence

Cairness has three related principles:

  • No Spec, No Code: implementation begins from a reviewable spec.
  • Spec is Truth: review, test, and completion must agree with the spec.
  • Fresh Evidence: a claim about the current implementation needs evidence produced for the current implementation.

These are enforced through tools rather than reminders.

Check What it catches
cc-verify Aggregates Harness, adapter, and project verification
cc-deps orphans Files changed in Git but declared by no Change
cc-deps conflicts Overlapping file scopes across open Changes
cc-delta-check New failures introduced during implementation
cc-schema-check Invalid spec, task, and review documents
cc-spec-scope-check Implementation outside the frozen spec boundary
cc-readset --check Manually altered generated readsets
cc-subagent-evidence-check Unstructured evidence from subagents
cc-knowledge-check Stale paths in the team knowledge index

A host hook can warn when an agent tries to write business code without a spec, but it deliberately does not pretend to be the only protection. The hook is non-blocking and has exemptions for framework state, tests, CI files, and configuration. The hard protection belongs to deterministic checks and CI.

That distinction is worth making explicit in any AI development tool: a useful warning is not the same thing as an enforceable boundary.

3. More Context Is Not Better Context

Large, ever-growing prompts are a poor substitute for context management. Cairness gives each command a readset with three categories:

always_reads:
  # Small, required starting context
conditional_reads:
  when_task_touches_database: [database-changes.yaml]
  when_task_touches_security_boundary: [security.yaml]
optional_reads:
  # Reference material excluded from the default context
Enter fullscreen mode Exit fullscreen mode

Readsets are generated from the command YAML with cc-readset --write; they are not meant to be edited manually. cc-readset --check catches drift.

The framework also has topic rules for database changes, API compatibility, concurrency, performance, security, configuration, observability, release work, and more. They use two complementary triggers:

  • Deterministic triggers use file globs, content regexes, and import regexes. A migration path or CREATE TABLE, for example, can attach the database rule with no model-token cost.
  • Semantic triggers let the model recognize a relevant concern from the intent of the Change.

Deterministic matching provides a low-cost baseline; semantic matching covers what static patterns cannot express.

For a specific task, cc-context-pack can package the task brief, spec, needed context, and review diff under a content fingerprint. A worker or reviewer receives a compact, reproducible package instead of a controller repeatedly pasting a long history.

The same approach applies to team memory. .cairness/knowledge/index.md maps keywords to descriptions and knowledge files. During proposal, implementation, review, repair, and discussion, the agent loads knowledge that matches the work instead of relying on someone to remember which document to open.

4. Parallelism Must Be Controlled, Not Competitive

Multiple agents can make delivery faster, but only when their work is isolated and their dependencies are explicit.

wave

Cairness uses wave planning and write isolation. It enforces three constraints:

Constraint How it is checked
Parallel writers must have disjoint targets cc-wave-plan plus schema validation
A subagent's write scope must be a subset of its parent command's writes parent_writes_subset policy and cc-role-check
A subagent result must satisfy a six-field output_contract cc-subagent-evidence-check

If the task graph is missing or ambiguous, cc-wave-plan returns E_WAVE006. It fails closed instead of guessing a schedule.

That is a recurring Cairness rule: when evidence is insufficient, keep the answer null or return an explicit failure. Do not turn unknown data into a pass. The same policy applies to verification calibration, optimization analysis, and adapter token-usage collection.

There is another practical detail: successful tasks in a wave can be committed independently. A failed task is marked blocked or partial and is not committed; the next wave remains gated until it is repaired, retried, split, or aborted. One failure should not erase independent, verified work, but it should stop unsafe dependencies from continuing.

5. Autonomy Works Best as a Trust Envelope

Traditional governance has an adoption problem. Add enough approval gates and people eventually click "yes" without reading them. The workflow becomes slower without becoming safer.

The Loop profile changes the division of responsibility: humans define the boundary; the agent can operate within it.

loop

Here is a simplified Loop configuration:

trust_envelope:
  max_scope: small
  max_residual_risk: medium

  allowed_change_types:
    - refactor
    - bugfix
    - test
    - doc
    - feature_small

  disallowed_change_types:
    - schema_migration
    - security_change
    - api_breaking_change
    - architecture_change

  autonomy:
    scope_overage: supervised
    risk_overage: staged

  verification:
    require_all_tests_pass: true
    require_no_open_findings: true
Enter fullscreen mode Exit fullscreen mode

cc-self-eval --decision routes a Change as one of the following:

Decision Meaning
autonomous Inside the envelope; continue automatically
supervised A single hard-gate authorization, then execution against a frozen wave plan
staged Confirmation at wave boundaries
blocked Stop; task splitting or confirmation-field edits cannot bypass the block

Loop does not reduce verification standards. It changes who confirms a gate. Change types outside the envelope, Critical or Security review findings, repeated verification failures, invalid schemas or state, and repeated self-evaluation failures are circuit breakers. Automatic decisions and escalations are written under .cairness/loop-audit/ for later review.

This is human-on-the-loop rather than human-in-the-loop: people define autonomy boundaries, review evidence, and handle escalations instead of mechanically approving every safe step.

Quality Before Efficiency Is an Executable Rule

Most tools claim to be both faster and safer. Cairness makes the ordering explicit.

Mode Intended use Verification strategy
normal Everyday local work Changed-only routing and a verification cache; dynamic gates and project tests stay fresh
ci Merge, release, formal acceptance Full verification; quality failures block
optimize Scheduled efficiency analysis Full verification followed by cc-optimize analysis

The fast path must be selected explicitly. Running cc-verify without --execution-mode keeps historical full-verification behavior. The cache can only reuse static checks with a matching fingerprint that passed previously; dynamic governance gates, behavior replay, and project tests are never replaced by stale results.

When comparing candidates, cc-benchmark checks deterministic failures, Critical escapes, task success, and Important recall before looking at input tokens, wall time, or verify count. If quality or efficiency evidence is incomplete, it does not claim an optimization. cc-optimize is read-only and returns observe, propose, or reject; it does not modify policy, readsets, or business code on its own.

The policy fits in one sentence:

Fewer tokens or less wall-clock time cannot compensate for a regression in task success, Important recall, or deterministic verification.

Operational Details That Build Trust

Architecture is only useful if the operational boundaries are clear.

Project state is physically separate from framework assets

Directory Ownership What upgrades do
.claude/ Claude Code adapter Framework-managed adapter assets may be replaced
.codex/ and .agents/skills/ Codex adapter Framework-managed adapter assets may be replaced
.cairness/ Your project state The framework does not delete it

cc-cairn update updates the active adapter. cc-cairn uninstall --adapter codex removes the selected adapter's managed assets. Neither command removes shared .cairness/ state, and modified Codex Skills are preserved on uninstall.

CI pins its version

The workflow produced by cc-cairn init downloads the matching release archive and checksum, verifies them, then installs temporarily. It does not silently follow main or latest. Download failure, checksum mismatch, or internal version mismatch is a hard failure. Ordinary CI uses an offline adapter baseline, so it does not require a Claude Code or Codex login and does not incur model costs.

Telemetry stays local and can be disabled

Runtime summaries are stored locally in .cairness/observability/runtime-events.jsonl. They exclude prompts, source code, business paths, change IDs, and PII. Disable the summaries without disabling lifecycle checks or verification:

DO_NOT_TRACK=1 .claude/scripts/cc-verify --execution-mode normal
Enter fullscreen mode Exit fullscreen mode

Getting Started in Five Minutes

# Requirements: Python 3.9+, Git, and Claude Code or Codex for interactive workflows
git clone https://github.com/lq5657/Cairness.git
cd Cairness
python3 cairn_install

# Onboard a project. Choose the primary language explicitly.
cd /path/to/your-project
cc-cairn onboard --language python --yes

# For Codex:
cc-cairn onboard --adapter codex --language python --yes

# Preview onboarding changes without writing them.
cc-cairn onboard --dry-run --json

# Diagnose installation, configuration, adapters, and project state.
cc-cairn doctor
Enter fullscreen mode Exit fullscreen mode

Then, in a Claude Code or Codex session:

cc-propose "Fix the connection leak after a login API timeout"
Enter fullscreen mode Exit fullscreen mode

New installations default to the Loop profile. To return to a gate-by-gate human-confirmation workflow, run:

cc-cairn loop disable
Enter fullscreen mode Exit fullscreen mode

Where It Fits, and Where It Does Not

Cairness is a fit when you have real delivery pressure, code that needs to survive beyond a demo, substantial AI participation in implementation, a team that needs durable engineering knowledge, or audit requirements.

It is probably not a fit for a one-off script, a casual weekend prototype, or a workflow whose central value proposition is zero process. Governance has a cost. Cairness intentionally pays that cost early, in specification and explicit boundaries, to avoid discovering the wrong direction halfway through implementation.

The project also documents current limitations rather than obscuring them:

  • Codex pre_write_hook and file_write_interception are emulated, not equivalent to Claude Code blocking semantics.
  • Codex compaction_session_resume is optional, not a completion requirement.
  • Loop continuation happens in the current host session; it is not an unattended background service.
  • The No Spec, No Code host hook warns rather than blocks. Scripts and CI provide the hard fallback.
  • Linux, macOS, and WSL are officially supported. Native Windows is experimental; WSL is recommended for complete Bash-hook and POSIX-script support.

The Point Is Verifiable Trust

The next bottleneck in AI-assisted software development is not only model capability. It is verifiable trust.

Which files did the agent change? Did it remain inside the agreed scope? Does "tests pass" have fresh evidence? Can parallel agents work without overwriting one another? Will a lesson from six months ago be loaded when the same risk appears again?

Those questions should not be answered by a sterner prompt. They should be declared as contracts, checked by scripts, reproduced in CI, and recorded for audit.

Cairness is one attempt to build that layer. Its goal is not to make an AI agent perform more ceremony. It is to keep the agent inside the right boundaries: fast feedback for ordinary work, full quality gates for CI and release, and comparable evidence before declaring an efficiency gain.

Learn More

git clone https://github.com/lq5657/Cairness.git
cd Cairness
python3 cairn_install
Enter fullscreen mode Exit fullscreen mode

The counts, commands, configuration excerpts, and diagrams in this article were checked against Cairness v1.3.5. The test result cited above is a local run of python3 -m pytest -q; duration and warning counts vary by machine and environment.

Top comments (0)