Skip to content

Latest commit

 

History

History
376 lines (281 loc) · 11.4 KB

File metadata and controls

376 lines (281 loc) · 11.4 KB

AGENTS.md - AI Development Guidelines

This document defines the standards and constraints that AI assistants must follow when developing the rc project.

Language Requirements

Important: All content must be in English, except for conversations with AI assistants which may use Chinese:

  • Code comments
  • Commit messages
  • PR titles and descriptions
  • Documentation in code
  • Error messages in code
  • Log messages
  • Variable and function names

Workflow

0. Branch Base Policy

  1. For any code change task, always base work on the latest origin/main.
  2. Before implementing code changes, run git fetch origin and ensure your working branch is created from or rebased onto origin/main.
  3. Exception: if the task explicitly asks to fix or update a specific PR branch, continue on that PR branch instead of rebasing to origin/main unless explicitly requested.

1. Before Starting

  1. Understand the task goals and acceptance criteria
  2. Identify related modules and existing tests

2. Before Modifying

  1. Check if the target file is a protected file
  2. If it's a protected file, follow the Breaking Change process
  3. Read related existing code to understand patterns and conventions

3. During Implementation

  1. Write tests first (red)
  2. Implement minimum code to pass tests (green)
  3. Refactor and clean up code
  4. Ensure all tests pass

4. After Completion

⚠️ Important: All checks must pass before each commit!

  1. Run cargo fmt --all - Code formatting
  2. Run cargo clippy --workspace -- -D warnings - Static analysis, must have zero warnings
  3. Run cargo test --workspace - Unit tests, must all pass
  4. Only create a git commit after all above checks pass
    • Commit message format: feat(phase-N): <description>
    • Example: feat(phase-1): implement alias commands and core infrastructure

Exception (markdown-only non-code updates):

  • If the change only updates Markdown files unrelated to executable code (for example AGENTS.md, README.md, or other documentation .md files), compile/lint/test validation may be skipped.
  • This exception does not apply when changes affect schemas, config behavior, generated outputs, or any Rust/source code.

Do not commit code when checks have not passed!


Protected Files

The following files require the Breaking Change process for modifications:

File Description
docs/SPEC.md CLI behavior contract
schemas/output_v1.json JSON output schema
crates/cli/src/exit_code.rs Exit code definitions
crates/core/src/config.rs Config schema_version related

Breaking Change Process

Modifying protected files requires:

  1. Update version number

    • Config changes: bump schema_version
    • Output changes: create new output_v2.json schema
  2. Provide migration path

    • Config migration: add migrations/v{N}_to_v{N+1}.rs
    • Documentation update: update relevant SPEC.md sections
  3. PR marking

    • Include BREAKING in PR title or description

Absolute Prohibitions

Code Level

  1. Using use aws_sdk_s3 directly in cli crate

    • Must access S3 functionality through core trait abstractions
    • Violation: breaks dependency boundaries
  2. Using .unwrap() (except in test code)

    • Must use ? or expect("reason")
    • Violation: may cause panic
  3. Using unsafe code

    • No exceptions
    • Violation: security risk
  4. Printing credentials in logs/errors

    • Includes: access_key, secret_key, Authorization headers
    • Violation: security risk

Process Level

  1. Modifying protected files without following Breaking Change process

    • Violation: breaks backward compatibility
  2. Deleting or disabling tests to "fix" CI

    • Must fix the root cause of test failures
    • Violation: reduces code quality
  3. Cross-layer refactoring without ADR

    • Example: moving s3 logic to cli
    • Requires recording decision in docs/ADR/
  4. Using --no-verify to bypass commit hooks

    • No exceptions

Code Style

Error Handling

// Recommended: Use thiserror to define error types
use thiserror::Error;

#[derive(Error, Debug)]
pub enum MyError {
    #[error("Configuration error: {0}")]
    Config(String),

    #[error("Network error: {0}")]
    Network(#[from] std::io::Error),
}

// Recommended: Use ? to propagate errors
fn do_something() -> Result<()> {
    let config = load_config()?;
    // ...
    Ok(())
}

// Forbidden: bare unwrap
fn bad() {
    let x = something().unwrap(); // ❌
}

// Allowed: expect with explanation (only when failure is impossible)
fn ok() {
    let x = "123".parse::<i32>().expect("hardcoded valid number"); // ✓
}

Async Code

// Recommended: Use tokio
use tokio;

#[tokio::main]
async fn main() {
    // ...
}

// Forbidden: Using block_on in async context
fn bad() {
    tokio::runtime::Runtime::new().unwrap().block_on(async_fn()); // ❌
}

Logging

use tracing::{debug, info, warn, error};

// Recommended: Use appropriate log levels
debug!("Detailed debug info");
info!("Normal operation info");
warn!("Warning message");
error!("Error message");

// Forbidden: Logging sensitive information
error!("Auth failed: key={}", secret_key); // ❌ Absolutely forbidden
error!("Auth failed: endpoint={}", endpoint); // ✓ Non-sensitive info is OK

Comments

// Recommended: Comments explain WHY, not just WHAT

// Using path-style addressing because some S3-compatible services
// don't support virtual-hosted style
let client = S3Client::new_with_path_style();

// Forbidden: Obvious comments
// Increment counter
counter += 1; // ❌ This comment adds no value

Command Implementation Template

New commands must follow this template:

// crates/cli/src/commands/example.rs

use crate::exit_code::ExitCode;
use crate::output::Formatter;
use core::{ObjectStore, Result};

/// Command description (shown in --help)
#[derive(clap::Args, Debug)]
pub struct ExampleArgs {
    /// Argument description
    #[arg(short, long)]
    pub flag: bool,

    /// Path argument
    pub path: String,
}

/// Execute the command
pub async fn execute(
    args: ExampleArgs,
    store: &dyn ObjectStore,
    formatter: &Formatter,
) -> ExitCode {
    match do_work(args, store).await {
        Ok(result) => {
            formatter.output(&result);
            ExitCode::Success
        }
        Err(e) => {
            formatter.error(&e.to_string());
            ExitCode::from_error(&e)
        }
    }
}

async fn do_work(args: ExampleArgs, store: &dyn ObjectStore) -> Result<OutputType> {
    // Implementation logic
    todo!()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_example_success() {
        // Test success scenario
        // assert_eq!(result.exit_code, ExitCode::Success);
    }

    #[tokio::test]
    async fn test_example_not_found() {
        // Test NOT_FOUND scenario
        // assert_eq!(result.exit_code, ExitCode::NotFound);
    }

    // Each command needs at least 2 exit code tests
}

PR Checklist

⚠️ All checklist items must pass before each commit:

Before submitting a PR, confirm all of the following:

  • cargo fmt --all --check passes (required unless the change is markdown-only non-code)
  • cargo clippy --workspace -- -D warnings passes (required unless the change is markdown-only non-code)
  • cargo test --workspace passes (required unless the change is markdown-only non-code)
  • No changes to CLI/JSON/config contracts (or followed Breaking Change process)
  • New behaviors have unit tests
  • Each new command has at least 2 exit code test scenarios
  • Golden tests pass (output schema not broken)
  • No sensitive information in logs
  • Complex logic has appropriate comments (explaining WHY)
  • Commit message and PR description are in English

Do not skip checks and commit directly! Code that fails CI should not be merged.


Dependency Boundaries

┌─────────────────────────────────────────────────────────┐
│                         cli                             │
│  (command handling, output formatting, progress bar)    │
│                                                         │
│  ✓ Can depend on: core                                  │
│  ✗ Cannot depend on: s3, aws-sdk-*                      │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│                        core                              │
│  (config, alias, path parsing, ObjectStore trait)       │
│                                                         │
│  ✓ Can depend on: std, serde, tokio, etc.               │
│  ✗ Cannot depend on: aws-sdk-*                          │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│                         s3                               │
│  (aws-sdk-s3 wrapper, implements ObjectStore trait)     │
│                                                         │
│  ✓ Can depend on: core, aws-sdk-s3                      │
└─────────────────────────────────────────────────────────┘

Common Errors and Fixes

Compilation Errors

Error Wrong Approach Correct Approach
Type mismatch Delete the code Understand types, convert correctly
Missing trait Comment out the call Implement or import required trait
Lifetime error Add 'static Analyze ownership, use Clone or refactor

Test Failures

Situation Wrong Approach Correct Approach
Test hangs #[ignore] Analyze cause, fix code or test
Assertion fails Change the assertion Check if it's code error or test error
Timeout Delete the test Optimize code or increase timeout limit

Phase Work Guidelines

Phase 0: Project Initialization

  • Create workspace structure
  • Set up CI configuration
  • Create documentation skeleton

Phase 1: Core Infrastructure

  • Implement exit codes and error types
  • Implement config and Alias management
  • Implement path parsing
  • Implement ObjectStore trait
  • Implement alias command

Phase 2+: Command Implementation

  • Follow command implementation template
  • Each command needs tests
  • Update SPEC.md (if needed)
  • Update Golden tests

Git Commit Guidelines

Each completed phase should have a commit:

  • Format: feat(phase-N): <brief description>
  • Example: feat(phase-0): initialize project structure and CI
  • Example: feat(phase-1): implement core infrastructure and alias commands