This document defines the standards and constraints that AI assistants must follow when developing the rc project.
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
- Read
IMPLEMENTATION_PLAN.mdto confirm the current phase - Check if the current phase status is "In Progress"
- Understand the goals and acceptance criteria for the current phase
- Check if the target file is a protected file
- If it's a protected file, follow the Breaking Change process
- Read related existing code to understand patterns and conventions
- Write tests first (red)
- Implement minimum code to pass tests (green)
- Refactor and clean up code
- Ensure all tests pass
- Run
cargo fmt --all- Code formatting - Run
cargo clippy --workspace -- -D warnings- Static analysis, must have zero warnings - Run
cargo test --workspace- Unit tests, must all pass - Update
IMPLEMENTATION_PLAN.mdstatus - 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
- Commit message format:
Do not commit code when checks have not passed!
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 |
Modifying protected files requires:
-
Update version number
- Config changes: bump
schema_version - Output changes: create new
output_v2.jsonschema
- Config changes: bump
-
Provide migration path
- Config migration: add
migrations/v{N}_to_v{N+1}.rs - Documentation update: update relevant SPEC.md sections
- Config migration: add
-
Update CHANGELOG
- Add BREAKING CHANGE entry in CHANGELOG.md
-
PR marking
- Include
BREAKINGin PR title or description
- Include
-
Using
use aws_sdk_s3directly inclicrate- Must access S3 functionality through
coretrait abstractions - Violation: breaks dependency boundaries
- Must access S3 functionality through
-
Using
.unwrap()(except in test code)- Must use
?orexpect("reason") - Violation: may cause panic
- Must use
-
Using
unsafecode- No exceptions
- Violation: security risk
-
Printing credentials in logs/errors
- Includes: access_key, secret_key, Authorization headers
- Violation: security risk
-
Modifying protected files without following Breaking Change process
- Violation: breaks backward compatibility
-
Deleting or disabling tests to "fix" CI
- Must fix the root cause of test failures
- Violation: reduces code quality
-
Cross-layer refactoring without ADR
- Example: moving s3 logic to cli
- Requires recording decision in
docs/ADR/
-
Using
--no-verifyto bypass commit hooks- No exceptions
// 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"); // ✓
}// 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()); // ❌
}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// 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 valueNew 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
}Before submitting a PR, confirm all of the following:
-
cargo fmt --all --checkpasses (required) -
cargo clippy --workspace -- -D warningspasses (required, zero warnings) -
cargo test --workspacepasses (required, all must pass) - 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)
- Updated IMPLEMENTATION_PLAN.md status (if applicable)
- Commit message and PR description are in English
Do not skip checks and commit directly! Code that fails CI should not be merged.
┌─────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────┘
| 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 |
| 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 |
- Create workspace structure
- Set up CI configuration
- Create documentation skeleton
- Implement exit codes and error types
- Implement config and Alias management
- Implement path parsing
- Implement ObjectStore trait
- Implement alias command
- Follow command implementation template
- Each command needs tests
- Update SPEC.md (if needed)
- Update Golden tests
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