diff --git a/.codex/skills/onboard/SKILL.md b/.codex/skills/onboard/SKILL.md deleted file mode 100644 index fdf55acb49c..00000000000 --- a/.codex/skills/onboard/SKILL.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -name: onboard -description: Design or improve onboarding flows, empty states, and first-time user experiences. Helps users get started successfully and understand value quickly. -args: - - name: target - description: The feature or area needing onboarding (optional) - required: false -user-invokable: true ---- - -Create or improve onboarding experiences that help users understand, adopt, and succeed with the product quickly. - -## Assess Onboarding Needs - -Understand what users need to learn and why: - -1. **Identify the challenge**: - - What are users trying to accomplish? - - What's confusing or unclear about current experience? - - Where do users get stuck or drop off? - - What's the "aha moment" we want users to reach? - -2. **Understand the users**: - - What's their experience level? (Beginners, power users, mixed?) - - What's their motivation? (Excited and exploring? Required by work?) - - What's their time commitment? (5 minutes? 30 minutes?) - - What alternatives do they know? (Coming from competitor? New to category?) - -3. **Define success**: - - What's the minimum users need to learn to be successful? - - What's the key action we want them to take? (First project? First invite?) - - How do we know onboarding worked? (Completion rate? Time to value?) - -**CRITICAL**: Onboarding should get users to value as quickly as possible, not teach everything possible. - -## Onboarding Principles - -Follow these core principles: - -### Show, Don't Tell -- Demonstrate with working examples, not just descriptions -- Provide real functionality in onboarding, not separate tutorial mode -- Use progressive disclosure - teach one thing at a time - -### Make It Optional (When Possible) -- Let experienced users skip onboarding -- Don't block access to product -- Provide "Skip" or "I'll explore on my own" options - -### Time to Value -- Get users to their "aha moment" ASAP -- Front-load most important concepts -- Teach 20% that delivers 80% of value -- Save advanced features for contextual discovery - -### Context Over Ceremony -- Teach features when users need them, not upfront -- Empty states are onboarding opportunities -- Tooltips and hints at point of use - -### Respect User Intelligence -- Don't patronize or over-explain -- Be concise and clear -- Assume users can figure out standard patterns - -## Design Onboarding Experiences - -Create appropriate onboarding for the context: - -### Initial Product Onboarding - -**Welcome Screen**: -- Clear value proposition (what is this product?) -- What users will learn/accomplish -- Time estimate (honest about commitment) -- Option to skip (for experienced users) - -**Account Setup**: -- Minimal required information (collect more later) -- Explain why you're asking for each piece of information -- Smart defaults where possible -- Social login when appropriate - -**Core Concept Introduction**: -- Introduce 1-3 core concepts (not everything) -- Use simple language and examples -- Interactive when possible (do, don't just read) -- Progress indication (step 1 of 3) - -**First Success**: -- Guide users to accomplish something real -- Pre-populated examples or templates -- Celebrate completion (but don't overdo it) -- Clear next steps - -### Feature Discovery & Adoption - -**Empty States**: -Instead of blank space, show: -- What will appear here (description + screenshot/illustration) -- Why it's valuable -- Clear CTA to create first item -- Example or template option - -Example: -``` -No projects yet -Projects help you organize your work and collaborate with your team. -[Create your first project] or [Start from template] -``` - -**Contextual Tooltips**: -- Appear at relevant moment (first time user sees feature) -- Point directly at relevant UI element -- Brief explanation + benefit -- Dismissable (with "Don't show again" option) -- Optional "Learn more" link - -**Feature Announcements**: -- Highlight new features when they're released -- Show what's new and why it matters -- Let users try immediately -- Dismissable - -**Progressive Onboarding**: -- Teach features when users encounter them -- Badges or indicators on new/unused features -- Unlock complexity gradually (don't show all options immediately) - -### Guided Tours & Walkthroughs - -**When to use**: -- Complex interfaces with many features -- Significant changes to existing product -- Industry-specific tools needing domain knowledge - -**How to design**: -- Spotlight specific UI elements (dim rest of page) -- Keep steps short (3-7 steps max per tour) -- Allow users to click through tour freely -- Include "Skip tour" option -- Make replayable (help menu) - -**Best practices**: -- Interactive > passive (let users click real buttons) -- Focus on workflow, not features ("Create a project" not "This is the project button") -- Provide sample data so actions work - -### Interactive Tutorials - -**When to use**: -- Users need hands-on practice -- Concepts are complex or unfamiliar -- High stakes (better to practice in safe environment) - -**How to design**: -- Sandbox environment with sample data -- Clear objectives ("Create a chart showing sales by region") -- Step-by-step guidance -- Validation (confirm they did it right) -- Graduation moment (you're ready!) - -### Documentation & Help - -**In-product help**: -- Contextual help links throughout interface -- Keyboard shortcut reference -- Search-able help center -- Video tutorials for complex workflows - -**Help patterns**: -- `?` icon near complex features -- "Learn more" links in tooltips -- Keyboard shortcut hints (`⌘K` shown on search box) - -## Empty State Design - -Every empty state needs: - -### What Will Be Here -"Your recent projects will appear here" - -### Why It Matters -"Projects help you organize your work and collaborate with your team" - -### How to Get Started -[Create project] or [Import from template] - -### Visual Interest -Illustration or icon (not just text on blank page) - -### Contextual Help -"Need help getting started? [Watch 2-min tutorial]" - -**Empty state types**: -- **First use**: Never used this feature (emphasize value, provide template) -- **User cleared**: Intentionally deleted everything (light touch, easy to recreate) -- **No results**: Search or filter returned nothing (suggest different query, clear filters) -- **No permissions**: Can't access (explain why, how to get access) -- **Error state**: Failed to load (explain what happened, retry option) - -## Implementation Patterns - -### Technical approaches: - -**Tooltip libraries**: Tippy.js, Popper.js -**Tour libraries**: Intro.js, Shepherd.js, React Joyride -**Modal patterns**: Focus trap, backdrop, ESC to close -**Progress tracking**: LocalStorage for "seen" states -**Analytics**: Track completion, drop-off points - -**Storage patterns**: -```javascript -// Track which onboarding steps user has seen -localStorage.setItem('onboarding-completed', 'true'); -localStorage.setItem('feature-tooltip-seen-reports', 'true'); -``` - -**IMPORTANT**: Don't show same onboarding twice (annoying). Track completion and respect dismissals. - -**NEVER**: -- Force users through long onboarding before they can use product -- Patronize users with obvious explanations -- Show same tooltip repeatedly (respect dismissals) -- Block all UI during tour (let users explore) -- Create separate tutorial mode disconnected from real product -- Overwhelm with information upfront (progressive disclosure!) -- Hide "Skip" or make it hard to find -- Forget about returning users (don't show initial onboarding again) - -## Verify Onboarding Quality - -Test with real users: - -- **Time to completion**: Can users complete onboarding quickly? -- **Comprehension**: Do users understand after completing? -- **Action**: Do users take desired next step? -- **Skip rate**: Are too many users skipping? (Maybe it's too long/not valuable) -- **Completion rate**: Are users completing? (If low, simplify) -- **Time to value**: How long until users get first value? - -Remember: You're a product educator with excellent teaching instincts. Get users to their "aha moment" as quickly as possible. Teach the essential, make it contextual, respect user time and intelligence. - diff --git a/.codex/skills/optimize/SKILL.md b/.codex/skills/optimize/SKILL.md deleted file mode 100644 index 720ccc792d7..00000000000 --- a/.codex/skills/optimize/SKILL.md +++ /dev/null @@ -1,269 +0,0 @@ ---- -name: optimize -description: Improve interface performance across loading speed, rendering, animations, images, and bundle size. Makes experiences faster and smoother. -args: - - name: target - description: The feature or area to optimize (optional) - required: false -user-invokable: true ---- - -Identify and fix performance issues to create faster, smoother user experiences. - -## Assess Performance Issues - -Understand current performance and identify problems: - -1. **Measure current state**: - - **Core Web Vitals**: LCP, FID/INP, CLS scores - - **Load time**: Time to interactive, first contentful paint - - **Bundle size**: JavaScript, CSS, image sizes - - **Runtime performance**: Frame rate, memory usage, CPU usage - - **Network**: Request count, payload sizes, waterfall - -2. **Identify bottlenecks**: - - What's slow? (Initial load? Interactions? Animations?) - - What's causing it? (Large images? Expensive JavaScript? Layout thrashing?) - - How bad is it? (Perceivable? Annoying? Blocking?) - - Who's affected? (All users? Mobile only? Slow connections?) - -**CRITICAL**: Measure before and after. Premature optimization wastes time. Optimize what actually matters. - -## Optimization Strategy - -Create systematic improvement plan: - -### Loading Performance - -**Optimize Images**: -- Use modern formats (WebP, AVIF) -- Proper sizing (don't load 3000px image for 300px display) -- Lazy loading for below-fold images -- Responsive images (`srcset`, `picture` element) -- Compress images (80-85% quality is usually imperceptible) -- Use CDN for faster delivery - -```html -Hero image -``` - -**Reduce JavaScript Bundle**: -- Code splitting (route-based, component-based) -- Tree shaking (remove unused code) -- Remove unused dependencies -- Lazy load non-critical code -- Use dynamic imports for large components - -```javascript -// Lazy load heavy component -const HeavyChart = lazy(() => import('./HeavyChart')); -``` - -**Optimize CSS**: -- Remove unused CSS -- Critical CSS inline, rest async -- Minimize CSS files -- Use CSS containment for independent regions - -**Optimize Fonts**: -- Use `font-display: swap` or `optional` -- Subset fonts (only characters you need) -- Preload critical fonts -- Use system fonts when appropriate -- Limit font weights loaded - -```css -@font-face { - font-family: 'CustomFont'; - src: url('/fonts/custom.woff2') format('woff2'); - font-display: swap; /* Show fallback immediately */ - unicode-range: U+0020-007F; /* Basic Latin only */ -} -``` - -**Optimize Loading Strategy**: -- Critical resources first (async/defer non-critical) -- Preload critical assets -- Prefetch likely next pages -- Service worker for offline/caching -- HTTP/2 or HTTP/3 for multiplexing - -### Rendering Performance - -**Avoid Layout Thrashing**: -```javascript -// ❌ Bad: Alternating reads and writes (causes reflows) -elements.forEach(el => { - const height = el.offsetHeight; // Read (forces layout) - el.style.height = height * 2; // Write -}); - -// ✅ Good: Batch reads, then batch writes -const heights = elements.map(el => el.offsetHeight); // All reads -elements.forEach((el, i) => { - el.style.height = heights[i] * 2; // All writes -}); -``` - -**Optimize Rendering**: -- Use CSS `contain` property for independent regions -- Minimize DOM depth (flatter is faster) -- Reduce DOM size (fewer elements) -- Use `content-visibility: auto` for long lists -- Virtual scrolling for very long lists (react-window, react-virtualized) - -**Reduce Paint & Composite**: -- Use `transform` and `opacity` for animations (GPU-accelerated) -- Avoid animating layout properties (width, height, top, left) -- Use `will-change` sparingly for known expensive operations -- Minimize paint areas (smaller is faster) - -### Animation Performance - -**GPU Acceleration**: -```css -/* ✅ GPU-accelerated (fast) */ -.animated { - transform: translateX(100px); - opacity: 0.5; -} - -/* ❌ CPU-bound (slow) */ -.animated { - left: 100px; - width: 300px; -} -``` - -**Smooth 60fps**: -- Target 16ms per frame (60fps) -- Use `requestAnimationFrame` for JS animations -- Debounce/throttle scroll handlers -- Use CSS animations when possible -- Avoid long-running JavaScript during animations - -**Intersection Observer**: -```javascript -// Efficiently detect when elements enter viewport -const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - // Element is visible, lazy load or animate - } - }); -}); -``` - -### React/Framework Optimization - -**React-specific**: -- Use `memo()` for expensive components -- `useMemo()` and `useCallback()` for expensive computations -- Virtualize long lists -- Code split routes -- Avoid inline function creation in render -- Use React DevTools Profiler - -**Framework-agnostic**: -- Minimize re-renders -- Debounce expensive operations -- Memoize computed values -- Lazy load routes and components - -### Network Optimization - -**Reduce Requests**: -- Combine small files -- Use SVG sprites for icons -- Inline small critical assets -- Remove unused third-party scripts - -**Optimize APIs**: -- Use pagination (don't load everything) -- GraphQL to request only needed fields -- Response compression (gzip, brotli) -- HTTP caching headers -- CDN for static assets - -**Optimize for Slow Connections**: -- Adaptive loading based on connection (navigator.connection) -- Optimistic UI updates -- Request prioritization -- Progressive enhancement - -## Core Web Vitals Optimization - -### Largest Contentful Paint (LCP < 2.5s) -- Optimize hero images -- Inline critical CSS -- Preload key resources -- Use CDN -- Server-side rendering - -### First Input Delay (FID < 100ms) / INP (< 200ms) -- Break up long tasks -- Defer non-critical JavaScript -- Use web workers for heavy computation -- Reduce JavaScript execution time - -### Cumulative Layout Shift (CLS < 0.1) -- Set dimensions on images and videos -- Don't inject content above existing content -- Use `aspect-ratio` CSS property -- Reserve space for ads/embeds -- Avoid animations that cause layout shifts - -```css -/* Reserve space for image */ -.image-container { - aspect-ratio: 16 / 9; -} -``` - -## Performance Monitoring - -**Tools to use**: -- Chrome DevTools (Lighthouse, Performance panel) -- WebPageTest -- Core Web Vitals (Chrome UX Report) -- Bundle analyzers (webpack-bundle-analyzer) -- Performance monitoring (Sentry, DataDog, New Relic) - -**Key metrics**: -- LCP, FID/INP, CLS (Core Web Vitals) -- Time to Interactive (TTI) -- First Contentful Paint (FCP) -- Total Blocking Time (TBT) -- Bundle size -- Request count - -**IMPORTANT**: Measure on real devices with real network conditions. Desktop Chrome with fast connection isn't representative. - -**NEVER**: -- Optimize without measuring (premature optimization) -- Sacrifice accessibility for performance -- Break functionality while optimizing -- Use `will-change` everywhere (creates new layers, uses memory) -- Lazy load above-fold content -- Optimize micro-optimizations while ignoring major issues (optimize the biggest bottleneck first) -- Forget about mobile performance (often slower devices, slower connections) - -## Verify Improvements - -Test that optimizations worked: - -- **Before/after metrics**: Compare Lighthouse scores -- **Real user monitoring**: Track improvements for real users -- **Different devices**: Test on low-end Android, not just flagship iPhone -- **Slow connections**: Throttle to 3G, test experience -- **No regressions**: Ensure functionality still works -- **User perception**: Does it *feel* faster? - -Remember: Performance is a feature. Fast experiences feel more responsive, more polished, more professional. Optimize systematically, measure ruthlessly, and prioritize user-perceived performance. - diff --git a/.codex/skills/review/SKILL.md b/.codex/skills/review/SKILL.md deleted file mode 100644 index 88f24150ccd..00000000000 --- a/.codex/skills/review/SKILL.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -name: review -version: 1.0.0 -description: | - Pre-landing PR review. Analyzes diff against main for SQL safety, LLM trust - boundary violations, conditional side effects, and other structural issues. -allowed-tools: - - Bash - - Read - - Edit - - Write - - Grep - - Glob - - AskUserQuestion ---- - -# Pre-Landing PR Review - -You are running the `/review` workflow. Analyze the current branch's diff against main for structural issues that tests don't catch. - ---- - -## Step 1: Check branch - -1. Run `git branch --show-current` to get the current branch. -2. If on `main`, output: **"Nothing to review — you're on main or have no changes against main."** and stop. -3. Run `git fetch origin main --quiet && git diff origin/main --stat` to check if there's a diff. If no diff, output the same message and stop. - ---- - -## Step 2: Read the checklist - -Read `checklist.md`. - -**If the file cannot be read, STOP and report the error.** Do not proceed without the checklist. - ---- - -## Step 3: Get the diff - -Fetch the latest main to avoid false positives from a stale local main: - -```bash -git fetch origin main --quiet -``` - -Run `git diff origin/main` to get the full diff. This includes both committed and uncommitted changes against the latest main. - ---- - -## Step 4: Two-pass review - -Apply the checklist against the diff in two passes: - -1. **Pass 1 (CRITICAL):** SQL & Data Safety, LLM Output Trust Boundary -2. **Pass 2 (INFORMATIONAL):** Conditional Side Effects, Magic Numbers & String Coupling, Dead Code & Consistency, LLM Prompt Issues, Test Gaps, View/Frontend - -Follow the output format specified in the checklist. Respect the suppressions — do NOT flag items listed in the "DO NOT flag" section. - ---- - -## Step 5: Output findings - -**Always output ALL findings** — both critical and informational. The user must see every issue. - -- If CRITICAL issues found: output all findings, then for EACH critical issue use a separate AskUserQuestion with the problem, your recommended fix, and options (A: Fix it now, B: Acknowledge, C: False positive — skip). - After all critical questions are answered, output a summary of what the user chose for each issue. If the user chose A (fix) on any issue, apply the recommended fixes. If only B/C were chosen, no action needed. -- If only non-critical issues found: output findings. No further action needed. -- If no issues found: output `Pre-Landing Review: No issues found.` - ---- - -## Important Rules - -- **Read the FULL diff before commenting.** Do not flag issues already addressed in the diff. -- **Read-only by default.** Only modify files if the user explicitly chooses "Fix it now" on a critical issue. Never commit, push, or create PRs. -- **Be terse.** One line problem, one line fix. No preamble. -- **Only flag real problems.** Skip anything that's fine. diff --git a/.codex/skills/review/checklist.md b/.codex/skills/review/checklist.md deleted file mode 100644 index e3218900b14..00000000000 --- a/.codex/skills/review/checklist.md +++ /dev/null @@ -1,125 +0,0 @@ -# Pre-Landing Review Checklist - -## Instructions - -Review the `git diff origin/main` output for the issues listed below. Be specific — cite `file:line` and suggest fixes. Skip anything that's fine. Only flag real problems. - -**Two-pass review:** -- **Pass 1 (CRITICAL):** Run SQL & Data Safety and LLM Output Trust Boundary first. These can block `/ship`. -- **Pass 2 (INFORMATIONAL):** Run all remaining categories. These are included in the PR body but do not block. - -**Output format:** - -``` -Pre-Landing Review: N issues (X critical, Y informational) - -**CRITICAL** (blocking /ship): -- [file:line] Problem description - Fix: suggested fix - -**Issues** (non-blocking): -- [file:line] Problem description - Fix: suggested fix -``` - -If no issues found: `Pre-Landing Review: No issues found.` - -Be terse. For each issue: one line describing the problem, one line with the fix. No preamble, no summaries, no "looks good overall." - ---- - -## Review Categories - -### Pass 1 — CRITICAL - -#### SQL & Data Safety -- String interpolation in SQL (even if values are `.to_i`/`.to_f` — use `sanitize_sql_array` or Arel) -- TOCTOU races: check-then-set patterns that should be atomic `WHERE` + `update_all` -- `update_column`/`update_columns` bypassing validations on fields that have or should have constraints -- N+1 queries: `.includes()` missing for associations used in loops/views (especially avatar, attachments) - -#### Race Conditions & Concurrency -- Read-check-write without uniqueness constraint or `rescue RecordNotUnique; retry` (e.g., `where(hash:).first` then `save!` without handling concurrent insert) -- `find_or_create_by` on columns without unique DB index — concurrent calls can create duplicates -- Status transitions that don't use atomic `WHERE old_status = ? UPDATE SET new_status` — concurrent updates can skip or double-apply transitions -- `html_safe` on user-controlled data (XSS) — check any `.html_safe`, `raw()`, or string interpolation into `html_safe` output - -#### LLM Output Trust Boundary -- LLM-generated values (emails, URLs, names) written to DB or passed to mailers without format validation. Add lightweight guards (`EMAIL_REGEXP`, `URI.parse`, `.strip`) before persisting. -- Structured tool output (arrays, hashes) accepted without type/shape checks before database writes. - -### Pass 2 — INFORMATIONAL - -#### Conditional Side Effects -- Code paths that branch on a condition but forget to apply a side effect on one branch. Example: item promoted to verified but URL only attached when a secondary condition is true — the other branch promotes without the URL, creating an inconsistent record. -- Log messages that claim an action happened but the action was conditionally skipped. The log should reflect what actually occurred. - -#### Magic Numbers & String Coupling -- Bare numeric literals used in multiple files — should be named constants documented together -- Error message strings used as query filters elsewhere (grep for the string — is anything matching on it?) - -#### Dead Code & Consistency -- Variables assigned but never read -- Version mismatch between PR title and VERSION/CHANGELOG files -- CHANGELOG entries that describe changes inaccurately (e.g., "changed from X to Y" when X never existed) -- Comments/docstrings that describe old behavior after the code changed - -#### LLM Prompt Issues -- 0-indexed lists in prompts (LLMs reliably return 1-indexed) -- Prompt text listing available tools/capabilities that don't match what's actually wired up in the `tool_classes`/`tools` array -- Word/token limits stated in multiple places that could drift - -#### Test Gaps -- Negative-path tests that assert type/status but not the side effects (URL attached? field populated? callback fired?) -- Assertions on string content without checking format (e.g., asserting title present but not URL format) -- `.expects(:something).never` missing when a code path should explicitly NOT call an external service -- Security enforcement features (blocking, rate limiting, auth) without integration tests verifying the enforcement path works end-to-end - -#### Crypto & Entropy -- Truncation of data instead of hashing (last N chars instead of SHA-256) — less entropy, easier collisions -- `rand()` / `Random.rand` for security-sensitive values — use `SecureRandom` instead -- Non-constant-time comparisons (`==`) on secrets or tokens — vulnerable to timing attacks - -#### Time Window Safety -- Date-key lookups that assume "today" covers 24h — report at 8am PT only sees midnight→8am under today's key -- Mismatched time windows between related features — one uses hourly buckets, another uses daily keys for the same data - -#### Type Coercion at Boundaries -- Values crossing Ruby→JSON→JS boundaries where type could change (numeric vs string) — hash/digest inputs must normalize types -- Hash/digest inputs that don't call `.to_s` or equivalent before serialization — `{ cores: 8 }` vs `{ cores: "8" }` produce different hashes - -#### View/Frontend -- Inline `