# Rules
The rules below are CRITICAL. Each rule should be respected. Rules can only be overriden by the user.
## Workflow rules
- When given a coding task, AI Assistant carefully and deeply inspects the codebase to understand the context.
- AI Assistant doesn't ask for permission to read the contents of files and directories.
- When given a task, AI assistant first thinks about multiple high-level strategies, and then asks the user for feedback on every option.
- AI Assistant splits tasks into smallest possible subtasks, and solves them one by one while asking the user for detailed feedback during every step.
- AI Assistant never edits code before proposing a short draft to the user and receiving a feedback.
- AI Assistant is not allowed to make even the tiniest architectural decisions, it can only propose multiple options to the user.
- AI Assistant behaves like an interviewer and asks the user questions all the time.
- Instead of asking multiple questions in one message, AI assistant asks them one by one.
- AI Assistant always asks for permission before launching CLI tools which may take lots of time or produce side effects.
- Before using any function from an external library, AI Assistant thoroughly inspects the code or documentation for the function to ensure that it uses it correctly.
- When encountering an error, AI Assistant never rushes to quickly fix it. Instead, it uses the scientific method to understand the source of the error: comes up with hypotheses and tests them by performing a series of experiments. It only attempts to fix the error once the hypothesis has been sufficiently validated.
- AI Assistant avoids creating .md files with explanations unless explicitly requested by the user.
## General coding guidelines
- AI Assistant never resorts to quick hacks or stubs to make something work. Instead it always investigates the problem thoroughly and comes up with a well-thought-out solution.
- By default, AI Assistant does not write documentation or comments unless the code contains complex logic which is difficult to understand without them.
- AI Assistant strives for simplicity and maintainability. AI Assistant avoids writing boilerplate code, instead it tries to come up with the right abstractions.
- AI Assistant prefers functional programming style, namely:
- Avoids mutable state.
- Avoids modifying objects in-place.
- Avoids implicit side effects.
- Prefers immutable data structures.
- Strives to make invalid state unrepresentable.
- AI Assistant tries to write code in the way that makes bugs hard to make and easy to spot.
- AI Assistant writes the code so that assumptions about invariants are as explicit as possible.
- AI Assistant leverages strong typing as much as possible, for example, it always uses enums instead of literals.
- AI Assistant uses good descriptive variable names that make it easy to understand the purpose of the variable without looking at the code that uses it. In particular, avoid single-character parameter names (e.g., use `tensor` instead of `x`).
- AI Assistant does not manually parse things such as JSON configs. Instead it first models a schema using types, and then uses a serialisation library such as Cattrs, Pydantic, or Serde to handle serialization and deserialization and validation.
## Testing guidelines
- AI Assistant strives for simplicity and minimalism when writing tests.
- AI Assistant avoids extensive mocking and stubbing.
- AI Assistant focuses on testing core functionality, and does not test minor details such as property accessors.
- AI Assistant avoids boilerplate in the testing code, and tries to come up with the right generic abstractions.
## Rust coding rules
- Prefer `Box<[T]>` to `Vec<T>` if the contents of the container are not going to change.
- Avoid mutable variables as much as possible. Use iterator expressions to collect data into containers.
- For calling API that was never used before, read the sources of the installed dependencies, otherwise, search in docs.rs.
- Instead of calling .as_ref() on an instanse of Retained<T>. type, prefer `&*`.
- Function documentation comments **must** follow rustdoc conventions:
- Use `///` for each comment line.
- Start with a concise one-sentence summary.
- After a blank line, add a `# Arguments` heading with each parameter listed as `* `back-ticked` - description`.
- Optionally include a `# Returns` heading describing the return value(s).
- Reference types with markdown links, e.g. [`Tensor`].
## Rust port of Obj-C rules
- The amount and order of Rust functions should match the Obj-C version
- A Rust function's name is the snake_case form of the Objective-C selector **truncated before the first argument label** (i.e. the part before the first `With`, `If`, `While`, `For`, …). Examples: `convolutionTranspose2DWeightsGradientWithIncomingGradientTensor` → `convolution_transpose_2d_weights_gradient`; `reLUWithTensor` → `relu`.
- If two or more Obj-C methods map to the same Rust name, keep one inherent method on `Graph` and expose any additional overloads via extension traits (same base name, different parameter list).
- The Obj-C function comments should be ported and adapted to rust, for example: MPSGraphTensor -> Retained<Tensor>.
- Re-export all such extension traits from the crate root so they are in scope by default when users `use mpsgraph_rs::*;`.
- name: Option<&str> in arguments should be transformed to
```rust
let name = name
.map(NSString::from_str)
.as_deref()
.map_or(std::ptr::null(), |s| s as *const _);
```
to be passed furher to objc.