Files
codex/docs/rust-docs.md
Josh McKinney 301a43b141 docs: Add documentation guidelines to AGENTS.md
Added a secondary rust-docs.md to make it easier for codex to pull this information in when needed for writing docs, but otherwise not have to pollute the context
2025-10-31 12:43:27 -07:00

6.3 KiB
Raw Permalink Blame History

Rust Documentation Guidelines (Codex)

Codex code should be self-explanatory to future maintainers without hunting Slack threads or PR comments.
Document intent, invariants, and system behavior — not line-by-line code.
This is a ratcheting standard: improve docs where you touch code.

Confidentiality & Privacy

  • Never include personally identifiable information (PII) in docs or examples.
  • Do not disclose OpenAI confidential details (internal systems, keys, roadmap).
  • Use scrubbed or fictional data when demonstrating behavior.

Core Principles

  • Prefer intent + invariants over restating implementation.
  • Write docs that help a contributor orient quickly.
  • Capture non-obvious behavior (I/O, concurrency, retries, lifetime/safety constraints).
  • Prefer short, factual docs over verbose or marketing language.
  • When in doubt: what would future you want written here?
  • Improve docs incrementally, file-by-file.

Docs should:

  • Explain what the item does and when to use it.
  • Note invariants, assumptions, side effects.
  • Link to related components using backticked intra-links, e.g., [SchedulerClient].
  • Provide minimal but meaningful examples.

Docs should NOT:

  • Translate code to English.
  • Duplicate type signatures.
  • Include speculative ideas or stale TODOs — delete instead.
  • Add noise or break flow when reading the code.

When to Update Docs

Update/add docs when code changes involving:

  • New public types or functions
  • Module purpose shifts
  • Error model changes (retry, backoff, timeouts, error variants)
  • New configuration or env vars
  • Cross-service boundaries or RPC changes
  • Unsafe code
  • Performance-sensitive, async, or concurrent logic

If a Slack thread or PR explains the reasoning, summarize the key logic in code.

Module-Level Docs (//!)

Use modules as orientation maps.

Include:

  • High-level purpose in the system
  • Responsibilities and flows
  • Key types with links: [AppConfig], [ArtifactStore], [SchedulerClient]
  • Assumptions & invariants
  • Behavior around I/O, async, retries
  • Any platform or environment differences

When helpful, add module maps:

//! Scheduler coordination layer.
//!
//! Responsibilities:
//! - Submit jobs to system
//! - Track execution state
//! - Stream scheduler events
//!
//! Key types:
//! - [`SchedulerClient`]
//! - [`JobId`]
//! - [`JobSpec`]
//!
//! Flows:
//! - submit → queue → event stream → completion
//! - watch events → reconcile local state
//!
//! Invariants:
//! - Jobs have stable IDs
//! - Event stream is monotonic where possible

Struct-Level Docs

For complex structs, treat docs as a map to the API surface.

Include:

  • What the type represents
  • High-level behavior it provides
  • Groups of related methods for orientation (not exhaustive listing)

Example:

/// Client for interacting with the distributed artifact store.
///
/// Major operations:
/// - Upload blobs (`store_*` fns)
/// - Download & stream content (`fetch_*`)
/// - Verify checksums
///
/// Related APIs:
/// - [`ArtifactId`]
/// - [`UploadConfig`]
///
/// Invariants:
/// - Uploads are atomic when possible
/// - IDs validated before use
pub struct ArtifactStore { /* ... */ }

Function & Method Docs (///)

Template structure:

  1. One-sentence summary
  2. Subtle behaviors / invariants
  3. Sections only if needed:
  • # Errors
  • # Panics
  • # Safety
  • # Invariants
  • # Examples
  • # Notes
  • # Performance

Example:

/// Resolve configuration sources and produce a validated [`AppConfig`].
///
/// Searches CLI args, env, and default paths, applying merge rules and
/// canonicalizing paths.
///
/// # Errors
/// Returns `ConfigError` if required fields are missing or config is malformed.
///
/// # Examples
/// ```rust
/// # use codex::config::load_config;
/// let cfg = load_config(None)?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```

unsafe Code Docs

Include both doc comments and // SAFETY: inline comments.

/// Write bytes into a raw buffer without bounds checks.
///
/// # Safety
/// Caller must guarantee:
/// - `ptr` is valid and uniquely owned
/// - `len <= capacity`
/// - Memory remains valid for the duration
pub unsafe fn write_unchecked(ptr: *mut u8, len: usize) { /* ... */ }

Inline:

// SAFETY: caller guarantees buffer validity and non-aliasing.

Examples & Doctests

  • Keep examples minimal and compiling
  • no_run for network/FS
  • Use compile_fail for negative tests demonstrating invariants
missing_required_field();

Always include backticks inside intra-links:

Correct:

[`AppConfig`]
[`crate::scheduler::SchedulerClient`]

Incorrect:

[AppConfig]

Use short cross-links when unambiguous.

Style Rules

  • First line: one sentence, present tense
  • Brevity over completeness
  • Bullet lists for behavior > text walls
  • ≤ ~100 character line width preferred
  • If a doc becomes stale: update or delete

Rule of thumb:

Docs should reduce cognitive load more than they increase it.

Platform, Performance & Error Notes

Call out when code behavior depends on:

  • OS/filesystem differences
  • Retry/backoff/network semantics
  • Async vs blocking behavior
  • Resource constraints (memory, threads, streaming)

Ratcheting Documentation Enforcement

We improve docs incrementally:

  • When editing a file, raise its doc standard
  • Add #![warn(missing_docs)] only after docs are acceptable for that file
  • Gradually expand to entire crate

Eventually enable crate-level policies:

#![warn(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]

But do it module-by-module, not all at once.

Codex Agent Guidance

When Codex modifies Rust:

  • Add or update docs for changed public APIs
  • Update module/struct “maps” when responsibilities change
  • Add/repair backticked intra-doc links
  • Summarize complex reasoning in ~3 bullet points
  • Add/refresh minimal doctests
  • Skip trivial boilerplate docs

Codex should leave the codebase more explainable than it found it.

What Not to Do

  • Dont narrate code
  • Dont restate type signatures
  • Dont leave stale docs
  • Dont add noise or philosophical commentary
  • Dont document trivial functions (unless there are caveats)

Docs should always help new contributors build correct mental models quickly.