Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .agents/agents/reidbaker-agent/skills/api-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: api-review
description: Reviews the specified code against the canonical API Design guidelines. Use this skill when the user asks for an API review or to check code against API design principles.
---

# API review skill

This skill reviews code against the canonical API Design guidelines.

## Instructions

1. **Load Guidelines**: Read the API design guidelines from [references/canonical_api_design.md](references/canonical_api_design.md) to ensure they are fully available in the context.
2. **Identify Target**: Identify the code to review.
- If the user specified files (e.g., "review main.dart"), use those.
- If the user has an open file in their context, assume that is the target.
- If neither, ask the user to specify the target files.
3. **Analyze**: For each target file, perform a deep analysis against the "Foundations of Canonical API Design Principles" (loaded in step 1), specifically looking for:
- **Contract-First**: Is the interface clear and decoupled from implementation?
- **KISS/YAGNI**: Are there unnecessary parameters or over-generalized features?
- **Ergonomics**: Are names intent-revealing? Do they follow the Principle of Least Astonishment?
- **CQS**: Are commands and queries separated?
- **Safety**: Are types used strictly (Enums vs Strings)? Is validation visible?
- **Explicit Configuration**: Are dependencies explicitly injected rather than implicitly resolved via global state, registries, or environment variables?
4. **Report**: Generate a structured report:
- **Score**: Give a letter grade (A-F) based on alignment.
- **Critical Issues**: Violations that _must_ be fixed (e.g., severe strictness or safety issues).
- **Suggestions**: Ergonomic improvements (renaming, rearranging).
- **Code Examples**: Provide `before` vs `after` code blocks for the suggested improvements.
- Save the report as a markdown artifact in the conversation artifacts directory (e.g., `<appDataDir>/brain/<conversation-id>/api_review_results.md`).
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Foundations of canonical API design principles

This document contains the canonical principles for designing and improving APIs within the GenUI ecosystem. These principles are distilled from established software engineering best practices.

## Table of contents

- [Core architectural philosophy](#core-architectural-philosophy)
- [1. Contract-first design (API first)](#1-contract-first-design-api-first)
- [2. The KISS mandate (minimal surface area)](#2-the-kiss-mandate-minimal-surface-area)
- [3. YAGNI (avoid speculative generality)](#3-yagni-avoid-speculative-generality)
- [4. Separation of concerns (information hiding)](#4-separation-of-concerns-information-hiding)
- [5. Explicit configuration (dependency injection over stateful globals)](#5-explicit-configuration-dependency-injection-over-stateful-globals)
- [Interface ergonomics & semantics](#interface-ergonomics--semantics)
- [1. The principle of least astonishment (predictability)](#1-the-principle-of-least-astonishment-predictability)
- [2. Intent-revealing names](#2-intent-revealing-names)
- [3. Command-query separation (CQS)](#3-command-query-separation-cqs)
- [4. Orthogonality (composable primitives)](#4-orthogonality-composable-primitives)
- [Operational reliability & robustness](#operational-reliability--robustness)
- [1. Idempotency (safe retries)](#1-idempotency-safe-retries)
- [2. The robustness principle (Postel’s Law)](#2-the-robustness-principle-postels-law)
- [3. Circuit breaking (fail fast)](#3-circuit-breaking-fail-fast)
- [4. Bulk & batch operations](#4-bulk--batch-operations)
- [Data handling & evolution](#data-handling--evolution)
- [1. Scalable pagination (cursor over offset)](#1-scalable-pagination-cursor-over-offset)
- [2. Evolutionary design (versioning)](#2-evolutionary-design-versioning)
- [3. Type safety & strict validation](#3-type-safety-strict-validation)
- [4. Structured error reporting](#4-structured-error-reporting)
- [5. Single source of truth (DRY data)](#5-single-source-of-truth-dry-data)

## Core architectural philosophy

Foundational decisions that shape the system's structure and maintainability.

### 1. Contract-first design (API first)

Treat the interface definition as the primary product artifact, distinct from its implementation. Define the contract (the "what") rigorously before writing the code (the "how"). This decoupling allows consumers to validate the design against requirements before engineering resources are committed, and it serves as the single source of truth for the system's capabilities.

### 2. The KISS mandate (minimal surface area)

Complexity is the primary vector for defects and integration friction. Expose the smallest number of concepts necessary to solve the problem, aiming for "just enough power." Avoid "Swiss Army knife" interfaces that perform multiple unrelated operations. As a useful heuristic, if an interface requires extensive setup or explanation to use, it likely violates this principle.

### 3. YAGNI (avoid speculative generality)

Do not add parameters, operations, or data fields for hypothetical future needs. Speculative features introduce "accidental complexity"—complexity arising from the solution rather than the problem. Aim to build only what is required for current, concrete use cases to maintain a lean and testable interface.

### 4. Separation of concerns (information hiding)

The API must expose capabilities, not internal state or storage models. Never leak implementation details, such as database schemas or specific algorithms, through the interface. This encapsulation ensures that the internal architecture can be refactored or completely replaced without breaking consumers.

### 5. Explicit configuration (dependency injection over stateful globals)

Prefer explicit parameter passing and dependency injection over stateful global state, singletons, registries, or environment variables for API configuration. Implicit configurations obscure dependencies from caller visibility, prevent static type safety, and introduce global state mutations that make concurrent execution and parallel testing difficult. Programmatic instantiations are statically verifiable, isolate test cases, and make dependency compilation boundaries transparent to bundling tools.

## Interface ergonomics & semantics

Principles for ensuring the API is predictable, descriptive, and easy to use.

### 1. The principle of least astonishment (predictability)

An interface should behave exactly as a user expects based on their prior knowledge of the system. If a standard pattern exists for naming conventions or error structures, deviate from it only with significant justification. Consistency reduces the cognitive load required to learn and use the API.

### 2. Intent-revealing names

Names should describe business intent rather than technical mechanics. For example, a method named `publishArticle()` is superior to `updateRowStatus()`. Use specific, self-descriptive terminology, like `temperatureCelsius` instead of `temp`, to prevent ambiguity and reduce reliance on external documentation.

### 3. Command-query separation (CQS)

Clearly distinguish between operations that retrieve data (queries) and operations that modify state (commands). Queries should ideally be safe and side-effect-free, allowing consumers to call them repeatedly without risk. Avoid mixing data retrieval with state mutation in a single operation, as it leads to unpredictable system behavior.

### 4. Orthogonality (composable primitives)

Design small, independent primitives that can be composed to create complex behaviors, rather than creating rigid, complex operations for every specific scenario. Changing one independent parameter should not have unexpected side effects on unrelated parts of the request.

## Operational reliability & robustness

Designing for failure, distributed systems, and performance in a production environment.

### 1. Idempotency (safe retries)

In a distributed system, network failures are inevitable. Operations that change state must be designed to be idempotent, meaning they can be safely retried multiple times without producing cumulative side effects, such as double-charging. This is often achieved by requiring clients to provide a unique idempotency key or transaction identifier.

### 2. The robustness principle (Postel’s Law)

Follow the robustness principle: "Be conservative in what you send, be liberal in what you accept." Strictly adhere to the interface contract when generating output, but implement tolerance when processing input, such as ignoring unknown fields rather than crashing. This approach improves interoperability and allows the system to evolve without immediately breaking older clients.

### 3. Circuit breaking (fail fast)

If a dependency or subsystem is failing, stop calling it immediately to prevent cascading failures. The interface should fail fast and return a specific error rather than hanging indefinitely. This preserves system resources and provides immediate feedback to the consumer.

### 4. Bulk & batch operations

To reduce network overhead and latency, provide mechanisms to process multiple items in a single request, such as `createItems([item1, item2])`. Ensure the behavior of partial failures is well-defined: either the entire batch fails atomically, or the response clearly indicates the success or failure status of each individual item.

## Data handling & evolution

Guidelines for managing state, validation, and long-term interface maintenance.

### 1. Scalable pagination (cursor over offset)

Never return unbounded lists of data. For large datasets, prefer cursor-based (keyset) pagination over offset-based pagination. Cursors, which point to a specific record, provide constant-time performance (O(1)) and data stability. In contrast, offsets degrade in performance (O(n)) and suffer from skipped or duplicate records when data is modified during iteration.

### 2. Evolutionary design (versioning)

Plan for change from day one. Interfaces will evolve, and breaking changes must be managed without disrupting existing consumers. Use explicit versioning strategies, such as semantic versioning, and establish a clear deprecation lifecycle (warn, then sunset, and finally remove) to give consumers time to migrate.

### 3. Type safety & strict validation

Enforce constraints at the boundary. Use strong types, such as enums instead of raw strings, or distinct types for monetary values, to make invalid states unrepresentable. Validate all input rigorously before processing to prevent data corruption and security vulnerabilities.

### 4. Structured error reporting

Errors must be machine-readable and actionable. Return specific error codes, rather than generic failure indicators, accompanied by descriptive messages. Where possible, include structured metadata that allows the consumer to programmatically recover or correct their input.

### 5. Single source of truth (DRY data)

Avoid defining the same business logic or data structure in multiple places. Ensure that a concept, such as a user or an order, has a canonical representation. Divergent definitions lead to integration errors where one part of the system enforces rules that another ignores.
69 changes: 69 additions & 0 deletions .agents/agents/reidbaker-agent/skills/code-documentation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: code-documentation
description: Guide for writing effective code documentation, including docstrings, JSDoc, dartdoc, and implementation comments. Use this skill when writing new code, adding features, or improving existing documentation in Dart, Python, or TypeScript to ensure clarity and maintainability.
---

# Code Documentation Skill

This skill provides comprehensive guidelines for documenting code, prioritizing user-centric writing, clarity, and consistency.

## 1. General Philosophy

- **User-Centric**: Write for the person using your API. If you had to look up how to use something, document it so others don't have to.
- **Explain "Why"**: Explain _why_ code exists and _how_ to use it effectively, since the code signature already tells _what_ it does.
- **Be Concise**: Omit fluff. Avoid merely restating the code name, as it is not helpful.
- **Consistency**: Use standard terminology and consistent formatting.
- **Public APIs**: Document all public APIs (classes, members, top-level functions) without exception.
- **Code Samples**: Strongly consider adding code samples to explain usage.

## 2. General Structure

Follow this general structure for documentation comments across languages:

1. **Summary Sentence**: Start with a single-sentence summary on the first line, ending with a period.
2. **Blank Line**: Follow the summary with a blank line.
3. **Details**: Add paragraphs, code samples, or lists as needed to explain parameters, return values, exceptions, and behavior.
4. **Annotations**: Place doc comments **before** any metadata annotations.

## 3. Writing Guidelines

### Brevity & Style

- **Avoid Fluff**: Omit "This class...", "This method...", "Is used to...", "Note that...".
- _Bad_: "This method is used to calculate the total."
- _Good_: "Calculates the total."
- **Third-Person Verbs**: Start function/method docs with a third-person singular verb.
- _Examples_: "Returns...", "Calculates...", "Updates...", "Creates...".
- **Noun Phrases**: Start variable/property docs with a noun phrase.
- _Examples_: "The current color.", "A list of active users.".
- **Booleans**: Always start with "Whether" (or similar clear indicator).
- _Good_: "Whether this widget is enabled."
- _Bad_: "If this widget is enabled...", "True if...", "Flag to indicate...".
- **Avoid Jargon**: Use plain English unless the term is a widely accepted standard (e.g., "HTTP", "URL").

### Formatting

- **Sparingly**: Use Markdown features (bold, lists) sparingly.
- **No HTML**: Avoid HTML unless strictly necessary and supported by the documentation tool.
- **Parameters/Returns/Exceptions**: Use prose to describe parameters, return values, and thrown exceptions. Do not rely solely on tags like `@param` unless mandated by the language standard (e.g., Javadoc).

## 4. Implementation Comments

Ensure implementation comments (`//`) are accurate, relevant, factual, and provide information that is not readily understandable from the code. Remove or reword comments that do not meet these criteria. If an implementation comment provides information useful to an API consumer that is not already in the documentation comments, move it to the documentation comments.

## 5. Review Checklist

Use this checklist to verify your documentation:

1. [ ] **Summary**: Ensure every public member starts with a one-sentence summary ending in a period.
2. [ ] **Brevity**: Remove "This class..." or "This function..." fluff.
3. [ ] **Completeness**: Document strict constraints (e.g., "must not be null") and exceptions.
4. [ ] **Examples**: Consider adding a code sample for complex widgets or methods.

## 6. Language Specific Instructions

Refer to the language guides for detailed instructions on structure, linking, and framework-specific patterns:

- **Dart / Flutter**: [references/dart.md](references/dart.md)
- **TypeScript / JavaScript**: [references/typescript.md](references/typescript.md)
- **Python**: [references/python.md](references/python.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Dart & Flutter Documentation

## Documentation Structure (`///`)

Use `///` (doc comments) for all public members to allow tools like `dartdoc` to process them.

### Comments Format

1. **Summary Sentence**: Start with a single-sentence summary on the first line, ending with a period.
2. **Blank Line**: Follow the summary with a blank line.
3. **Details**: Add paragraphs, code samples, or lists as needed to explain parameters, return values, exceptions, and behavior.
4. **Annotations**: Place doc comments **before** any metadata annotations (e.g., `@override`, `@Deprecated`).

```dart
/// A button that initiates a purchase flow.
///
/// This widget handles the loading state automatically and disables
/// itself while the transaction is processing.
@Deprecated('Use PurchaseButtonV2 instead')
class PurchaseButton extends StatelessWidget { ... }
```

### Property Documentation

- **Getters override Setters**: Document the getter and omit documentation on the setter, as documentation tools combine them automatically. Do not document both.
```dart
/// The current optimization level (0.0 to 1.0).
double get optimizationLevel => _level;
set optimizationLevel(double value) { ... }
```

### Library Documentation

- **Library Comments**: Add a doc comment at the top of the file (before imports) for libraries (files) to provide a high-level overview.

## Writing Guidelines

### Terminology

- Use **canonical terms**:
- Refer to "widgets", "state", "build context", "render object".
- Avoid generic terms like "component" or "element" when you mean "Widget".

### Code References

- Use square brackets `[MyClass]`, `[variableName]`, `[methodName]` to link to in-scope identifiers.
- Use backticks `` `true` ``, `` `null` ``, `` `this` `` for keywords and literals.
- **Code Samples**: Include code blocks to demonstrate usage.
````dart
/// Example:
///
/// ```dart
/// final path = FlightPath(coordinates: [a, b]);
/// ```
````

## Flutter Specifics

### Widgets

- **Purpose**: Explain what the widget does and when to use it.
- **Parameters**: Document key parameters, especially if they are required or have complex constraints.
- **State**: Explain any interesting state behavior, such as keeping position on scroll.

```dart
/// Displays a flight path on a map.
///
/// Use this widget within a [MapLayout]. The path is drawn using
/// the provided [coordinates].
class FlightPath extends StatelessWidget {
/// Creates a flight path.
///
/// The [coordinates] must contain at least two points.
const FlightPath({required this.coordinates, super.key});
```

### State Management

- **Lifecycle**: Explain how to dispose of controllers or other classes that manage a complex lifecycle.
- **Private Classes**: Document significantly complex private classes (such as intricate `State` logic) to aid maintainability, even though public APIs are the priority.
Loading
Loading