Status: Binding Scope: Production code, tests, examples, and engineering changes.
This is the front door. Read principles.md first.
These standards intentionally stay small. Deeper rules live in the linked specialized documents.
For meaningful changes, reason in this order:
Problem
→ developer experience
→ invariants
→ public behavior
→ failure cases
→ internal model
→ implementation
→ tests
Do not let implementation accidents define product behavior.
Prefer the smallest clear solution that preserves the required guarantees.
Public APIs represent user intent, not runtime machinery.
- Keep the happy path small.
- Prefer good defaults over required configuration.
- Expose advanced controls as escape hatches.
- Avoid leaking internal ports, storage identities, provider objects, or lifecycle bookkeeping unless they are intentionally part of the product contract.
- Preserve native access where practical; do not create abstraction prison.
Stable contracts point inward; integrations stay at the edges.
- Core must not depend on concrete engines, stores, telemetry providers, or serving frameworks.
- Runtime coordinates behavior through contracts and ports, not concrete adapters.
- Adapters isolate external SDKs and should not depend on each other.
- Surfaces consume AgentDeck behavior; they do not reimplement runtime semantics.
- Architecture exceptions must be explicit and registered.
See architecture.md and import-boundaries.md.
Type boundaries as contracts.
- Annotate all new public and cross-layer functions.
- Use closed types (
Literal, enums) for closed domains. - Avoid
Anyin contracts unless the value is intentionally opaque. - Use explicit schemas for durable/process/protocol boundaries.
- Prefer immutable value objects when mutation is not part of the model.
- Do not distort straightforward code merely to satisfy a type checker; use narrow documented suppressions when necessary.
Errors are part of developer experience.
An error should say:
- what happened,
- why,
- what to do next when there is an obvious next step.
Translate external SDK failures at integration boundaries unless native exceptions are intentionally exposed.
Never silently swallow unexpected failures.
- Do not block async runtime paths.
- Every spawned task must have an owner, failure story, and shutdown story.
- Do not depend on scheduler timing for correctness.
- Concurrency outcomes must follow explicit invariants.
- A component that requires scheduling progress must provide the scheduling opportunity it depends on.
See runtime-contracts.md.
Runtime guarantees are product contracts.
At minimum:
- observed durable events are already persisted,
- terminal means terminal,
- durable ordering has one authoritative owner,
- control happens at explicit safe points,
- observability does not own execution,
- races have defined winners/outcomes,
- recovery preserves the identity and meaning of the run.
See runtime-contracts.md.
Prefer:
- explicit control flow,
- meaningful domain names,
- small coherent units,
- localized policy,
- predictable ownership,
- standard Python.
Avoid:
- speculative abstractions,
- unnecessary indirection,
- generic dumping-ground modules,
- duplicated policy,
- hidden side effects,
- cleverness that saves lines but costs understanding.
Comments explain why, not what.
Public APIs get concise contract-oriented docstrings.
Tests protect AgentDeck's promises, not implementation accidents.
- Keep tests deterministic.
- Express cross-engine guarantees as shared contract tests where practical.
- Test races, recovery, and failure boundaries intentionally.
- Assert outcomes and invariants, not timing coincidences.
- Name tests after the guarantee they protect.
- A flaky test is a defect.
See testing.md.
Dependencies must earn their place.
Prefer existing project capability, then stdlib, then a focused dependency.
Keep provider-specific dependencies localized to their integration boundary whenever practical.
See dependencies.md.
A change should have one understandable purpose.
- Avoid unrelated cleanup.
- Avoid formatting files you do not otherwise need to touch.
- Separate refactoring from behavior change when that materially improves reviewability.
- Record non-obvious engineering judgments and deviations, not routine implementation choices.
- Do not weaken tests, lint rules, goldens, or CI merely to make a change pass.
See repository-policy.md.
Committed repo configuration is authoritative for mechanical concerns such as formatting, linting, typing, imports, and test commands.
Do not duplicate tool configuration as prose.
Do not introduce competing tooling without a deliberate project decision.
Coding agents follow the same standards as maintainers, plus the agent-specific rules in coding-agents.md.
Reserve absolute rules for genuine invariants.
Where several simple and correct solutions exist, use engineering judgment.
If a rule is repeatedly waived, fix the implementation or fix the rule. Do not accumulate permanent exceptions around bad policy.