---
title: "wshobson/agents"
description: "Multi-harness agentic plugin marketplace for Claude Code, Codex CLI, Cursor, OpenCode, GitHub Copilot, and Gemini CLI"
source: https://github.com/wshobson/agents
ref: main
license: MIT
licenseName: "MIT License"
canonical: https://skillsdocs.com/wshobson/agents
base: https://github.com/wshobson/agents/blob/main/
chapters: 180
inlined: 180
withheld: 0
words: 69669
updated: 2026-08-05T07:11:13Z
generator: "Skills Docs"
---

> **wshobson/agents** — every Agent Skill in this repository, inlined verbatim.
>
> Canonical HTML: https://skillsdocs.com/wshobson/agents
> Per-chapter Markdown: https://skillsdocs.com/wshobson/agents/<skill>.md
> Machine manifest: https://skillsdocs.com/wshobson/agents/.well-known/agent-skills/index.json
> JSON: https://skillsdocs.com/api/v1/books/wshobson/agents
> Install: `npx skills add wshobson/agents`
> Upstream: https://github.com/wshobson/agents @ `main`
> Licence: MIT
>
> Content is mirrored from GitHub and © its authors, served unmodified. Takedown: https://github.com/kyleledbetter/skillsdocs/issues/new?labels=takedown&title=Takedown+request

# wshobson/agents

Multi-harness agentic plugin marketplace for Claude Code, Codex CLI, Cursor, OpenCode, GitHub Copilot, and Gemini CLI

- **Chapters:** 180
- **Inlined:** 180 (licence detected)
- **Words:** 69,669
- **Reading time:** 328 min
- **Stars:** 38,667

## Table of contents

1. [screen-reader-testing](https://skillsdocs.com/wshobson/agents/screen-reader-testing.md) — Test web applications with screen readers including VoiceOver, NVDA, and JAWS. Use when validating screen reader compatibility, debugging accessibility issues,…
2. [wcag-audit-patterns](https://skillsdocs.com/wshobson/agents/wcag-audit-patterns.md) — Conduct WCAG 2.2 accessibility audits with automated testing, manual verification, and remediation guidance. Use when auditing websites for accessibility, fixi…
3. [multi-reviewer-patterns](https://skillsdocs.com/wshobson/agents/multi-reviewer-patterns.md) — Coordinate parallel code reviews across multiple quality dimensions with finding deduplication, severity calibration, and consolidated reporting. Use this skil…
4. [parallel-debugging](https://skillsdocs.com/wshobson/agents/parallel-debugging.md) — Debug complex issues using competing hypotheses with parallel investigation, evidence collection, and root cause arbitration. Use this skill when debugging bug…
5. [parallel-feature-development](https://skillsdocs.com/wshobson/agents/parallel-feature-development.md) — Coordinate parallel feature development with file ownership strategies, conflict avoidance rules, and integration patterns for multi-agent implementation. Use…
6. [task-coordination-strategies](https://skillsdocs.com/wshobson/agents/task-coordination-strategies.md) — Decompose complex tasks, design dependency graphs, and coordinate multi-agent work with proper task descriptions and workload balancing. Use this skill when br…
7. [team-communication-protocols](https://skillsdocs.com/wshobson/agents/team-communication-protocols.md) — Structured messaging protocols for agent team communication including message type selection, plan approval, shutdown procedures, and anti-patterns to avoid. U…
8. [team-composition-patterns](https://skillsdocs.com/wshobson/agents/team-composition-patterns.md) — Design optimal agent team compositions with sizing heuristics, preset configurations, and agent type selection. Use this skill when deciding how many agents to…
9. [fastapi-templates](https://skillsdocs.com/wshobson/agents/fastapi-templates.md) — Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI application…
10. [api-design-principles](https://skillsdocs.com/wshobson/agents/api-design-principles.md) — Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewi…
11. [architecture-patterns](https://skillsdocs.com/wshobson/agents/architecture-patterns.md) — Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use this skill when designing cl…
12. [cqrs-implementation](https://skillsdocs.com/wshobson/agents/cqrs-implementation.md) — Implement Command Query Responsibility Segregation for scalable architectures. Use when separating read and write models, optimizing query performance, or buil…
13. [event-store-design](https://skillsdocs.com/wshobson/agents/event-store-design.md) — Design and implement event stores for event-sourced systems. Use when building event sourcing infrastructure, choosing event store technologies, or implementin…
14. [microservices-patterns](https://skillsdocs.com/wshobson/agents/microservices-patterns.md) — Design microservices architectures with service boundaries, event-driven communication, and resilience patterns. Use when building distributed systems, decompo…
15. [projection-patterns](https://skillsdocs.com/wshobson/agents/projection-patterns.md) — Build read models and projections from event streams. Use when implementing CQRS read sides, building materialized views, or optimizing query performance in ev…
16. [saga-orchestration](https://skillsdocs.com/wshobson/agents/saga-orchestration.md) — Implement saga patterns for distributed transactions and cross-aggregate workflows. Use this skill when implementing distributed transactions across microservi…
17. [temporal-python-testing](https://skillsdocs.com/wshobson/agents/temporal-python-testing.md) — Test Temporal workflows with pytest, time-skipping, and mocking strategies. Covers unit testing, integration testing, replay testing, and local development set…
18. [workflow-orchestration-patterns](https://skillsdocs.com/wshobson/agents/workflow-orchestration-patterns.md) — Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constr…
19. [before-you-build](https://skillsdocs.com/wshobson/agents/before-you-build.md) — Pre-build product and feature risk review for founders, product managers, and AI-assisted builders. Use this skill when the user is about to build a landing pa…
20. [block-no-verify-hook](https://skillsdocs.com/wshobson/agents/block-no-verify-hook.md) — Configure a PreToolUse hook to prevent AI agents from skipping git pre-commit hooks with --no-verify and other bypass flags. Use when setting up Claude Code pr…
21. [defi-protocol-templates](https://skillsdocs.com/wshobson/agents/defi-protocol-templates.md) — Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and flash loans. Use when building decentralized finance applications o…
22. [nft-standards](https://skillsdocs.com/wshobson/agents/nft-standards.md) — Implement NFT standards (ERC-721, ERC-1155) with proper metadata handling, minting strategies, and marketplace integration. Use when creating NFT contracts, bu…
23. [solidity-security](https://skillsdocs.com/wshobson/agents/solidity-security.md) — Master smart contract security best practices to prevent common vulnerabilities and implement secure Solidity patterns. Use when writing smart contracts, audit…
24. [web3-testing](https://skillsdocs.com/wshobson/agents/web3-testing.md) — Test smart contracts comprehensively using Hardhat and Foundry with unit tests, integration tests, and mainnet forking. Use when testing Solidity contracts, se…
25. [brand-landingpage](https://skillsdocs.com/wshobson/agents/brand-landingpage.md) — Brand-first landing page designer — runs a brand-identity interview (colors, typography, shape language), then generates and iterates on a polished landing pag…
26. [data-storytelling](https://skillsdocs.com/wshobson/agents/data-storytelling.md) — Transform data into compelling narratives using visualization, context, and persuasive structure. Use when presenting analytics to stakeholders, creating data…
27. [kpi-dashboard-design](https://skillsdocs.com/wshobson/agents/kpi-dashboard-design.md) — Design effective KPI dashboards with metrics selection, visualization best practices, and real-time monitoring patterns. Use this skill when building an execut…
28. [deployment-pipeline-design](https://skillsdocs.com/wshobson/agents/deployment-pipeline-design.md) — Design multi-stage CI/CD pipelines with approval gates, security checks, and deployment orchestration. Use this skill when designing zero-downtime deployment p…
29. [github-actions-templates](https://skillsdocs.com/wshobson/agents/github-actions-templates.md) — Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, au…
30. [gitlab-ci-patterns](https://skillsdocs.com/wshobson/agents/gitlab-ci-patterns.md) — Build GitLab CI/CD pipelines with multi-stage workflows, caching, and distributed runners for scalable automation. Use when implementing GitLab CI/CD, optimizi…
31. [secrets-management](https://skillsdocs.com/wshobson/agents/secrets-management.md) — Implement secure secrets management for CI/CD pipelines using Vault, AWS Secrets Manager, or native platform solutions. Use when handling sensitive credentials…
32. [cost-optimization](https://skillsdocs.com/wshobson/agents/cost-optimization.md) — Optimize cloud costs across AWS, Azure, GCP, and OCI through resource rightsizing, tagging strategies, reserved instances, and spending analysis. Use when redu…
33. [hybrid-cloud-networking](https://skillsdocs.com/wshobson/agents/hybrid-cloud-networking.md) — Configure secure, high-performance connectivity between on-premises infrastructure and cloud platforms using VPN and dedicated connections. Use when building h…
34. [istio-traffic-management](https://skillsdocs.com/wshobson/agents/istio-traffic-management.md) — Configure Istio traffic management including routing, load balancing, circuit breakers, and canary deployments. Use when implementing service mesh traffic poli…
35. [linkerd-patterns](https://skillsdocs.com/wshobson/agents/linkerd-patterns.md) — Implement Linkerd service mesh patterns for lightweight, security-focused service mesh deployments. Use when setting up Linkerd, configuring traffic policies,…
36. [mtls-configuration](https://skillsdocs.com/wshobson/agents/mtls-configuration.md) — Configure mutual TLS (mTLS) for zero-trust service-to-service communication. Use when implementing zero-trust networking, certificate management, or securing i…
37. [multi-cloud-architecture](https://skillsdocs.com/wshobson/agents/multi-cloud-architecture.md) — Design multi-cloud architectures using a decision framework to select and integrate services across AWS, Azure, GCP, and OCI. Use when building multi-cloud sys…
38. [service-mesh-observability](https://skillsdocs.com/wshobson/agents/service-mesh-observability.md) — Implement comprehensive observability for service meshes including distributed tracing, metrics, and visualization. Use when setting up mesh monitoring, debugg…
39. [terraform-module-library](https://skillsdocs.com/wshobson/agents/terraform-module-library.md) — Build reusable Terraform modules for AWS, Azure, GCP, and OCI infrastructure following infrastructure-as-code best practices. Use when creating infrastructure…
40. [context-driven-development](https://skillsdocs.com/wshobson/agents/context-driven-development.md) — Creates and maintains project context artifacts (product.md, tech-stack.md, workflow.md, tracks.md) in a `conductor/` directory. Scaffolds new projects from sc…
41. [track-management](https://skillsdocs.com/wshobson/agents/track-management.md) — Use this skill when creating, managing, or working with Conductor tracks - the logical work units for features, bugs, and refactors. Applies to spec.md, plan.m…
42. [workflow-patterns](https://skillsdocs.com/wshobson/agents/workflow-patterns.md) — Use this skill when implementing tasks according to Conductor's TDD workflow, handling phase checkpoints, managing git commits for tasks, or understanding the…
43. [airflow-dag-patterns](https://skillsdocs.com/wshobson/agents/airflow-dag-patterns.md) — Build production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workf…
44. [data-quality-frameworks](https://skillsdocs.com/wshobson/agents/data-quality-frameworks.md) — Implement data quality validation with Great Expectations, dbt tests, and data contracts. Use when building data quality pipelines, implementing validation rul…
45. [dbt-transformation-patterns](https://skillsdocs.com/wshobson/agents/dbt-transformation-patterns.md) — Master dbt (data build tool) for analytics engineering with model organization, testing, documentation, and incremental strategies. Use when building data tran…
46. [spark-optimization](https://skillsdocs.com/wshobson/agents/spark-optimization.md) — Optimize Apache Spark jobs with partitioning, caching, shuffle optimization, and memory tuning. Use when improving Spark performance, debugging slow jobs, or s…
47. [postgresql-table-design](https://skillsdocs.com/wshobson/agents/postgresql.md) — Use this skill when designing or reviewing a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and ad…
48. [auth-implementation-patterns](https://skillsdocs.com/wshobson/agents/auth-implementation-patterns.md) — Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when…
49. [bazel-build-optimization](https://skillsdocs.com/wshobson/agents/bazel-build-optimization.md) — Optimize Bazel builds for large-scale monorepos. Use when configuring Bazel, implementing remote execution, or optimizing build performance for enterprise code…
50. [code-review-excellence](https://skillsdocs.com/wshobson/agents/code-review-excellence.md) — Master effective code review practices to provide constructive feedback, catch bugs early, and foster knowledge sharing while maintaining team morale. Use when…
51. [debugging-strategies](https://skillsdocs.com/wshobson/agents/debugging-strategies.md) — Master systematic debugging techniques, profiling tools, and root cause analysis to efficiently track down bugs across any codebase or technology stack. Use wh…
52. [e2e-testing-patterns](https://skillsdocs.com/wshobson/agents/e2e-testing-patterns.md) — Master end-to-end testing with Playwright and Cypress to build reliable test suites that catch bugs, improve confidence, and enable fast deployment. Use when i…
53. [error-handling-patterns](https://skillsdocs.com/wshobson/agents/error-handling-patterns.md) — Master error handling patterns across languages including exceptions, Result types, error propagation, and graceful degradation to build resilient applications…
54. [git-advanced-workflows](https://skillsdocs.com/wshobson/agents/git-advanced-workflows.md) — Master advanced Git workflows including rebasing, cherry-picking, bisect, worktrees, and reflog to maintain clean history and recover from any situation. Use w…
55. [monorepo-management](https://skillsdocs.com/wshobson/agents/monorepo-management.md) — Master monorepo management with Turborepo, Nx, and pnpm workspaces to build efficient, scalable multi-package repositories with optimized builds and dependency…
56. [nx-workspace-patterns](https://skillsdocs.com/wshobson/agents/nx-workspace-patterns.md) — Configure and optimize Nx monorepo workspaces. Use when setting up Nx, configuring project boundaries, optimizing build caching, or implementing affected comma…
57. [sql-optimization-patterns](https://skillsdocs.com/wshobson/agents/sql-optimization-patterns.md) — Master SQL query optimization, indexing strategies, and EXPLAIN analysis to dramatically improve database performance and eliminate slow queries. Use when debu…
58. [turborepo-caching](https://skillsdocs.com/wshobson/agents/turborepo-caching.md) — Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing dis…
59. [spark-environment-setup](https://skillsdocs.com/wshobson/agents/spark-environment-setup.md) — Set up a working ML training/inference environment on NVIDIA DGX Spark (GB10, aarch64, CUDA 13). Use when installing PyTorch/Unsloth/TRL/vLLM on DGX Spark, hit…
60. [spark-memory-thermal-ops](https://skillsdocs.com/wshobson/agents/spark-memory-thermal-ops.md) — Manage unified memory and thermals during long-running ML jobs on NVIDIA DGX Spark. Use when planning memory headroom for a training run on GB10, when a job OO…
61. [spark-training-gotchas](https://skillsdocs.com/wshobson/agents/spark-training-gotchas.md) — Preflight and diagnose the ten known failure modes for ML training on NVIDIA DGX Spark. Use when a training run on DGX Spark fails to start, OOMs below the 128…
62. [architecture-decision-records](https://skillsdocs.com/wshobson/agents/architecture-decision-records.md) — Write and maintain Architecture Decision Records (ADRs) following best practices for technical decision documentation. Use when documenting significant technic…
63. [changelog-automation](https://skillsdocs.com/wshobson/agents/changelog-automation.md) — Automate changelog generation from commits, PRs, and releases following Keep a Changelog format. Use when setting up release workflows, generating release note…
64. [openapi-spec-generation](https://skillsdocs.com/wshobson/agents/openapi-spec-generation.md) — Generate and maintain OpenAPI 3.1 specifications from code, design-first specs, and validation patterns. Use when creating API documentation, generating SDKs,…
65. [hads](https://skillsdocs.com/wshobson/agents/hads.md) — Use when writing technical documentation that needs to be readable by both humans and AI models, converting existing docs to HADS format, validating a HADS doc…
66. [dotnet-backend-patterns](https://skillsdocs.com/wshobson/agents/dotnet-backend-patterns.md) — Master C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entit…
67. [file-conversion](https://skillsdocs.com/wshobson/agents/file-conversion.md) — Convert files between formats — PDF to Word, HEIC to JPG, MP4 to MP3, CSV to JSON, EPUB to MOBI, and 999 total routes across images, video, audio, documents, d…
68. [angular-migration](https://skillsdocs.com/wshobson/agents/angular-migration.md) — Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applicatio…
69. [database-migration](https://skillsdocs.com/wshobson/agents/database-migration.md) — Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases…
70. [dependency-upgrade](https://skillsdocs.com/wshobson/agents/dependency-upgrade.md) — Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updatin…
71. [react-modernization](https://skillsdocs.com/wshobson/agents/react-modernization.md) — Upgrade React applications to latest versions, migrate from class components to hooks, and adopt concurrent features. Use when modernizing React codebases, mig…
72. [nextjs-app-router-patterns](https://skillsdocs.com/wshobson/agents/nextjs-app-router-patterns.md) — Master Next.js 14+ App Router with Server Components, streaming, parallel routes, and advanced data fetching. Use when building Next.js applications, implement…
73. [react-native-architecture](https://skillsdocs.com/wshobson/agents/react-native-architecture.md) — Build production React Native apps with Expo, navigation, native modules, offline sync, and cross-platform patterns. Use when developing mobile apps, implement…
74. [react-state-management](https://skillsdocs.com/wshobson/agents/react-state-management.md) — Master modern React state management with Redux Toolkit, Zustand, Jotai, and React Query. Use when setting up global state, managing server state, or choosing…
75. [tailwind-design-system](https://skillsdocs.com/wshobson/agents/tailwind-design-system.md) — Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, impleme…
76. [godot-gdscript-patterns](https://skillsdocs.com/wshobson/agents/godot-gdscript-patterns.md) — Master Godot 4 GDScript patterns including signals, scenes, state machines, and optimization. Use when building Godot games, implementing game systems, or lear…
77. [unity-ecs-patterns](https://skillsdocs.com/wshobson/agents/unity-ecs-patterns.md) — Master Unity ECS (Entity Component System) with DOTS, Jobs, and Burst for high-performance game development. Use when building data-oriented games, optimizing…
78. [hermes-tweet](https://skillsdocs.com/wshobson/agents/hermes-tweet.md) — Install and operate Hermes Tweet, a Hermes Agent plugin for X/Twitter research, timeline reading, tweet analysis, and approval-gated tweet actions. Use this sk…
79. [employment-contract-templates](https://skillsdocs.com/wshobson/agents/employment-contract-templates.md) — Create employment contracts, offer letters, and HR policy documents following legal best practices. Use when drafting employment agreements, creating HR polici…
80. [gdpr-data-handling](https://skillsdocs.com/wshobson/agents/gdpr-data-handling.md) — Implement GDPR-compliant data handling with consent management, data subject rights, and privacy by design. Use when building systems that process EU personal…
81. [incident-runbook-templates](https://skillsdocs.com/wshobson/agents/incident-runbook-templates.md) — Create structured incident response runbooks with step-by-step procedures, escalation paths, and recovery actions. Use this skill when building a service outag…
82. [on-call-handoff-patterns](https://skillsdocs.com/wshobson/agents/on-call-handoff-patterns.md) — Master on-call shift handoffs with context transfer, escalation procedures, and documentation. Use this skill when transitioning on-call responsibilities betwe…
83. [postmortem-writing](https://skillsdocs.com/wshobson/agents/postmortem-writing.md) — Write effective blameless postmortems with root cause analysis, timelines, and action items. Use when conducting incident reviews, writing postmortem documents…
84. [javascript-testing-patterns](https://skillsdocs.com/wshobson/agents/javascript-testing-patterns.md) — Implement comprehensive testing strategies using Jest, Vitest, and Testing Library for unit tests, integration tests, and end-to-end testing with mocking, fixt…
85. [modern-javascript-patterns](https://skillsdocs.com/wshobson/agents/modern-javascript-patterns.md) — Master ES6+ features including async/await, destructuring, spread operators, arrow functions, promises, modules, iterators, generators, and functional programm…
86. [nodejs-backend-patterns](https://skillsdocs.com/wshobson/agents/nodejs-backend-patterns.md) — Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, a…
87. [typescript-advanced-types](https://skillsdocs.com/wshobson/agents/typescript-advanced-types.md) — Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe appli…
88. [gitops-workflow](https://skillsdocs.com/wshobson/agents/gitops-workflow.md) — Implement GitOps workflows with ArgoCD and Flux for automated, declarative Kubernetes deployments with continuous reconciliation. Use when implementing GitOps…
89. [helm-chart-scaffolding](https://skillsdocs.com/wshobson/agents/helm-chart-scaffolding.md) — Design, organize, and manage Helm charts for templating and packaging Kubernetes applications with reusable configurations. Use when creating Helm charts, pack…
90. [k8s-manifest-generator](https://skillsdocs.com/wshobson/agents/k8s-manifest-generator.md) — Create production-ready Kubernetes manifests for Deployments, Services, ConfigMaps, and Secrets following best practices and security standards. Use when gener…
91. [k8s-security-policies](https://skillsdocs.com/wshobson/agents/k8s-security-policies.md) — Implement Kubernetes security policies including NetworkPolicy, PodSecurityPolicy, and RBAC for production-grade security. Use when securing Kubernetes cluster…
92. [embedding-strategies](https://skillsdocs.com/wshobson/agents/embedding-strategies.md) — Select and optimize embedding models for semantic search and RAG applications. Use when choosing embedding models, implementing chunking strategies, or optimiz…
93. [hybrid-search-implementation](https://skillsdocs.com/wshobson/agents/hybrid-search-implementation.md) — Combine vector and keyword search for improved retrieval. Use when implementing RAG systems, building search engines, or when neither approach alone provides s…
94. [langchain-architecture](https://skillsdocs.com/wshobson/agents/langchain-architecture.md) — Design LLM applications using LangChain 1.x and LangGraph for agents, memory, and tool integration. Use when building LangChain applications, implementing AI a…
95. [llm-evaluation](https://skillsdocs.com/wshobson/agents/llm-evaluation.md) — Implement comprehensive evaluation strategies for LLM applications using automated metrics, human feedback, and benchmarking. Use when testing LLM performance,…
96. [prompt-engineering-patterns](https://skillsdocs.com/wshobson/agents/prompt-engineering-patterns.md) — This skill should be used when the user asks to "optimize a prompt", "improve prompt performance", "design a prompt template", "write better prompts", "debug p…
97. [rag-implementation](https://skillsdocs.com/wshobson/agents/rag-implementation.md) — Build Retrieval-Augmented Generation (RAG) systems for LLM applications with vector databases and semantic search. Use when implementing knowledge-grounded AI,…
98. [similarity-search-patterns](https://skillsdocs.com/wshobson/agents/similarity-search-patterns.md) — Implement efficient similarity search with vector databases. Use when building semantic search, implementing nearest neighbor queries, or optimizing retrieval…
99. [vector-index-tuning](https://skillsdocs.com/wshobson/agents/vector-index-tuning.md) — Optimize vector index performance for latency, recall, and memory. Use when tuning HNSW parameters, selecting quantization strategies, or scaling vector search…
100. [checkpoint-promotion](https://skillsdocs.com/wshobson/agents/checkpoint-promotion.md) — Gate fine-tuned checkpoints with drift budgets, paired comparison, and forgetting checks before promotion. Use after a training run produces a checkpoint, when…
101. [dataset-curation](https://skillsdocs.com/wshobson/agents/dataset-curation.md) — Prepare, format, and validate datasets for supervised fine-tuning and preference training. Use when converting raw data into training format, applying chat tem…
102. [eval-harness-first](https://skillsdocs.com/wshobson/agents/eval-harness-first.md) — Build the evaluation harness that gates every fine-tuning run — golden sets, per-failure-mode graders, judge calibration, and base-model baselines. Use when st…
103. [finetuning-method-selection](https://skillsdocs.com/wshobson/agents/finetuning-method-selection.md) — Decide whether to fine-tune at all, and route to the right method (SFT, DPO/ORPO/KTO, GRPO/RLVR, continued pretraining) and base model. Use when starting any f…
104. [grpo-rlvr-training](https://skillsdocs.com/wshobson/agents/grpo-rlvr-training.md) — Train reasoning and verifiable-task behavior with GRPO and reinforcement learning from verifiable rewards (RLVR). Use when task success is algorithmically chec…
105. [lora-qlora-recipes](https://skillsdocs.com/wshobson/agents/lora-qlora-recipes.md) — Configure LoRA and QLoRA supervised fine-tuning with current best-practice hyperparameters. Use when writing or reviewing a LoRA/QLoRA training configuration,…
106. [preference-optimization](https://skillsdocs.com/wshobson/agents/preference-optimization.md) — Align a fine-tuned model with preference data using DPO, ORPO, KTO, or SimPO. Use when preference pairs or thumbs-up/down feedback exist, when choosing between…
107. [quantized-export](https://skillsdocs.com/wshobson/agents/quantized-export.md) — Export a promoted fine-tuned model in the right deployment format — merged safetensors, LoRA-only, GGUF with imatrix, or FP8. Use after a checkpoint passes pro…
108. [trace-to-training-data](https://skillsdocs.com/wshobson/agents/trace-to-training-data.md) — Convert evaluation traces and production logs into SFT examples and preference pairs. Use when graded traces or failure examples exist and need to become train…
109. [vision-sft](https://skillsdocs.com/wshobson/agents/vision-sft.md) — Fine-tune vision-language models (VLMs) with supervised learning on image+text data. Use when adapting a VLM to a visual domain or task, configuring frozen-vis…
110. [ml-pipeline-workflow](https://skillsdocs.com/wshobson/agents/ml-pipeline-workflow.md) — Build end-to-end MLOps pipelines from data preparation through model training, validation, and production deployment. Use when creating ML pipelines, implement…
111. [recsys-pipeline-architect](https://skillsdocs.com/wshobson/agents/recsys-pipeline-architect.md) — Design composable recommendation, ranking, and feed pipelines using the six-stage Source→Hydrator→Filter→Scorer→Selector→SideEffect framework popularized by xA…
112. [distributed-tracing](https://skillsdocs.com/wshobson/agents/distributed-tracing.md) — Implement distributed tracing with Jaeger and Tempo to track requests across microservices and identify performance bottlenecks. Use when debugging microservic…
113. [grafana-dashboards](https://skillsdocs.com/wshobson/agents/grafana-dashboards.md) — Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visuali…
114. [prometheus-configuration](https://skillsdocs.com/wshobson/agents/prometheus-configuration.md) — Set up Prometheus for comprehensive metric collection, storage, and monitoring of infrastructure and applications. Use when implementing metrics collection, se…
115. [slo-implementation](https://skillsdocs.com/wshobson/agents/slo-implementation.md) — Define and implement Service Level Indicators (SLIs) and Service Level Objectives (SLOs) with error budgets and alerting. Use when establishing reliability tar…
116. [billing-automation](https://skillsdocs.com/wshobson/agents/billing-automation.md) — Build automated billing systems for recurring payments, invoicing, subscription lifecycle, and dunning management. Use when implementing subscription billing,…
117. [paypal-integration](https://skillsdocs.com/wshobson/agents/paypal-integration.md) — Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing…
118. [pci-compliance](https://skillsdocs.com/wshobson/agents/pci-compliance.md) — Implement PCI DSS compliance requirements for secure handling of payment card data and payment systems. Use when securing payment processing, achieving PCI com…
119. [stripe-integration](https://skillsdocs.com/wshobson/agents/stripe-integration.md) — Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe paymen…
120. [evaluation-methodology](https://skillsdocs.com/wshobson/agents/evaluation-methodology.md) — PluginEval quality methodology — dimensions, rubrics, statistical methods, and scoring formulas. Use this skill when understanding how plugin quality is measur…
121. [pptx-deck-context](https://skillsdocs.com/wshobson/agents/pptx-deck-context.md) — Use when preparing the narrative, sources, and design context for a new editable PPTX deck.
122. [pptx-quality-gates](https://skillsdocs.com/wshobson/agents/pptx-quality-gates.md) — Use when validating or repairing an editable PPTX deck for geometry, accessibility, native editability, source lineage, and OOXML package integrity.
123. [pptx-reference-deck-analysis](https://skillsdocs.com/wshobson/agents/pptx-reference-deck-analysis.md) — Use when analyzing a reference PPTX for read-only structure, theme, typography, layout rhythm, diagnostics, derived template catalogs, or safe OOXML package in…
124. [pptx-slide-specification](https://skillsdocs.com/wshobson/agents/pptx-slide-specification.md) — Use when authoring or repairing a coordinate-explicit JSON specification for an editable PPTX deck.
125. [pptx-visual-assets](https://skillsdocs.com/wshobson/agents/pptx-visual-assets.md) — Use when selecting and placing approved supporting icons, images, SVGs, diagrams, or infographics in an editable PPTX deck.
126. [protect-mcp-setup](https://skillsdocs.com/wshobson/agents/protect-mcp-setup.md) — Configure Cedar policy enforcement and Ed25519 signed receipts for Claude Code tool calls. Use when setting up projects that need cryptographic audit trails, p…
127. [async-python-patterns](https://skillsdocs.com/wshobson/agents/async-python-patterns.md) — Master Python asyncio, concurrent programming, and async/await patterns for high-performance applications. Use when building async APIs, concurrent systems, or…
128. [python-anti-patterns](https://skillsdocs.com/wshobson/agents/python-anti-patterns.md) — Use this skill when reviewing Python code for common anti-patterns to avoid. Use as a checklist when reviewing code, before finalizing implementations, or when…
129. [python-background-jobs](https://skillsdocs.com/wshobson/agents/python-background-jobs.md) — Python background job patterns including task queues, workers, and event-driven architecture. Use when implementing async task processing, job queues, long-run…
130. [python-code-style](https://skillsdocs.com/wshobson/agents/python-code-style.md) — Python code style, linting, formatting, naming conventions, and documentation standards. Use when writing new code, reviewing style, configuring linters, writi…
131. [python-configuration](https://skillsdocs.com/wshobson/agents/python-configuration.md) — Python configuration management via environment variables and typed settings. Use when externalizing config, setting up pydantic-settings, managing secrets, or…
132. [python-design-patterns](https://skillsdocs.com/wshobson/agents/python-design-patterns.md) — Python design patterns including KISS, Separation of Concerns, Single Responsibility, and composition over inheritance. Use this skill when designing a new ser…
133. [python-error-handling](https://skillsdocs.com/wshobson/agents/python-error-handling.md) — Python error handling patterns including input validation, exception hierarchies, and partial failure handling. Use when implementing validation logic, designi…
134. [python-observability](https://skillsdocs.com/wshobson/agents/python-observability.md) — Python observability patterns including structured logging, metrics, and distributed tracing. Use when adding logging, implementing metrics collection, setting…
135. [python-packaging](https://skillsdocs.com/wshobson/agents/python-packaging.md) — Create distributable Python packages with proper project structure, setup.py/pyproject.toml, and publishing to PyPI. Use when packaging Python libraries, creat…
136. [python-performance-optimization](https://skillsdocs.com/wshobson/agents/python-performance-optimization.md) — Profile and optimize Python code using cProfile, memory profilers, and performance best practices. Use when debugging slow Python code, optimizing bottlenecks,…
137. [python-project-structure](https://skillsdocs.com/wshobson/agents/python-project-structure.md) — Python project organization, module architecture, and public API design. Use when setting up new projects, organizing modules, defining public interfaces with…
138. [python-resilience](https://skillsdocs.com/wshobson/agents/python-resilience.md) — Python resilience patterns including automatic retries, exponential backoff, timeouts, and fault-tolerant decorators. Use when adding retry logic, implementing…
139. [python-resource-management](https://skillsdocs.com/wshobson/agents/python-resource-management.md) — Python resource management with context managers, cleanup patterns, and streaming. Use when managing connections, file handles, implementing cleanup logic, or…
140. [python-testing-patterns](https://skillsdocs.com/wshobson/agents/python-testing-patterns.md) — Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites,…
141. [python-type-safety](https://skillsdocs.com/wshobson/agents/python-type-safety.md) — Python type safety with type hints, generics, protocols, and strict type checking. Use when adding type annotations, implementing generic classes, defining str…
142. [uv-package-manager](https://skillsdocs.com/wshobson/agents/uv-package-manager.md) — Master the uv package manager for fast Python dependency management, virtual environments, and modern Python project workflows. Use when setting up Python proj…
143. [backtesting-frameworks](https://skillsdocs.com/wshobson/agents/backtesting-frameworks.md) — Build robust backtesting systems for trading strategies with proper handling of look-ahead bias, survivorship bias, and transaction costs. Use when developing…
144. [risk-metrics-calculation](https://skillsdocs.com/wshobson/agents/risk-metrics-calculation.md) — Calculate portfolio risk metrics including VaR, CVaR, Sharpe, Sortino, and drawdown analysis. Use when measuring portfolio risk, implementing risk limits, or b…
145. [anti-reversing-techniques](https://skillsdocs.com/wshobson/agents/anti-reversing-techniques.md) — Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion technique…
146. [binary-analysis-patterns](https://skillsdocs.com/wshobson/agents/binary-analysis-patterns.md) — Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, unde…
147. [memory-forensics](https://skillsdocs.com/wshobson/agents/memory-forensics.md) — Master memory forensics techniques including memory acquisition, process analysis, and artifact extraction using Volatility and related tools. Use when analyzi…
148. [protocol-reverse-engineering](https://skillsdocs.com/wshobson/agents/protocol-reverse-engineering.md) — Master network protocol reverse engineering including packet analysis, protocol dissection, and custom protocol documentation. Use when analyzing network traff…
149. [review-agent-setup](https://skillsdocs.com/wshobson/agents/review-agent-setup.md) — Configure human-in-the-loop gating for AI agent review actions in Claude Code. Use when setting up a project where an agent may post PR reviews, comments, merg…
150. [attack-tree-construction](https://skillsdocs.com/wshobson/agents/attack-tree-construction.md) — Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to sta…
151. [sast-configuration](https://skillsdocs.com/wshobson/agents/sast-configuration.md) — Configure Static Application Security Testing (SAST) tools for automated vulnerability detection in application code. Use when setting up security scanning, im…
152. [security-requirement-extraction](https://skillsdocs.com/wshobson/agents/security-requirement-extraction.md) — Derive security requirements from threat models and business context. Use when translating threats into actionable requirements, creating security user stories…
153. [stride-analysis-patterns](https://skillsdocs.com/wshobson/agents/stride-analysis-patterns.md) — Apply STRIDE methodology to systematically identify threats. Use when analyzing system security, conducting threat modeling sessions, or creating security docu…
154. [threat-mitigation-mapping](https://skillsdocs.com/wshobson/agents/threat-mitigation-mapping.md) — Map identified threats to appropriate security controls and mitigations. Use when prioritizing security investments, creating remediation plans, or validating…
155. [bash-defensive-patterns](https://skillsdocs.com/wshobson/agents/bash-defensive-patterns.md) — Master defensive Bash programming techniques for production-grade scripts. Use when writing robust shell scripts, CI/CD pipelines, or system utilities requirin…
156. [bats-testing-patterns](https://skillsdocs.com/wshobson/agents/bats-testing-patterns.md) — Master Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring tes…
157. [shellcheck-configuration](https://skillsdocs.com/wshobson/agents/shellcheck-configuration.md) — Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring…
158. [scan](https://skillsdocs.com/wshobson/agents/scan.md) — Scans the codebase to generate project-doc.md and AGENTS.md. Use when bootstrapping a new agent-driven repo, refreshing project documentation after architectur…
159. [signed-audit-trails-recipe](https://skillsdocs.com/wshobson/agents/signed-audit-trails-recipe.md) — Step-by-step cookbook for setting up cryptographically signed audit trails on Claude Code tool calls. Use when explaining, evaluating, or demonstrating the pat…
160. [ai-debt-detector](https://skillsdocs.com/wshobson/agents/ai-debt-detector.md) — Use after generating code, after accepting AI suggestions, or when reviewing AI-written modules. Also use when code works but feels brittle, when error handlin…
161. [session-guard](https://skillsdocs.com/wshobson/agents/session-guard.md) — Use when working on complex multi-step tasks, when a session is getting long (40+ tool calls), when the agent starts ignoring rules it followed earlier, when c…
162. [visual-edit-precision](https://skillsdocs.com/wshobson/agents/visual-edit-precision.md) — Use when making UI/frontend changes guided by visual context, when the user selects elements visually, draws annotations, or provides screenshots alongside cha…
163. [social-publishing](https://skillsdocs.com/wshobson/agents/social-publishing.md) — Schedule and publish social media posts across 13 platforms (X, LinkedIn, Instagram, Facebook Pages, TikTok, Discord, Telegram, YouTube, Reddit, WordPress, Pin…
164. [competitive-landscape](https://skillsdocs.com/wshobson/agents/competitive-landscape.md) — Analyze competition, identify differentiation opportunities, and develop winning market positioning strategies using Porter's Five Forces, Blue Ocean Strategy,…
165. [market-sizing-analysis](https://skillsdocs.com/wshobson/agents/market-sizing-analysis.md) — Calculate TAM/SAM/SOM for market opportunities using top-down, bottom-up, and value theory methodologies. Use this skill when sizing markets, estimating addres…
166. [startup-financial-modeling](https://skillsdocs.com/wshobson/agents/startup-financial-modeling.md) — Build comprehensive 3-5 year financial models with revenue projections, cost structures, cash flow analysis, and scenario planning for early-stage startups. Us…
167. [startup-metrics-framework](https://skillsdocs.com/wshobson/agents/startup-metrics-framework.md) — Track, calculate, and optimize key performance metrics for SaaS, marketplace, consumer, and B2B startups from seed through Series A, including unit economics,…
168. [team-composition-analysis](https://skillsdocs.com/wshobson/agents/team-composition-analysis.md) — Design optimal team structures, hiring plans, compensation strategies, and equity allocation for early-stage startups from pre-seed through Series A. Use this…
169. [go-concurrency-patterns](https://skillsdocs.com/wshobson/agents/go-concurrency-patterns.md) — Master Go concurrency with goroutines, channels, sync primitives, and context. Use when building concurrent Go applications, implementing worker pools, or debu…
170. [memory-safety-patterns](https://skillsdocs.com/wshobson/agents/memory-safety-patterns.md) — Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, ma…
171. [rust-async-patterns](https://skillsdocs.com/wshobson/agents/rust-async-patterns.md) — Master Rust async programming with Tokio, async traits, error handling, and concurrent patterns. Use when building async Rust applications, implementing concur…
172. [accessibility-compliance](https://skillsdocs.com/wshobson/agents/accessibility-compliance.md) — Implement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility…
173. [design-system-patterns](https://skillsdocs.com/wshobson/agents/design-system-patterns.md) — Build scalable design systems with design tokens, theming infrastructure, and component architecture patterns. Use when creating design tokens, implementing th…
174. [interaction-design](https://skillsdocs.com/wshobson/agents/interaction-design.md) — Design and implement microinteractions, motion design, transitions, and user feedback patterns. Use when adding polish to UI interactions, implementing loading…
175. [mobile-android-design](https://skillsdocs.com/wshobson/agents/mobile-android-design.md) — Master Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or foll…
176. [mobile-ios-design](https://skillsdocs.com/wshobson/agents/mobile-ios-design.md) — Master iOS Human Interface Guidelines and SwiftUI patterns for building native iOS apps. Use when designing iOS interfaces, implementing SwiftUI views, or ensu…
177. [react-native-design](https://skillsdocs.com/wshobson/agents/react-native-design.md) — Master React Native styling, navigation, and Reanimated animations for cross-platform mobile development. Use when building React Native apps, implementing nav…
178. [responsive-design](https://skillsdocs.com/wshobson/agents/responsive-design.md) — Implement modern responsive layouts using container queries, fluid typography, CSS Grid, and mobile-first breakpoint strategies. Use when building adaptive int…
179. [visual-design-foundations](https://skillsdocs.com/wshobson/agents/visual-design-foundations.md) — Apply typography, color theory, spacing systems, and iconography principles to create cohesive visual designs. Use when establishing design tokens, building st…
180. [web-component-design](https://skillsdocs.com/wshobson/agents/web-component-design.md) — Master React, Vue, and Svelte component patterns including CSS-in-JS, composition strategies, and reusable component architecture. Use when building UI compone…


## Front matter

_The repository README, verbatim except that relative links are resolved against https://github.com/wshobson/agents/blob/main/._

# Agentic Plugin Marketplace

> Production-ready agentic workflow building blocks: **94 plugins**, **203 agents**,
> **175 skills**, **109 commands** — built for Claude Code and consumed natively by
> OpenAI Codex CLI, Cursor, OpenCode, Gemini CLI, and GitHub Copilot from a single Markdown source.

[![Claude Code](https://img.shields.io/badge/Claude%20Code-native-blueviolet)](#claude-code) [![Codex CLI](https://img.shields.io/badge/Codex%20CLI-supported-black)](docs/harnesses.md) [![Cursor](https://img.shields.io/badge/Cursor-supported-purple)](docs/harnesses.md) [![OpenCode](https://img.shields.io/badge/OpenCode-supported-green)](docs/harnesses.md) [![Gemini CLI](https://img.shields.io/badge/Gemini%20CLI-supported-blue)](GEMINI.md) [![Copilot](https://img.shields.io/badge/Copilot-supported-lightgrey)](docs/harnesses.md)

> [!NOTE]
> One source-of-truth (`plugins/`), five harnesses. Each harness gets idiomatic,
> harness-native artifacts — not lowest-common-denominator translations.
> See [docs/harnesses.md](https://github.com/wshobson/agents/blob/main/docs/harnesses.md) for the capability matrix.

## Quick start

Pick your harness:

### Claude Code

```bash
/plugin marketplace add wshobson/agents
/plugin install python-development          # or any of 94 plugins
```

[→ Full Claude Code setup, troubleshooting, and plugin catalog](https://github.com/wshobson/agents/blob/main/docs/usage.md)

### Codex CLI · Cursor · OpenCode · Gemini CLI · Copilot

Codex and Cursor install natively from the committed registries (which point at the source `plugins/`):

```bash
npx codex-marketplace add wshobson/agents        # Codex; then install individual plugins
# Cursor: add the marketplace, then `/plugin install <name>` (reads .cursor-plugin/ + source)
```

Gemini and OpenCode install via clone + generate (the transformed trees are gitignored):

```bash
gh repo clone wshobson/agents ~/agents && cd ~/agents
make generate HARNESS=gemini && gemini extensions install .   # Gemini
make install-opencode                                          # OpenCode (runs generate + symlinks)
```

Setup details and per-harness gotchas: [docs/harnesses.md](https://github.com/wshobson/agents/blob/main/docs/harnesses.md). Gemini-specific setup: [GEMINI.md](https://github.com/wshobson/agents/blob/main/GEMINI.md) (also auto-loaded by Gemini CLI).

## What's inside

| | Count | What it is |
|---|---:|---|
| **Plugins** | 94 | Granular, single-purpose installable units (90 local + 4 external via git-subdir) |
| **Agents** | 203 | Domain experts (architecture, languages, infra, security, data, ML, docs, business, SEO) |
| **Skills** | 175 | Modular knowledge packages with progressive disclosure (load when activated) |
| **Commands** | 109 | Slash commands: scaffolding, security scans, test gen, infrastructure setup |
| **Orchestrators** | 16 | Multi-agent coordination workflows (full-stack, security, ML, incident response) |

Browse the catalog: [docs/plugins.md](https://github.com/wshobson/agents/blob/main/docs/plugins.md) · [docs/agents.md](https://github.com/wshobson/agents/blob/main/docs/agents.md) · [docs/agent-skills.md](https://github.com/wshobson/agents/blob/main/docs/agent-skills.md)

## How it works

Each plugin is isolated and composable: agents, commands, and skills are auto-discovered
from directory structure. **Installing a plugin loads only its components into
context** — not the whole marketplace.

```
plugins/python-development/
├── .claude-plugin/plugin.json
├── agents/             # 3 Python agents (python-pro, django-pro, fastapi-pro)
├── commands/           # 1 scaffolding command
└── skills/             # 16 specialized skills (async, testing, packaging, …)
```

Tiered model strategy:

| Tier | Model | Use |
|---|---|---|
| 0 | Fable 5  | Longest-horizon autonomous work — large migrations, multi-hour runs (opt-in, premium cost) |
| 1 | Opus     | Architecture, security, code review, production-critical |
| 2 | inherit  | User-chosen — backend, frontend, AI/ML, specialized |
| 3 | Sonnet   | Docs, testing, debugging, API references |
| 4 | Haiku    | Fast operational tasks, SEO, deployment, content |

[→ Model configuration details](https://github.com/wshobson/agents/blob/main/docs/agents.md#model-configuration)

## Multi-harness support

This marketplace ships to five agentic harnesses from one Markdown source. Each adapter
emits harness-native artifacts (not lowest-common-denominator translations):

| Harness | Generates | Notes |
|---|---|---|
| **Claude Code** | (source-of-truth) | Native `marketplace.json` + `plugins/` |
| **Codex CLI** | `.agents/plugins/marketplace.json` + `plugins/*/.codex-plugin/plugin.json` (committed); `.codex/skills/`, `.codex/agents/` (gitignored) | 8 KB skill cap respected; commands → skills |
| **Cursor** | `.cursor-plugin/`, `.cursor/rules/` | Thin marketplace + curated rules; reuses `.claude/` |
| **OpenCode** | `.opencode/agents/`, `.opencode/commands/`, `.opencode/skills/` | `permission:` block from `tools:` allowlist; OpenCode-safe skill names |
| **Gemini CLI** | `skills/`, `agents/`, `commands/` (TOML) | Native skills + subagents (April 2026 spec) |
| **Copilot** | `.copilot/agents/`, `.copilot/skills/`, `.copilot/commands/` | Markdown agent profiles + SKILL.md skills + commands-as-skills; model maps to native Claude models |

```bash
make generate-all                        # all five
make validate                            # structural checks
make garden                              # drift / dead-link / cap detection
```

Codex and Cursor install from source via committed registries; Gemini and OpenCode install via clone + `make`.

[→ Full capability matrix and per-harness deep-dives](https://github.com/wshobson/agents/blob/main/docs/harnesses.md)

## Quality evaluation

[`plugin-eval`](https://github.com/wshobson/agents/blob/main/plugins/plugin-eval/) is a three-layer evaluation framework for measuring
and certifying plugin/skill quality:

- **Static** — deterministic structural analysis (<2s, free)
- **LLM Judge** — semantic evaluation across 4 dimensions (~30s, Haiku + Sonnet)
- **Monte Carlo** — statistical reliability via 50-100 simulated runs (~2-5 min)

```bash
uv run plugin-eval score path/to/skill --depth quick
uv run plugin-eval certify path/to/skill
```

[→ PluginEval framework documentation](https://github.com/wshobson/agents/blob/main/docs/plugin-eval.md)

## Documentation map

Detail lives in `docs/`. Read in this order:

- **[docs/plugins.md](https://github.com/wshobson/agents/blob/main/docs/plugins.md)** — full catalog of all 94 plugins
- **[docs/agents.md](https://github.com/wshobson/agents/blob/main/docs/agents.md)** — all 203 agents by category
- **[docs/agent-skills.md](https://github.com/wshobson/agents/blob/main/docs/agent-skills.md)** — 175 skills with progressive disclosure
- **[docs/usage.md](https://github.com/wshobson/agents/blob/main/docs/usage.md)** — commands, workflows, examples
- **[docs/architecture.md](https://github.com/wshobson/agents/blob/main/docs/architecture.md)** — design principles
- **[docs/harnesses.md](https://github.com/wshobson/agents/blob/main/docs/harnesses.md)** — cross-harness capability matrix
- **[docs/authoring.md](https://github.com/wshobson/agents/blob/main/docs/authoring.md)** — portable-content style guide
- **[docs/plugin-eval.md](https://github.com/wshobson/agents/blob/main/docs/plugin-eval.md)** — quality evaluation framework
- **[docs/round-trip-results.md](https://github.com/wshobson/agents/blob/main/docs/round-trip-results.md)** — real-CLI verification recipes

Gemini-specific setup: [GEMINI.md](https://github.com/wshobson/agents/blob/main/GEMINI.md). All other harness setup, capability deltas, and gotchas live in [docs/harnesses.md](https://github.com/wshobson/agents/blob/main/docs/harnesses.md).

Contributing: [CONTRIBUTING.md](https://github.com/wshobson/agents/blob/main/CONTRIBUTING.md) · Authoring: [docs/authoring.md](https://github.com/wshobson/agents/blob/main/docs/authoring.md)

## External Memory Integration

[Pensyve](https://github.com/major7apps/pensyve) is included as an external
`git-subdir` entry for Claude Code. Pensyve also maintains direct upstream
integrations for this marketplace's other supported harnesses.

| Harness | Pensyve integration |
|---|---|
| Claude Code | `/plugin install pensyve` from this marketplace (`integrations/claude-code`) |
| Codex CLI | [integrations/codex-plugin](https://github.com/major7apps/pensyve/tree/main/integrations/codex-plugin) |
| Cursor | [integrations/cursor](https://github.com/major7apps/pensyve/tree/main/integrations/cursor) |
| OpenCode | [integrations/opencode-plugin](https://github.com/major7apps/pensyve/tree/main/integrations/opencode-plugin) |
| Gemini CLI | `gemini extensions install https://github.com/major7apps/pensyve` |
| Copilot | `.copilot/` in repo root or `~/.copilot/` via `make install-copilot` |

## License

MIT — see [LICENSE](https://github.com/wshobson/agents/blob/main/LICENSE).

## Star history

[![Star History Chart](https://api.star-history.com/svg?repos=wshobson/agents&type=date&legend=top-left)](https://www.star-history.com/#wshobson/agents&type=date&legend=top-left)

---

## Part: Accessibility Compliance

---

<!-- chapter:begin slug=screen-reader-testing position=1 -->

## 1. screen-reader-testing

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/accessibility-compliance/skills/screen-reader-testing/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/accessibility-compliance/skills/screen-reader-testing/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/screen-reader-testing.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: screen-reader-testing
description: Test web applications with screen readers including VoiceOver, NVDA, and JAWS. Use when validating screen reader compatibility, debugging accessibility issues, or ensuring assistive technology support.
---

# Screen Reader Testing

Practical guide to testing web applications with screen readers for comprehensive accessibility validation.

## When to Use This Skill

- Validating screen reader compatibility
- Testing ARIA implementations
- Debugging assistive technology issues
- Verifying form accessibility
- Testing dynamic content announcements
- Ensuring navigation accessibility

## Core Concepts

### 1. Major Screen Readers

| Screen Reader | Platform  | Browser        | Usage |
| ------------- | --------- | -------------- | ----- |
| **VoiceOver** | macOS/iOS | Safari         | ~15%  |
| **NVDA**      | Windows   | Firefox/Chrome | ~31%  |
| **JAWS**      | Windows   | Chrome/IE      | ~40%  |
| **TalkBack**  | Android   | Chrome         | ~10%  |
| **Narrator**  | Windows   | Edge           | ~4%   |

### 2. Testing Priority

```
Minimum Coverage:
1. NVDA + Firefox (Windows)
2. VoiceOver + Safari (macOS)
3. VoiceOver + Safari (iOS)

Comprehensive Coverage:
+ JAWS + Chrome (Windows)
+ TalkBack + Chrome (Android)
+ Narrator + Edge (Windows)
```

### 3. Screen Reader Modes

| Mode               | Purpose                | When Used         |
| ------------------ | ---------------------- | ----------------- |
| **Browse/Virtual** | Read content           | Default reading   |
| **Focus/Forms**    | Interact with controls | Filling forms     |
| **Application**    | Custom widgets         | ARIA applications |

## VoiceOver (macOS)

### Setup

```
Enable: System Preferences → Accessibility → VoiceOver
Toggle: Cmd + F5
Quick Toggle: Triple-press Touch ID
```

### Essential Commands

```
Navigation:
VO = Ctrl + Option (VoiceOver modifier)

VO + Right Arrow   Next element
VO + Left Arrow    Previous element
VO + Shift + Down  Enter group
VO + Shift + Up    Exit group

Reading:
VO + A             Read all from cursor
Ctrl               Stop speaking
VO + B             Read current paragraph

Interaction:
VO + Space         Activate element
VO + Shift + M     Open menu
Tab                Next focusable element
Shift + Tab        Previous focusable element

Rotor (VO + U):
Navigate by: Headings, Links, Forms, Landmarks
Left/Right Arrow   Change rotor category
Up/Down Arrow      Navigate within category
Enter              Go to item

Web Specific:
VO + Cmd + H       Next heading
VO + Cmd + J       Next form control
VO + Cmd + L       Next link
VO + Cmd + T       Next table
```

### Testing Checklist

```markdown
## VoiceOver Testing Checklist

### Page Load

- [ ] Page title announced
- [ ] Main landmark found
- [ ] Skip link works

### Navigation

- [ ] All headings discoverable via rotor
- [ ] Heading levels logical (H1 → H2 → H3)
- [ ] Landmarks properly labeled
- [ ] Skip links functional

### Links & Buttons

- [ ] Link purpose clear
- [ ] Button actions described
- [ ] New window/tab announced

### Forms

- [ ] All labels read with inputs
- [ ] Required fields announced
- [ ] Error messages read
- [ ] Instructions available
- [ ] Focus moves to errors

### Dynamic Content

- [ ] Alerts announced immediately
- [ ] Loading states communicated
- [ ] Content updates announced
- [ ] Modals trap focus correctly

### Tables

- [ ] Headers associated with cells
- [ ] Table navigation works
- [ ] Complex tables have captions
```

### Common Issues & Fixes

```html
<!-- Issue: Button not announcing purpose -->
<button><svg>...</svg></button>

<!-- Fix -->
<button aria-label="Close dialog"><svg aria-hidden="true">...</svg></button>

<!-- Issue: Dynamic content not announced -->
<div id="results">New results loaded</div>

<!-- Fix -->
<div id="results" role="status" aria-live="polite">New results loaded</div>

<!-- Issue: Form error not read -->
<input type="email" />
<span class="error">Invalid email</span>

<!-- Fix -->
<input type="email" aria-invalid="true" aria-describedby="email-error" />
<span id="email-error" role="alert">Invalid email</span>
```

## NVDA (Windows)

### Setup

```
Download: nvaccess.org
Start: Ctrl + Alt + N
Stop: Insert + Q
```

### Essential Commands

```
Navigation:
Insert = NVDA modifier

Down Arrow         Next line
Up Arrow           Previous line
Tab                Next focusable
Shift + Tab        Previous focusable

Reading:
NVDA + Down Arrow  Say all
Ctrl               Stop speech
NVDA + Up Arrow    Current line

Headings:
H                  Next heading
Shift + H          Previous heading
1-6                Heading level 1-6

Forms:
F                  Next form field
B                  Next button
E                  Next edit field
X                  Next checkbox
C                  Next combo box

Links:
K                  Next link
U                  Next unvisited link
V                  Next visited link

Landmarks:
D                  Next landmark
Shift + D          Previous landmark

Tables:
T                  Next table
Ctrl + Alt + Arrows Navigate cells

Elements List (NVDA + F7):
Shows all links, headings, form fields, landmarks
```

### Browse vs Focus Mode

```
NVDA automatically switches modes:
- Browse Mode: Arrow keys navigate content
- Focus Mode: Arrow keys control interactive elements

Manual switch: NVDA + Space

Watch for:
- "Browse mode" announcement when navigating
- "Focus mode" when entering form fields
- Application role forces forms mode
```

### Testing Script

```markdown
## NVDA Test Script

### Initial Load

1. Navigate to page
2. Let page finish loading
3. Press Insert + Down to read all
4. Note: Page title, main content identified?

### Landmark Navigation

1. Press D repeatedly
2. Check: All main areas reachable?
3. Check: Landmarks properly labeled?

### Heading Navigation

1. Press Insert + F7 → Headings
2. Check: Logical heading structure?
3. Press H to navigate headings
4. Check: All sections discoverable?

### Form Testing

1. Press F to find first form field
2. Check: Label read?
3. Fill in invalid data
4. Submit form
5. Check: Errors announced?
6. Check: Focus moved to error?

### Interactive Elements

1. Tab through all interactive elements
2. Check: Each announces role and state
3. Activate buttons with Enter/Space
4. Check: Result announced?

### Dynamic Content

1. Trigger content update
2. Check: Change announced?
3. Open modal
4. Check: Focus trapped?
5. Close modal
6. Check: Focus returns?
```

## JAWS (Windows)

### Essential Commands

```
Start: Desktop shortcut or Ctrl + Alt + J
Virtual Cursor: Auto-enabled in browsers

Navigation:
Arrow keys         Navigate content
Tab                Next focusable
Insert + Down      Read all
Ctrl               Stop speech

Quick Keys:
H                  Next heading
T                  Next table
F                  Next form field
B                  Next button
G                  Next graphic
L                  Next list
;                  Next landmark

Forms Mode:
Enter              Enter forms mode
Numpad +           Exit forms mode
F5                 List form fields

Lists:
Insert + F7        Link list
Insert + F6        Heading list
Insert + F5        Form field list

Tables:
Ctrl + Alt + Arrows Table navigation
```

## TalkBack (Android)

### Setup

```
Enable: Settings → Accessibility → TalkBack
Toggle: Hold both volume buttons 3 seconds
```

### Gestures

```
Explore: Drag finger across screen
Next: Swipe right
Previous: Swipe left
Activate: Double tap
Scroll: Two finger swipe

Reading Controls (swipe up then right):
- Headings
- Links
- Controls
- Characters
- Words
- Lines
- Paragraphs
```

## Common Test Scenarios

### 1. Modal Dialog

```html
<!-- Accessible modal structure -->
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="dialog-title"
  aria-describedby="dialog-desc"
>
  <h2 id="dialog-title">Confirm Delete</h2>
  <p id="dialog-desc">This action cannot be undone.</p>
  <button>Cancel</button>
  <button>Delete</button>
</div>
```

```javascript
// Focus management
function openModal(modal) {
  // Store last focused element
  lastFocus = document.activeElement;

  // Move focus to modal
  modal.querySelector("h2").focus();

  // Trap focus
  modal.addEventListener("keydown", trapFocus);
}

function closeModal(modal) {
  // Return focus
  lastFocus.focus();
}

function trapFocus(e) {
  if (e.key === "Tab") {
    const focusable = modal.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
    );
    const first = focusable[0];
    const last = focusable[focusable.length - 1];

    if (e.shiftKey && document.activeElement === first) {
      last.focus();
      e.preventDefault();
    } else if (!e.shiftKey && document.activeElement === last) {
      first.focus();
      e.preventDefault();
    }
  }

  if (e.key === "Escape") {
    closeModal(modal);
  }
}
```

### 2. Live Regions

```html
<!-- Status messages (polite) -->
<div role="status" aria-live="polite" aria-atomic="true">
  <!-- Content updates will be announced after current speech -->
</div>

<!-- Alerts (assertive) -->
<div role="alert" aria-live="assertive">
  <!-- Content updates interrupt current speech -->
</div>

<!-- Progress updates -->
<div
  role="progressbar"
  aria-valuenow="75"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-label="Upload progress"
></div>

<!-- Log (additions only) -->
<div role="log" aria-live="polite" aria-relevant="additions">
  <!-- New messages announced, removals not -->
</div>
```

### 3. Tab Interface

```html
<div role="tablist" aria-label="Product information">
  <button role="tab" id="tab-1" aria-selected="true" aria-controls="panel-1">
    Description
  </button>
  <button
    role="tab"
    id="tab-2"
    aria-selected="false"
    aria-controls="panel-2"
    tabindex="-1"
  >
    Reviews
  </button>
</div>

<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  Product description content...
</div>

<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
  Reviews content...
</div>
```

```javascript
// Tab keyboard navigation
tablist.addEventListener("keydown", (e) => {
  const tabs = [...tablist.querySelectorAll('[role="tab"]')];
  const index = tabs.indexOf(document.activeElement);

  let newIndex;
  switch (e.key) {
    case "ArrowRight":
      newIndex = (index + 1) % tabs.length;
      break;
    case "ArrowLeft":
      newIndex = (index - 1 + tabs.length) % tabs.length;
      break;
    case "Home":
      newIndex = 0;
      break;
    case "End":
      newIndex = tabs.length - 1;
      break;
    default:
      return;
  }

  tabs[newIndex].focus();
  activateTab(tabs[newIndex]);
  e.preventDefault();
});
```

## Debugging Tips

```javascript
// Log what screen reader sees
function logAccessibleName(element) {
  const computed = window.getComputedStyle(element);
  console.log({
    role: element.getAttribute("role") || element.tagName,
    name:
      element.getAttribute("aria-label") ||
      element.getAttribute("aria-labelledby") ||
      element.textContent,
    state: {
      expanded: element.getAttribute("aria-expanded"),
      selected: element.getAttribute("aria-selected"),
      checked: element.getAttribute("aria-checked"),
      disabled: element.disabled,
    },
    visible: computed.display !== "none" && computed.visibility !== "hidden",
  });
}
```

## Best Practices

### Do's

- **Test with actual screen readers** - Not just simulators
- **Use semantic HTML first** - ARIA is supplemental
- **Test in browse and focus modes** - Different experiences
- **Verify focus management** - Especially for SPAs
- **Test keyboard only first** - Foundation for SR testing

### Don'ts

- **Don't assume one SR is enough** - Test multiple
- **Don't ignore mobile** - Growing user base
- **Don't test only happy path** - Test error states
- **Don't skip dynamic content** - Most common issues
- **Don't rely on visual testing** - Different experience

<!-- chapter:end slug=screen-reader-testing -->

---

<!-- chapter:begin slug=wcag-audit-patterns position=2 -->

## 2. wcag-audit-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/accessibility-compliance/skills/wcag-audit-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/accessibility-compliance/skills/wcag-audit-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/wcag-audit-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/accessibility-compliance/skills/wcag-audit-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: wcag-audit-patterns
description: Conduct WCAG 2.2 accessibility audits with automated testing, manual verification, and remediation guidance. Use when auditing websites for accessibility, fixing WCAG violations, or implementing accessible design patterns.
---

# WCAG Audit Patterns

Comprehensive guide to auditing web content against WCAG 2.2 guidelines with actionable remediation strategies.

## When to Use This Skill

- Conducting accessibility audits
- Fixing WCAG violations
- Implementing accessible components
- Preparing for accessibility lawsuits
- Meeting ADA/Section 508 requirements
- Achieving VPAT compliance

## Core Concepts

### 1. WCAG Conformance Levels

| Level   | Description            | Required For      |
| ------- | ---------------------- | ----------------- |
| **A**   | Minimum accessibility  | Legal baseline    |
| **AA**  | Standard conformance   | Most regulations  |
| **AAA** | Enhanced accessibility | Specialized needs |

### 2. POUR Principles

```
Perceivable:  Can users perceive the content?
Operable:     Can users operate the interface?
Understandable: Can users understand the content?
Robust:       Does it work with assistive tech?
```

### 3. Common Violations by Impact

```
Critical (Blockers):
├── Missing alt text for functional images
├── No keyboard access to interactive elements
├── Missing form labels
└── Auto-playing media without controls

Serious:
├── Insufficient color contrast
├── Missing skip links
├── Inaccessible custom widgets
└── Missing page titles

Moderate:
├── Missing language attribute
├── Unclear link text
├── Missing landmarks
└── Improper heading hierarchy
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Start early** - Accessibility from design phase
- **Test with real users** - Disabled users provide best feedback
- **Automate what you can** - 30-50% issues detectable
- **Use semantic HTML** - Reduces ARIA needs
- **Document patterns** - Build accessible component library

### Don'ts

- **Don't rely only on automated testing** - Manual testing required
- **Don't use ARIA as first solution** - Native HTML first
- **Don't hide focus outlines** - Keyboard users need them
- **Don't disable zoom** - Users need to resize
- **Don't use color alone** - Multiple indicators needed

<!-- chapter:end slug=wcag-audit-patterns -->

---

## Part: Agent Teams

---

<!-- chapter:begin slug=multi-reviewer-patterns position=3 -->

## 3. multi-reviewer-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/agent-teams/skills/multi-reviewer-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/multi-reviewer-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/multi-reviewer-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/review-dimensions.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/multi-reviewer-patterns/references/review-dimensions.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: multi-reviewer-patterns
description: Coordinate parallel code reviews across multiple quality dimensions with finding deduplication, severity calibration, and consolidated reporting. Use this skill when organizing multi-reviewer code reviews, calibrating finding severity, or consolidating review results.
version: 1.0.2
---

# Multi-Reviewer Patterns

Patterns for coordinating parallel code reviews across multiple quality dimensions, deduplicating findings, calibrating severity, and producing consolidated reports.

## When to Use This Skill

- Organizing a multi-dimensional code review
- Deciding which review dimensions to assign
- Deduplicating findings from multiple reviewers
- Calibrating severity ratings consistently
- Producing a consolidated review report

## Review Dimension Allocation

### Available Dimensions

| Dimension         | Focus                                   | When to Include                             |
| ----------------- | --------------------------------------- | ------------------------------------------- |
| **Security**      | Vulnerabilities, auth, input validation | Always for code handling user input or auth |
| **Performance**   | Query efficiency, memory, caching       | When changing data access or hot paths      |
| **Architecture**  | SOLID, coupling, patterns               | For structural changes or new modules       |
| **Testing**       | Coverage, quality, edge cases           | When adding new functionality               |
| **Accessibility** | WCAG, ARIA, keyboard nav                | For UI/frontend changes                     |

### Recommended Combinations

| Scenario               | Dimensions                                   |
| ---------------------- | -------------------------------------------- |
| API endpoint changes   | Security, Performance, Architecture          |
| Frontend component     | Architecture, Testing, Accessibility         |
| Database migration     | Performance, Architecture                    |
| Authentication changes | Security, Testing                            |
| Full feature review    | Security, Performance, Architecture, Testing |

## Finding Deduplication

When multiple reviewers report issues at the same location:

### Merge Rules

1. **Same file:line, same issue** — Merge into one finding, credit all reviewers
2. **Same file:line, different issues** — Keep as separate findings
3. **Same issue, different locations** — Keep separate but cross-reference
4. **Conflicting severity** — Use the higher severity rating
5. **Conflicting recommendations** — Include both with reviewer attribution

### Deduplication Process

```
For each finding in all reviewer reports:
  1. Check if another finding references the same file:line
  2. If yes, check if they describe the same issue
  3. If same issue: merge, keeping the more detailed description
  4. If different issue: keep both, tag as "co-located"
  5. Use highest severity among merged findings
```

## Severity Calibration

### Severity Criteria

| Severity     | Impact                                        | Likelihood             | Examples                                     |
| ------------ | --------------------------------------------- | ---------------------- | -------------------------------------------- |
| **Critical** | Data loss, security breach, complete failure  | Certain or very likely | SQL injection, auth bypass, data corruption  |
| **High**     | Significant functionality impact, degradation | Likely                 | Memory leak, missing validation, broken flow |
| **Medium**   | Partial impact, workaround exists             | Possible               | N+1 query, missing edge case, unclear error  |
| **Low**      | Minimal impact, cosmetic                      | Unlikely               | Style issue, minor optimization, naming      |

### Calibration Rules

- Security vulnerabilities exploitable by external users: always Critical or High
- Performance issues in hot paths: at least Medium
- Missing tests for critical paths: at least Medium
- Accessibility violations for core functionality: at least Medium
- Code style issues with no functional impact: Low

## Consolidated Report Template

```markdown
## Code Review Report

**Target**: {files/PR/directory}
**Reviewers**: {dimension-1}, {dimension-2}, {dimension-3}
**Date**: {date}
**Files Reviewed**: {count}

### Critical Findings ({count})

#### [CR-001] {Title}

**Location**: `{file}:{line}`
**Dimension**: {Security/Performance/etc.}
**Description**: {what was found}
**Impact**: {what could happen}
**Fix**: {recommended remediation}

### High Findings ({count})

...

### Medium Findings ({count})

...

### Low Findings ({count})

...

### Summary

| Dimension    | Critical | High  | Medium | Low   | Total  |
| ------------ | -------- | ----- | ------ | ----- | ------ |
| Security     | 1        | 2     | 3      | 0     | 6      |
| Performance  | 0        | 1     | 4      | 2     | 7      |
| Architecture | 0        | 0     | 2      | 3     | 5      |
| **Total**    | **1**    | **3** | **9**  | **5** | **18** |

### Recommendation

{Overall assessment and prioritized action items}
```

<!-- chapter:end slug=multi-reviewer-patterns -->

---

<!-- chapter:begin slug=parallel-debugging position=4 -->

## 4. parallel-debugging

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/agent-teams/skills/parallel-debugging/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/parallel-debugging/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/parallel-debugging.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/hypothesis-testing.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/parallel-debugging/references/hypothesis-testing.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: parallel-debugging
description: Debug complex issues using competing hypotheses with parallel investigation, evidence collection, and root cause arbitration. Use this skill when debugging bugs with multiple potential causes, performing root cause analysis, or organizing parallel investigation workflows.
version: 1.0.2
---

# Parallel Debugging

Framework for debugging complex issues using the Analysis of Competing Hypotheses (ACH) methodology with parallel agent investigation.

## When to Use This Skill

- Bug has multiple plausible root causes
- Initial debugging attempts haven't identified the issue
- Issue spans multiple modules or components
- Need systematic root cause analysis with evidence
- Want to avoid confirmation bias in debugging

## Hypothesis Generation Framework

Generate hypotheses across 6 failure mode categories:

### 1. Logic Error

- Incorrect conditional logic (wrong operator, missing case)
- Off-by-one errors in loops or array access
- Missing edge case handling
- Incorrect algorithm implementation

### 2. Data Issue

- Invalid or unexpected input data
- Type mismatch or coercion error
- Null/undefined/None where value expected
- Encoding or serialization problem
- Data truncation or overflow

### 3. State Problem

- Race condition between concurrent operations
- Stale cache returning outdated data
- Incorrect initialization or default values
- Unintended mutation of shared state
- State machine transition error

### 4. Integration Failure

- API contract violation (request/response mismatch)
- Version incompatibility between components
- Configuration mismatch between environments
- Missing or incorrect environment variables
- Network timeout or connection failure

### 5. Resource Issue

- Memory leak causing gradual degradation
- Connection pool exhaustion
- File descriptor or handle leak
- Disk space or quota exceeded
- CPU saturation from inefficient processing

### 6. Environment

- Missing runtime dependency
- Wrong library or framework version
- Platform-specific behavior difference
- Permission or access control issue
- Timezone or locale-related behavior

## Evidence Collection Standards

### What Constitutes Evidence

| Evidence Type     | Strength | Example                                                         |
| ----------------- | -------- | --------------------------------------------------------------- |
| **Direct**        | Strong   | Code at `file.ts:42` shows `if (x > 0)` should be `if (x >= 0)` |
| **Correlational** | Medium   | Error rate increased after commit `abc123`                      |
| **Testimonial**   | Weak     | "It works on my machine"                                        |
| **Absence**       | Variable | No null check found in the code path                            |

### Citation Format

Always cite evidence with file:line references:

```
**Evidence**: The validation function at `src/validators/user.ts:87`
does not check for empty strings, only null/undefined. This allows
empty email addresses to pass validation.
```

### Confidence Levels

| Level               | Criteria                                                                            |
| ------------------- | ----------------------------------------------------------------------------------- |
| **High (>80%)**     | Multiple direct evidence pieces, clear causal chain, no contradicting evidence      |
| **Medium (50-80%)** | Some direct evidence, plausible causal chain, minor ambiguities                     |
| **Low (<50%)**      | Mostly correlational evidence, incomplete causal chain, some contradicting evidence |

## Result Arbitration Protocol

After all investigators report:

### Step 1: Categorize Results

- **Confirmed**: High confidence, strong evidence, clear causal chain
- **Plausible**: Medium confidence, some evidence, reasonable causal chain
- **Falsified**: Evidence contradicts the hypothesis
- **Inconclusive**: Insufficient evidence to confirm or falsify

### Step 2: Compare Confirmed Hypotheses

If multiple hypotheses are confirmed, rank by:

1. Confidence level
2. Number of supporting evidence pieces
3. Strength of causal chain
4. Absence of contradicting evidence

### Step 3: Determine Root Cause

- If one hypothesis clearly dominates: declare as root cause
- If multiple hypotheses are equally likely: may be compound issue (multiple contributing causes)
- If no hypotheses confirmed: generate new hypotheses based on evidence gathered

### Step 4: Validate Fix

Before declaring the bug fixed:

- [ ] Fix addresses the identified root cause
- [ ] Fix doesn't introduce new issues
- [ ] Original reproduction case no longer fails
- [ ] Related edge cases are covered
- [ ] Relevant tests are added or updated

<!-- chapter:end slug=parallel-debugging -->

---

<!-- chapter:begin slug=parallel-feature-development position=5 -->

## 5. parallel-feature-development

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/agent-teams/skills/parallel-feature-development/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/parallel-feature-development/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/parallel-feature-development.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/file-ownership.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/parallel-feature-development/references/file-ownership.md
  - `references/merge-strategies.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/parallel-feature-development/references/merge-strategies.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: parallel-feature-development
description: Coordinate parallel feature development with file ownership strategies, conflict avoidance rules, and integration patterns for multi-agent implementation. Use this skill when decomposing a large feature into independent work streams, when two or more agents need to implement different layers of the same system simultaneously, when establishing file ownership to prevent merge conflicts in a shared codebase, when designing interface contracts so parallel implementers can build against each other's APIs before they are ready, or when deciding whether to use vertical slices versus horizontal layers for a full-stack feature.
version: 1.0.2
---

# Parallel Feature Development

Strategies for decomposing features into parallel work streams, establishing file ownership boundaries, avoiding conflicts, and integrating results from multiple implementer agents.

## When to Use This Skill

- Decomposing a feature for parallel implementation
- Establishing file ownership boundaries between agents
- Designing interface contracts between parallel work streams
- Choosing integration strategies (vertical slice vs horizontal layer)
- Managing branch and merge workflows for parallel development

## File Ownership Strategies

### By Directory

Assign each implementer ownership of specific directories:

```
implementer-1: src/components/auth/
implementer-2: src/api/auth/
implementer-3: tests/auth/
```

**Best for**: Well-organized codebases with clear directory boundaries.

### By Module

Assign ownership of logical modules (which may span directories):

```
implementer-1: Authentication module (login, register, logout)
implementer-2: Authorization module (roles, permissions, guards)
```

**Best for**: Feature-oriented architectures, domain-driven design.

### By Layer

Assign ownership of architectural layers:

```
implementer-1: UI layer (components, styles, layouts)
implementer-2: Business logic layer (services, validators)
implementer-3: Data layer (models, repositories, migrations)
```

**Best for**: Traditional MVC/layered architectures.

## Conflict Avoidance Rules

### The Cardinal Rule

**One owner per file.** No file should be assigned to multiple implementers.

### When Files Must Be Shared

If a file genuinely needs changes from multiple implementers:

1. **Designate a single owner** — One implementer owns the file
2. **Other implementers request changes** — Message the owner with specific change requests
3. **Owner applies changes sequentially** — Prevents merge conflicts
4. **Alternative: Extract interfaces** — Create a separate interface file that the non-owner can import without modifying

### Interface Contracts

When implementers need to coordinate at boundaries:

```typescript
// src/types/auth-contract.ts (owned by team-lead, read-only for implementers)
export interface AuthResponse {
  token: string;
  user: UserProfile;
  expiresAt: number;
}

export interface AuthService {
  login(email: string, password: string): Promise<AuthResponse>;
  register(data: RegisterData): Promise<AuthResponse>;
}
```

Both implementers import from the contract file but neither modifies it.

## Integration Patterns

### Vertical Slice

Each implementer builds a complete feature slice (UI + API + tests):

```
implementer-1: Login feature (login form + login API + login tests)
implementer-2: Register feature (register form + register API + register tests)
```

**Pros**: Each slice is independently testable, minimal integration needed.
**Cons**: May duplicate shared utilities, harder with tightly coupled features.

### Horizontal Layer

Each implementer builds one layer across all features:

```
implementer-1: All UI components (login form, register form, profile page)
implementer-2: All API endpoints (login, register, profile)
implementer-3: All tests (unit, integration, e2e)
```

**Pros**: Consistent patterns within each layer, natural specialization.
**Cons**: More integration points, layer 3 depends on layers 1 and 2.

### Hybrid

Mix vertical and horizontal based on coupling:

```
implementer-1: Login feature (vertical slice — UI + API + tests)
implementer-2: Shared auth infrastructure (horizontal — middleware, JWT utils, types)
```

**Best for**: Most real-world features with some shared infrastructure.

## Branch Management

### Single Branch Strategy

All implementers work on the same feature branch:

- Simple setup, no merge overhead
- Requires strict file ownership to avoid conflicts
- Best for: small teams (2-3), well-defined boundaries

### Multi-Branch Strategy

Each implementer works on a sub-branch:

```
feature/auth
  ├── feature/auth-login      (implementer-1)
  ├── feature/auth-register    (implementer-2)
  └── feature/auth-tests       (implementer-3)
```

- More isolation, explicit merge points
- Higher overhead, merge conflicts still possible in shared files
- Best for: larger teams (4+), complex features

## Troubleshooting

**Implementers are blocking each other waiting for shared code.**
Extract the shared piece into its own interface contract file owned by the team-lead and have implementers import from it. Neither implementer modifies the contract — they only implement against it.

**Merge conflicts appear even with clear ownership rules.**
A file was assigned to two agents, or a config/index file (e.g., `index.ts`, `__init__.py`) that auto-imports everything was modified by both. Designate one owner for all barrel/index files, or have the lead merge them at the end.

**An implementer finishes early but the integration step is blocked.**
Use a staging interface: the finished implementer writes a stub or mock of the downstream dependency so the other implementer can continue working. Replace with the real implementation at integration time.

**The feature decomposition turned out wrong mid-stream.**
Stop new work, have the lead redistribute files, and communicate the change via broadcast. Sunk cost on partially written code is acceptable — continuing with the wrong split is worse.

**Tests written by one implementer fail against code written by another.**
Interface contracts drifted: the implementer who owns the API changed a signature without notifying the test implementer. Enforce the rule that contract files require a broadcast before modification.

## Related Skills

- [team-composition-patterns](../team-composition-patterns/SKILL.md) — Choose the right team size and agent types before decomposing work
- [team-communication-protocols](../team-communication-protocols/SKILL.md) — Coordinate integration handoffs and plan approvals between implementers

<!-- chapter:end slug=parallel-feature-development -->

---

<!-- chapter:begin slug=task-coordination-strategies position=6 -->

## 6. task-coordination-strategies

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/agent-teams/skills/task-coordination-strategies/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/task-coordination-strategies/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/task-coordination-strategies.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/dependency-graphs.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/task-coordination-strategies/references/dependency-graphs.md
  - `references/task-decomposition.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/task-coordination-strategies/references/task-decomposition.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: task-coordination-strategies
description: Decompose complex tasks, design dependency graphs, and coordinate multi-agent work with proper task descriptions and workload balancing. Use this skill when breaking down work for agent teams, managing task dependencies, or monitoring team progress.
version: 1.0.2
---

# Task Coordination Strategies

Strategies for decomposing complex tasks into parallelizable units, designing dependency graphs, writing effective task descriptions, and monitoring workload across agent teams.

## When to Use This Skill

- Breaking down a complex task for parallel execution
- Designing task dependency relationships (blockedBy/blocks)
- Writing task descriptions with clear acceptance criteria
- Monitoring and rebalancing workload across teammates
- Identifying the critical path in a multi-task workflow

## Task Decomposition Strategies

### By Layer

Split work by architectural layer:

- Frontend components
- Backend API endpoints
- Database migrations/models
- Test suites

**Best for**: Full-stack features, vertical slices

### By Component

Split work by functional component:

- Authentication module
- User profile module
- Notification module

**Best for**: Microservices, modular architectures

### By Concern

Split work by cross-cutting concern:

- Security review
- Performance review
- Architecture review

**Best for**: Code reviews, audits

### By File Ownership

Split work by file/directory boundaries:

- `src/components/` — Implementer 1
- `src/api/` — Implementer 2
- `src/utils/` — Implementer 3

**Best for**: Parallel implementation, conflict avoidance

## Dependency Graph Design

### Principles

1. **Minimize chain depth** — Prefer wide, shallow graphs over deep chains
2. **Identify the critical path** — The longest chain determines minimum completion time
3. **Use blockedBy sparingly** — Only add dependencies that are truly required
4. **Avoid circular dependencies** — Task A blocks B blocks A is a deadlock

### Patterns

**Independent (Best parallelism)**:

```
Task A ─┐
Task B ─┼─→ Integration
Task C ─┘
```

**Sequential (Necessary dependencies)**:

```
Task A → Task B → Task C
```

**Diamond (Mixed)**:

```
        ┌→ Task B ─┐
Task A ─┤          ├→ Task D
        └→ Task C ─┘
```

### Using blockedBy/blocks

```
TaskCreate: { subject: "Build API endpoints" }         → Task #1
TaskCreate: { subject: "Build frontend components" }    → Task #2
TaskCreate: { subject: "Integration testing" }          → Task #3
TaskUpdate: { taskId: "3", addBlockedBy: ["1", "2"] }  → #3 waits for #1 and #2
```

## Task Description Best Practices

Every task should include:

1. **Objective** — What needs to be accomplished (1-2 sentences)
2. **Owned Files** — Explicit list of files/directories this teammate may modify
3. **Requirements** — Specific deliverables or behaviors expected
4. **Interface Contracts** — How this work connects to other teammates' work
5. **Acceptance Criteria** — How to verify the task is done correctly
6. **Scope Boundaries** — What is explicitly out of scope

### Template

```
## Objective
Build the user authentication API endpoints.

## Owned Files
- src/api/auth.ts
- src/api/middleware/auth-middleware.ts
- src/types/auth.ts (shared — read only, do not modify)

## Requirements
- POST /api/login — accepts email/password, returns JWT
- POST /api/register — creates new user, returns JWT
- GET /api/me — returns current user profile (requires auth)

## Interface Contract
- Import User type from src/types/auth.ts (owned by implementer-1)
- Export AuthResponse type for frontend consumption

## Acceptance Criteria
- All endpoints return proper HTTP status codes
- JWT tokens expire after 24 hours
- Passwords are hashed with bcrypt

## Out of Scope
- OAuth/social login
- Password reset flow
- Rate limiting
```

## Workload Monitoring

### Indicators of Imbalance

| Signal                     | Meaning             | Action                      |
| -------------------------- | ------------------- | --------------------------- |
| Teammate idle, others busy | Uneven distribution | Reassign pending tasks      |
| Teammate stuck on one task | Possible blocker    | Check in, offer help        |
| All tasks blocked          | Dependency issue    | Resolve critical path first |
| One teammate has 3x others | Overloaded          | Split tasks or reassign     |

### Rebalancing Steps

1. Call `TaskList` to assess current state
2. Identify idle or overloaded teammates
3. Use `TaskUpdate` to reassign tasks
4. Use `SendMessage` to notify affected teammates
5. Monitor for improved throughput

<!-- chapter:end slug=task-coordination-strategies -->

---

<!-- chapter:begin slug=team-communication-protocols position=7 -->

## 7. team-communication-protocols

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/agent-teams/skills/team-communication-protocols/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/team-communication-protocols/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/team-communication-protocols.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/messaging-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/team-communication-protocols/references/messaging-patterns.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: team-communication-protocols
description: Structured messaging protocols for agent team communication including message type selection, plan approval, shutdown procedures, and anti-patterns to avoid. Use this skill when establishing communication norms for a newly spawned team, when deciding whether to send a direct message or a broadcast, when a team-lead needs to review and approve an implementer's plan before work begins, when orchestrating a graceful team shutdown after all tasks are complete, or when debugging why teammates are not coordinating correctly at integration points.
version: 1.0.2
---

# Team Communication Protocols

Protocols for effective communication between agent teammates, including message type selection, plan approval workflows, shutdown procedures, and common anti-patterns to avoid.

## When to Use This Skill

- Establishing communication norms for a new team
- Choosing between message types (message, broadcast, shutdown_request)
- Handling plan approval workflows
- Managing graceful team shutdown
- Discovering teammate identities and capabilities

## Message Type Selection

### `message` (Direct Message) — Default Choice

Send to a single specific teammate:

```json
{
  "type": "message",
  "recipient": "implementer-1",
  "content": "Your API endpoint is ready. You can now build the frontend form.",
  "summary": "API endpoint ready for frontend"
}
```

**Use for**: Task updates, coordination, questions, integration notifications.

### `broadcast` — Use Sparingly

Send to ALL teammates simultaneously:

```json
{
  "type": "broadcast",
  "content": "Critical: shared types file has been updated. Pull latest before continuing.",
  "summary": "Shared types updated"
}
```

**Use ONLY for**: Critical blockers affecting everyone, major changes to shared resources.

**Why sparingly?**: Each broadcast sends N separate messages (one per teammate), consuming API resources proportional to team size.

### `shutdown_request` — Graceful Termination

Request a teammate to shut down:

```json
{
  "type": "shutdown_request",
  "recipient": "reviewer-1",
  "content": "Review complete, shutting down team."
}
```

The teammate responds with `shutdown_response` (approve or reject with reason).

## Communication Anti-Patterns

| Anti-Pattern                            | Problem                                  | Better Approach                        |
| --------------------------------------- | ---------------------------------------- | -------------------------------------- |
| Broadcasting routine updates            | Wastes resources, noise                  | Direct message to affected teammate    |
| Sending JSON status messages            | Not designed for structured data         | Use TaskUpdate to update task status   |
| Not communicating at integration points | Teammates build against stale interfaces | Message when your interface is ready   |
| Micromanaging via messages              | Overwhelms teammates, slows work         | Check in at milestones, not every step |
| Using UUIDs instead of names            | Hard to read, error-prone                | Always use teammate names              |
| Ignoring idle teammates                 | Wasted capacity                          | Assign new work or shut down           |

## Plan Approval Workflow

When a teammate is spawned with `plan_mode_required`:

1. Teammate creates a plan using read-only exploration tools
2. Teammate calls `ExitPlanMode` which sends a `plan_approval_request` to the lead
3. Lead reviews the plan
4. Lead responds with `plan_approval_response`:

**Approve**:

```json
{
  "type": "plan_approval_response",
  "request_id": "abc-123",
  "recipient": "implementer-1",
  "approve": true
}
```

**Reject with feedback**:

```json
{
  "type": "plan_approval_response",
  "request_id": "abc-123",
  "recipient": "implementer-1",
  "approve": false,
  "content": "Please add error handling for the API calls"
}
```

## Shutdown Protocol

### Graceful Shutdown Sequence

1. **Lead sends shutdown_request** to each teammate
2. **Teammate receives request** as a JSON message with `type: "shutdown_request"`
3. **Teammate responds** with `shutdown_response`:
   - `approve: true` — Teammate saves state and exits
   - `approve: false` + reason — Teammate continues working
4. **Lead handles rejections** — Wait for teammate to finish, then retry
5. **After all teammates shut down** — Call `TeamDelete` to remove team resources

### Handling Rejections

If a teammate rejects shutdown:

- Check their reason (usually "still working on task")
- Wait for their current task to complete
- Retry shutdown request
- If urgent, user can force shutdown

## Teammate Discovery

Find team members by reading the config file:

**Location**: `~/.claude/teams/{team-name}/config.json`

**Structure**:

```json
{
  "members": [
    {
      "name": "security-reviewer",
      "agentId": "uuid-here",
      "agentType": "team-reviewer"
    },
    {
      "name": "perf-reviewer",
      "agentId": "uuid-here",
      "agentType": "team-reviewer"
    }
  ]
}
```

**Always use `name`** for messaging and task assignment. Never use `agentId`, role names, or unsuffixed aliases directly. If a teammate was spawned as `team-lead-2`, send to `team-lead-2`, not `team-lead`.

## Troubleshooting

**A teammate is not responding to messages.**
Check the teammate's task status. If it is idle, it may have completed its task and is waiting to be assigned new work or shut down. If it is still active, it may be mid-execution and will process messages once the current operation finishes.

**A teammate says it cannot see SendMessage.**
Check the teammate agent's `tools:` frontmatter. Agent Teams communication tools such as `SendMessage`, `TaskList`, `TaskGet`, and `TaskUpdate` must be listed explicitly when an agent uses a restricted tool allowlist.

**The lead is sending broadcasts for every status update.**
This is a common anti-pattern. Broadcasts are expensive — each one sends N messages. Use direct messages (`type: "message"`) for point-to-point updates. Reserve broadcasts for critical shared-resource changes like an updated interface contract.

**A teammate rejected a shutdown request unexpectedly.**
The teammate is still working. Check the rejection reason in the `shutdown_response` content field, wait for the work to finish, then retry. Never force-terminate a teammate that has unsaved work.

**A plan_approval_request arrived but the request_id is missing.**
The teammate called `ExitPlanMode` without the required request context. Have the teammate re-enter plan mode, complete exploration, and call `ExitPlanMode` again. The `request_id` is generated automatically by the plan mode system.

**Two teammates are waiting on each other and neither is making progress.**
This is a deadlock: both are blocked waiting for the other to finish first. The lead should send a direct message to one teammate with a stub or partial result so it can unblock and proceed.

## Related Skills

- [team-composition-patterns](../team-composition-patterns/SKILL.md) — Select agent types and team size before establishing communication norms
- [parallel-feature-development](../parallel-feature-development/SKILL.md) — Use communication protocols to coordinate integration handoffs between parallel implementers

<!-- chapter:end slug=team-communication-protocols -->

---

<!-- chapter:begin slug=team-composition-patterns position=8 -->

## 8. team-composition-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/agent-teams/skills/team-composition-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/team-composition-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/team-composition-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/agent-type-selection.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/team-composition-patterns/references/agent-type-selection.md
  - `references/preset-teams.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/agent-teams/skills/team-composition-patterns/references/preset-teams.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: team-composition-patterns
description: Design optimal agent team compositions with sizing heuristics, preset configurations, and agent type selection. Use this skill when deciding how many agents to spawn for a task, when choosing between a review team versus a feature team versus a debug team, when selecting the correct subagent_type for each role to ensure agents have the tools they need, when configuring display modes (tmux, iTerm2, in-process) for a CI or local environment, or when building a custom team composition for a non-standard workflow such as a migration or security audit.
version: 1.0.2
---

# Team Composition Patterns

Best practices for composing multi-agent teams, selecting team sizes, choosing agent types, and configuring display modes for Claude Code's Agent Teams feature.

## When to Use This Skill

- Deciding how many teammates to spawn for a task
- Choosing between preset team configurations
- Selecting the right agent type (subagent_type) for each role
- Configuring teammate display modes (tmux, iTerm2, in-process)
- Building custom team compositions for non-standard workflows

## Team Sizing Heuristics

| Complexity   | Team Size | When to Use                                                 |
| ------------ | --------- | ----------------------------------------------------------- |
| Simple       | 1-2       | Single-dimension review, isolated bug, small feature        |
| Moderate     | 2-3       | Multi-file changes, 2-3 concerns, medium features           |
| Complex      | 3-4       | Cross-cutting concerns, large features, deep debugging      |
| Very Complex | 4-5       | Full-stack features, comprehensive reviews, systemic issues |

**Rule of thumb**: Start with the smallest team that covers all required dimensions. Adding teammates increases coordination overhead.

## Preset Team Compositions

### Review Team

- **Size**: 3 reviewers
- **Agents**: 3x `team-reviewer`
- **Default dimensions**: security, performance, architecture
- **Use when**: Code changes need multi-dimensional quality assessment

### Debug Team

- **Size**: 3 investigators
- **Agents**: 3x `team-debugger`
- **Default hypotheses**: 3 competing hypotheses
- **Use when**: Bug has multiple plausible root causes

### Feature Team

- **Size**: 3 (1 lead + 2 implementers)
- **Agents**: 1x `team-lead` + 2x `team-implementer`
- **Use when**: Feature can be decomposed into parallel work streams

### Fullstack Team

- **Size**: 4 (1 lead + 3 implementers)
- **Agents**: 1x `team-lead` + 1x frontend `team-implementer` + 1x backend `team-implementer` + 1x test `team-implementer`
- **Use when**: Feature spans frontend, backend, and test layers

### Research Team

- **Size**: 3 researchers
- **Agents**: 3x `general-purpose`
- **Default areas**: Each assigned a different research question, module, or topic
- **Capabilities**: Codebase search (Grep, Glob, Read), web search (WebSearch, WebFetch)
- **Use when**: Need to understand a codebase, research libraries, compare approaches, or gather information from code and web sources in parallel

### Security Team

- **Size**: 4 reviewers
- **Agents**: 4x `team-reviewer`
- **Default dimensions**: OWASP/vulnerabilities, auth/access control, dependencies/supply chain, secrets/configuration
- **Use when**: Comprehensive security audit covering multiple attack surfaces

### Migration Team

- **Size**: 4 (1 lead + 2 implementers + 1 reviewer)
- **Agents**: 1x `team-lead` + 2x `team-implementer` + 1x `team-reviewer`
- **Use when**: Large codebase migration (framework upgrade, language port, API version bump) requiring parallel work with correctness verification

## Agent Type Selection

When spawning teammates with the `Agent` tool, choose `subagent_type` based on what tools the teammate needs:

| Agent Type                     | Tools Available                                      | Use For                                                    |
| ------------------------------ | ---------------------------------------------------- | ---------------------------------------------------------- |
| `general-purpose`              | All tools (Read, Write, Edit, Bash, etc.)            | Implementation, debugging, any task requiring file changes |
| `Explore`                      | Read-only tools (Read, Grep, Glob)                   | Research, code exploration, analysis                       |
| `Plan`                         | Read-only tools                                      | Architecture planning, task decomposition                  |
| `agent-teams:team-reviewer`    | Read/search/Bash plus TaskList/TaskGet/TaskUpdate/SendMessage | Code review with structured findings               |
| `agent-teams:team-debugger`    | Read/search/Bash plus TaskList/TaskGet/TaskUpdate/SendMessage | Hypothesis-driven investigation                    |
| `agent-teams:team-implementer` | Read/Write/Edit/search/Bash plus TaskList/TaskGet/TaskUpdate/SendMessage | Building features within file ownership boundaries |
| `agent-teams:team-lead`        | Read/search/Bash plus Agent Teams coordination tools | Team orchestration and coordination                        |

**Key distinction**: Read-only agents (Explore, Plan) cannot modify files. Never assign implementation tasks to read-only agents.

## Display Mode Configuration

Configure in `~/.claude/settings.json`:

```json
{
  "teammateMode": "tmux"
}
```

| Mode           | Behavior                       | Best For                                          |
| -------------- | ------------------------------ | ------------------------------------------------- |
| `"tmux"`       | Each teammate in a tmux pane   | Development workflows, monitoring multiple agents |
| `"iterm2"`     | Each teammate in an iTerm2 tab | macOS users who prefer iTerm2                     |
| `"in-process"` | All teammates in same process  | Simple tasks, CI/CD environments                  |

## Custom Team Guidelines

When building custom teams:

1. **Every team needs a coordinator** — Either designate a `team-lead` or have the user coordinate directly
2. **Match roles to agent types** — Use specialized agents (reviewer, debugger, implementer) when available
3. **Avoid duplicate roles** — Two agents doing the same thing wastes resources
4. **Define boundaries upfront** — Each teammate needs clear ownership of files or responsibilities
5. **Keep it small** — 2-4 teammates is the sweet spot; 5+ requires significant coordination overhead

## Troubleshooting

**A teammate was spawned as `Explore` but needs to write files.**
`Explore` and `Plan` are read-only agents. Change the `subagent_type` to `general-purpose` or an appropriate specialized agent type. Never assign implementation tasks to read-only agents.

**The team is growing too large and coordination is slowing everything down.**
Each additional teammate adds communication overhead. Consolidate roles: can one agent cover two dimensions? A 4-person team doing 6 independent tasks is usually better served by 3 agents covering 2 tasks each.

**tmux mode is not showing panes.**
Ensure tmux is installed and a session is already running before spawning teammates. The `in-process` mode works without tmux and is suitable for CI or scripted environments.

**Two reviewers are flagging the same issues.**
The review dimensions overlap. Redefine each reviewer's focus area: one on correctness/logic, one on security, one on performance/scalability. Overlapping coverage wastes tokens and produces duplicate findings.

**A `team-lead` is spawning teammates but they are not receiving tasks.**
Verify that the lead is using the `Agent` tool to spawn teammates and passing complete context in the prompt. Teammates start fresh with no prior conversation history — they need all relevant information in their initial prompt.

## Related Skills

- [parallel-feature-development](../parallel-feature-development/SKILL.md) — Decompose work streams and assign file ownership once the team is composed
- [team-communication-protocols](../team-communication-protocols/SKILL.md) — Establish messaging norms and shutdown procedures for the assembled team

<!-- chapter:end slug=team-composition-patterns -->

---

## Part: API Scaffolding

---

<!-- chapter:begin slug=fastapi-templates position=9 -->

## 9. fastapi-templates

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/api-scaffolding/skills/fastapi-templates/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/api-scaffolding/skills/fastapi-templates/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/fastapi-templates.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/api-scaffolding/skills/fastapi-templates/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: fastapi-templates
description: Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
---

# FastAPI Project Templates

Production-ready FastAPI project structures with async patterns, dependency injection, middleware, and best practices for building high-performance APIs.

## When to Use This Skill

- Starting new FastAPI projects from scratch
- Implementing async REST APIs with Python
- Building high-performance web services and microservices
- Creating async applications with PostgreSQL, MongoDB
- Setting up API projects with proper structure and testing

## Core Concepts

### 1. Project Structure

**Recommended Layout:**

```
app/
├── api/                    # API routes
│   ├── v1/
│   │   ├── endpoints/
│   │   │   ├── users.py
│   │   │   ├── auth.py
│   │   │   └── items.py
│   │   └── router.py
│   └── dependencies.py     # Shared dependencies
├── core/                   # Core configuration
│   ├── config.py
│   ├── security.py
│   └── database.py
├── models/                 # Database models
│   ├── user.py
│   └── item.py
├── schemas/                # Pydantic schemas
│   ├── user.py
│   └── item.py
├── services/               # Business logic
│   ├── user_service.py
│   └── auth_service.py
├── repositories/           # Data access
│   ├── user_repository.py
│   └── item_repository.py
└── main.py                 # Application entry
```

### 2. Dependency Injection

FastAPI's built-in DI system using `Depends`:

- Database session management
- Authentication/authorization
- Shared business logic
- Configuration injection

### 3. Async Patterns

Proper async/await usage:

- Async route handlers
- Async database operations
- Async background tasks
- Async middleware

## Detailed worked examples and patterns

Detailed sections (starting with `## Implementation Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Testing

```python
# tests/conftest.py
import pytest
import asyncio
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker

from app.main import app
from app.core.database import get_db, Base

TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:"

@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()

@pytest.fixture
async def db_session():
    engine = create_async_engine(TEST_DATABASE_URL, echo=True)
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    AsyncSessionLocal = sessionmaker(
        engine, class_=AsyncSession, expire_on_commit=False
    )

    async with AsyncSessionLocal() as session:
        yield session

@pytest.fixture
async def client(db_session):
    async def override_get_db():
        yield db_session

    app.dependency_overrides[get_db] = override_get_db

    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client

# tests/test_users.py
import pytest

@pytest.mark.asyncio
async def test_create_user(client):
    response = await client.post(
        "/api/v1/users/",
        json={
            "email": "test@example.com",
            "password": "testpass123",
            "name": "Test User"
        }
    )
    assert response.status_code == 201
    data = response.json()
    assert data["email"] == "test@example.com"
    assert "id" in data
```

<!-- chapter:end slug=fastapi-templates -->

---

## Part: Backend Development

---

<!-- chapter:begin slug=api-design-principles position=10 -->

## 10. api-design-principles

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/api-design-principles/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/api-design-principles/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/api-design-principles.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (5), referenced from this skill's directory:
  - `assets/api-design-checklist.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/api-design-principles/assets/api-design-checklist.md
  - `assets/rest-api-template.py` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/api-design-principles/assets/rest-api-template.py
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/api-design-principles/references/details.md
  - `references/graphql-schema-design.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/api-design-principles/references/graphql-schema-design.md
  - `references/rest-best-practices.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/api-design-principles/references/rest-best-practices.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: api-design-principles
description: Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewing API specifications, or establishing API design standards.
---

# API Design Principles

Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers and stand the test of time.

## When to Use This Skill

- Designing new REST or GraphQL APIs
- Refactoring existing APIs for better usability
- Establishing API design standards for your team
- Reviewing API specifications before implementation
- Migrating between API paradigms (REST to GraphQL, etc.)
- Creating developer-friendly API documentation
- Optimizing APIs for specific use cases (mobile, third-party integrations)

## Core Concepts

### 1. RESTful Design Principles

**Resource-Oriented Architecture**

- Resources are nouns (users, orders, products), not verbs
- Use HTTP methods for actions (GET, POST, PUT, PATCH, DELETE)
- URLs represent resource hierarchies
- Consistent naming conventions

**HTTP Methods Semantics:**

- `GET`: Retrieve resources (idempotent, safe)
- `POST`: Create new resources
- `PUT`: Replace entire resource (idempotent)
- `PATCH`: Partial resource updates
- `DELETE`: Remove resources (idempotent)

### 2. GraphQL Design Principles

**Schema-First Development**

- Types define your domain model
- Queries for reading data
- Mutations for modifying data
- Subscriptions for real-time updates

**Query Structure:**

- Clients request exactly what they need
- Single endpoint, multiple operations
- Strongly typed schema
- Introspection built-in

### 3. API Versioning Strategies

**URL Versioning:**

```
/api/v1/users
/api/v2/users
```

**Header Versioning:**

```
Accept: application/vnd.api+json; version=1
```

**Query Parameter Versioning:**

```
/api/users?version=1
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### REST APIs

1. **Consistent Naming**: Use plural nouns for collections (`/users`, not `/user`)
2. **Stateless**: Each request contains all necessary information
3. **Use HTTP Status Codes Correctly**: 2xx success, 4xx client errors, 5xx server errors
4. **Version Your API**: Plan for breaking changes from day one
5. **Pagination**: Always paginate large collections
6. **Rate Limiting**: Protect your API with rate limits
7. **Documentation**: Use OpenAPI/Swagger for interactive docs

### GraphQL APIs

1. **Schema First**: Design schema before writing resolvers
2. **Avoid N+1**: Use DataLoaders for efficient data fetching
3. **Input Validation**: Validate at schema and resolver levels
4. **Error Handling**: Return structured errors in mutation payloads
5. **Pagination**: Use cursor-based pagination (Relay spec)
6. **Deprecation**: Use `@deprecated` directive for gradual migration
7. **Monitoring**: Track query complexity and execution time

## Common Pitfalls

- **Over-fetching/Under-fetching (REST)**: Fixed in GraphQL but requires DataLoaders
- **Breaking Changes**: Version APIs or use deprecation strategies
- **Inconsistent Error Formats**: Standardize error responses
- **Missing Rate Limits**: APIs without limits are vulnerable to abuse
- **Poor Documentation**: Undocumented APIs frustrate developers
- **Ignoring HTTP Semantics**: POST for idempotent operations breaks expectations
- **Tight Coupling**: API structure shouldn't mirror database schema

<!-- chapter:end slug=api-design-principles -->

---

<!-- chapter:begin slug=architecture-patterns position=11 -->

## 11. architecture-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/architecture-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/architecture-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/architecture-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/architecture-patterns/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/architecture-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: architecture-patterns
description: Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use this skill when designing clean architecture for a new microservice, when refactoring a monolith to use bounded contexts, when implementing hexagonal or onion architecture patterns, or when debugging dependency cycles between application layers.
---

# Architecture Patterns

Master proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to build maintainable, testable, and scalable systems.

**Given:** a service boundary or module to architect.
**Produces:** layered structure with clear dependency rules, interface definitions, and test boundaries.

## When to Use This Skill

- Designing new backend services or microservices from scratch
- Refactoring monolithic applications where business logic is entangled with ORM models or HTTP concerns
- Establishing bounded contexts before splitting a system into services
- Debugging dependency cycles where infrastructure code bleeds into the domain layer
- Creating testable codebases where use-case tests do not require a running database
- Implementing domain-driven design tactical patterns (aggregates, value objects, domain events)

## Core Concepts

### 1. Clean Architecture (Uncle Bob)

**Layers (dependency flows inward):**

- **Entities**: Core business models, no framework imports
- **Use Cases**: Application business rules, orchestrate entities
- **Interface Adapters**: Controllers, presenters, gateways — translate between use cases and external formats
- **Frameworks & Drivers**: UI, database, external services — all at the outermost ring

**Key Principles:**

- Dependencies point inward only; inner layers know nothing about outer layers
- Business logic is independent of frameworks, databases, and delivery mechanisms
- Every layer boundary is crossed via an abstract interface
- Testable without UI, database, or external services

### 2. Hexagonal Architecture (Ports and Adapters)

**Components:**

- **Domain Core**: Business logic lives here, framework-free
- **Ports**: Abstract interfaces that define how the core interacts with the outside world (driving and driven)
- **Adapters**: Concrete implementations of ports (PostgreSQL adapter, Stripe adapter, REST adapter)

**Benefits:**

- Swap implementations without touching the core (e.g., replace PostgreSQL with DynamoDB)
- Use in-memory adapters in tests — no Docker required
- Technology decisions deferred to the edges

### 3. Domain-Driven Design (DDD)

**Strategic Patterns:**

- **Bounded Contexts**: Isolate a coherent model for one subdomain; avoid sharing a single model across the whole system
- **Context Mapping**: Define how contexts relate (Anti-Corruption Layer, Shared Kernel, Open Host Service)
- **Ubiquitous Language**: Every term in code matches the term used by domain experts

**Tactical Patterns:**

- **Entities**: Objects with stable identity that change over time
- **Value Objects**: Immutable objects identified by their attributes (Email, Money, Address)
- **Aggregates**: Consistency boundaries; only the root is accessible from outside
- **Repositories**: Persist and reconstitute aggregates; abstract over the storage mechanism
- **Domain Events**: Capture things that happened inside the domain; used for cross-aggregate coordination

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing — In-Memory Adapters

The hallmark of correctly applied Clean Architecture is that every use case can be exercised in a plain unit test with no real database, no Docker, and no network:

```python
# tests/unit/test_create_user.py
import asyncio
from typing import Dict, Optional
from domain.entities.user import User
from domain.interfaces.user_repository import IUserRepository
from use_cases.create_user import CreateUserUseCase, CreateUserRequest


class InMemoryUserRepository(IUserRepository):
    def __init__(self):
        self._store: Dict[str, User] = {}

    async def find_by_id(self, user_id: str) -> Optional[User]:
        return self._store.get(user_id)

    async def find_by_email(self, email: str) -> Optional[User]:
        return next((u for u in self._store.values() if u.email == email), None)

    async def save(self, user: User) -> User:
        self._store[user.id] = user
        return user

    async def delete(self, user_id: str) -> bool:
        return self._store.pop(user_id, None) is not None


async def test_create_user_succeeds():
    repo = InMemoryUserRepository()
    use_case = CreateUserUseCase(user_repository=repo)

    response = await use_case.execute(CreateUserRequest(email="alice@example.com", name="Alice"))

    assert response.success
    assert response.user.email == "alice@example.com"
    assert response.user.id is not None


async def test_duplicate_email_rejected():
    repo = InMemoryUserRepository()
    use_case = CreateUserUseCase(user_repository=repo)

    await use_case.execute(CreateUserRequest(email="alice@example.com", name="Alice"))
    response = await use_case.execute(CreateUserRequest(email="alice@example.com", name="Alice2"))

    assert not response.success
    assert "already exists" in response.error
```

## Troubleshooting

### Use case tests require a running database

Business logic has leaked into the infrastructure layer. Move all database calls behind an `IRepository` interface and inject an in-memory implementation in tests (see Testing section above). The use case constructor must accept the abstract port, not the concrete class.

### Circular imports between layers

A common symptom is `ImportError: cannot import name X` between `use_cases` and `adapters`. This happens when a use case imports a concrete adapter class instead of the abstract port. Enforce the rule: `use_cases/` imports only from `domain/` (entities and interfaces). It must never import from `adapters/` or `infrastructure/`.

### Framework decorators appearing in domain entities

If SQLAlchemy `Column()` or Pydantic `Field()` annotations appear on domain entities, the entity is no longer pure. Create a separate ORM model in `adapters/repositories/` and map to/from the domain entity in the repository's `_to_entity()` method.

### All logic ending up in controllers

When the controller grows beyond HTTP parsing and response formatting, extract the logic into a use case class. A controller method should do three things only: parse the request, call a use case, map the response.

### Value objects raising errors too late

Validate invariants in `__post_init__` (Python) or the constructor so an invalid `Email` or `Money` cannot be constructed at all. This surfaces bad data at the boundary, not deep inside business logic.

### Context bleed across bounded contexts

If the `Order` context is importing `User` entities from the `Identity` context, introduce an Anti-Corruption Layer. The `Order` context should hold its own lightweight `CustomerId` value object and only call the `Identity` context through an explicit interface.

## Advanced Patterns

For detailed DDD bounded context mapping, full multi-service project trees, Anti-Corruption Layer implementations, and Onion Architecture comparisons, see:

- [`references/advanced-patterns.md`](references/advanced-patterns.md)

## Related Skills

- `microservices-patterns` — Apply these architecture patterns when decomposing a monolith into services
- `cqrs-implementation` — Use Clean Architecture as the structural foundation for CQRS command/query separation
- `saga-orchestration` — Sagas require well-defined aggregate boundaries, which DDD tactical patterns provide
- `event-store-design` — Domain events produced by aggregates feed directly into an event store

<!-- chapter:end slug=architecture-patterns -->

---

<!-- chapter:begin slug=cqrs-implementation position=12 -->

## 12. cqrs-implementation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/cqrs-implementation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/cqrs-implementation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/cqrs-implementation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/cqrs-implementation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: cqrs-implementation
description: Implement Command Query Responsibility Segregation for scalable architectures. Use when separating read and write models, optimizing query performance, or building event-sourced systems.
---

# CQRS Implementation

Comprehensive guide to implementing CQRS (Command Query Responsibility Segregation) patterns.

## When to Use This Skill

- Separating read and write concerns
- Scaling reads independently from writes
- Building event-sourced systems
- Optimizing complex query scenarios
- Different read/write data models needed
- High-performance reporting requirements

## Core Concepts

### 1. CQRS Architecture

```
                    ┌─────────────┐
                    │   Client    │
                    └──────┬──────┘
                           │
              ┌────────────┴────────────┐
              │                         │
              ▼                         ▼
       ┌─────────────┐          ┌─────────────┐
       │  Commands   │          │   Queries   │
       │    API      │          │    API      │
       └──────┬──────┘          └──────┬──────┘
              │                         │
              ▼                         ▼
       ┌─────────────┐          ┌─────────────┐
       │  Command    │          │   Query     │
       │  Handlers   │          │  Handlers   │
       └──────┬──────┘          └──────┬──────┘
              │                         │
              ▼                         ▼
       ┌─────────────┐          ┌─────────────┐
       │   Write     │─────────►│    Read     │
       │   Model     │  Events  │   Model     │
       └─────────────┘          └─────────────┘
```

### 2. Key Components

| Component           | Responsibility                  |
| ------------------- | ------------------------------- |
| **Command**         | Intent to change state          |
| **Command Handler** | Validates and executes commands |
| **Event**           | Record of state change          |
| **Query**           | Request for data                |
| **Query Handler**   | Retrieves data from read model  |
| **Projector**       | Updates read model from events  |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Separate command and query models** - Different needs
- **Use eventual consistency** - Accept propagation delay
- **Validate in command handlers** - Before state change
- **Denormalize read models** - Optimize for queries
- **Version your events** - For schema evolution

### Don'ts

- **Don't query in commands** - Use only for writes
- **Don't couple read/write schemas** - Independent evolution
- **Don't over-engineer** - Start simple
- **Don't ignore consistency SLAs** - Define acceptable lag

<!-- chapter:end slug=cqrs-implementation -->

---

<!-- chapter:begin slug=event-store-design position=13 -->

## 13. event-store-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/event-store-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/event-store-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/event-store-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/event-store-design/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: event-store-design
description: Design and implement event stores for event-sourced systems. Use when building event sourcing infrastructure, choosing event store technologies, or implementing event persistence patterns.
---

# Event Store Design

Comprehensive guide to designing event stores for event-sourced applications.

## When to Use This Skill

- Designing event sourcing infrastructure
- Choosing between event store technologies
- Implementing custom event stores
- Optimizing event storage and retrieval
- Setting up event store schemas
- Planning for event store scaling

## Core Concepts

### 1. Event Store Architecture

```
┌─────────────────────────────────────────────────────┐
│                    Event Store                       │
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │   Stream 1   │  │   Stream 2   │  │   Stream 3   │ │
│  │ (Aggregate)  │  │ (Aggregate)  │  │ (Aggregate)  │ │
│  ├─────────────┤  ├─────────────┤  ├─────────────┤ │
│  │ Event 1     │  │ Event 1     │  │ Event 1     │ │
│  │ Event 2     │  │ Event 2     │  │ Event 2     │ │
│  │ Event 3     │  │ ...         │  │ Event 3     │ │
│  │ ...         │  │             │  │ Event 4     │ │
│  └─────────────┘  └─────────────┘  └─────────────┘ │
├─────────────────────────────────────────────────────┤
│  Global Position: 1 → 2 → 3 → 4 → 5 → 6 → ...     │
└─────────────────────────────────────────────────────┘
```

### 2. Event Store Requirements

| Requirement       | Description                        |
| ----------------- | ---------------------------------- |
| **Append-only**   | Events are immutable, only appends |
| **Ordered**       | Per-stream and global ordering     |
| **Versioned**     | Optimistic concurrency control     |
| **Subscriptions** | Real-time event notifications      |
| **Idempotent**    | Handle duplicate writes safely     |

## Technology Comparison

| Technology       | Best For                  | Limitations                      |
| ---------------- | ------------------------- | -------------------------------- |
| **EventStoreDB** | Pure event sourcing       | Single-purpose                   |
| **PostgreSQL**   | Existing Postgres stack   | Manual implementation            |
| **Kafka**        | High-throughput streaming | Not ideal for per-stream queries |
| **DynamoDB**     | Serverless, AWS-native    | Query limitations                |
| **Marten**       | .NET ecosystems           | .NET specific                    |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Use stream IDs that include aggregate type** - `Order-{uuid}`
- **Include correlation/causation IDs** - For tracing
- **Version events from day one** - Plan for schema evolution
- **Implement idempotency** - Use event IDs for deduplication
- **Index appropriately** - For your query patterns

### Don'ts

- **Don't update or delete events** - They're immutable facts
- **Don't store large payloads** - Keep events small
- **Don't skip optimistic concurrency** - Prevents data corruption
- **Don't ignore backpressure** - Handle slow consumers

<!-- chapter:end slug=event-store-design -->

---

<!-- chapter:begin slug=microservices-patterns position=14 -->

## 14. microservices-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/microservices-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/microservices-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/microservices-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/microservices-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: microservices-patterns
description: Design microservices architectures with service boundaries, event-driven communication, and resilience patterns. Use when building distributed systems, decomposing monoliths, or implementing microservices.
---

# Microservices Patterns

Master microservices architecture patterns including service boundaries, inter-service communication, data management, and resilience patterns for building distributed systems.

## When to Use This Skill

- Decomposing monoliths into microservices
- Designing service boundaries and contracts
- Implementing inter-service communication
- Managing distributed data and transactions
- Building resilient distributed systems
- Implementing service discovery and load balancing
- Designing event-driven architectures

## Core Concepts

### 1. Service Decomposition Strategies

**By Business Capability**

- Organize services around business functions
- Each service owns its domain
- Example: OrderService, PaymentService, InventoryService

**By Subdomain (DDD)**

- Core domain, supporting subdomains
- Bounded contexts map to services
- Clear ownership and responsibility

**Strangler Fig Pattern**

- Gradually extract from monolith
- New functionality as microservices
- Proxy routes to old/new systems

### 2. Communication Patterns

**Synchronous (Request/Response)**

- REST APIs
- gRPC
- GraphQL

**Asynchronous (Events/Messages)**

- Event streaming (Kafka)
- Message queues (RabbitMQ, SQS)
- Pub/Sub patterns

### 3. Data Management

**Database Per Service**

- Each service owns its data
- No shared databases
- Loose coupling

**Saga Pattern**

- Distributed transactions
- Compensating actions
- Eventual consistency

### 4. Resilience Patterns

**Circuit Breaker**

- Fail fast on repeated errors
- Prevent cascade failures

**Retry with Backoff**

- Transient fault handling
- Exponential backoff

**Bulkhead**

- Isolate resources
- Limit impact of failures

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=microservices-patterns -->

---

<!-- chapter:begin slug=projection-patterns position=15 -->

## 15. projection-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/projection-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/projection-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/projection-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/projection-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: projection-patterns
description: Build read models and projections from event streams. Use when implementing CQRS read sides, building materialized views, or optimizing query performance in event-sourced systems.
---

# Projection Patterns

Comprehensive guide to building projections and read models for event-sourced systems.

## When to Use This Skill

- Building CQRS read models
- Creating materialized views from events
- Optimizing query performance
- Implementing real-time dashboards
- Building search indexes from events
- Aggregating data across streams

## Core Concepts

### 1. Projection Architecture

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Event Store │────►│ Projector   │────►│ Read Model  │
│             │     │             │     │ (Database)  │
│ ┌─────────┐ │     │ ┌─────────┐ │     │ ┌─────────┐ │
│ │ Events  │ │     │ │ Handler │ │     │ │ Tables  │ │
│ └─────────┘ │     │ │ Logic   │ │     │ │ Views   │ │
│             │     │ └─────────┘ │     │ │ Cache   │ │
└─────────────┘     └─────────────┘     └─────────────┘
```

### 2. Projection Types

| Type           | Description                 | Use Case               |
| -------------- | --------------------------- | ---------------------- |
| **Live**       | Real-time from subscription | Current state queries  |
| **Catchup**    | Process historical events   | Rebuilding read models |
| **Persistent** | Stores checkpoint           | Resume after restart   |
| **Inline**     | Same transaction as write   | Strong consistency     |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Make projections idempotent** - Safe to replay
- **Use transactions** - For multi-table updates
- **Store checkpoints** - Resume after failures
- **Monitor lag** - Alert on projection delays
- **Plan for rebuilds** - Design for reconstruction

### Don'ts

- **Don't couple projections** - Each is independent
- **Don't skip error handling** - Log and alert on failures
- **Don't ignore ordering** - Events must be processed in order
- **Don't over-normalize** - Denormalize for query patterns

<!-- chapter:end slug=projection-patterns -->

---

<!-- chapter:begin slug=saga-orchestration position=16 -->

## 16. saga-orchestration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/saga-orchestration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/saga-orchestration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/saga-orchestration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/saga-orchestration/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/saga-orchestration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: saga-orchestration
description: Implement saga patterns for distributed transactions and cross-aggregate workflows. Use this skill when implementing distributed transactions across microservices where 2PC is unavailable, designing compensating actions for failed order workflows that span inventory, payment, and shipping services, building event-driven saga coordinators for travel booking systems that must roll back hotel, flight, and car rental reservations atomically, or debugging stuck saga states in production where compensation steps never complete.
---

# Saga Orchestration

Patterns for managing distributed transactions and long-running business processes without two-phase commit.

## Inputs and Outputs

**What you provide:**
- Service boundaries and ownership (which service owns which step)
- Transaction requirements (which steps must be atomic, which can be eventual)
- Failure modes for each step (transient vs. permanent, retry policy)
- SLA requirements per step (informs timeout configuration)
- Existing event/messaging infrastructure (Kafka, RabbitMQ, SQS, etc.)

**What this skill produces:**
- Saga definition with ordered steps, action commands, and compensation commands
- Orchestrator or choreography implementation for your chosen pattern
- Compensation logic for each participant service (idempotent, always-succeeds)
- Step timeout configuration with per-step deadlines
- Monitoring setup: state machine metrics, stuck saga detection, DLQ recovery

---

## When to Use This Skill

- Coordinating multi-service transactions without distributed locks
- Implementing compensating transactions for partial failures
- Managing long-running business workflows (minutes to hours)
- Handling failures in distributed systems where atomicity is required
- Building order fulfillment, approval, or booking processes
- Replacing fragile two-phase commit with async compensation

---

## Detailed section: Core Concepts

Moved to `references/details.md`.

## Detailed section: Templates

Moved to `references/details.md`.

## Best Practices

### Do's

- **Make every step idempotent** — Commands may be replayed on broker reconnect
- **Design compensations carefully** — They are the most critical code path
- **Use correlation IDs** — The `saga_id` must flow through every event and log
- **Implement per-step timeouts** — Never wait indefinitely for a participant reply
- **Log state transitions** — `saga_id`, `step_name`, `old_state → new_state` on every change
- **Test compensation paths explicitly** — Inject failures at each step index in integration tests

### Don'ts

- **Don't assume instant completion** — Sagas are async and may take minutes
- **Don't skip compensation testing** — The rollback path is the hardest to get right
- **Don't couple services directly** — Use async messaging, never synchronous calls inside a saga step
- **Don't ignore partial failures** — A step that partially executed still needs compensation
- **Don't use a global timeout** — Each step has different latency characteristics

---

## Troubleshooting

### Saga stuck in COMPENSATING state

A saga enters compensation but never reaches FAILED. This means a compensation handler is throwing an unhandled exception and never publishing `SagaCompensationCompleted`. Add dead-letter queue (DLQ) handling to compensation consumers and ensure every compensation action publishes a result event even when the underlying operation was already rolled back.

```python
async def handle_release_reservation(self, command: Dict):
    try:
        await self.release_reservation(command["original_result"]["reservation_id"])
    except ReservationNotFoundError:
        pass  # Already released — treat as success
    # Always publish completion, regardless of outcome
    await self.event_publisher.publish("SagaCompensationCompleted", {
        "saga_id": command["saga_id"],
        "step_name": "reserve_inventory"
    })
```

### Duplicate saga executions on restart

If your orchestrator service restarts mid-saga, it may replay events and re-execute already-completed steps. Guard every step action with an idempotency key — see **Template 3** above.

### Choreography saga losing events

In a choreography-based saga, a downstream service may miss an event if it was offline when published. Use a durable message broker (Kafka with replication, RabbitMQ with persistence) and store the current saga state in a dedicated `saga_log` table so you can replay from the last known good step.

### Timeout firing before a slow-but-valid step completes

A step like `create_shipment` might take up to 15 minutes during peak load but your global timeout is 5 minutes, causing spurious compensation. Make step timeouts configurable per step type — see `references/advanced-patterns.md` for the `TimeoutSagaOrchestrator` implementation and the `STEP_TIMEOUTS` dict pattern.

### Compensation order not matching execution order

When two steps both complete before a failure is detected, compensation must run in strict reverse order or you leave data in an inconsistent state. Verify that `_compensate()` iterates from `current_step - 1` down to `0`, and add an integration test that deliberately fails at each step index to confirm correct rollback order.

---

## Advanced Patterns

The `references/` directory contains production-grade implementations not needed for most sagas:

- **`references/advanced-patterns.md`** — Full `SagaOrchestrator` abstract base class, `TimeoutSagaOrchestrator` with per-step deadlines, detailed bank transfer compensating transaction chain, Prometheus instrumentation, stuck saga PromQL alerts, and DLQ recovery worker.

---

## Related Skills

- `cqrs-implementation` — Pair sagas with CQRS for read-model updates after each step completes
- `event-store-design` — Store saga events in an event store for full audit trail and replay capability
- `workflow-orchestration-patterns` — Higher-level workflow engines (Temporal, Conductor) that build on saga concepts

<!-- chapter:end slug=saga-orchestration -->

---

<!-- chapter:begin slug=temporal-python-testing position=17 -->

## 17. temporal-python-testing

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/temporal-python-testing/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/temporal-python-testing/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/temporal-python-testing.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `resources/integration-testing.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/temporal-python-testing/resources/integration-testing.md
  - `resources/local-setup.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/temporal-python-testing/resources/local-setup.md
  - `resources/replay-testing.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/temporal-python-testing/resources/replay-testing.md
  - `resources/unit-testing.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/temporal-python-testing/resources/unit-testing.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: temporal-python-testing
description: Test Temporal workflows with pytest, time-skipping, and mocking strategies. Covers unit testing, integration testing, replay testing, and local development setup. Use when implementing Temporal workflow tests or debugging test failures.
---

# Temporal Python Testing Strategies

Comprehensive testing approaches for Temporal workflows using pytest, progressive disclosure resources for specific testing scenarios.

## When to Use This Skill

- **Unit testing workflows** - Fast tests with time-skipping
- **Integration testing** - Workflows with mocked activities
- **Replay testing** - Validate determinism against production histories
- **Local development** - Set up Temporal server and pytest
- **CI/CD integration** - Automated testing pipelines
- **Coverage strategies** - Achieve ≥80% test coverage

## Testing Philosophy

**Recommended Approach** (Source: docs.temporal.io/develop/python/testing-suite):

- Write majority as integration tests
- Use pytest with async fixtures
- Time-skipping enables fast feedback (month-long workflows → seconds)
- Mock activities to isolate workflow logic
- Validate determinism with replay testing

**Three Test Types**:

1. **Unit**: Workflows with time-skipping, activities with ActivityEnvironment
2. **Integration**: Workers with mocked activities
3. **End-to-end**: Full Temporal server with real activities (use sparingly)

## Available Resources

This skill provides detailed guidance through progressive disclosure. Load specific resources based on your testing needs:

### Unit Testing Resources

**File**: `resources/unit-testing.md`
**When to load**: Testing individual workflows or activities in isolation
**Contains**:

- WorkflowEnvironment with time-skipping
- ActivityEnvironment for activity testing
- Fast execution of long-running workflows
- Manual time advancement patterns
- pytest fixtures and patterns

### Integration Testing Resources

**File**: `resources/integration-testing.md`
**When to load**: Testing workflows with mocked external dependencies
**Contains**:

- Activity mocking strategies
- Error injection patterns
- Multi-activity workflow testing
- Signal and query testing
- Coverage strategies

### Replay Testing Resources

**File**: `resources/replay-testing.md`
**When to load**: Validating determinism or deploying workflow changes
**Contains**:

- Determinism validation
- Production history replay
- CI/CD integration patterns
- Version compatibility testing

### Local Development Resources

**File**: `resources/local-setup.md`
**When to load**: Setting up development environment
**Contains**:

- Docker Compose configuration
- pytest setup and configuration
- Coverage tool integration
- Development workflow

## Quick Start Guide

### Basic Workflow Test

```python
import pytest
from temporalio.testing import WorkflowEnvironment
from temporalio.worker import Worker

@pytest.fixture
async def workflow_env():
    env = await WorkflowEnvironment.start_time_skipping()
    yield env
    await env.shutdown()

@pytest.mark.asyncio
async def test_workflow(workflow_env):
    async with Worker(
        workflow_env.client,
        task_queue="test-queue",
        workflows=[YourWorkflow],
        activities=[your_activity],
    ):
        result = await workflow_env.client.execute_workflow(
            YourWorkflow.run,
            args,
            id="test-wf-id",
            task_queue="test-queue",
        )
        assert result == expected
```

### Basic Activity Test

```python
from temporalio.testing import ActivityEnvironment

async def test_activity():
    env = ActivityEnvironment()
    result = await env.run(your_activity, "test-input")
    assert result == expected_output
```

## Coverage Targets

**Recommended Coverage** (Source: docs.temporal.io best practices):

- **Workflows**: ≥80% logic coverage
- **Activities**: ≥80% logic coverage
- **Integration**: Critical paths with mocked activities
- **Replay**: All workflow versions before deployment

## Key Testing Principles

1. **Time-Skipping** - Month-long workflows test in seconds
2. **Mock Activities** - Isolate workflow logic from external dependencies
3. **Replay Testing** - Validate determinism before deployment
4. **High Coverage** - ≥80% target for production workflows
5. **Fast Feedback** - Unit tests run in milliseconds

## How to Use Resources

**Load specific resource when needed**:

- "Show me unit testing patterns" → Load `resources/unit-testing.md`
- "How do I mock activities?" → Load `resources/integration-testing.md`
- "Setup local Temporal server" → Load `resources/local-setup.md`
- "Validate determinism" → Load `resources/replay-testing.md`

## Additional References

- Python SDK Testing: docs.temporal.io/develop/python/testing-suite
- Testing Patterns: github.com/temporalio/temporal/blob/main/docs/development/testing.md
- Python Samples: github.com/temporalio/samples-python

<!-- chapter:end slug=temporal-python-testing -->

---

<!-- chapter:begin slug=workflow-orchestration-patterns position=18 -->

## 18. workflow-orchestration-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/backend-development/skills/workflow-orchestration-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/workflow-orchestration-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/workflow-orchestration-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/backend-development/skills/workflow-orchestration-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: workflow-orchestration-patterns
description: Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
---

# Workflow Orchestration Patterns

Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems.

## When to Use Workflow Orchestration

### Ideal Use Cases (Source: docs.temporal.io)

- **Multi-step processes** spanning machines/services/databases
- **Distributed transactions** requiring all-or-nothing semantics
- **Long-running workflows** (hours to years) with automatic state persistence
- **Failure recovery** that must resume from last successful step
- **Business processes**: bookings, orders, campaigns, approvals
- **Entity lifecycle management**: inventory tracking, account management, cart workflows
- **Infrastructure automation**: CI/CD pipelines, provisioning, deployments
- **Human-in-the-loop** systems requiring timeouts and escalations

### When NOT to Use

- Simple CRUD operations (use direct API calls)
- Pure data processing pipelines (use Airflow, batch processing)
- Stateless request/response (use standard APIs)
- Real-time streaming (use Kafka, event processors)

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Workflow Design

1. **Keep workflows focused** - Single responsibility per workflow
2. **Small workflows** - Use child workflows for scalability
3. **Clear boundaries** - Workflow orchestrates, activities execute
4. **Test locally** - Use time-skipping test environment

### Activity Design

1. **Idempotent operations** - Safe to retry
2. **Short-lived** - Seconds to minutes, not hours
3. **Timeout configuration** - Always set timeouts
4. **Heartbeat for long tasks** - Report progress
5. **Error handling** - Distinguish retryable vs non-retryable

### Common Pitfalls

**Workflow Violations**:

- Using `datetime.now()` instead of `workflow.now()`
- Threading or async operations in workflow code
- Calling external APIs directly from workflow
- Non-deterministic logic in workflows

**Activity Mistakes**:

- Non-idempotent operations (can't handle retries)
- Missing timeouts (activities run forever)
- No error classification (retry validation errors)
- Ignoring payload limits (2MB per argument)

### Operational Considerations

**Monitoring**:

- Workflow execution duration
- Activity failure rates
- Retry attempts and backoff
- Pending workflow counts

**Scalability**:

- Horizontal scaling with workers
- Task queue partitioning
- Child workflow decomposition
- Activity batching when appropriate

## Additional Resources

**Official Documentation**:

- Temporal Core Concepts: docs.temporal.io/workflows
- Workflow Patterns: docs.temporal.io/evaluate/use-cases-design-patterns
- Best Practices: docs.temporal.io/develop/best-practices
- Saga Pattern: temporal.io/blog/saga-pattern-made-easy

**Key Principles**:

1. Workflows = orchestration, Activities = external calls
2. Determinism is non-negotiable for workflows
3. Idempotency is critical for activities
4. State preservation is automatic
5. Design for failure and recovery

<!-- chapter:end slug=workflow-orchestration-patterns -->

---

## Part: Before You Build

---

<!-- chapter:begin slug=before-you-build position=19 -->

## 19. before-you-build

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/before-you-build/skills/before-you-build/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/before-you-build/skills/before-you-build/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/before-you-build.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/risk-checklist.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/before-you-build/skills/before-you-build/references/risk-checklist.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: before-you-build
description: Pre-build product and feature risk review for founders, product managers, and AI-assisted builders. Use this skill when the user is about to build a landing page, MVP, SaaS product, internal tool, agent workflow, or major feature and needs to check demand, positioning, monetization, retention, trust, distribution, and adoption risk before implementation starts.
---

# Before You Build

Run a compact pre-mortem before implementation. The goal is not to block building; it is to identify the highest-risk assumption, the smallest validation step, and the build scope that should be delayed until evidence improves.

## When To Use

Use this skill when a user asks to build or ship:

- A new product, MVP, prototype, landing page, SaaS app, marketplace, content site, agent workflow, or internal tool
- A major feature with unclear adoption, revenue, retention, trust, or distribution impact
- A public launch asset where weak positioning could waste development or promotion effort

Skip this skill when the task is a narrow implementation fix, refactor, test repair, dependency update, or already-validated change with clear acceptance criteria.

## Risk Checklist

Review the idea across these risks:

- **Demand:** Is there evidence that a specific buyer or user urgently wants this?
- **Positioning:** Can the target user understand what it is and why it matters in one sentence?
- **Monetization:** Is there a credible path to payment, budget, or strategic value?
- **Retention:** Is there a reason users would return after the first try?
- **Trust:** Does the product require credibility, data access, integrations, or behavior change that users may resist?
- **Distribution:** Is there a repeatable way to reach the target user?
- **Feature adoption:** For feature work, will the feature change user behavior or just add surface area?

If the verdict is not obvious, use `references/risk-checklist.md` for deeper questions.

## Output Format

Keep the response short and decision-oriented:

1. **Risk verdict:** Low, medium, or high risk, with one sentence explaining why.
2. **Main assumption:** The single assumption most likely to break the project.
3. **Evidence to find first:** The smallest useful signal before building more.
4. **Do next:** One concrete validation step or reduced build scope.
5. **Delay:** What not to build yet.

## Guidance

- Be direct about weak evidence, but avoid dismissing the user's idea.
- Prefer smaller validation steps over large research plans.
- Separate product risk from engineering difficulty.
- If the idea is already validated, say what evidence makes it lower risk and suggest the smallest implementation slice.
- If facts are missing, name the missing evidence instead of inventing market claims.

<!-- chapter:end slug=before-you-build -->

---

## Part: Block No Verify

---

<!-- chapter:begin slug=block-no-verify-hook position=20 -->

## 20. block-no-verify-hook

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/block-no-verify/skills/block-no-verify-hook/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/block-no-verify/skills/block-no-verify-hook/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/block-no-verify-hook.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: block-no-verify-hook
description: Configure a PreToolUse hook to prevent AI agents from skipping git pre-commit hooks with --no-verify and other bypass flags. Use when setting up Claude Code projects that enforce commit quality gates.
---

# Block No-Verify Hook

PreToolUse hook configuration that intercepts and blocks bypass-flag usage before execution, ensuring AI agents cannot skip pre-commit hooks, GPG signing, or other git safety mechanisms.

## Overview

AI coding agents (Claude Code, Codex, etc.) can run shell commands with flags like `--no-verify` that bypass pre-commit hooks. This defeats the purpose of linting, formatting, testing, and security checks configured in pre-commit hooks. The block-no-verify hook adds a PreToolUse guard that rejects any tool call containing bypass flags before execution.

## Problem

When AI agents commit code, they may use bypass flags to avoid hook failures:

```bash
# These commands skip pre-commit hooks entirely
git commit --no-verify -m "quick fix"
git push --no-verify
git commit --no-gpg-sign -m "unsigned commit"
git merge --no-verify feature-branch
```

This allows:
- Unformatted code to enter the repository
- Linting errors to bypass checks
- Security scanning to be skipped
- Unsigned commits to bypass signing policies
- Test suites to be circumvented

## Solution

Add a `PreToolUse` hook to `.claude/settings.json` that inspects every Bash tool call and blocks commands containing bypass flags.

### Configuration

Add the following to your project's `.claude/settings.json`:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
```

### How It Works

1. **Matcher**: The hook targets only `Bash` tool calls, so it does not interfere with other tools (Read, Edit, Grep, etc.).
2. **Inspection**: The `$TOOL_INPUT` environment variable contains the full command the agent is about to execute. The hook uses `printf` to safely pass input (avoiding `echo` pitfalls with special characters) and checks for `--no-verify` or `--no-gpg-sign` flags only when preceded by a `git` command.
3. **Blocking**: If a bypass flag is found in a git command, the hook exits with code 2 and prints an error message. Exit code 2 signals Claude Code to reject the tool call entirely.
4. **Pass-through**: If no bypass flag is found, the hook exits with code 0 and the command executes normally.

### Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Allow the tool call to proceed |
| 1 | Error (tool call still proceeds, warning shown) |
| 2 | Block the tool call entirely |

## Blocked Flags

| Flag | Purpose | Why Blocked |
|------|---------|-------------|
| `--no-verify` | Skips pre-commit and commit-msg hooks | Bypasses linting, formatting, testing, security checks |
| `--no-gpg-sign` | Skips GPG commit signing | Bypasses commit signing policy |

## Installation

### Per-Project Setup

Create or update `.claude/settings.json` in your project root:

```bash
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
EOF
```

### Global Setup

To enforce across all projects, add to `~/.claude/settings.json`:

```bash
mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
EOF
```

## Verification

Test that the hook blocks bypass flags:

```bash
# This should be blocked by the hook:
git commit --no-verify -m "test"

# This should succeed normally:
git commit -m "test"
```

## Extending the Hook

### Adding More Blocked Flags

To block additional flags (e.g., `--force`), extend the grep pattern:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign|force-with-lease|force)'; then echo 'BLOCKED: Bypass flags are not allowed.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
```

### Combining with Other Hooks

The block-no-verify hook works alongside other PreToolUse hooks:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE '(^|&&|;|\\|)\\s*git\\s+.*--(no-verify|no-gpg-sign)'; then echo 'BLOCKED: Bypass flags not allowed.' >&2; exit 2; fi"
        }
      },
      {
        "matcher": "Bash",
        "hook": {
          "type": "command",
          "command": "if printf '%s' \"$TOOL_INPUT\" | grep -qE 'rm\\s+-rf\\s+/'; then echo 'BLOCKED: Dangerous rm command.' >&2; exit 2; fi"
        }
      }
    ]
  }
}
```

## Best Practices

1. **Commit the settings file** -- Add `.claude/settings.json` to version control so all team members benefit from the hook.
2. **Document in onboarding** -- Mention the hook in your project's contributing guide so developers understand why bypass flags are blocked.
3. **Pair with pre-commit hooks** -- The block-no-verify hook ensures pre-commit hooks run; make sure you have meaningful pre-commit hooks configured.
4. **Test after setup** -- Verify the hook works by intentionally triggering it in a test commit.

<!-- chapter:end slug=block-no-verify-hook -->

---

## Part: Blockchain Web3

---

<!-- chapter:begin slug=defi-protocol-templates position=21 -->

## 21. defi-protocol-templates

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/blockchain-web3/skills/defi-protocol-templates/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/defi-protocol-templates/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/defi-protocol-templates.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/defi-protocol-templates/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: defi-protocol-templates
description: Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and flash loans. Use when building decentralized finance applications or smart contract protocols.
---

# DeFi Protocol Templates

Production-ready templates for common DeFi protocols including staking, AMMs, governance, and flash loans.

## When to Use This Skill

- Building staking platforms with reward distribution
- Implementing AMM (Automated Market Maker) protocols
- Creating governance token systems
- Integrating flash loan functionality

## Staking Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract StakingRewards is ReentrancyGuard, Ownable {
    IERC20 public stakingToken;
    IERC20 public rewardsToken;

    uint256 public rewardRate = 100; // Rewards per second
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;

    mapping(address => uint256) public userRewardPerTokenPaid;
    mapping(address => uint256) public rewards;
    mapping(address => uint256) public balances;

    uint256 private _totalSupply;

    event Staked(address indexed user, uint256 amount);
    event Withdrawn(address indexed user, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);

    constructor(address _stakingToken, address _rewardsToken) {
        stakingToken = IERC20(_stakingToken);
        rewardsToken = IERC20(_rewardsToken);
    }

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        lastUpdateTime = block.timestamp;

        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

    function rewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return rewardPerTokenStored;
        }
        return rewardPerTokenStored +
            ((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply;
    }

    function earned(address account) public view returns (uint256) {
        return (balances[account] *
            (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18 +
            rewards[account];
    }

    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply += amount;
        balances[msg.sender] += amount;
        stakingToken.transferFrom(msg.sender, address(this), amount);
        emit Staked(msg.sender, amount);
    }

    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply -= amount;
        balances[msg.sender] -= amount;
        stakingToken.transfer(msg.sender, amount);
        emit Withdrawn(msg.sender, amount);
    }

    function getReward() public nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardsToken.transfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }

    function exit() external {
        withdraw(balances[msg.sender]);
        getReward();
    }
}
```

## AMM (Automated Market Maker)

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SimpleAMM {
    IERC20 public token0;
    IERC20 public token1;

    uint256 public reserve0;
    uint256 public reserve1;

    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;

    event Mint(address indexed to, uint256 amount);
    event Burn(address indexed from, uint256 amount);
    event Swap(address indexed trader, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out);

    constructor(address _token0, address _token1) {
        token0 = IERC20(_token0);
        token1 = IERC20(_token1);
    }

    function addLiquidity(uint256 amount0, uint256 amount1) external returns (uint256 shares) {
        token0.transferFrom(msg.sender, address(this), amount0);
        token1.transferFrom(msg.sender, address(this), amount1);

        if (totalSupply == 0) {
            shares = sqrt(amount0 * amount1);
        } else {
            shares = min(
                (amount0 * totalSupply) / reserve0,
                (amount1 * totalSupply) / reserve1
            );
        }

        require(shares > 0, "Shares = 0");
        _mint(msg.sender, shares);
        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Mint(msg.sender, shares);
    }

    function removeLiquidity(uint256 shares) external returns (uint256 amount0, uint256 amount1) {
        uint256 bal0 = token0.balanceOf(address(this));
        uint256 bal1 = token1.balanceOf(address(this));

        amount0 = (shares * bal0) / totalSupply;
        amount1 = (shares * bal1) / totalSupply;

        require(amount0 > 0 && amount1 > 0, "Amount0 or amount1 = 0");

        _burn(msg.sender, shares);
        _update(bal0 - amount0, bal1 - amount1);

        token0.transfer(msg.sender, amount0);
        token1.transfer(msg.sender, amount1);

        emit Burn(msg.sender, shares);
    }

    function swap(address tokenIn, uint256 amountIn) external returns (uint256 amountOut) {
        require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");

        bool isToken0 = tokenIn == address(token0);
        (IERC20 tokenIn_, IERC20 tokenOut, uint256 resIn, uint256 resOut) = isToken0
            ? (token0, token1, reserve0, reserve1)
            : (token1, token0, reserve1, reserve0);

        tokenIn_.transferFrom(msg.sender, address(this), amountIn);

        // 0.3% fee
        uint256 amountInWithFee = (amountIn * 997) / 1000;
        amountOut = (resOut * amountInWithFee) / (resIn + amountInWithFee);

        tokenOut.transfer(msg.sender, amountOut);

        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Swap(msg.sender, isToken0 ? amountIn : 0, isToken0 ? 0 : amountIn, isToken0 ? 0 : amountOut, isToken0 ? amountOut : 0);
    }

    function _mint(address to, uint256 amount) private {
        balanceOf[to] += amount;
        totalSupply += amount;
    }

    function _burn(address from, uint256 amount) private {
        balanceOf[from] -= amount;
        totalSupply -= amount;
    }

    function _update(uint256 res0, uint256 res1) private {
        reserve0 = res0;
        reserve1 = res1;
    }

    function sqrt(uint256 y) private pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    function min(uint256 x, uint256 y) private pure returns (uint256) {
        return x <= y ? x : y;
    }
}
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=defi-protocol-templates -->

---

<!-- chapter:begin slug=nft-standards position=22 -->

## 22. nft-standards

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/blockchain-web3/skills/nft-standards/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/nft-standards/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/nft-standards.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/nft-standards/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: nft-standards
description: Implement NFT standards (ERC-721, ERC-1155) with proper metadata handling, minting strategies, and marketplace integration. Use when creating NFT contracts, building NFT marketplaces, or implementing digital asset systems.
---

# NFT Standards

Master ERC-721 and ERC-1155 NFT standards, metadata best practices, and advanced NFT features.

## When to Use This Skill

- Creating NFT collections (art, gaming, collectibles)
- Implementing marketplace functionality
- Building on-chain or off-chain metadata
- Creating soulbound tokens (non-transferable)
- Implementing royalties and revenue sharing
- Developing dynamic/evolving NFTs

## ERC-721 (Non-Fungible Token Standard)

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract MyNFT is ERC721URIStorage, ERC721Enumerable, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    uint256 public constant MAX_SUPPLY = 10000;
    uint256 public constant MINT_PRICE = 0.08 ether;
    uint256 public constant MAX_PER_MINT = 20;

    constructor() ERC721("MyNFT", "MNFT") {}

    function mint(uint256 quantity) external payable {
        require(quantity > 0 && quantity <= MAX_PER_MINT, "Invalid quantity");
        require(_tokenIds.current() + quantity <= MAX_SUPPLY, "Exceeds max supply");
        require(msg.value >= MINT_PRICE * quantity, "Insufficient payment");

        for (uint256 i = 0; i < quantity; i++) {
            _tokenIds.increment();
            uint256 newTokenId = _tokenIds.current();
            _safeMint(msg.sender, newTokenId);
            _setTokenURI(newTokenId, generateTokenURI(newTokenId));
        }
    }

    function generateTokenURI(uint256 tokenId) internal pure returns (string memory) {
        // Return IPFS URI or on-chain metadata
        return string(abi.encodePacked("ipfs://QmHash/", Strings.toString(tokenId), ".json"));
    }

    // Required overrides
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId,
        uint256 batchSize
    ) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
    }

    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    function withdraw() external onlyOwner {
        payable(owner()).transfer(address(this).balance);
    }
}
```

## ERC-1155 (Multi-Token Standard)

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract GameItems is ERC1155, Ownable {
    uint256 public constant SWORD = 1;
    uint256 public constant SHIELD = 2;
    uint256 public constant POTION = 3;

    mapping(uint256 => uint256) public tokenSupply;
    mapping(uint256 => uint256) public maxSupply;

    constructor() ERC1155("ipfs://QmBaseHash/{id}.json") {
        maxSupply[SWORD] = 1000;
        maxSupply[SHIELD] = 500;
        maxSupply[POTION] = 10000;
    }

    function mint(
        address to,
        uint256 id,
        uint256 amount
    ) external onlyOwner {
        require(tokenSupply[id] + amount <= maxSupply[id], "Exceeds max supply");

        _mint(to, id, amount, "");
        tokenSupply[id] += amount;
    }

    function mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts
    ) external onlyOwner {
        for (uint256 i = 0; i < ids.length; i++) {
            require(tokenSupply[ids[i]] + amounts[i] <= maxSupply[ids[i]], "Exceeds max supply");
            tokenSupply[ids[i]] += amounts[i];
        }

        _mintBatch(to, ids, amounts, "");
    }

    function burn(
        address from,
        uint256 id,
        uint256 amount
    ) external {
        require(from == msg.sender || isApprovedForAll(from, msg.sender), "Not authorized");
        _burn(from, id, amount);
        tokenSupply[id] -= amount;
    }
}
```

## Metadata Standards

### Off-Chain Metadata (IPFS)

```json
{
  "name": "NFT #1",
  "description": "Description of the NFT",
  "image": "ipfs://QmImageHash",
  "attributes": [
    {
      "trait_type": "Background",
      "value": "Blue"
    },
    {
      "trait_type": "Rarity",
      "value": "Legendary"
    },
    {
      "trait_type": "Power",
      "value": 95,
      "display_type": "number",
      "max_value": 100
    }
  ]
}
```

### On-Chain Metadata

```solidity
contract OnChainNFT is ERC721 {
    struct Traits {
        uint8 background;
        uint8 body;
        uint8 head;
        uint8 rarity;
    }

    mapping(uint256 => Traits) public tokenTraits;

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        Traits memory traits = tokenTraits[tokenId];

        string memory json = Base64.encode(
            bytes(
                string(
                    abi.encodePacked(
                        '{"name": "NFT #', Strings.toString(tokenId), '",',
                        '"description": "On-chain NFT",',
                        '"image": "data:image/svg+xml;base64,', generateSVG(traits), '",',
                        '"attributes": [',
                        '{"trait_type": "Background", "value": "', Strings.toString(traits.background), '"},',
                        '{"trait_type": "Rarity", "value": "', getRarityName(traits.rarity), '"}',
                        ']}'
                    )
                )
            )
        );

        return string(abi.encodePacked("data:application/json;base64,", json));
    }

    function generateSVG(Traits memory traits) internal pure returns (string memory) {
        // Generate SVG based on traits
        return "...";
    }
}
```

## Royalties (EIP-2981)

```solidity
import "@openzeppelin/contracts/interfaces/IERC2981.sol";

contract NFTWithRoyalties is ERC721, IERC2981 {
    address public royaltyRecipient;
    uint96 public royaltyFee = 500; // 5%

    constructor() ERC721("Royalty NFT", "RNFT") {
        royaltyRecipient = msg.sender;
    }

    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        return (royaltyRecipient, (salePrice * royaltyFee) / 10000);
    }

    function setRoyalty(address recipient, uint96 fee) external onlyOwner {
        require(fee <= 1000, "Royalty fee too high"); // Max 10%
        royaltyRecipient = recipient;
        royaltyFee = fee;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, IERC165)
        returns (bool)
    {
        return interfaceId == type(IERC2981).interfaceId ||
               super.supportsInterface(interfaceId);
    }
}
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=nft-standards -->

---

<!-- chapter:begin slug=solidity-security position=23 -->

## 23. solidity-security

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/blockchain-web3/skills/solidity-security/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/solidity-security/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/solidity-security.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/solidity-security/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: solidity-security
description: Master smart contract security best practices to prevent common vulnerabilities and implement secure Solidity patterns. Use when writing smart contracts, auditing existing contracts, or implementing security measures for blockchain applications.
---

# Solidity Security

Master smart contract security best practices, vulnerability prevention, and secure Solidity development patterns.

## When to Use This Skill

- Writing secure smart contracts
- Auditing existing contracts for vulnerabilities
- Implementing secure DeFi protocols
- Preventing reentrancy, overflow, and access control issues
- Optimizing gas usage while maintaining security
- Preparing contracts for professional audits
- Understanding common attack vectors

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing for Security

```javascript
// Hardhat test example
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Security Tests", function () {
  it("Should prevent reentrancy attack", async function () {
    const [attacker] = await ethers.getSigners();

    const VictimBank = await ethers.getContractFactory("SecureBank");
    const bank = await VictimBank.deploy();

    const Attacker = await ethers.getContractFactory("ReentrancyAttacker");
    const attackerContract = await Attacker.deploy(bank.address);

    // Deposit funds
    await bank.deposit({ value: ethers.utils.parseEther("10") });

    // Attempt reentrancy attack
    await expect(
      attackerContract.attack({ value: ethers.utils.parseEther("1") }),
    ).to.be.revertedWith("ReentrancyGuard: reentrant call");
  });

  it("Should prevent integer overflow", async function () {
    const Token = await ethers.getContractFactory("SecureToken");
    const token = await Token.deploy();

    // Attempt overflow
    await expect(token.transfer(attacker.address, ethers.constants.MaxUint256))
      .to.be.reverted;
  });

  it("Should enforce access control", async function () {
    const [owner, attacker] = await ethers.getSigners();

    const Contract = await ethers.getContractFactory("SecureContract");
    const contract = await Contract.deploy();

    // Attempt unauthorized withdrawal
    await expect(contract.connect(attacker).withdraw(100)).to.be.revertedWith(
      "Ownable: caller is not the owner",
    );
  });
});
```

## Audit Preparation

```solidity
contract WellDocumentedContract {
    /**
     * @title Well Documented Contract
     * @dev Example of proper documentation for audits
     * @notice This contract handles user deposits and withdrawals
     */

    /// @notice Mapping of user balances
    mapping(address => uint256) public balances;

    /**
     * @dev Deposits ETH into the contract
     * @notice Anyone can deposit funds
     */
    function deposit() public payable {
        require(msg.value > 0, "Must send ETH");
        balances[msg.sender] += msg.value;
    }

    /**
     * @dev Withdraws user's balance
     * @notice Follows CEI pattern to prevent reentrancy
     * @param amount Amount to withdraw in wei
     */
    function withdraw(uint256 amount) public {
        // CHECKS
        require(amount <= balances[msg.sender], "Insufficient balance");

        // EFFECTS
        balances[msg.sender] -= amount;

        // INTERACTIONS
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
    }
}
```

<!-- chapter:end slug=solidity-security -->

---

<!-- chapter:begin slug=web3-testing position=24 -->

## 24. web3-testing

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/blockchain-web3/skills/web3-testing/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/web3-testing/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/web3-testing.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/blockchain-web3/skills/web3-testing/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: web3-testing
description: Test smart contracts comprehensively using Hardhat and Foundry with unit tests, integration tests, and mainnet forking. Use when testing Solidity contracts, setting up blockchain test suites, or validating DeFi protocols.
---

# Web3 Smart Contract Testing

Master comprehensive testing strategies for smart contracts using Hardhat, Foundry, and advanced testing patterns.

## When to Use This Skill

- Writing unit tests for smart contracts
- Setting up integration test suites
- Performing gas optimization testing
- Fuzzing for edge cases
- Forking mainnet for realistic testing
- Automating test coverage reporting
- Verifying contracts on Etherscan

## Hardhat Testing Setup

```javascript
// hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
require("@nomiclabs/hardhat-etherscan");
require("hardhat-gas-reporter");
require("solidity-coverage");

module.exports = {
  solidity: {
    version: "0.8.19",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200,
      },
    },
  },
  networks: {
    hardhat: {
      forking: {
        url: process.env.MAINNET_RPC_URL,
        blockNumber: 15000000,
      },
    },
    goerli: {
      url: process.env.GOERLI_RPC_URL,
      accounts: [process.env.PRIVATE_KEY],
    },
  },
  gasReporter: {
    enabled: true,
    currency: "USD",
    coinmarketcap: process.env.COINMARKETCAP_API_KEY,
  },
  etherscan: {
    apiKey: process.env.ETHERSCAN_API_KEY,
  },
};
```

## Unit Testing Patterns

```javascript
const { expect } = require("chai");
const { ethers } = require("hardhat");
const {
  loadFixture,
  time,
} = require("@nomicfoundation/hardhat-network-helpers");

describe("Token Contract", function () {
  // Fixture for test setup
  async function deployTokenFixture() {
    const [owner, addr1, addr2] = await ethers.getSigners();

    const Token = await ethers.getContractFactory("Token");
    const token = await Token.deploy();

    return { token, owner, addr1, addr2 };
  }

  describe("Deployment", function () {
    it("Should set the right owner", async function () {
      const { token, owner } = await loadFixture(deployTokenFixture);
      expect(await token.owner()).to.equal(owner.address);
    });

    it("Should assign total supply to owner", async function () {
      const { token, owner } = await loadFixture(deployTokenFixture);
      const ownerBalance = await token.balanceOf(owner.address);
      expect(await token.totalSupply()).to.equal(ownerBalance);
    });
  });

  describe("Transactions", function () {
    it("Should transfer tokens between accounts", async function () {
      const { token, owner, addr1 } = await loadFixture(deployTokenFixture);

      await expect(token.transfer(addr1.address, 50)).to.changeTokenBalances(
        token,
        [owner, addr1],
        [-50, 50],
      );
    });

    it("Should fail if sender doesn't have enough tokens", async function () {
      const { token, addr1 } = await loadFixture(deployTokenFixture);
      const initialBalance = await token.balanceOf(addr1.address);

      await expect(
        token.connect(addr1).transfer(owner.address, 1),
      ).to.be.revertedWith("Insufficient balance");
    });

    it("Should emit Transfer event", async function () {
      const { token, owner, addr1 } = await loadFixture(deployTokenFixture);

      await expect(token.transfer(addr1.address, 50))
        .to.emit(token, "Transfer")
        .withArgs(owner.address, addr1.address, 50);
    });
  });

  describe("Time-based tests", function () {
    it("Should handle time-locked operations", async function () {
      const { token } = await loadFixture(deployTokenFixture);

      // Increase time by 1 day
      await time.increase(86400);

      // Test time-dependent functionality
    });
  });

  describe("Gas optimization", function () {
    it("Should use gas efficiently", async function () {
      const { token } = await loadFixture(deployTokenFixture);

      const tx = await token.transfer(addr1.address, 100);
      const receipt = await tx.wait();

      expect(receipt.gasUsed).to.be.lessThan(50000);
    });
  });
});
```

## Foundry Testing (Forge)

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../src/Token.sol";

contract TokenTest is Test {
    Token token;
    address owner = address(1);
    address user1 = address(2);
    address user2 = address(3);

    function setUp() public {
        vm.prank(owner);
        token = new Token();
    }

    function testInitialSupply() public {
        assertEq(token.totalSupply(), 1000000 * 10**18);
    }

    function testTransfer() public {
        vm.prank(owner);
        token.transfer(user1, 100);

        assertEq(token.balanceOf(user1), 100);
        assertEq(token.balanceOf(owner), token.totalSupply() - 100);
    }

    function testFailTransferInsufficientBalance() public {
        vm.prank(user1);
        token.transfer(user2, 100); // Should fail
    }

    function testCannotTransferToZeroAddress() public {
        vm.prank(owner);
        vm.expectRevert("Invalid recipient");
        token.transfer(address(0), 100);
    }

    // Fuzzing test
    function testFuzzTransfer(uint256 amount) public {
        vm.assume(amount > 0 && amount <= token.totalSupply());

        vm.prank(owner);
        token.transfer(user1, amount);

        assertEq(token.balanceOf(user1), amount);
    }

    // Test with cheatcodes
    function testDealAndPrank() public {
        // Give ETH to address
        vm.deal(user1, 10 ether);

        // Impersonate address
        vm.prank(user1);

        // Test functionality
        assertEq(user1.balance, 10 ether);
    }

    // Mainnet fork test
    function testForkMainnet() public {
        vm.createSelectFork("https://eth-mainnet.alchemyapi.io/v2/...");

        // Interact with mainnet contracts
        address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
        assertEq(IERC20(dai).symbol(), "DAI");
    }
}
```

## Advanced Testing Patterns

### Snapshot and Revert

```javascript
describe("Complex State Changes", function () {
  let snapshotId;

  beforeEach(async function () {
    snapshotId = await network.provider.send("evm_snapshot");
  });

  afterEach(async function () {
    await network.provider.send("evm_revert", [snapshotId]);
  });

  it("Test 1", async function () {
    // Make state changes
  });

  it("Test 2", async function () {
    // State reverted, clean slate
  });
});
```

### Mainnet Forking

```javascript
describe("Mainnet Fork Tests", function () {
  let uniswapRouter, dai, usdc;

  before(async function () {
    await network.provider.request({
      method: "hardhat_reset",
      params: [
        {
          forking: {
            jsonRpcUrl: process.env.MAINNET_RPC_URL,
            blockNumber: 15000000,
          },
        },
      ],
    });

    // Connect to existing mainnet contracts
    uniswapRouter = await ethers.getContractAt(
      "IUniswapV2Router",
      "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
    );

    dai = await ethers.getContractAt(
      "IERC20",
      "0x6B175474E89094C44Da98b954EedeAC495271d0F",
    );
  });

  it("Should swap on Uniswap", async function () {
    // Test with real Uniswap contracts
  });
});
```

### Impersonating Accounts

```javascript
it("Should impersonate whale account", async function () {
  const whaleAddress = "0x...";

  await network.provider.request({
    method: "hardhat_impersonateAccount",
    params: [whaleAddress],
  });

  const whale = await ethers.getSigner(whaleAddress);

  // Use whale's tokens
  await dai
    .connect(whale)
    .transfer(addr1.address, ethers.utils.parseEther("1000"));
});
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=web3-testing -->

---

## Part: Brand Landingpage

---

<!-- chapter:begin slug=brand-landingpage position=25 -->

## 25. brand-landingpage

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/brand-landingpage/skills/brand-landingpage/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/brand-landingpage/skills/brand-landingpage/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/brand-landingpage.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (3), referenced from this skill's directory:
  - `references/interview-framework.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/brand-landingpage/skills/brand-landingpage/references/interview-framework.md
  - `references/state-and-pitfalls.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/brand-landingpage/skills/brand-landingpage/references/state-and-pitfalls.md
  - `references/stitch-architecture.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/brand-landingpage/skills/brand-landingpage/references/stitch-architecture.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: brand-landingpage
description: >
  Brand-first landing page designer — runs a brand-identity interview (colors,
  typography, shape language), then generates and iterates on a polished landing
  page via Stitch with deployment-ready HTML. Use when the user asks to create,
  design, or build a landing page, homepage, or marketing page and has no
  established visual direction. Skip when they have a design mockup, need a
  dashboard or app UI, are working at component level, building a multi-page
  app, or restyling with known design tokens — use frontend-design instead.
---

# Brand Landing Page Designer

You are a design consultant embedded in a developer's workflow. Your user has built a product, side project, or service and needs a landing page -- but hasn't thought much about brand identity, visual direction, or how to communicate their product to non-technical visitors. You guide them through a focused brand interview, translate their answers into design decisions, generate screens via Stitch, lead iterative refinement through structured design feedback, and deliver a deployment-ready bundle.

Scope: single-purpose landing pages and product marketing sites. Not full multi-page applications, not dashboards, not documentation sites.

Tone: technically direct -- the user understands APIs, environment variables, and HTML. Design and brand concepts are what need translating. Don't hide the toolchain; do explain why visual hierarchy matters.

---

## Phase 0: Prerequisites & Stitch Connection

Stitch enables the visual generation and iteration loop — generating designs, previewing them in the browser, and refining based on feedback. The interactive design workflow is what makes this skill effective.

### Getting Stitch Ready

Finish Phase 0 before starting Phase 1. The interview has little use without a working Stitch connection to generate against.

1. Consult the SDK documentation to verify the SDK is installed and is at its latest version. The Stitch SDK is still new and evolving, so consider the Stitch SDK documentation as the ground truth.
2. If the SDK is missing, install it (global install by default, project's package manager if clearly inside a project).
3. Verify the API key env var (as named in the docs) is set. If the key is missing, have the user generate one at their Stitch dashboard and export it in their shell or `.env`.
4. Make one minimal SDK call to confirm auth. Diagnose and retry once on failure before involving the user.

Aim to get the user to the interview without bothering them with installation technicalities — the Stitch Documentation section has the setup details, so handle them yourself. Never display, transcribe, or echo the key.

### SDK Usage Notes

- **Discover MCP tool names through the agent runtime.** If Stitch MCP tools are available, use the agent runtime's tool-listing mechanism (e.g., `list_tools`) to capture exact tool names. Names may be prefixed (e.g., `stitch_create_project`, `mcp__stitch__create_project`). Use the discovered names for later tool calls — don't assume the unprefixed names in this document.
- **Prefer the SDK's own response data over memory.** When an SDK call returns structured data (return types, enum values), use the returned values directly rather than guessing at shapes from training knowledge.
- **Fail fast, recover quietly.** If an SDK call fails with a shape mismatch, fix the call based on the SDK's error message and retry once before surfacing the error to the user.

---

## Reference Files

Read these files at the indicated moments. Do not re-read them on every iteration.

| File | When to read | Contains |
|------|-------------|----------|
| `references/interview-framework.md` | Before starting the interview (Phase 1) | Full question bank, follow-up triggers, feedback facilitation guide |
| `references/stitch-architecture.md` | Before creating the design system (Phase 2) | Font mappings, color variant guide, prompt templates, section taxonomy |
| `references/state-and-pitfalls.md` | At project start and before delivery (Phase 4) | metadata.json schema, state rules, common pitfalls, DEPLOY.md template |

---

## Workflow Overview

```
PHASE 0          PHASE 1          PHASE 2             PHASE 3                    PHASE 4
SETUP     -----> INTERVIEW -----> DESIGN SYSTEM ----> GENERATE & REVIEW LOOP --> DELIVER
Stitch SDK       (3 parts)        (translate &        (generate -> show ->       (bundle
+ env config      A: Product       create in           feedback -> edit/          zip for
+ verify          B: Brand Feel    Stitch)             variant -> repeat)         deployment)
                  C: Visual
```

All project state persists in `.stitch/metadata.json` (see `references/state-and-pitfalls.md` for schema). If this file exists when the skill starts, resume from the saved state instead of re-interviewing.

---

## Phase 1: Brand Interview

Read `references/interview-framework.md` before starting this phase.

### Opening

The user will likely want to skip straight to generation. Resist this gently -- the interview is where most of the value is. Without it, you're generating a generic template.

> "Before I generate anything, I want to ask a few quick questions about your project and how you want it to come across. This takes about 5 minutes and makes the difference between a generic template and a page that actually fits your brand. About 10 questions total."

If `.stitch/metadata.json` exists with status beyond "interview", skip to the appropriate phase, open the last saved HTML in the browser, and resume from there.

### Phase A: Product & Purpose

Ask about: product/project name, what it does, who the target users are, what action visitors should take (sign up, try demo, join waitlist, etc.).

**Transition rule:** Move to Phase B when you have: project name + what it does + target users + desired CTA. These four are non-negotiable.

### Phase B: Brand Feel

Ask about: 3 brand adjectives (provide a menu), a product or site whose landing page they admire (optional), light vs dark preference.

**Transition rule:** Move to Phase C when you have: 3 brand adjectives + light/dark direction.

### Phase C: Visual Preferences

Ask about: existing brand/app colors or color feeling, modern vs traditional font preference, sharp vs rounded shapes.

**Transition rule:** Move to generation when you have: color direction + font direction + shape direction. Confirm the full summary with the user before proceeding.

### Image Handling

Do NOT ask the user to provide images or logos. Stitch does not accept image uploads via API.

IF the user spontaneously attaches an image (logo, app screenshot, design inspiration):

1. Ask the user to describe the image in their own words (dominant colors, overall mood, shape language, typography if relevant) rather than auto-analyzing it yourself.
2. Save the original file to `.stitch/user-assets/` with a descriptive filename for later handoff.
3. Incorporate the user's described attributes into the design system and generation prompts.
4. Tell the user: "I've noted the style you described — I'll reflect it in the design. The original file is saved in the output bundle so you can swap it into the final HTML."

If the user asks why you can't embed their logo directly: "Stitch generates from text prompts, not image inputs. I'll match the style you described, and the original file is in the bundle so you can drop it into the HTML yourself — it's a straightforward `<img>` swap."

---

## Phase 2: Design System Creation

Read `references/stitch-architecture.md` before starting this phase.

### Translation Table

Map interview answers to Stitch design system parameters:

| Interview answer | Design system parameter | Reference |
|-----------------|------------------------|-----------|
| 3 brand adjectives | `colorVariant` enum | Color Variant Decision Tree in `references/stitch-architecture.md` |
| Light / dark preference | `colorMode` (LIGHT or DARK) | Direct mapping |
| Primary color (hex) | `customColor` | Direct mapping |
| Modern / traditional font | `headlineFont` + `bodyFont` | Font Personality Guide in `references/stitch-architecture.md` |
| Sharp / rounded shapes | `roundness` enum | ROUND_FOUR (sharp) through ROUND_FULL (rounded) |

### Steps

1. **Create project:** Call `create_project` with the project/product name as the title.
2. **Build DesignSystem object** from the translation table above.
3. **Create design system:** Call `create_design_system` on the project.
4. **Update design system:** Immediately call `update_design_system`. This step is required -- create alone does not render the system.
5. **Write DESIGN.md:** Create `.stitch/DESIGN.md` documenting the design system in semantic language:
   ```
   # {Project Name} -- Design System
   ## Brand Feel
   {adj1}, {adj2}, {adj3}
   ## Color Direction
   Primary: {color name} ({hex}) -- {why this fits the brand}
   Mode: {Light/Dark}  Variant: {colorVariant}
   ## Typography
   Headlines: {font name} -- Body: {font name}
   ## Shape
   {Roundness description}
   ```
6. **Save state:** Write project ID, design system asset ID, and interview summary to `.stitch/metadata.json`.

---

## Phase 3: Generate & Review Loop

This is the core workflow. The loop runs until the user approves the design.

### First Generation

1. Select sections based on product type (see Section Taxonomy in `references/stitch-architecture.md`).
2. Craft the generation prompt using the template from `references/stitch-architecture.md`.
3. Call `generate_screen_from_text` with `deviceType: DESKTOP`.
4. Generation takes 1-3 minutes. Do NOT retry if it seems slow.
5. Save the HTML output returned by your Stitch SDK call into `.stitch/designs/` using a versioned filename: `desktop-v1.html` for the first generation, `desktop-v2.html` for the next iteration, and so on. Use the same convention for mobile (`mobile-v1.html`, `mobile-v2.html`). Use the SDK's response-handling pattern to retrieve the output — don't perform arbitrary HTTP fetches.
6. **Open the saved HTML file in the user's browser** so they can see the design at full fidelity. Use `open` (macOS), `xdg-open` (Linux), or `start` (Windows, via `cmd /c start`). If none work in the current environment, tell the user the file path.
7. Save the screen ID to `.stitch/metadata.json` under `screens.desktop.current` and append to `screens.desktop.history`.

### Presenting Results

After every generation, edit, or variant selection:

1. Save the updated HTML from the Stitch SDK response and open the local file in the browser.
2. Briefly orient the user: "I've opened the latest version in your browser. Hero section at top with the headline and CTA, then {describe sections}, footer at the bottom."
3. Ask the three feedback questions from `references/interview-framework.md`:
   - "What's your gut reaction in the first 5 seconds?"
   - "Does this feel like YOUR product?"
   - "Is there anything that feels wrong, missing, or not quite right?"

Draw the user's attention to specific design dimensions (see Feedback Facilitation Guide in `references/interview-framework.md`): message clarity, CTA visibility, color alignment with their adjectives, reading flow.

### Feedback Translation

| Feedback pattern | Action | Tool |
|-----------------|--------|------|
| Specific targeted change ("move X", "change the headline to Y") | Direct edit | `edit_screens` |
| General dissatisfaction ("I don't like it", "it's boring") | Explore alternatives | `generate_variants` with EXPLORE (2-3 variants) |
| Partial approval ("love the layout, hate the colors") | Targeted variant | `generate_variants` with specific aspects only |
| Wants to compare ("show me some options") | Broad exploration | `generate_variants` with 3 variants, EXPLORE |
| "Something totally different" | Full rethink | `generate_variants` with REIMAGINE |
| "I liked the earlier version better" | Rollback | Re-fetch from `screens.desktop.history` |
| CSS-level feedback ("needs more padding", "font too small") | Translate to design intent | `edit_screens` with design-level instruction |
| Explicit approval ("looks good", "ship it") | Exit loop | Proceed to mobile question, then Phase 4 |

When the user gives feedback in implementation terms (CSS, pixels, Tailwind classes), acknowledge their intent but translate to design language for Stitch.

### Showing Variants

Save the HTML from each Stitch variant response as `desktop-vN-option-a.html`, `desktop-vN-option-b.html`, `desktop-vN-option-c.html` in `.stitch/designs/` (where `N` is the current iteration number). Open all of them locally so the user can compare in separate tabs. Note one distinguishing feature each. Ask: "Which direction do you prefer? Or should I combine elements from different options?" Once a variant is picked, save the chosen one as the next versioned file (`desktop-vN+1.html`) and continue the loop from there.

### Loop Guardrails

- **Always open the updated HTML** in the browser after any edit or variant selection.
- **Update metadata** after every state change. Never discard previous versions.
- **After 3 rounds** of positive feedback: "This is looking solid. Keep iterating or ship it and refine later?"
- **After 5 rounds**: "What's the single most important change left?"

### Mobile Variant

After desktop approval, offer: "Want me to generate a mobile layout too?" If yes, generate with `deviceType: MOBILE` and run a short review loop (typically 1-2 rounds).

---

## Phase 4: Delivery Bundle

Read `references/state-and-pitfalls.md` for the DEPLOY.md template.

### Bundle Structure

```
{project-name}-landing-page/
  index.html                  # Final desktop HTML
  mobile.html                 # Mobile HTML (if created)
  design/
    DESIGN.md                 # Brand design system documentation
    color-tokens.json         # Design tokens as structured data
  assets/
    {user-provided images}
  DEPLOY.md                   # Deployment checklist
```

### Creation Steps

1. Identify the latest approved versions in `.stitch/designs/` (highest `desktop-vN.html`, and `mobile-vN.html` if mobile was generated). Copy them into the bundle root, renaming desktop to `index.html` and mobile to `mobile.html`. Do not include intermediate versions or variant-comparison files in the bundle.
2. Generate `color-tokens.json` with primary color, colorMode, colorVariant, fonts, roundness.
3. Copy `.stitch/DESIGN.md`.
4. Collect user assets from `.stitch/user-assets/` if any exist.
5. Generate `DEPLOY.md` using the template in `references/state-and-pitfalls.md`.
6. Create the zip: `zip -r "{project-name}-landing-page.zip" "{project-name}-landing-page/"`
7. Tell the user: "Bundle is ready at `{path}`. See `DEPLOY.md` for the deployment checklist."

---

## Stitch Documentation

- Stitch SDK usage and installation documentation: `https://stitch-design.ai/docs/sdk/ai-sdk`
- DESIGN.md documentation and examples: `https://stitch-design.ai/docs/design-md/overview`

---

## Resume & Error Recovery

- **Session interrupted:** Check for `.stitch/metadata.json`. Load state, open the last saved HTML in the browser, and ask where to continue.
- **Generation fails:** Do NOT retry immediately. Use `get_screen` or `list_screens` to check whether it completed asynchronously. If genuinely failed, try once more with a simplified prompt.
- **Rate limiting:** Inform the user: "Stitch rate-limited. Retrying in 30 seconds."
- **Project expired on resume:** "Previous Stitch project expired, but your brand data is saved. Recreating now." Re-run Phase 2 from saved interview data.

<!-- chapter:end slug=brand-landingpage -->

---

## Part: Business Analytics

---

<!-- chapter:begin slug=data-storytelling position=26 -->

## 26. data-storytelling

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/business-analytics/skills/data-storytelling/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/business-analytics/skills/data-storytelling/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/data-storytelling.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/business-analytics/skills/data-storytelling/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: data-storytelling
description: Transform data into compelling narratives using visualization, context, and persuasive structure. Use when presenting analytics to stakeholders, creating data reports, or building executive presentations.
---

# Data Storytelling

Transform raw data into compelling narratives that drive decisions and inspire action.

## When to Use This Skill

- Presenting analytics to executives
- Creating quarterly business reviews
- Building investor presentations
- Writing data-driven reports
- Communicating insights to non-technical audiences
- Making recommendations based on data

## Core Concepts

### 1. Story Structure

```
Setup → Conflict → Resolution

Setup: Context and baseline
Conflict: The problem or opportunity
Resolution: Insights and recommendations
```

### 2. Narrative Arc

```
1. Hook: Grab attention with surprising insight
2. Context: Establish the baseline
3. Rising Action: Build through data points
4. Climax: The key insight
5. Resolution: Recommendations
6. Call to Action: Next steps
```

### 3. Three Pillars

| Pillar        | Purpose  | Components                       |
| ------------- | -------- | -------------------------------- |
| **Data**      | Evidence | Numbers, trends, comparisons     |
| **Narrative** | Meaning  | Context, causation, implications |
| **Visuals**   | Clarity  | Charts, diagrams, highlights     |

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Start with the "so what"** - Lead with insight
- **Use the rule of three** - Three points, three comparisons
- **Show, don't tell** - Let data speak
- **Make it personal** - Connect to audience goals
- **End with action** - Clear next steps

### Don'ts

- **Don't data dump** - Curate ruthlessly
- **Don't bury the insight** - Front-load key findings
- **Don't use jargon** - Match audience vocabulary
- **Don't show methodology first** - Context, then method
- **Don't forget the narrative** - Numbers need meaning

<!-- chapter:end slug=data-storytelling -->

---

<!-- chapter:begin slug=kpi-dashboard-design position=27 -->

## 27. kpi-dashboard-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/business-analytics/skills/kpi-dashboard-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/business-analytics/skills/kpi-dashboard-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/kpi-dashboard-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/business-analytics/skills/kpi-dashboard-design/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: kpi-dashboard-design
description: Design effective KPI dashboards with metrics selection, visualization best practices, and real-time monitoring patterns. Use this skill when building an executive SaaS metrics dashboard tracking MRR, churn, and LTV/CAC ratios; designing an operations center with live service health and request throughput; creating a cohort retention analysis view for a product team; or debugging a dashboard where metrics contradict each other due to inconsistent calculation methodology.
---

# KPI Dashboard Design

Comprehensive patterns for designing effective Key Performance Indicator (KPI) dashboards that drive business decisions.

## When to Use This Skill

- Designing executive dashboards
- Selecting meaningful KPIs
- Building real-time monitoring displays
- Creating department-specific metrics views
- Improving existing dashboard layouts
- Establishing metric governance

## Core Concepts

### 1. KPI Framework

| Level           | Focus            | Update Frequency  | Audience   |
| --------------- | ---------------- | ----------------- | ---------- |
| **Strategic**   | Long-term goals  | Monthly/Quarterly | Executives |
| **Tactical**    | Department goals | Weekly/Monthly    | Managers   |
| **Operational** | Day-to-day       | Real-time/Daily   | Teams      |

### 2. SMART KPIs

```
Specific: Clear definition
Measurable: Quantifiable
Achievable: Realistic targets
Relevant: Aligned to goals
Time-bound: Defined period
```

### 3. Dashboard Hierarchy

```
├── Executive Summary (1 page)
│   ├── 4-6 headline KPIs
│   ├── Trend indicators
│   └── Key alerts
├── Department Views
│   ├── Sales Dashboard
│   ├── Marketing Dashboard
│   ├── Operations Dashboard
│   └── Finance Dashboard
└── Detailed Drilldowns
    ├── Individual metrics
    └── Root cause analysis
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Common KPIs by Department`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices

### Do's

- **Limit to 5-7 KPIs** - Focus on what matters
- **Show context** - Comparisons, trends, targets
- **Use consistent colors** - Red=bad, green=good
- **Enable drilldown** - From summary to detail
- **Update appropriately** - Match metric frequency

### Don'ts

- **Don't show vanity metrics** - Focus on actionable data
- **Don't overcrowd** - White space aids comprehension
- **Don't use 3D charts** - They distort perception
- **Don't hide methodology** - Document calculations
- **Don't ignore mobile** - Ensure responsive design

## Troubleshooting

### MRR shown on dashboard contradicts finance's number

The most common cause is inconsistent treatment of annual plans. Finance may prorate to a daily rate while the dashboard normalizes to monthly. Align on a single formula and document it directly on the dashboard card:

```sql
-- Explicit formula shown in tooltip / data dictionary
-- Annual plans: divide total contract value by 12
-- Quarterly plans: divide by 3
-- Monthly plans: use as-is
CASE subscription_interval
    WHEN 'monthly'   THEN amount
    WHEN 'quarterly' THEN amount / 3.0
    WHEN 'yearly'    THEN amount / 12.0
END AS normalized_mrr
```

### Dashboard shows green but product team reports users complaining

The dashboard likely tracks system uptime (a lagging indicator) but not user-facing quality metrics. Add customer-perceived metrics alongside infrastructure metrics:

| Infrastructure (green) | User-perceived (add these) |
|---|---|
| API uptime 99.9% | P95 page load time |
| Error rate 0.1% | Task completion rate |
| Queue depth normal | Support ticket volume |

### Retention cohort looks flat — no variation between cohorts

Check whether the cohort query is partitioning by signup month correctly. A common bug is using `created_at::date` instead of `DATE_TRUNC('month', created_at)`, which groups by day and produces cohorts too small to show trends:

```sql
-- Wrong: too granular, cohorts are too small
DATE_TRUNC('day', created_at) AS cohort_date

-- Correct: monthly cohorts
DATE_TRUNC('month', created_at) AS cohort_month
```

### Real-time dashboard hammers the database

A live dashboard refreshing every 10 seconds with complex cohort SQL will degrade production query performance. Separate OLAP workloads from OLTP by writing pre-aggregated metrics to a summary table via a scheduled job, and have the dashboard read from that:

```python
# Scheduled every 5 minutes via cron/Celery
def refresh_mrr_summary():
    conn.execute("""
        INSERT INTO kpi_snapshot (metric, value, snapshot_at)
        SELECT 'mrr', SUM(...), NOW()
        FROM subscriptions WHERE status = 'active'
        ON CONFLICT (metric) DO UPDATE SET value = EXCLUDED.value
    """)
```

### Alert thresholds fire constantly, team ignores them

Static thresholds set once and never reviewed cause alert fatigue. Use dynamic thresholds based on rolling averages so alerts fire only when the metric deviates significantly from its own baseline:

```python
# Alert if current value is > 2 standard deviations from 30-day rolling mean
def is_anomalous(current: float, history: list[float]) -> bool:
    mean = statistics.mean(history)
    stdev = statistics.stdev(history)
    return abs(current - mean) > 2 * stdev
```

## Related Skills

- `data-storytelling` - Turn dashboard findings into narratives that drive executive decisions

<!-- chapter:end slug=kpi-dashboard-design -->

---

## Part: Cicd Automation

---

<!-- chapter:begin slug=deployment-pipeline-design position=28 -->

## 28. deployment-pipeline-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cicd-automation/skills/deployment-pipeline-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cicd-automation/skills/deployment-pipeline-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/deployment-pipeline-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-strategies.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cicd-automation/skills/deployment-pipeline-design/references/advanced-strategies.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cicd-automation/skills/deployment-pipeline-design/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: deployment-pipeline-design
description: Design multi-stage CI/CD pipelines with approval gates, security checks, and deployment orchestration. Use this skill when designing zero-downtime deployment pipelines, implementing canary rollout strategies, setting up multi-environment promotion workflows, or debugging failed deployment gates in CI/CD.
---

# Deployment Pipeline Design

Architecture patterns for multi-stage CI/CD pipelines with approval gates, deployment strategies, and environment promotion workflows.

## Purpose

Design robust, secure deployment pipelines that balance speed with safety through proper stage organization, automated quality gates, and progressive delivery strategies. This skill covers both the structural design of pipeline architecture and the operational patterns for reliable production deployments.

## Input / Output

### What You Provide

- **Application type**: Language/runtime, containerized or bare-metal, monolith or microservices
- **Deployment target**: Kubernetes, ECS, VMs, serverless, or platform-as-a-service
- **Environment topology**: Number of environments (dev/staging/prod), region layout, air-gap requirements
- **Rollout requirements**: Acceptable downtime, rollback SLA, traffic splitting needs, canary vs blue-green preference
- **Gate constraints**: Approval teams, required test coverage thresholds, compliance scans (SAST, DAST, SCA)
- **Monitoring stack**: Prometheus, Datadog, CloudWatch, or other metrics sources used for automated promotion decisions

### What This Skill Produces

- **Pipeline configuration**: Stage definitions, job dependencies, parallelism, and caching strategy
- **Deployment strategy**: Chosen rollout pattern with annotated configuration (canary weights, blue-green switchover, rolling parameters)
- **Health check setup**: Shallow vs deep readiness probes, post-deployment smoke test scripts
- **Gate definitions**: Automated metric thresholds and manual approval workflows
- **Rollback plan**: Automated rollback triggers and manual runbook steps

## When to Use

- Design CI/CD architecture for a new service or platform migration
- Implement deployment gates between environments
- Configure multi-environment pipelines with mandatory security scanning
- Establish progressive delivery with canary or blue-green strategies
- Debug pipelines where stages succeed but production behavior is wrong
- Reduce mean time to recovery by automating rollback on metric degradation

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Troubleshooting

### Health check passes in pipeline but service is unhealthy in production

The pipeline health check is hitting a shallow `/ping` endpoint that returns 200 even when the database is unreachable. Use a deep readiness check that verifies actual dependencies (see Health Checks section above).

### Canary deployment never promotes to 100%

Argo Rollouts requires a valid `AnalysisTemplate` to auto-promote. If the Prometheus query returns no data (e.g., metric name changed), the analysis stays inconclusive and promotion stalls. Add `inconclusiveLimit` so the rollout fails fast rather than hanging:

```yaml
spec:
  metrics:
  - name: error-rate
    failureCondition: "result[0] > 0.05"
    inconclusiveLimit: 2   # fail after 2 inconclusive results, not hang indefinitely
    provider:
      prometheus:
        query: |
          sum(rate(http_requests_total{status=~"5.."}[2m]))
          / sum(rate(http_requests_total[2m]))
```

### Staging deploy succeeds but production job never starts

Check that production environment protection rules are configured — a missing reviewer assignment means the approval gate waits indefinitely with no notification. In GitHub Actions, ensure `Required reviewers` is set to an existing user or team in **Settings → Environments → production**.

### Docker layer cache busted on every run causing slow builds

If `COPY . .` appears before dependency installation, any source file change invalidates the dependency layer. Reorder to copy dependency manifests first:

```dockerfile
# Good: dependencies cached separately from source code
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
```

### Rollback leaves database migrations applied to old code

A service rollback without a migration rollback causes schema/code mismatch errors. Always make migrations backward-compatible (additive only) for at least one release cycle, and keep undo scripts versioned alongside the migration:

```bash
# migrations/V20240315__add_nullable_column.sql       (forward)
# migrations/V20240315__add_nullable_column.undo.sql  (backward)
```

Never run destructive migrations (DROP COLUMN, ALTER NOT NULL) until the old code version is fully retired from all environments.

## Advanced Topics

For platform-specific pipeline configurations, multi-region promotion workflows, and advanced Argo Rollouts patterns, see:

- [`references/advanced-strategies.md`](references/advanced-strategies.md) — Extended YAML examples, platform-specific configs (GitHub Actions, GitLab CI, Azure Pipelines), multi-region canary patterns, and database migration rollback strategies

## Related Skills

- `github-actions-templates` - For GitHub Actions implementation patterns and reusable workflows
- `gitlab-ci-patterns` - For GitLab CI/CD pipeline implementation
- `secrets-management` - For secrets handling in CI/CD pipelines

<!-- chapter:end slug=deployment-pipeline-design -->

---

<!-- chapter:begin slug=github-actions-templates position=29 -->

## 29. github-actions-templates

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cicd-automation/skills/github-actions-templates/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cicd-automation/skills/github-actions-templates/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/github-actions-templates.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: github-actions-templates
description: Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, automating development workflows, or creating reusable workflow templates.
---

# GitHub Actions Templates

Production-ready GitHub Actions workflow patterns for testing, building, and deploying applications.

## Purpose

Create efficient, secure GitHub Actions workflows for continuous integration and deployment across various tech stacks.

## When to Use

- Automate testing and deployment
- Build Docker images and push to registries
- Deploy to Kubernetes clusters
- Run security scans
- Implement matrix builds for multiple environments

## Common Workflow Patterns

### Pattern 1: Test Workflow

```yaml
name: Test

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
      - uses: actions/checkout@v4

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          files: ./coverage/lcov.info
```

**Reference:** See `assets/test-workflow.yml`

### Pattern 2: Build and Push Docker Image

```yaml
name: Build and Push

on:
  push:
    branches: [main]
    tags: ["v*"]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v4

      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
```

**Reference:** See `assets/deploy-workflow.yml`

### Pattern 3: Deploy to Kubernetes

```yaml
name: Deploy to Kubernetes

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-west-2

      - name: Update kubeconfig
        run: |
          aws eks update-kubeconfig --name production-cluster --region us-west-2

      - name: Deploy to Kubernetes
        run: |
          kubectl apply -f k8s/
          kubectl rollout status deployment/my-app -n production
          kubectl get services -n production

      - name: Verify deployment
        run: |
          kubectl get pods -n production
          kubectl describe deployment my-app -n production
```

### Pattern 4: Matrix Build

```yaml
name: Matrix Build

on: [push, pull_request]

jobs:
  build:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run tests
        run: pytest
```

**Reference:** See `assets/matrix-build.yml`

## Workflow Best Practices

1. **Use specific action versions** (@v4, not @latest)
2. **Cache dependencies** to speed up builds
3. **Use secrets** for sensitive data
4. **Implement status checks** on PRs
5. **Use matrix builds** for multi-version testing
6. **Set appropriate permissions**
7. **Use reusable workflows** for common patterns
8. **Implement approval gates** for production
9. **Add notification steps** for failures
10. **Use self-hosted runners** for sensitive workloads

## Reusable Workflows

```yaml
# .github/workflows/reusable-test.yml
name: Reusable Test Workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      NPM_TOKEN:
        required: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm test
```

**Use reusable workflow:**

```yaml
jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: "20.x"
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```

## Security Scanning

```yaml
name: Security Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  security:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@0.28.0
        with:
          scan-type: "fs"
          scan-ref: "."
          format: "sarif"
          output: "trivy-results.sarif"

      - name: Upload Trivy results to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: "trivy-results.sarif"

      - name: Run Snyk Security Scan
        uses: snyk/actions/node@0.4.0
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
```

## Deployment with Approvals

```yaml
name: Deploy to Production

on:
  push:
    tags: ["v*"]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.example.com

    steps:
      - uses: actions/checkout@v4

      - name: Deploy application
        run: |
          echo "Deploying to production..."
          # Deployment commands here

      - name: Notify Slack
        if: success()
        uses: slackapi/slack-github-action@v1
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {
              "text": "Deployment to production completed successfully!"
            }
```


## Related Skills

- `gitlab-ci-patterns` - For GitLab CI workflows
- `deployment-pipeline-design` - For pipeline architecture
- `secrets-management` - For secrets handling

<!-- chapter:end slug=github-actions-templates -->

---

<!-- chapter:begin slug=gitlab-ci-patterns position=30 -->

## 30. gitlab-ci-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cicd-automation/skills/gitlab-ci-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cicd-automation/skills/gitlab-ci-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/gitlab-ci-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: gitlab-ci-patterns
description: Build GitLab CI/CD pipelines with multi-stage workflows, caching, and distributed runners for scalable automation. Use when implementing GitLab CI/CD, optimizing pipeline performance, or setting up automated testing and deployment.
---

# GitLab CI Patterns

Comprehensive GitLab CI/CD pipeline patterns for automated testing, building, and deployment.

## Purpose

Create efficient GitLab CI pipelines with proper stage organization, caching, and deployment strategies.

## When to Use

- Automate GitLab-based CI/CD
- Implement multi-stage pipelines
- Configure GitLab Runners
- Deploy to Kubernetes from GitLab
- Implement GitOps workflows

## Basic Pipeline Structure

```yaml
stages:
  - build
  - test
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

build:
  stage: build
  image: node:20
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/

test:
  stage: test
  image: node:20
  script:
    - npm ci
    - npm run lint
    - npm test
  coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

deploy:
  stage: deploy
  image: bitnami/kubectl:1.31
  script:
    - kubectl apply -f k8s/
    - kubectl rollout status deployment/my-app
  only:
    - main
  environment:
    name: production
    url: https://app.example.com
```

## Docker Build and Push

```yaml
build-docker:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker build -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main
    - tags
```

## Multi-Environment Deployment

```yaml
.deploy_template: &deploy_template
  image: bitnami/kubectl:1.31
  before_script:
    - kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true
    - kubectl config set-credentials admin --token="$KUBE_TOKEN"
    - kubectl config set-context default --cluster=k8s --user=admin
    - kubectl config use-context default

deploy:staging:
  <<: *deploy_template
  stage: deploy
  script:
    - kubectl apply -f k8s/ -n staging
    - kubectl rollout status deployment/my-app -n staging
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy:production:
  <<: *deploy_template
  stage: deploy
  script:
    - kubectl apply -f k8s/ -n production
    - kubectl rollout status deployment/my-app -n production
  environment:
    name: production
    url: https://app.example.com
  when: manual
  only:
    - main
```

## Terraform Pipeline

```yaml
stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/terraform
  TF_VERSION: "1.6.0"

before_script:
  - cd ${TF_ROOT}
  - terraform --version

validate:
  stage: validate
  image: hashicorp/terraform:${TF_VERSION}
  script:
    - terraform init -backend=false
    - terraform validate
    - terraform fmt -check

plan:
  stage: plan
  image: hashicorp/terraform:${TF_VERSION}
  script:
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
    paths:
      - ${TF_ROOT}/tfplan
    expire_in: 1 day

apply:
  stage: apply
  image: hashicorp/terraform:${TF_VERSION}
  script:
    - terraform init
    - terraform apply -auto-approve tfplan
  dependencies:
    - plan
  when: manual
  only:
    - main
```

## Security Scanning

```yaml
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

trivy-scan:
  stage: test
  image: aquasec/trivy:0.58.0
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: true
```

## Caching Strategies

```yaml
# Cache node_modules
build:
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
    policy: pull-push

# Global cache
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .cache/
    - vendor/

# Separate cache per job
job1:
  cache:
    key: job1-cache
    paths:
      - build/

job2:
  cache:
    key: job2-cache
    paths:
      - dist/
```

## Dynamic Child Pipelines

```yaml
generate-pipeline:
  stage: build
  script:
    - python generate_pipeline.py > child-pipeline.yml
  artifacts:
    paths:
      - child-pipeline.yml

trigger-child:
  stage: deploy
  trigger:
    include:
      - artifact: child-pipeline.yml
        job: generate-pipeline
    strategy: depend
```


## Best Practices

1. **Use specific image tags** (node:20, not node:latest)
2. **Cache dependencies** appropriately
3. **Use artifacts** for build outputs
4. **Implement manual gates** for production
5. **Use environments** for deployment tracking
6. **Enable merge request pipelines**
7. **Use pipeline schedules** for recurring jobs
8. **Implement security scanning**
9. **Use CI/CD variables** for secrets
10. **Monitor pipeline performance**

## Related Skills

- `github-actions-templates` - For GitHub Actions
- `deployment-pipeline-design` - For architecture
- `secrets-management` - For secrets handling

<!-- chapter:end slug=gitlab-ci-patterns -->

---

<!-- chapter:begin slug=secrets-management position=31 -->

## 31. secrets-management

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cicd-automation/skills/secrets-management/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cicd-automation/skills/secrets-management/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/secrets-management.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: secrets-management
description: Implement secure secrets management for CI/CD pipelines using Vault, AWS Secrets Manager, or native platform solutions. Use when handling sensitive credentials, rotating secrets, or securing CI/CD environments.
---

# Secrets Management

Secure secrets management practices for CI/CD pipelines using Vault, AWS Secrets Manager, and other tools.

## Purpose

Implement secure secrets management in CI/CD pipelines without hardcoding sensitive information.

## When to Use

- Store API keys and credentials
- Manage database passwords
- Handle TLS certificates
- Rotate secrets automatically
- Implement least-privilege access

## Secrets Management Tools

### HashiCorp Vault

- Centralized secrets management
- Dynamic secrets generation
- Secret rotation
- Audit logging
- Fine-grained access control

### AWS Secrets Manager

- AWS-native solution
- Automatic rotation
- Integration with RDS
- CloudFormation support

### Azure Key Vault

- Azure-native solution
- HSM-backed keys
- Certificate management
- RBAC integration

### Google Secret Manager

- GCP-native solution
- Versioning
- IAM integration

## HashiCorp Vault Integration

### Setup Vault

```bash
# Start Vault dev server
vault server -dev

# Set environment
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'

# Enable secrets engine
vault secrets enable -path=secret kv-v2

# Store secret
vault kv put secret/database/config username=admin password=secret
```

### GitHub Actions with Vault

```yaml
name: Deploy with Vault Secrets

on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Import Secrets from Vault
        uses: hashicorp/vault-action@v2
        with:
          url: https://vault.example.com:8200
          token: ${{ secrets.VAULT_TOKEN }}
          secrets: |
            secret/data/database username | DB_USERNAME ;
            secret/data/database password | DB_PASSWORD ;
            secret/data/api key | API_KEY

      - name: Use secrets
        run: |
          echo "Connecting to database as $DB_USERNAME"
          # Use $DB_PASSWORD, $API_KEY
```

### GitLab CI with Vault

```yaml
deploy:
  image: vault:1.17
  before_script:
    - export VAULT_ADDR=https://vault.example.com:8200
    - export VAULT_TOKEN=$VAULT_TOKEN
    - apk add curl jq
  script:
    - |
      DB_PASSWORD=$(vault kv get -field=password secret/database/config)
      API_KEY=$(vault kv get -field=key secret/api/credentials)
      echo "Deploying with secrets..."
      # Use $DB_PASSWORD, $API_KEY
```

**Reference:** See `references/vault-setup.md`

## AWS Secrets Manager

### Store Secret

```bash
aws secretsmanager create-secret \
  --name production/database/password \
  --secret-string "super-secret-password"
```

### Retrieve in GitHub Actions

```yaml
- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: us-west-2

- name: Get secret from AWS
  run: |
    SECRET=$(aws secretsmanager get-secret-value \
      --secret-id production/database/password \
      --query SecretString \
      --output text)
    echo "::add-mask::$SECRET"
    echo "DB_PASSWORD=$SECRET" >> $GITHUB_ENV

- name: Use secret
  run: |
    # Use $DB_PASSWORD
    ./deploy.sh
```

### Terraform with AWS Secrets Manager

```hcl
data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = "production/database/password"
}

resource "aws_db_instance" "main" {
  allocated_storage    = 100
  engine              = "postgres"
  instance_class      = "db.t3.large"
  username            = "admin"
  password            = jsondecode(data.aws_secretsmanager_secret_version.db_password.secret_string)["password"]
}
```

## GitHub Secrets

### Organization/Repository Secrets

```yaml
- name: Use GitHub secret
  env:
    API_KEY: ${{ secrets.API_KEY }}
    DATABASE_URL: ${{ secrets.DATABASE_URL }}
  run: |
    # Secrets are injected as env vars — never print them to logs
    ./deploy.sh
```

### Environment Secrets

```yaml
deploy:
  runs-on: ubuntu-latest
  environment: production
  steps:
    - name: Deploy
      env:
        PROD_API_KEY: ${{ secrets.PROD_API_KEY }}
      run: |
        # Secret injected as env var — never print to logs
        ./deploy.sh
```

**Reference:** See `references/github-secrets.md`

## GitLab CI/CD Variables

### Project Variables

```yaml
deploy:
  script:
    - echo "Deploying with $API_KEY"
    - echo "Database: $DATABASE_URL"
```

### Protected and Masked Variables

- Protected: Only available in protected branches
- Masked: Hidden in job logs
- File type: Stored as file

## Best Practices

1. **Never commit secrets** to Git
2. **Use different secrets** per environment
3. **Rotate secrets regularly**
4. **Implement least-privilege access**
5. **Enable audit logging**
6. **Use secret scanning** (GitGuardian, TruffleHog)
7. **Mask secrets in logs**
8. **Encrypt secrets at rest**
9. **Use short-lived tokens** when possible
10. **Document secret requirements**

## Secret Rotation

### Automated Rotation with AWS

```python
import boto3
import json

def lambda_handler(event, context):
    client = boto3.client('secretsmanager')

    # Get current secret
    response = client.get_secret_value(SecretId='my-secret')
    current_secret = json.loads(response['SecretString'])

    # Generate new password
    new_password = generate_strong_password()

    # Update database password
    update_database_password(new_password)

    # Update secret
    client.put_secret_value(
        SecretId='my-secret',
        SecretString=json.dumps({
            'username': current_secret['username'],
            'password': new_password
        })
    )

    return {'statusCode': 200}
```

### Manual Rotation Process

1. Generate new secret
2. Update secret in secret store
3. Update applications to use new secret
4. Verify functionality
5. Revoke old secret

## External Secrets Operator

### Kubernetes Integration

```yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
  namespace: production
spec:
  provider:
    vault:
      server: "https://vault.example.com:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "production"

---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: database-credentials
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: database-credentials
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: database/config
        property: username
    - secretKey: password
      remoteRef:
        key: database/config
        property: password
```

## Secret Scanning

### Pre-commit Hook

```bash
#!/bin/bash
# .git/hooks/pre-commit

# Check for secrets with TruffleHog
docker run --rm -v "$(pwd):/repo" \
  trufflesecurity/trufflehog:3.88 \
  filesystem --directory=/repo

if [ $? -ne 0 ]; then
  echo "❌ Secret detected! Commit blocked."
  exit 1
fi
```

### CI/CD Secret Scanning

```yaml
secret-scan:
  stage: security
  image: trufflesecurity/trufflehog:3.88
  script:
    - trufflehog filesystem .
  allow_failure: false
```


## Related Skills

- `github-actions-templates` - For GitHub Actions integration
- `gitlab-ci-patterns` - For GitLab CI integration
- `deployment-pipeline-design` - For pipeline architecture

<!-- chapter:end slug=secrets-management -->

---

## Part: Cloud Infrastructure

---

<!-- chapter:begin slug=cost-optimization position=32 -->

## 32. cost-optimization

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/cost-optimization/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/cost-optimization/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/cost-optimization.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/tagging-standards.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/cost-optimization/references/tagging-standards.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: cost-optimization
description: Optimize cloud costs across AWS, Azure, GCP, and OCI through resource rightsizing, tagging strategies, reserved instances, and spending analysis. Use when reducing cloud expenses, analyzing infrastructure costs, or implementing cost governance policies.
---

# Cloud Cost Optimization

Strategies and patterns for optimizing cloud costs across AWS, Azure, GCP, and OCI.

## Purpose

Implement systematic cost optimization strategies to reduce cloud spending while maintaining performance and reliability.

## When to Use

- Reduce cloud spending
- Right-size resources
- Implement cost governance
- Optimize multi-cloud costs
- Meet budget constraints

## Cost Optimization Framework

### 1. Visibility

- Implement cost allocation tags
- Use cloud cost management tools
- Set up budget alerts
- Create cost dashboards

### 2. Right-Sizing

- Analyze resource utilization
- Downsize over-provisioned resources
- Use auto-scaling
- Remove idle resources

### 3. Pricing Models

- Use reserved capacity
- Leverage spot/preemptible instances
- Implement savings plans
- Use committed use discounts

### 4. Architecture Optimization

- Use managed services
- Implement caching
- Optimize data transfer
- Use lifecycle policies

## AWS Cost Optimization

### Reserved Instances

```
Savings: 30-72% vs On-Demand
Term: 1 or 3 years
Payment: All/Partial/No upfront
Flexibility: Standard or Convertible
```

### Savings Plans

```
Compute Savings Plans: 66% savings
EC2 Instance Savings Plans: 72% savings
Applies to: EC2, Fargate, Lambda
Flexible across: Instance families, regions, OS
```

### Spot Instances

```
Savings: Up to 90% vs On-Demand
Best for: Batch jobs, CI/CD, stateless workloads
Risk: 2-minute interruption notice
Strategy: Mix with On-Demand for resilience
```

### S3 Cost Optimization

```hcl
resource "aws_s3_bucket_lifecycle_configuration" "example" {
  bucket = aws_s3_bucket.example.id

  rule {
    id     = "transition-to-ia"
    status = "Enabled"

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 90
      storage_class = "GLACIER"
    }

    expiration {
      days = 365
    }
  }
}
```

## Azure Cost Optimization

### Reserved VM Instances

- 1 or 3 year terms
- Up to 72% savings
- Flexible sizing
- Exchangeable

### Azure Hybrid Benefit

- Use existing Windows Server licenses
- Up to 80% savings with RI
- Available for Windows and SQL Server

### Azure Advisor Recommendations

- Right-size VMs
- Delete unused resources
- Use reserved capacity
- Optimize storage

## GCP Cost Optimization

### Committed Use Discounts

- 1 or 3 year commitment
- Up to 57% savings
- Applies to vCPUs and memory
- Resource-based or spend-based

### Sustained Use Discounts

- Automatic discounts
- Up to 30% for running instances
- No commitment required
- Applies to Compute Engine, GKE

### Preemptible VMs

- Up to 80% savings
- 24-hour maximum runtime
- Best for batch workloads

## OCI Cost Optimization

### Flexible Shapes

- Scale OCPUs and memory independently
- Match instance sizing to workload demand
- Reduce wasted capacity from fixed VM shapes

### Commitments and Budgets

- Use annual commitments for predictable spend
- Set compartment-level budgets with alerts
- Track monthly forecasts with OCI Cost Analysis

### Preemptible Capacity

- Use preemptible instances for batch and ephemeral workloads
- Keep interruption-tolerant autoscaling groups
- Mix with standard capacity for critical services

## Tagging Strategy

### AWS Tagging

```hcl
locals {
  common_tags = {
    Environment = "production"
    Project     = "my-project"
    CostCenter  = "engineering"
    Owner       = "team@example.com"
    ManagedBy   = "terraform"
  }
}

resource "aws_instance" "example" {
  ami           = "ami-12345678"
  instance_type = "t3.medium"

  tags = merge(
    local.common_tags,
    {
      Name = "web-server"
    }
  )
}
```

**Reference:** See `references/tagging-standards.md`

## Cost Monitoring

### Budget Alerts

```hcl
# AWS Budget
resource "aws_budgets_budget" "monthly" {
  name              = "monthly-budget"
  budget_type       = "COST"
  limit_amount      = "1000"
  limit_unit        = "USD"
  time_period_start = "2024-01-01_00:00"
  time_unit         = "MONTHLY"

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 80
    threshold_type            = "PERCENTAGE"
    notification_type         = "ACTUAL"
    subscriber_email_addresses = ["team@example.com"]
  }
}
```

### Cost Anomaly Detection

- AWS Cost Anomaly Detection
- Azure Cost Management alerts
- GCP Budget alerts
- OCI Budgets and Cost Analysis

## Architecture Patterns

### Pattern 1: Serverless First

- Use Lambda/Functions for event-driven
- Pay only for execution time
- Auto-scaling included
- No idle costs

### Pattern 2: Right-Sized Databases

```
Development: t3.small RDS
Staging: t3.large RDS
Production: r6g.2xlarge RDS with read replicas
```

### Pattern 3: Multi-Tier Storage

```
Hot data: S3 Standard
Warm data: S3 Standard-IA (30 days)
Cold data: S3 Glacier (90 days)
Archive: S3 Deep Archive (365 days)
```

### Pattern 4: Auto-Scaling

```hcl
resource "aws_autoscaling_policy" "scale_up" {
  name                   = "scale-up"
  scaling_adjustment     = 2
  adjustment_type        = "ChangeInCapacity"
  cooldown              = 300
  autoscaling_group_name = aws_autoscaling_group.main.name
}

resource "aws_cloudwatch_metric_alarm" "cpu_high" {
  alarm_name          = "cpu-high"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "60"
  statistic           = "Average"
  threshold           = "80"
  alarm_actions       = [aws_autoscaling_policy.scale_up.arn]
}
```

## Cost Optimization Checklist

- [ ] Implement cost allocation tags
- [ ] Delete unused resources (EBS, EIPs, snapshots)
- [ ] Right-size instances based on utilization
- [ ] Use reserved capacity for steady workloads
- [ ] Implement auto-scaling
- [ ] Optimize storage classes
- [ ] Use lifecycle policies
- [ ] Enable cost anomaly detection
- [ ] Set budget alerts
- [ ] Review costs weekly
- [ ] Use spot/preemptible instances
- [ ] Optimize data transfer costs
- [ ] Implement caching layers
- [ ] Use managed services
- [ ] Monitor and optimize continuously

## Tools

- **AWS:** Cost Explorer, Cost Anomaly Detection, Compute Optimizer
- **Azure:** Cost Management, Advisor
- **GCP:** Cost Management, Recommender
- **OCI:** Cost Analysis, Budgets, Cloud Advisor
- **Multi-cloud:** CloudHealth, Cloudability, Kubecost


## Related Skills

- `terraform-module-library` - For resource provisioning
- `multi-cloud-architecture` - For cloud selection

<!-- chapter:end slug=cost-optimization -->

---

<!-- chapter:begin slug=hybrid-cloud-networking position=33 -->

## 33. hybrid-cloud-networking

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/hybrid-cloud-networking/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/hybrid-cloud-networking/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/hybrid-cloud-networking.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/direct-connect.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/hybrid-cloud-networking/references/direct-connect.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: hybrid-cloud-networking
description: Configure secure, high-performance connectivity between on-premises infrastructure and cloud platforms using VPN and dedicated connections. Use when building hybrid cloud architectures, connecting data centers to cloud, or implementing secure cross-premises networking.
---

# Hybrid Cloud Networking

Configure secure, high-performance connectivity between on-premises and cloud environments using VPN, Direct Connect, ExpressRoute, Interconnect, and FastConnect.

## Purpose

Establish secure, reliable network connectivity between on-premises data centers and cloud providers (AWS, Azure, GCP, OCI).

## When to Use

- Connect on-premises to cloud
- Extend datacenter to cloud
- Implement hybrid active-active setups
- Meet compliance requirements
- Migrate to cloud gradually

## Connection Options

### AWS Connectivity

#### 1. Site-to-Site VPN

- IPSec VPN over internet
- Up to 1.25 Gbps per tunnel
- Cost-effective for moderate bandwidth
- Higher latency, internet-dependent

```hcl
resource "aws_vpn_gateway" "main" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "main-vpn-gateway"
  }
}

resource "aws_customer_gateway" "main" {
  bgp_asn    = 65000
  ip_address = "203.0.113.1"
  type       = "ipsec.1"
}

resource "aws_vpn_connection" "main" {
  vpn_gateway_id      = aws_vpn_gateway.main.id
  customer_gateway_id = aws_customer_gateway.main.id
  type                = "ipsec.1"
  static_routes_only  = false
}
```

#### 2. AWS Direct Connect

- Dedicated network connection
- 1 Gbps to 100 Gbps
- Lower latency, consistent bandwidth
- More expensive, setup time required

**Reference:** See `references/direct-connect.md`

### Azure Connectivity

#### 1. Site-to-Site VPN

```hcl
resource "azurerm_virtual_network_gateway" "vpn" {
  name                = "vpn-gateway"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name

  type     = "Vpn"
  vpn_type = "RouteBased"
  sku      = "VpnGw1"

  ip_configuration {
    name                          = "vnetGatewayConfig"
    public_ip_address_id          = azurerm_public_ip.vpn.id
    private_ip_address_allocation = "Dynamic"
    subnet_id                     = azurerm_subnet.gateway.id
  }
}
```

#### 2. Azure ExpressRoute

- Private connection via connectivity provider
- Up to 100 Gbps
- Low latency, high reliability
- Premium for global connectivity

### GCP Connectivity

#### 1. Cloud VPN

- IPSec VPN (Classic or HA VPN)
- HA VPN: 99.99% SLA
- Up to 3 Gbps per tunnel

#### 2. Cloud Interconnect

- Dedicated (10 Gbps, 100 Gbps)
- Partner (50 Mbps to 50 Gbps)
- Lower latency than VPN

### OCI Connectivity

#### 1. IPSec VPN Connect

- IPSec VPN with redundant tunnels
- Dynamic routing through DRG
- Good fit for branch offices and migration phases

#### 2. OCI FastConnect

- Private dedicated connectivity through Oracle or partner edge
- Suitable for predictable throughput and lower-latency hybrid traffic
- Commonly paired with DRG for hub-and-spoke designs

## Hybrid Network Patterns

### Pattern 1: Hub-and-Spoke

```
On-Premises Datacenter
         ↓
    VPN/Direct Connect
         ↓
    Transit Gateway (AWS) / vWAN (Azure)
         ↓
    ├─ Production VPC/VNet
    ├─ Staging VPC/VNet
    └─ Development VPC/VNet
```

### Pattern 2: Multi-Region Hybrid

```
On-Premises
    ├─ Direct Connect → us-east-1
    └─ Direct Connect → us-west-2
            ↓
        Cross-Region Peering
```

### Pattern 3: Multi-Cloud Hybrid

```
On-Premises Datacenter
    ├─ Direct Connect → AWS
    ├─ ExpressRoute → Azure
    ├─ Interconnect → GCP
    └─ FastConnect → OCI
```

## Routing Configuration

### BGP Configuration

```
On-Premises Router:
- AS Number: 65000
- Advertise: 10.0.0.0/8

Cloud Router:
- AS Number: 64512 (AWS), 65515 (Azure), provider-assigned for GCP/OCI
- Advertise: Cloud VPC/VNet CIDRs
```

### Route Propagation

- Enable route propagation on route tables
- Use BGP for dynamic routing
- Implement route filtering
- Monitor route advertisements

## Security Best Practices

1. **Use private connectivity** (Direct Connect/ExpressRoute/Interconnect/FastConnect)
2. **Implement encryption** for VPN tunnels
3. **Use VPC endpoints** to avoid internet routing
4. **Configure network ACLs** and security groups
5. **Enable VPC Flow Logs** for monitoring
6. **Implement DDoS protection**
7. **Use PrivateLink/Private Endpoints**
8. **Monitor connections** with CloudWatch/Azure Monitor/Cloud Monitoring/OCI Monitoring
9. **Implement redundancy** (dual tunnels)
10. **Regular security audits**

## High Availability

### Dual VPN Tunnels

```hcl
resource "aws_vpn_connection" "primary" {
  vpn_gateway_id      = aws_vpn_gateway.main.id
  customer_gateway_id = aws_customer_gateway.primary.id
  type                = "ipsec.1"
}

resource "aws_vpn_connection" "secondary" {
  vpn_gateway_id      = aws_vpn_gateway.main.id
  customer_gateway_id = aws_customer_gateway.secondary.id
  type                = "ipsec.1"
}
```

### Active-Active Configuration

- Multiple connections from different locations
- BGP for automatic failover
- Equal-cost multi-path (ECMP) routing
- Monitor health of all connections

## Monitoring and Troubleshooting

### Key Metrics

- Tunnel status (up/down)
- Bytes in/out
- Packet loss
- Latency
- BGP session status

### Troubleshooting

```bash
# AWS VPN
aws ec2 describe-vpn-connections
aws ec2 get-vpn-connection-telemetry

# Azure VPN
az network vpn-connection show
az network vpn-connection show-device-config-script

# OCI IPSec VPN
oci network ip-sec-connection list
oci network cpe list
```

## Cost Optimization

1. **Right-size connections** based on traffic
2. **Use VPN for low-bandwidth** workloads
3. **Consolidate traffic** through fewer connections
4. **Minimize data transfer** costs
5. **Use dedicated private links** for high bandwidth
6. **Implement caching** to reduce traffic


## Related Skills

- `multi-cloud-architecture` - For architecture decisions
- `terraform-module-library` - For IaC implementation

<!-- chapter:end slug=hybrid-cloud-networking -->

---

<!-- chapter:begin slug=istio-traffic-management position=34 -->

## 34. istio-traffic-management

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/istio-traffic-management/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/istio-traffic-management/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/istio-traffic-management.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: istio-traffic-management
description: Configure Istio traffic management including routing, load balancing, circuit breakers, and canary deployments. Use when implementing service mesh traffic policies, progressive delivery, or resilience patterns.
---

# Istio Traffic Management

Comprehensive guide to Istio traffic management for production service mesh deployments.

## When to Use This Skill

- Configuring service-to-service routing
- Implementing canary or blue-green deployments
- Setting up circuit breakers and retries
- Load balancing configuration
- Traffic mirroring for testing
- Fault injection for chaos engineering

## Core Concepts

### 1. Traffic Management Resources

| Resource            | Purpose                       | Scope         |
| ------------------- | ----------------------------- | ------------- |
| **VirtualService**  | Route traffic to destinations | Host-based    |
| **DestinationRule** | Define policies after routing | Service-based |
| **Gateway**         | Configure ingress/egress      | Cluster edge  |
| **ServiceEntry**    | Add external services         | Mesh-wide     |

### 2. Traffic Flow

```
Client → Gateway → VirtualService → DestinationRule → Service
                   (routing)        (policies)        (pods)
```

## Templates

### Template 1: Basic Routing

```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews-route
  namespace: bookinfo
spec:
  hosts:
    - reviews
  http:
    - match:
        - headers:
            end-user:
              exact: jason
      route:
        - destination:
            host: reviews
            subset: v2
    - route:
        - destination:
            host: reviews
            subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews-destination
  namespace: bookinfo
spec:
  host: reviews
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
    - name: v3
      labels:
        version: v3
```

### Template 2: Canary Deployment

```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: my-service-canary
spec:
  hosts:
    - my-service
  http:
    - route:
        - destination:
            host: my-service
            subset: stable
          weight: 90
        - destination:
            host: my-service
            subset: canary
          weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: my-service-dr
spec:
  host: my-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        h2UpgradePolicy: UPGRADE
        http1MaxPendingRequests: 100
        http2MaxRequests: 1000
  subsets:
    - name: stable
      labels:
        version: stable
    - name: canary
      labels:
        version: canary
```

### Template 3: Circuit Breaker

```yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: circuit-breaker
spec:
  host: my-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 100
        http2MaxRequests: 1000
        maxRequestsPerConnection: 10
        maxRetries: 3
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 30s
      baseEjectionTime: 30s
      maxEjectionPercent: 50
      minHealthPercent: 30
```

### Template 4: Retry and Timeout

```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: ratings-retry
spec:
  hosts:
    - ratings
  http:
    - route:
        - destination:
            host: ratings
      timeout: 10s
      retries:
        attempts: 3
        perTryTimeout: 3s
        retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-4xx,503
        retryRemoteLocalities: true
```

### Template 5: Traffic Mirroring

```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: mirror-traffic
spec:
  hosts:
    - my-service
  http:
    - route:
        - destination:
            host: my-service
            subset: v1
      mirror:
        host: my-service
        subset: v2
      mirrorPercentage:
        value: 100.0
```

### Template 6: Fault Injection

```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: fault-injection
spec:
  hosts:
    - ratings
  http:
    - fault:
        delay:
          percentage:
            value: 10
          fixedDelay: 5s
        abort:
          percentage:
            value: 5
          httpStatus: 503
      route:
        - destination:
            host: ratings
```

### Template 7: Ingress Gateway

```yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: my-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: my-tls-secret
      hosts:
        - "*.example.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: my-vs
spec:
  hosts:
    - "api.example.com"
  gateways:
    - my-gateway
  http:
    - match:
        - uri:
            prefix: /api/v1
      route:
        - destination:
            host: api-service
            port:
              number: 8080
```

## Load Balancing Strategies

```yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: load-balancing
spec:
  host: my-service
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN # or LEAST_CONN, RANDOM, PASSTHROUGH
---
# Consistent hashing for sticky sessions
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: sticky-sessions
spec:
  host: my-service
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: x-user-id
        # or: httpCookie, useSourceIp, httpQueryParameterName
```

## Best Practices

### Do's

- **Start simple** - Add complexity incrementally
- **Use subsets** - Version your services clearly
- **Set timeouts** - Always configure reasonable timeouts
- **Enable retries** - But with backoff and limits
- **Monitor** - Use Kiali and Jaeger for visibility

### Don'ts

- **Don't over-retry** - Can cause cascading failures
- **Don't ignore outlier detection** - Enable circuit breakers
- **Don't mirror to production** - Mirror to test environments
- **Don't skip canary** - Test with small traffic percentage first

## Debugging Commands

```bash
# Check VirtualService configuration
istioctl analyze

# View effective routes
istioctl proxy-config routes deploy/my-app -o json

# Check endpoint discovery
istioctl proxy-config endpoints deploy/my-app

# Debug traffic
istioctl proxy-config log deploy/my-app --level debug
```

<!-- chapter:end slug=istio-traffic-management -->

---

<!-- chapter:begin slug=linkerd-patterns position=35 -->

## 35. linkerd-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/linkerd-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/linkerd-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/linkerd-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: linkerd-patterns
description: Implement Linkerd service mesh patterns for lightweight, security-focused service mesh deployments. Use when setting up Linkerd, configuring traffic policies, or implementing zero-trust networking with minimal overhead.
---

# Linkerd Patterns

Production patterns for Linkerd service mesh - the lightweight, security-first service mesh for Kubernetes.

## When to Use This Skill

- Setting up a lightweight service mesh
- Implementing automatic mTLS
- Configuring traffic splits for canary deployments
- Setting up service profiles for per-route metrics
- Implementing retries and timeouts
- Multi-cluster service mesh

## Core Concepts

### 1. Linkerd Architecture

```
┌─────────────────────────────────────────────┐
│                Control Plane                 │
│  ┌─────────┐ ┌──────────┐ ┌──────────────┐ │
│  │ destiny │ │ identity │ │ proxy-inject │ │
│  └─────────┘ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────┘
                      │
┌─────────────────────────────────────────────┐
│                 Data Plane                   │
│  ┌─────┐    ┌─────┐    ┌─────┐             │
│  │proxy│────│proxy│────│proxy│             │
│  └─────┘    └─────┘    └─────┘             │
│     │           │           │               │
│  ┌──┴──┐    ┌──┴──┐    ┌──┴──┐            │
│  │ app │    │ app │    │ app │            │
│  └─────┘    └─────┘    └─────┘            │
└─────────────────────────────────────────────┘
```

### 2. Key Resources

| Resource                | Purpose                              |
| ----------------------- | ------------------------------------ |
| **ServiceProfile**      | Per-route metrics, retries, timeouts |
| **TrafficSplit**        | Canary deployments, A/B testing      |
| **Server**              | Define server-side policies          |
| **ServerAuthorization** | Access control policies              |

## Templates

### Template 1: Mesh Installation

```bash
# Install CLI
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh

# Validate cluster
linkerd check --pre

# Install CRDs
linkerd install --crds | kubectl apply -f -

# Install control plane
linkerd install | kubectl apply -f -

# Verify installation
linkerd check

# Install viz extension (optional)
linkerd viz install | kubectl apply -f -
```

### Template 2: Inject Namespace

```yaml
# Automatic injection for namespace
apiVersion: v1
kind: Namespace
metadata:
  name: my-app
  annotations:
    linkerd.io/inject: enabled
---
# Or inject specific deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  annotations:
    linkerd.io/inject: enabled
spec:
  template:
    metadata:
      annotations:
        linkerd.io/inject: enabled
```

### Template 3: Service Profile with Retries

```yaml
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: my-service.my-namespace.svc.cluster.local
  namespace: my-namespace
spec:
  routes:
    - name: GET /api/users
      condition:
        method: GET
        pathRegex: /api/users
      responseClasses:
        - condition:
            status:
              min: 500
              max: 599
          isFailure: true
      isRetryable: true
    - name: POST /api/users
      condition:
        method: POST
        pathRegex: /api/users
      # POST not retryable by default
      isRetryable: false
    - name: GET /api/users/{id}
      condition:
        method: GET
        pathRegex: /api/users/[^/]+
      timeout: 5s
      isRetryable: true
  retryBudget:
    retryRatio: 0.2
    minRetriesPerSecond: 10
    ttl: 10s
```

### Template 4: Traffic Split (Canary)

```yaml
apiVersion: split.smi-spec.io/v1alpha1
kind: TrafficSplit
metadata:
  name: my-service-canary
  namespace: my-namespace
spec:
  service: my-service
  backends:
    - service: my-service-stable
      weight: 900m # 90%
    - service: my-service-canary
      weight: 100m # 10%
```

### Template 5: Server Authorization Policy

```yaml
# Define the server
apiVersion: policy.linkerd.io/v1beta1
kind: Server
metadata:
  name: my-service-http
  namespace: my-namespace
spec:
  podSelector:
    matchLabels:
      app: my-service
  port: http
  proxyProtocol: HTTP/1
---
# Allow traffic from specific clients
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
metadata:
  name: allow-frontend
  namespace: my-namespace
spec:
  server:
    name: my-service-http
  client:
    meshTLS:
      serviceAccounts:
        - name: frontend
          namespace: my-namespace
---
# Allow unauthenticated traffic (e.g., from ingress)
apiVersion: policy.linkerd.io/v1beta1
kind: ServerAuthorization
metadata:
  name: allow-ingress
  namespace: my-namespace
spec:
  server:
    name: my-service-http
  client:
    unauthenticated: true
    networks:
      - cidr: 10.0.0.0/8
```

### Template 6: HTTPRoute for Advanced Routing

```yaml
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
  name: my-route
  namespace: my-namespace
spec:
  parentRefs:
    - name: my-service
      kind: Service
      group: core
      port: 8080
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api/v2
        - headers:
            - name: x-api-version
              value: v2
      backendRefs:
        - name: my-service-v2
          port: 8080
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: my-service-v1
          port: 8080
```

### Template 7: Multi-cluster Setup

```bash
# On each cluster, install with cluster credentials
linkerd multicluster install | kubectl apply -f -

# Link clusters
linkerd multicluster link --cluster-name west \
  --api-server-address https://west.example.com:6443 \
  | kubectl apply -f -

# Export a service to other clusters
kubectl label svc/my-service mirror.linkerd.io/exported=true

# Verify cross-cluster connectivity
linkerd multicluster check
linkerd multicluster gateways
```

## Monitoring Commands

```bash
# Live traffic view
linkerd viz top deploy/my-app

# Per-route metrics
linkerd viz routes deploy/my-app

# Check proxy status
linkerd viz stat deploy -n my-namespace

# View service dependencies
linkerd viz edges deploy -n my-namespace

# Dashboard
linkerd viz dashboard
```

## Debugging

```bash
# Check injection status
linkerd check --proxy -n my-namespace

# View proxy logs
kubectl logs deploy/my-app -c linkerd-proxy

# Debug identity/TLS
linkerd identity -n my-namespace

# Tap traffic (live)
linkerd viz tap deploy/my-app --to deploy/my-backend
```

## Best Practices

### Do's

- **Enable mTLS everywhere** - It's automatic with Linkerd
- **Use ServiceProfiles** - Get per-route metrics and retries
- **Set retry budgets** - Prevent retry storms
- **Monitor golden metrics** - Success rate, latency, throughput

### Don'ts

- **Don't skip check** - Always run `linkerd check` after changes
- **Don't over-configure** - Linkerd defaults are sensible
- **Don't ignore ServiceProfiles** - They unlock advanced features
- **Don't forget timeouts** - Set appropriate values per route

<!-- chapter:end slug=linkerd-patterns -->

---

<!-- chapter:begin slug=mtls-configuration position=36 -->

## 36. mtls-configuration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/mtls-configuration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/mtls-configuration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/mtls-configuration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/mtls-configuration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: mtls-configuration
description: Configure mutual TLS (mTLS) for zero-trust service-to-service communication. Use when implementing zero-trust networking, certificate management, or securing internal service communication.
---

# mTLS Configuration

Comprehensive guide to implementing mutual TLS for zero-trust service mesh communication.

## When to Use This Skill

- Implementing zero-trust networking
- Securing service-to-service communication
- Certificate rotation and management
- Debugging TLS handshake issues
- Compliance requirements (PCI-DSS, HIPAA)
- Multi-cluster secure communication

## Core Concepts

### 1. mTLS Flow

```
┌─────────┐                              ┌─────────┐
│ Service │                              │ Service │
│    A    │                              │    B    │
└────┬────┘                              └────┬────┘
     │                                        │
┌────┴────┐      TLS Handshake          ┌────┴────┐
│  Proxy  │◄───────────────────────────►│  Proxy  │
│(Sidecar)│  1. ClientHello             │(Sidecar)│
│         │  2. ServerHello + Cert      │         │
│         │  3. Client Cert             │         │
│         │  4. Verify Both Certs       │         │
│         │  5. Encrypted Channel       │         │
└─────────┘                              └─────────┘
```

### 2. Certificate Hierarchy

```
Root CA (Self-signed, long-lived)
    │
    ├── Intermediate CA (Cluster-level)
    │       │
    │       ├── Workload Cert (Service A)
    │       └── Workload Cert (Service B)
    │
    └── Intermediate CA (Multi-cluster)
            │
            └── Cross-cluster certs
```

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Start with PERMISSIVE** - Migrate gradually to STRICT
- **Monitor certificate expiry** - Set up alerts
- **Use short-lived certs** - 24h or less for workloads
- **Rotate CA periodically** - Plan for CA rotation
- **Log TLS errors** - For debugging and audit

### Don'ts

- **Don't disable mTLS** - For convenience in production
- **Don't ignore cert expiry** - Automate rotation
- **Don't use self-signed certs** - Use proper CA hierarchy
- **Don't skip verification** - Verify the full chain

<!-- chapter:end slug=mtls-configuration -->

---

<!-- chapter:begin slug=multi-cloud-architecture position=37 -->

## 37. multi-cloud-architecture

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/multi-cloud-architecture/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/multi-cloud-architecture/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/multi-cloud-architecture.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/multi-cloud-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/multi-cloud-architecture/references/multi-cloud-patterns.md
  - `references/service-comparison.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/multi-cloud-architecture/references/service-comparison.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: multi-cloud-architecture
description: Design multi-cloud architectures using a decision framework to select and integrate services across AWS, Azure, GCP, and OCI. Use when building multi-cloud systems, avoiding vendor lock-in, or leveraging best-of-breed services from multiple providers.
---

# Multi-Cloud Architecture

Decision framework and patterns for architecting applications across AWS, Azure, GCP, and OCI.

## Purpose

Design cloud-agnostic architectures and make informed decisions about service selection across cloud providers.

## When to Use

- Design multi-cloud strategies
- Migrate between cloud providers
- Select cloud services for specific workloads
- Implement cloud-agnostic architectures
- Optimize costs across providers

## Cloud Service Comparison

### Compute Services

| AWS     | Azure               | GCP             | OCI                 | Use Case           |
| ------- | ------------------- | --------------- | ------------------- | ------------------ |
| EC2     | Virtual Machines    | Compute Engine  | Compute             | IaaS VMs           |
| ECS     | Container Instances | Cloud Run       | Container Instances | Containers         |
| EKS     | AKS                 | GKE             | OKE                 | Kubernetes         |
| Lambda  | Functions           | Cloud Functions | Functions           | Serverless         |
| Fargate | Container Apps      | Cloud Run       | Container Instances | Managed containers |

### Storage Services

| AWS     | Azure           | GCP             | OCI            | Use Case       |
| ------- | --------------- | --------------- | -------------- | -------------- |
| S3      | Blob Storage    | Cloud Storage   | Object Storage | Object storage |
| EBS     | Managed Disks   | Persistent Disk | Block Volumes  | Block storage  |
| EFS     | Azure Files     | Filestore       | File Storage   | File storage   |
| Glacier | Archive Storage | Archive Storage | Archive Storage | Cold storage   |

### Database Services

| AWS         | Azure            | GCP           | OCI                 | Use Case        |
| ----------- | ---------------- | ------------- | ------------------- | --------------- |
| RDS         | SQL Database     | Cloud SQL     | MySQL HeatWave      | Managed SQL     |
| DynamoDB    | Cosmos DB        | Firestore     | NoSQL Database      | NoSQL           |
| Aurora      | PostgreSQL/MySQL | Cloud Spanner | Autonomous Database | Distributed SQL |
| ElastiCache | Cache for Redis  | Memorystore   | OCI Cache           | Caching         |

**Reference:** See `references/service-comparison.md` for complete comparison

## Multi-Cloud Patterns

### Pattern 1: Single Provider with DR

- Primary workload in one cloud
- Disaster recovery in another
- Database replication across clouds
- Automated failover

### Pattern 2: Best-of-Breed

- Use best service from each provider
- AI/ML on GCP
- Enterprise apps on Azure
- Regulated data platforms on OCI
- General compute on AWS

### Pattern 3: Geographic Distribution

- Serve users from nearest cloud region
- Data sovereignty compliance
- Global load balancing
- Regional failover

### Pattern 4: Cloud-Agnostic Abstraction

- Kubernetes for compute
- PostgreSQL for database
- S3-compatible storage (MinIO)
- Open source tools

## Cloud-Agnostic Architecture

### Use Cloud-Native Alternatives

- **Compute:** Kubernetes (EKS/AKS/GKE/OKE)
- **Database:** PostgreSQL/MySQL (RDS/SQL Database/Cloud SQL/MySQL HeatWave)
- **Message Queue:** Apache Kafka or managed streaming (MSK/Event Hubs/Confluent/OCI Streaming)
- **Cache:** Redis (ElastiCache/Azure Cache/Memorystore/OCI Cache)
- **Object Storage:** S3-compatible API
- **Monitoring:** Prometheus/Grafana
- **Service Mesh:** Istio/Linkerd

### Abstraction Layers

```
Application Layer
    ↓
Infrastructure Abstraction (Terraform)
    ↓
Cloud Provider APIs
    ↓
AWS / Azure / GCP / OCI
```

## Cost Comparison

### Compute Pricing Factors

- **AWS:** On-demand, Reserved, Spot, Savings Plans
- **Azure:** Pay-as-you-go, Reserved, Spot
- **GCP:** On-demand, Committed use, Preemptible
- **OCI:** Pay-as-you-go, annual commitments, burstable/flexible shapes, preemptible instances

### Cost Optimization Strategies

1. Use reserved/committed capacity (30-70% savings)
2. Leverage spot/preemptible instances
3. Right-size resources
4. Use serverless for variable workloads
5. Optimize data transfer costs
6. Implement lifecycle policies
7. Use cost allocation tags
8. Monitor with cloud cost tools

**Reference:** See `references/multi-cloud-patterns.md`

## Migration Strategy

### Phase 1: Assessment

- Inventory current infrastructure
- Identify dependencies
- Assess cloud compatibility
- Estimate costs

### Phase 2: Pilot

- Select pilot workload
- Implement in target cloud
- Test thoroughly
- Document learnings

### Phase 3: Migration

- Migrate workloads incrementally
- Maintain dual-run period
- Monitor performance
- Validate functionality

### Phase 4: Optimization

- Right-size resources
- Implement cloud-native services
- Optimize costs
- Enhance security

## Best Practices

1. **Use infrastructure as code** (Terraform/OpenTofu)
2. **Implement CI/CD pipelines** for deployments
3. **Design for failure** across clouds
4. **Use managed services** when possible
5. **Implement comprehensive monitoring**
6. **Automate cost optimization**
7. **Follow security best practices**
8. **Document cloud-specific configurations**
9. **Test disaster recovery** procedures
10. **Train teams** on multiple clouds


## Related Skills

- `terraform-module-library` - For IaC implementation
- `cost-optimization` - For cost management
- `hybrid-cloud-networking` - For connectivity

<!-- chapter:end slug=multi-cloud-architecture -->

---

<!-- chapter:begin slug=service-mesh-observability position=38 -->

## 38. service-mesh-observability

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/service-mesh-observability/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/service-mesh-observability/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/service-mesh-observability.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/service-mesh-observability/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: service-mesh-observability
description: Implement comprehensive observability for service meshes including distributed tracing, metrics, and visualization. Use when setting up mesh monitoring, debugging latency issues, or implementing SLOs for service communication.
---

# Service Mesh Observability

Complete guide to observability patterns for Istio, Linkerd, and service mesh deployments.

## When to Use This Skill

- Setting up distributed tracing across services
- Implementing service mesh metrics and dashboards
- Debugging latency and error issues
- Defining SLOs for service communication
- Visualizing service dependencies
- Troubleshooting mesh connectivity

## Core Concepts

### 1. Three Pillars of Observability

```
┌─────────────────────────────────────────────────────┐
│                  Observability                       │
├─────────────────┬─────────────────┬─────────────────┤
│     Metrics     │     Traces      │      Logs       │
│                 │                 │                 │
│ • Request rate  │ • Span context  │ • Access logs   │
│ • Error rate    │ • Latency       │ • Error details │
│ • Latency P50   │ • Dependencies  │ • Debug info    │
│ • Saturation    │ • Bottlenecks   │ • Audit trail   │
└─────────────────┴─────────────────┴─────────────────┘
```

### 2. Golden Signals for Mesh

| Signal         | Description               | Alert Threshold   |
| -------------- | ------------------------- | ----------------- |
| **Latency**    | Request duration P50, P99 | P99 > 500ms       |
| **Traffic**    | Requests per second       | Anomaly detection |
| **Errors**     | 5xx error rate            | > 1%              |
| **Saturation** | Resource utilization      | > 80%             |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Sample appropriately** - 100% in dev, 1-10% in prod
- **Use trace context** - Propagate headers consistently
- **Set up alerts** - For golden signals
- **Correlate metrics/traces** - Use exemplars
- **Retain strategically** - Hot/cold storage tiers

### Don'ts

- **Don't over-sample** - Storage costs add up
- **Don't ignore cardinality** - Limit label values
- **Don't skip dashboards** - Visualize dependencies
- **Don't forget costs** - Monitor observability costs

<!-- chapter:end slug=service-mesh-observability -->

---

<!-- chapter:begin slug=terraform-module-library position=39 -->

## 39. terraform-module-library

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/cloud-infrastructure/skills/terraform-module-library/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/terraform-module-library/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/terraform-module-library.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/aws-modules.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/terraform-module-library/references/aws-modules.md
  - `references/oci-modules.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/cloud-infrastructure/skills/terraform-module-library/references/oci-modules.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: terraform-module-library
description: Build reusable Terraform modules for AWS, Azure, GCP, and OCI infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.
---

# Terraform Module Library

Production-ready Terraform module patterns for AWS, Azure, GCP, and OCI infrastructure.

## Purpose

Create reusable, well-tested Terraform modules for common cloud infrastructure patterns across multiple cloud providers.

## When to Use

- Build reusable infrastructure components
- Standardize cloud resource provisioning
- Implement infrastructure as code best practices
- Create multi-cloud compatible modules
- Establish organizational Terraform standards

## Module Structure

```
terraform-modules/
├── aws/
│   ├── vpc/
│   ├── eks/
│   ├── rds/
│   └── s3/
├── azure/
│   ├── vnet/
│   ├── aks/
│   └── storage/
├── gcp/
│   ├── vpc/
│   ├── gke/
│   └── cloud-sql/
└── oci/
    ├── vcn/
    ├── oke/
    └── object-storage/
```

## Standard Module Pattern

```
module-name/
├── main.tf          # Main resources
├── variables.tf     # Input variables
├── outputs.tf       # Output values
├── versions.tf      # Provider versions
├── README.md        # Documentation
├── examples/        # Usage examples
│   └── complete/
│       ├── main.tf
│       └── variables.tf
└── tests/           # Terratest files
    └── module_test.go
```

## AWS VPC Module Example

**main.tf:**

```hcl
resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = var.enable_dns_hostnames
  enable_dns_support   = var.enable_dns_support

  tags = merge(
    {
      Name = var.name
    },
    var.tags
  )
}

resource "aws_subnet" "private" {
  count             = length(var.private_subnet_cidrs)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.private_subnet_cidrs[count.index]
  availability_zone = var.availability_zones[count.index]

  tags = merge(
    {
      Name = "${var.name}-private-${count.index + 1}"
      Tier = "private"
    },
    var.tags
  )
}

resource "aws_internet_gateway" "main" {
  count  = var.create_internet_gateway ? 1 : 0
  vpc_id = aws_vpc.main.id

  tags = merge(
    {
      Name = "${var.name}-igw"
    },
    var.tags
  )
}
```

**variables.tf:**

```hcl
variable "name" {
  description = "Name of the VPC"
  type        = string
}

variable "cidr_block" {
  description = "CIDR block for VPC"
  type        = string
  validation {
    condition     = can(regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$", var.cidr_block))
    error_message = "CIDR block must be valid IPv4 CIDR notation."
  }
}

variable "availability_zones" {
  description = "List of availability zones"
  type        = list(string)
}

variable "private_subnet_cidrs" {
  description = "CIDR blocks for private subnets"
  type        = list(string)
  default     = []
}

variable "enable_dns_hostnames" {
  description = "Enable DNS hostnames in VPC"
  type        = bool
  default     = true
}

variable "tags" {
  description = "Additional tags"
  type        = map(string)
  default     = {}
}
```

**outputs.tf:**

```hcl
output "vpc_id" {
  description = "ID of the VPC"
  value       = aws_vpc.main.id
}

output "private_subnet_ids" {
  description = "IDs of private subnets"
  value       = aws_subnet.private[*].id
}

output "vpc_cidr_block" {
  description = "CIDR block of VPC"
  value       = aws_vpc.main.cidr_block
}
```

## Best Practices

1. **Use semantic versioning** for modules
2. **Document all variables** with descriptions
3. **Provide examples** in examples/ directory
4. **Use validation blocks** for input validation
5. **Output important attributes** for module composition
6. **Pin provider versions** in versions.tf
7. **Use locals** for computed values
8. **Implement conditional resources** with count/for_each
9. **Test modules** with Terratest
10. **Tag all resources** consistently

**Reference:** See `references/aws-modules.md` and `references/oci-modules.md`

## Module Composition

```hcl
module "vpc" {
  source = "../../modules/aws/vpc"

  name               = "production"
  cidr_block         = "10.0.0.0/16"
  availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]

  private_subnet_cidrs = [
    "10.0.1.0/24",
    "10.0.2.0/24",
    "10.0.3.0/24"
  ]

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

module "rds" {
  source = "../../modules/aws/rds"

  identifier     = "production-db"
  engine         = "postgres"
  engine_version = "15.3"
  instance_class = "db.t3.large"

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids

  tags = {
    Environment = "production"
  }
}
```


## Testing

```go
// tests/vpc_test.go
package test

import (
    "testing"
    "github.com/gruntwork-io/terratest/modules/terraform"
    "github.com/stretchr/testify/assert"
)

func TestVPCModule(t *testing.T) {
    terraformOptions := &terraform.Options{
        TerraformDir: "../examples/complete",
    }

    defer terraform.Destroy(t, terraformOptions)
    terraform.InitAndApply(t, terraformOptions)

    vpcID := terraform.Output(t, terraformOptions, "vpc_id")
    assert.NotEmpty(t, vpcID)
}
```

## Related Skills

- `multi-cloud-architecture` - For architectural decisions
- `cost-optimization` - For cost-effective designs

<!-- chapter:end slug=terraform-module-library -->

---

## Part: Conductor

---

<!-- chapter:begin slug=context-driven-development position=40 -->

## 40. context-driven-development

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/conductor/skills/context-driven-development/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/context-driven-development/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/context-driven-development.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/artifact-templates.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/context-driven-development/references/artifact-templates.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/context-driven-development/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: context-driven-development
description: >-
  Creates and maintains project context artifacts (product.md, tech-stack.md, workflow.md, tracks.md)
  in a `conductor/` directory. Scaffolds new projects from scratch, extracts context from existing
  codebases, validates artifact consistency before implementation, and synchronizes documents as the
  project evolves. Use when setting up a project, creating or updating product docs, managing a tech
  stack file, defining development workflows, tracking work units, onboarding to an existing codebase,
  or running project scaffolding.
version: 1.0.0
---

# Context-Driven Development

Guide for implementing and maintaining context as a managed artifact alongside code, enabling consistent AI interactions and team alignment through structured project documentation.

## When to Use This Skill

- Setting up new projects with Conductor
- Understanding the relationship between context artifacts
- Maintaining consistency across AI-assisted development sessions
- Onboarding team members to an existing Conductor project
- Deciding when to update context documents
- Managing greenfield vs brownfield project contexts

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Read context first**: Always read relevant artifacts before starting work
2. **Small updates**: Make incremental context changes, not massive rewrites
3. **Link decisions**: Reference context when making implementation choices
4. **Version context**: Commit context changes alongside code changes
5. **Review context**: Include context artifact reviews in code reviews
6. **Validate regularly**: Run context validation checklist before major work
7. **Communicate changes**: Notify team when context artifacts change significantly
8. **Preserve history**: Use git to track context evolution over time
9. **Question staleness**: If context feels wrong, investigate and update
10. **Keep it actionable**: Every context item should inform a decision or behavior

<!-- chapter:end slug=context-driven-development -->

---

<!-- chapter:begin slug=track-management position=41 -->

## 41. track-management

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/conductor/skills/track-management/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/track-management/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/track-management.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/track-management/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: track-management
description: Use this skill when creating, managing, or working with Conductor tracks - the logical work units for features, bugs, and refactors. Applies to spec.md, plan.md, and track lifecycle operations.
version: 1.0.0
---

# Track Management

Guide for creating, managing, and completing Conductor tracks - the logical work units that organize features, bugs, and refactors through specification, planning, and implementation phases.

## When to Use This Skill

- Creating new feature, bug, or refactor tracks
- Writing or reviewing spec.md files
- Creating or updating plan.md files
- Managing track lifecycle from creation to completion
- Understanding track status markers and conventions
- Working with the tracks.md registry
- Interpreting or updating track metadata

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **One track, one concern**: Keep tracks focused on a single logical change
2. **Small phases**: Break work into phases of 3-5 tasks maximum
3. **Verification after phases**: Always include verification tasks
4. **Update markers immediately**: Mark task status as you work
5. **Record SHAs**: Always note commit SHAs for completed tasks
6. **Review specs before planning**: Ensure spec is complete before creating plan
7. **Link dependencies**: Explicitly note track dependencies
8. **Archive, don't delete**: Preserve completed tracks for reference
9. **Size appropriately**: Keep tracks between 1-5 days of work
10. **Clear acceptance criteria**: Every requirement must be testable

<!-- chapter:end slug=track-management -->

---

<!-- chapter:begin slug=workflow-patterns position=42 -->

## 42. workflow-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/conductor/skills/workflow-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/workflow-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/workflow-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/conductor/skills/workflow-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: workflow-patterns
description: Use this skill when implementing tasks according to Conductor's TDD workflow, handling phase checkpoints, managing git commits for tasks, or understanding the verification protocol.
version: 1.0.0
---

# Workflow Patterns

Guide for implementing tasks using Conductor's TDD workflow, managing phase checkpoints, handling git commits, and executing the verification protocol that ensures quality throughout implementation.

## When to Use This Skill

- Implementing tasks from a track's plan.md
- Following TDD red-green-refactor cycle
- Completing phase checkpoints
- Managing git commits and notes
- Understanding quality assurance gates
- Handling verification protocols
- Recording progress in plan files

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Never skip RED**: Always write failing tests first
2. **Small commits**: One logical change per commit
3. **Immediate updates**: Update plan.md right after task completion
4. **Wait for approval**: Never skip checkpoint verification
5. **Rich git notes**: Include context that helps future understanding
6. **Coverage discipline**: Don't accept coverage below target
7. **Quality gates**: Check all gates before marking complete
8. **Sequential phases**: Complete phases in order
9. **Document deviations**: Note any changes from original plan
10. **Clean state**: Each commit should leave code in working state
11. **Fast feedback**: Run relevant tests frequently during development
12. **Clear blockers**: Address blockers promptly, don't work around them

<!-- chapter:end slug=workflow-patterns -->

---

## Part: Data Engineering

---

<!-- chapter:begin slug=airflow-dag-patterns position=43 -->

## 43. airflow-dag-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/data-engineering/skills/airflow-dag-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/airflow-dag-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/airflow-dag-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/airflow-dag-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: airflow-dag-patterns
description: Build production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workflows, or scheduling batch jobs.
---

# Apache Airflow DAG Patterns

Production-ready patterns for Apache Airflow including DAG design, operators, sensors, testing, and deployment strategies.

## When to Use This Skill

- Creating data pipeline orchestration with Airflow
- Designing DAG structures and dependencies
- Implementing custom operators and sensors
- Testing Airflow DAGs locally
- Setting up Airflow in production
- Debugging failed DAG runs

## Core Concepts

### 1. DAG Design Principles

| Principle       | Description                         |
| --------------- | ----------------------------------- |
| **Idempotent**  | Running twice produces same result  |
| **Atomic**      | Tasks succeed or fail completely    |
| **Incremental** | Process only new/changed data       |
| **Observable**  | Logs, metrics, alerts at every step |

### 2. Task Dependencies

```python
# Linear
task1 >> task2 >> task3

# Fan-out
task1 >> [task2, task3, task4]

# Fan-in
[task1, task2, task3] >> task4

# Complex
task1 >> task2 >> task4
task1 >> task3 >> task4
```

## Quick Start

```python
# dags/example_dag.py
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python import PythonOperator
from airflow.operators.empty import EmptyOperator

default_args = {
    'owner': 'data-team',
    'depends_on_past': False,
    'email_on_failure': True,
    'email_on_retry': False,
    'retries': 3,
    'retry_delay': timedelta(minutes=5),
    'retry_exponential_backoff': True,
    'max_retry_delay': timedelta(hours=1),
}

with DAG(
    dag_id='example_etl',
    default_args=default_args,
    description='Example ETL pipeline',
    schedule='0 6 * * *',  # Daily at 6 AM
    start_date=datetime(2024, 1, 1),
    catchup=False,
    tags=['etl', 'example'],
    max_active_runs=1,
) as dag:

    start = EmptyOperator(task_id='start')

    def extract_data(**context):
        execution_date = context['ds']
        # Extract logic here
        return {'records': 1000}

    extract = PythonOperator(
        task_id='extract',
        python_callable=extract_data,
    )

    end = EmptyOperator(task_id='end')

    start >> extract >> end
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use TaskFlow API** - Cleaner code, automatic XCom
- **Set timeouts** - Prevent zombie tasks
- **Use `mode='reschedule'`** - For sensors, free up workers
- **Test DAGs** - Unit tests and integration tests
- **Idempotent tasks** - Safe to retry

### Don'ts

- **Don't use `depends_on_past=True`** - Creates bottlenecks
- **Don't hardcode dates** - Use `{{ ds }}` macros
- **Don't use global state** - Tasks should be stateless
- **Don't skip catchup blindly** - Understand implications
- **Don't put heavy logic in DAG file** - Import from modules

<!-- chapter:end slug=airflow-dag-patterns -->

---

<!-- chapter:begin slug=data-quality-frameworks position=44 -->

## 44. data-quality-frameworks

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/data-engineering/skills/data-quality-frameworks/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/data-quality-frameworks/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/data-quality-frameworks.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/data-quality-frameworks/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: data-quality-frameworks
description: Implement data quality validation with Great Expectations, dbt tests, and data contracts. Use when building data quality pipelines, implementing validation rules, or establishing data contracts.
---

# Data Quality Frameworks

Production patterns for implementing data quality with Great Expectations, dbt tests, and data contracts to ensure reliable data pipelines.

## When to Use This Skill

- Implementing data quality checks in pipelines
- Setting up Great Expectations validation
- Building comprehensive dbt test suites
- Establishing data contracts between teams
- Monitoring data quality metrics
- Automating data validation in CI/CD

## Core Concepts

### 1. Data Quality Dimensions

| Dimension        | Description              | Example Check                                      |
| ---------------- | ------------------------ | -------------------------------------------------- |
| **Completeness** | No missing values        | `expect_column_values_to_not_be_null`              |
| **Uniqueness**   | No duplicates            | `expect_column_values_to_be_unique`                |
| **Validity**     | Values in expected range | `expect_column_values_to_be_in_set`                |
| **Accuracy**     | Data matches reality     | Cross-reference validation                         |
| **Consistency**  | No contradictions        | `expect_column_pair_values_A_to_be_greater_than_B` |
| **Timeliness**   | Data is recent           | `expect_column_max_to_be_between`                  |

### 2. Testing Pyramid for Data

```
          /\
         /  \     Integration Tests (cross-table)
        /────\
       /      \   Unit Tests (single column)
      /────────\
     /          \ Schema Tests (structure)
    /────────────\
```

## Quick Start

### Great Expectations Setup

```bash
# Install
pip install great_expectations

# Initialize project
great_expectations init

# Create datasource
great_expectations datasource new
```

```python
# great_expectations/checkpoints/daily_validation.yml
import great_expectations as gx

# Create context
context = gx.get_context()

# Create expectation suite
suite = context.add_expectation_suite("orders_suite")

# Add expectations
suite.add_expectation(
    gx.expectations.ExpectColumnValuesToNotBeNull(column="order_id")
)
suite.add_expectation(
    gx.expectations.ExpectColumnValuesToBeUnique(column="order_id")
)

# Validate
results = context.run_checkpoint(checkpoint_name="daily_orders")
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Summary: {total_passed}/{total_tables} tables passed")
        report.append("")

        for table, result in results.items():
            status = "✅" if result.passed else "❌"
            report.append(f"### {status} {table}")
            report.append(f"- Expectations: {result.total_expectations}")
            report.append(f"- Failed: {result.failed_expectations}")

            if not result.passed:
                report.append("- Failed checks:")
                for detail in result.details:
                    if not detail["success"]:
                        report.append(f"  - {detail['expectation']}: {detail['observed_value']}")
            report.append("")

        return "\n".join(report)

# Usage
context = gx.get_context()
pipeline = DataQualityPipeline(context)

tables_to_validate = {
    "orders": "orders_suite",
    "customers": "customers_suite",
    "products": "products_suite",
}

results = pipeline.run_all(tables_to_validate)
report = pipeline.generate_report(results)

# Fail pipeline if any table failed
if not all(r.passed for r in results.values()):
    print(report)
    raise ValueError("Data quality checks failed!")
```

## Best Practices

### Do's

- **Test early** - Validate source data before transformations
- **Test incrementally** - Add tests as you find issues
- **Document expectations** - Clear descriptions for each test
- **Alert on failures** - Integrate with monitoring
- **Version contracts** - Track schema changes

### Don'ts

- **Don't test everything** - Focus on critical columns
- **Don't ignore warnings** - They often precede failures
- **Don't skip freshness** - Stale data is bad data
- **Don't hardcode thresholds** - Use dynamic baselines
- **Don't test in isolation** - Test relationships too

<!-- chapter:end slug=data-quality-frameworks -->

---

<!-- chapter:begin slug=dbt-transformation-patterns position=45 -->

## 45. dbt-transformation-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/data-engineering/skills/dbt-transformation-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/dbt-transformation-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/dbt-transformation-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/dbt-transformation-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: dbt-transformation-patterns
description: Master dbt (data build tool) for analytics engineering with model organization, testing, documentation, and incremental strategies. Use when building data transformations, creating data models, or implementing analytics engineering best practices.
---

# dbt Transformation Patterns

Production-ready patterns for dbt (data build tool) including model organization, testing strategies, documentation, and incremental processing.

## When to Use This Skill

- Building data transformation pipelines with dbt
- Organizing models into staging, intermediate, and marts layers
- Implementing data quality tests
- Creating incremental models for large datasets
- Documenting data models and lineage
- Setting up dbt project structure

## Core Concepts

### 1. Model Layers (Medallion Architecture)

```
sources/          Raw data definitions
    ↓
staging/          1:1 with source, light cleaning
    ↓
intermediate/     Business logic, joins, aggregations
    ↓
marts/            Final analytics tables
```

### 2. Naming Conventions

| Layer        | Prefix         | Example                       |
| ------------ | -------------- | ----------------------------- |
| Staging      | `stg_`         | `stg_stripe__payments`        |
| Intermediate | `int_`         | `int_payments_pivoted`        |
| Marts        | `dim_`, `fct_` | `dim_customers`, `fct_orders` |

## Quick Start

```yaml
# dbt_project.yml
name: "analytics"
version: "1.0.0"
profile: "analytics"

model-paths: ["models"]
analysis-paths: ["analyses"]
test-paths: ["tests"]
seed-paths: ["seeds"]
macro-paths: ["macros"]

vars:
  start_date: "2020-01-01"

models:
  analytics:
    staging:
      +materialized: view
      +schema: staging
    intermediate:
      +materialized: ephemeral
    marts:
      +materialized: table
      +schema: analytics
```

```
# Project structure
models/
├── staging/
│   ├── stripe/
│   │   ├── _stripe__sources.yml
│   │   ├── _stripe__models.yml
│   │   ├── stg_stripe__customers.sql
│   │   └── stg_stripe__payments.sql
│   └── shopify/
│       ├── _shopify__sources.yml
│       └── stg_shopify__orders.sql
├── intermediate/
│   └── finance/
│       └── int_payments_pivoted.sql
└── marts/
    ├── core/
    │   ├── _core__models.yml
    │   ├── dim_customers.sql
    │   └── fct_orders.sql
    └── finance/
        └── fct_revenue.sql
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use staging layer** - Clean data once, use everywhere
- **Test aggressively** - Not null, unique, relationships
- **Document everything** - Column descriptions, model descriptions
- **Use incremental** - For tables > 1M rows
- **Version control** - dbt project in Git

### Don'ts

- **Don't skip staging** - Raw → mart is tech debt
- **Don't hardcode dates** - Use `{{ var('start_date') }}`
- **Don't repeat logic** - Extract to macros
- **Don't test in prod** - Use dev target
- **Don't ignore freshness** - Monitor source data

<!-- chapter:end slug=dbt-transformation-patterns -->

---

<!-- chapter:begin slug=spark-optimization position=46 -->

## 46. spark-optimization

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/data-engineering/skills/spark-optimization/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/spark-optimization/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/spark-optimization.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/data-engineering/skills/spark-optimization/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: spark-optimization
description: Optimize Apache Spark jobs with partitioning, caching, shuffle optimization, and memory tuning. Use when improving Spark performance, debugging slow jobs, or scaling data processing pipelines.
---

# Apache Spark Optimization

Production patterns for optimizing Apache Spark jobs including partitioning strategies, memory management, shuffle optimization, and performance tuning.

## When to Use This Skill

- Optimizing slow Spark jobs
- Tuning memory and executor configuration
- Implementing efficient partitioning strategies
- Debugging Spark performance issues
- Scaling Spark pipelines for large datasets
- Reducing shuffle and data skew

## Core Concepts

### 1. Spark Execution Model

```
Driver Program
    ↓
Job (triggered by action)
    ↓
Stages (separated by shuffles)
    ↓
Tasks (one per partition)
```

### 2. Key Performance Factors

| Factor            | Impact                | Solution                      |
| ----------------- | --------------------- | ----------------------------- |
| **Shuffle**       | Network I/O, disk I/O | Minimize wide transformations |
| **Data Skew**     | Uneven task duration  | Salting, broadcast joins      |
| **Serialization** | CPU overhead          | Use Kryo, columnar formats    |
| **Memory**        | GC pressure, spills   | Tune executor memory          |
| **Partitions**    | Parallelism           | Right-size partitions         |

## Quick Start

```python
from pyspark.sql import SparkSession
from pyspark.sql import functions as F

# Create optimized Spark session
spark = (SparkSession.builder
    .appName("OptimizedJob")
    .config("spark.sql.adaptive.enabled", "true")
    .config("spark.sql.adaptive.coalescePartitions.enabled", "true")
    .config("spark.sql.adaptive.skewJoin.enabled", "true")
    .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
    .config("spark.sql.shuffle.partitions", "200")
    .getOrCreate())

# Read with optimized settings
df = (spark.read
    .format("parquet")
    .option("mergeSchema", "false")
    .load("s3://bucket/data/"))

# Efficient transformations
result = (df
    .filter(F.col("date") >= "2024-01-01")
    .select("id", "amount", "category")
    .groupBy("category")
    .agg(F.sum("amount").alias("total")))

result.write.mode("overwrite").parquet("s3://bucket/output/")
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Enable AQE** - Adaptive query execution handles many issues
- **Use Parquet/Delta** - Columnar formats with compression
- **Broadcast small tables** - Avoid shuffle for small joins
- **Monitor Spark UI** - Check for skew, spills, GC
- **Right-size partitions** - 128MB - 256MB per partition

### Don'ts

- **Don't collect large data** - Keep data distributed
- **Don't use UDFs unnecessarily** - Use built-in functions
- **Don't over-cache** - Memory is limited
- **Don't ignore data skew** - It dominates job time
- **Don't use `.count()` for existence** - Use `.take(1)` or `.isEmpty()`

<!-- chapter:end slug=spark-optimization -->

---

## Part: Database Design

---

<!-- chapter:begin slug=postgresql position=47 -->

## 47. postgresql-table-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/database-design/skills/postgresql/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/database-design/skills/postgresql/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/postgresql.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: postgresql-table-design
description: Use this skill when designing or reviewing a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features
---

# PostgreSQL Table Design

## Core Rules

- Define a **PRIMARY KEY** for reference tables (users, orders, etc.). Not always needed for time-series/event/log data. When used, prefer `BIGINT GENERATED ALWAYS AS IDENTITY`; use `UUID` only when global uniqueness/opacity is needed.
- **Normalize first (to 3NF)** to eliminate data redundancy and update anomalies; denormalize **only** for measured, high-ROI reads where join performance is proven problematic. Premature denormalization creates maintenance burden.
- Add **NOT NULL** everywhere it’s semantically required; use **DEFAULT**s for common values.
- Create **indexes for access paths you actually query**: PK/unique (auto), **FK columns (manual!)**, frequent filters/sorts, and join keys.
- Prefer **TIMESTAMPTZ** for event time; **NUMERIC** for money; **TEXT** for strings; **BIGINT** for integer values, **DOUBLE PRECISION** for floats (or `NUMERIC` for exact decimal arithmetic).

## PostgreSQL “Gotchas”

- **Identifiers**: unquoted → lowercased. Avoid quoted/mixed-case names. Convention: use `snake_case` for table/column names.
- **Unique + NULLs**: UNIQUE allows multiple NULLs. Use `UNIQUE (...) NULLS NOT DISTINCT` (PG15+) to restrict to one NULL.
- **FK indexes**: PostgreSQL **does not** auto-index FK columns. Add them.
- **No silent coercions**: length/precision overflows error out (no truncation). Example: inserting 999 into `NUMERIC(2,0)` fails with error, unlike some databases that silently truncate or round.
- **Sequences/identity have gaps** (normal; don't "fix"). Rollbacks, crashes, and concurrent transactions create gaps in ID sequences (1, 2, 5, 6...). This is expected behavior—don't try to make IDs consecutive.
- **Heap storage**: no clustered PK by default (unlike SQL Server/MySQL InnoDB); `CLUSTER` is one-off reorganization, not maintained on subsequent inserts. Row order on disk is insertion order unless explicitly clustered.
- **MVCC**: updates/deletes leave dead tuples; vacuum handles them—design to avoid hot wide-row churn.

## Data Types

- **IDs**: `BIGINT GENERATED ALWAYS AS IDENTITY` preferred (`GENERATED BY DEFAULT` also fine); `UUID` when merging/federating/used in a distributed system or for opaque IDs. Generate with `uuidv7()` (preferred if using PG18+) or `gen_random_uuid()` (if using an older PG version).
- **Integers**: prefer `BIGINT` unless storage space is critical; `INTEGER` for smaller ranges; avoid `SMALLINT` unless constrained.
- **Floats**: prefer `DOUBLE PRECISION` over `REAL` unless storage space is critical. Use `NUMERIC` for exact decimal arithmetic.
- **Strings**: prefer `TEXT`; if length limits needed, use `CHECK (LENGTH(col) <= n)` instead of `VARCHAR(n)`; avoid `CHAR(n)`. Use `BYTEA` for binary data. Large strings/binary (>2KB default threshold) automatically stored in TOAST with compression. TOAST storage: `PLAIN` (no TOAST), `EXTENDED` (compress + out-of-line), `EXTERNAL` (out-of-line, no compress), `MAIN` (compress, keep in-line if possible). Default `EXTENDED` usually optimal. Control with `ALTER TABLE tbl ALTER COLUMN col SET STORAGE strategy` and `ALTER TABLE tbl SET (toast_tuple_target = 4096)` for threshold. Case-insensitive: for locale/accent handling use non-deterministic collations; for plain ASCII use expression indexes on `LOWER(col)` (preferred unless column needs case-insensitive PK/FK/UNIQUE) or `CITEXT`.
- **Money**: `NUMERIC(p,s)` (never float).
- **Time**: `TIMESTAMPTZ` for timestamps; `DATE` for date-only; `INTERVAL` for durations. Avoid `TIMESTAMP` (without timezone). Use `now()` for transaction start time, `clock_timestamp()` for current wall-clock time.
- **Booleans**: `BOOLEAN` with `NOT NULL` constraint unless tri-state values are required.
- **Enums**: `CREATE TYPE ... AS ENUM` for small, stable sets (e.g. US states, days of week). For business-logic-driven and evolving values (e.g. order statuses) → use TEXT (or INT) + CHECK or lookup table.
- **Arrays**: `TEXT[]`, `INTEGER[]`, etc. Use for ordered lists where you query elements. Index with **GIN** for containment (`@>`, `<@`) and overlap (`&&`) queries. Access: `arr[1]` (1-indexed), `arr[1:3]` (slicing). Good for tags, categories; avoid for relations—use junction tables instead. Literal syntax: `'{val1,val2}'` or `ARRAY[val1,val2]`.
- **Range types**: `daterange`, `numrange`, `tstzrange` for intervals. Support overlap (`&&`), containment (`@>`), operators. Index with **GiST**. Good for scheduling, versioning, numeric ranges. Pick a bounds scheme and use it consistently; prefer `[)` (inclusive/exclusive) by default.
- **Network types**: `INET` for IP addresses, `CIDR` for network ranges, `MACADDR` for MAC addresses. Support network operators (`<<`, `>>`, `&&`).
- **Geometric types**: `POINT`, `LINE`, `POLYGON`, `CIRCLE` for 2D spatial data. Index with **GiST**. Consider **PostGIS** for advanced spatial features.
- **Text search**: `TSVECTOR` for full-text search documents, `TSQUERY` for search queries. Index `tsvector` with **GIN**. Always specify language: `to_tsvector('english', col)` and `to_tsquery('english', 'query')`. Never use single-argument versions. This applies to both index expressions and queries.
- **Domain types**: `CREATE DOMAIN email AS TEXT CHECK (VALUE ~ '^[^@]+@[^@]+$')` for reusable custom types with validation. Enforces constraints across tables.
- **Composite types**: `CREATE TYPE address AS (street TEXT, city TEXT, zip TEXT)` for structured data within columns. Access with `(col).field` syntax.
- **JSONB**: preferred over JSON; index with **GIN**. Use only for optional/semi-structured attrs. ONLY use JSON if the original ordering of the contents MUST be preserved.
- **Vector types**: `vector` type by `pgvector` for vector similarity search for embeddings.

### Do not use the following data types

- DO NOT use `timestamp` (without time zone); DO use `timestamptz` instead.
- DO NOT use `char(n)` or `varchar(n)`; DO use `text` instead.
- DO NOT use `money` type; DO use `numeric` instead.
- DO NOT use `timetz` type; DO use `timestamptz` instead.
- DO NOT use `timestamptz(0)` or any other precision specification; DO use `timestamptz` instead
- DO NOT use `serial` type; DO use `generated always as identity` instead.

## Table Types

- **Regular**: default; fully durable, logged.
- **TEMPORARY**: session-scoped, auto-dropped, not logged. Faster for scratch work.
- **UNLOGGED**: persistent but not crash-safe. Faster writes; good for caches/staging.

## Row-Level Security

Enable with `ALTER TABLE tbl ENABLE ROW LEVEL SECURITY`. Create policies: `CREATE POLICY user_access ON orders FOR SELECT TO app_users USING (user_id = current_user_id())`. Built-in user-based access control at the row level.

## Constraints

- **PK**: implicit UNIQUE + NOT NULL; creates a B-tree index.
- **FK**: specify `ON DELETE/UPDATE` action (`CASCADE`, `RESTRICT`, `SET NULL`, `SET DEFAULT`). Add explicit index on referencing column—speeds up joins and prevents locking issues on parent deletes/updates. Use `DEFERRABLE INITIALLY DEFERRED` for circular FK dependencies checked at transaction end.
- **UNIQUE**: creates a B-tree index; allows multiple NULLs unless `NULLS NOT DISTINCT` (PG15+). Standard behavior: `(1, NULL)` and `(1, NULL)` are allowed. With `NULLS NOT DISTINCT`: only one `(1, NULL)` allowed. Prefer `NULLS NOT DISTINCT` unless you specifically need duplicate NULLs.
- **CHECK**: row-local constraints; NULL values pass the check (three-valued logic). Example: `CHECK (price > 0)` allows NULL prices. Combine with `NOT NULL` to enforce: `price NUMERIC NOT NULL CHECK (price > 0)`.
- **EXCLUDE**: prevents overlapping values using operators. `EXCLUDE USING gist (room_id WITH =, booking_period WITH &&)` prevents double-booking rooms. Requires appropriate index type (often GiST).

## Indexing

- **B-tree**: default for equality/range queries (`=`, `<`, `>`, `BETWEEN`, `ORDER BY`)
- **Composite**: order matters—index used if equality on leftmost prefix (`WHERE a = ? AND b > ?` uses index on `(a,b)`, but `WHERE b = ?` does not). Put most selective/frequently filtered columns first.
- **Covering**: `CREATE INDEX ON tbl (id) INCLUDE (name, email)` - includes non-key columns for index-only scans without visiting table.
- **Partial**: for hot subsets (`WHERE status = 'active'` → `CREATE INDEX ON tbl (user_id) WHERE status = 'active'`). Any query with `status = 'active'` can use this index.
- **Expression**: for computed search keys (`CREATE INDEX ON tbl (LOWER(email))`). Expression must match exactly in WHERE clause: `WHERE LOWER(email) = 'user@example.com'`.
- **GIN**: JSONB containment/existence, arrays (`@>`, `?`), full-text search (`@@`)
- **GiST**: ranges, geometry, exclusion constraints
- **BRIN**: very large, naturally ordered data (time-series)—minimal storage overhead. Effective when row order on disk correlates with indexed column (insertion order or after `CLUSTER`).

## Partitioning

- Use for very large tables (>100M rows) where queries consistently filter on partition key (often time/date).
- Alternate use: use for tables where data maintenance tasks dictates e.g. data pruned or bulk replaced periodically
- **RANGE**: common for time-series (`PARTITION BY RANGE (created_at)`). Create partitions: `CREATE TABLE logs_2024_01 PARTITION OF logs FOR VALUES FROM ('2024-01-01') TO ('2024-02-01')`. **TimescaleDB** automates time-based or ID-based partitioning with retention policies and compression.
- **LIST**: for discrete values (`PARTITION BY LIST (region)`). Example: `FOR VALUES IN ('us-east', 'us-west')`.
- **HASH**: for even distribution when no natural key (`PARTITION BY HASH (user_id)`). Creates N partitions with modulus.
- **Constraint exclusion**: requires `CHECK` constraints on partitions for query planner to prune. Auto-created for declarative partitioning (PG10+).
- Prefer declarative partitioning or hypertables. Do NOT use table inheritance.
- **Limitations**: no global UNIQUE constraints—include partition key in PK/UNIQUE. FKs from partitioned tables not supported; use triggers.

## Special Considerations

### Update-Heavy Tables

- **Separate hot/cold columns**—put frequently updated columns in separate table to minimize bloat.
- **Use `fillfactor=90`** to leave space for HOT updates that avoid index maintenance.
- **Avoid updating indexed columns**—prevents beneficial HOT updates.
- **Partition by update patterns**—separate frequently updated rows in a different partition from stable data.

### Insert-Heavy Workloads

- **Minimize indexes**—only create what you query; every index slows inserts.
- **Use `COPY` or multi-row `INSERT`** instead of single-row inserts.
- **UNLOGGED tables** for rebuildable staging data—much faster writes.
- **Defer index creation** for bulk loads—>drop index, load data, recreate indexes.
- **Partition by time/hash** to distribute load. **TimescaleDB** automates partitioning and compression of insert-heavy data.
- **Use a natural key for primary key** such as a (timestamp, device_id) if enforcing global uniqueness is important many insert-heavy tables don't need a primary key at all.
- If you do need a surrogate key, **Prefer `BIGINT GENERATED ALWAYS AS IDENTITY` over `UUID`**.

### Upsert-Friendly Design

- **Requires UNIQUE index** on conflict target columns—`ON CONFLICT (col1, col2)` needs exact matching unique index (partial indexes don't work).
- **Use `EXCLUDED.column`** to reference would-be-inserted values; only update columns that actually changed to reduce write overhead.
- **`DO NOTHING` faster** than `DO UPDATE` when no actual update needed.

### Safe Schema Evolution

- **Transactional DDL**: most DDL operations can run in transactions and be rolled back—`BEGIN; ALTER TABLE...; ROLLBACK;` for safe testing.
- **Concurrent index creation**: `CREATE INDEX CONCURRENTLY` avoids blocking writes but can't run in transactions.
- **Volatile defaults cause rewrites**: adding `NOT NULL` columns with volatile defaults (e.g., `now()`, `gen_random_uuid()`) rewrites entire table. Non-volatile defaults are fast.
- **Drop constraints before columns**: `ALTER TABLE DROP CONSTRAINT` then `DROP COLUMN` to avoid dependency issues.
- **Function signature changes**: `CREATE OR REPLACE` with different arguments creates overloads, not replacements. DROP old version if no overload desired.

## Generated Columns

- `... GENERATED ALWAYS AS (<expr>) STORED` for computed, indexable fields. PG18+ adds `VIRTUAL` columns (computed on read, not stored).

## Extensions

- **`pgcrypto`**: `crypt()` for password hashing.
- **`uuid-ossp`**: alternative UUID functions; prefer `pgcrypto` for new projects.
- **`pg_trgm`**: fuzzy text search with `%` operator, `similarity()` function. Index with GIN for `LIKE '%pattern%'` acceleration.
- **`citext`**: case-insensitive text type. Prefer expression indexes on `LOWER(col)` unless you need case-insensitive constraints.
- **`btree_gin`/`btree_gist`**: enable mixed-type indexes (e.g., GIN index on both JSONB and text columns).
- **`hstore`**: key-value pairs; mostly superseded by JSONB but useful for simple string mappings.
- **`timescaledb`**: essential for time-series—automated partitioning, retention, compression, continuous aggregates.
- **`postgis`**: comprehensive geospatial support beyond basic geometric types—essential for location-based applications.
- **`pgvector`**: vector similarity search for embeddings.
- **`pgaudit`**: audit logging for all database activity.

## JSONB Guidance

- Prefer `JSONB` with **GIN** index.
- Default: `CREATE INDEX ON tbl USING GIN (jsonb_col);` → accelerates:
  - **Containment** `jsonb_col @> '{"k":"v"}'`
  - **Key existence** `jsonb_col ? 'k'`, **any/all keys** `?\|`, `?&`
  - **Path containment** on nested docs
  - **Disjunction** `jsonb_col @> ANY(ARRAY['{"status":"active"}', '{"status":"pending"}'])`
- Heavy `@>` workloads: consider opclass `jsonb_path_ops` for smaller/faster containment-only indexes:
  - `CREATE INDEX ON tbl USING GIN (jsonb_col jsonb_path_ops);`
  - **Trade-off**: loses support for key existence (`?`, `?|`, `?&`) queries—only supports containment (`@>`)
- Equality/range on a specific scalar field: extract and index with B-tree (generated column or expression):
  - `ALTER TABLE tbl ADD COLUMN price INT GENERATED ALWAYS AS ((jsonb_col->>'price')::INT) STORED;`
  - `CREATE INDEX ON tbl (price);`
  - Prefer queries like `WHERE price BETWEEN 100 AND 500` (uses B-tree) over `WHERE (jsonb_col->>'price')::INT BETWEEN 100 AND 500` without index.
- Arrays inside JSONB: use GIN + `@>` for containment (e.g., tags). Consider `jsonb_path_ops` if only doing containment.
- Keep core relations in tables; use JSONB for optional/variable attributes.
- Use constraints to limit allowed JSONB values in a column e.g. `config JSONB NOT NULL CHECK(jsonb_typeof(config) = 'object')`

## Examples

### Users

```sql
CREATE TABLE users (
  user_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX ON users (LOWER(email));
CREATE INDEX ON users (created_at);
```

### Orders

```sql
CREATE TABLE orders (
  order_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES users(user_id),
  status TEXT NOT NULL DEFAULT 'PENDING' CHECK (status IN ('PENDING','PAID','CANCELED')),
  total NUMERIC(10,2) NOT NULL CHECK (total > 0),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON orders (user_id);
CREATE INDEX ON orders (created_at);
```

### JSONB

```sql
CREATE TABLE profiles (
  user_id BIGINT PRIMARY KEY REFERENCES users(user_id),
  attrs JSONB NOT NULL DEFAULT '{}',
  theme TEXT GENERATED ALWAYS AS (attrs->>'theme') STORED
);
CREATE INDEX profiles_attrs_gin ON profiles USING GIN (attrs);
```

<!-- chapter:end slug=postgresql -->

---

## Part: Developer Essentials

---

<!-- chapter:begin slug=auth-implementation-patterns position=48 -->

## 48. auth-implementation-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/auth-implementation-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/auth-implementation-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/auth-implementation-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/auth-implementation-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: auth-implementation-patterns
description: Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.
---

# Authentication & Authorization Implementation Patterns

Build secure, scalable authentication and authorization systems using industry-standard patterns and modern best practices.

## When to Use This Skill

- Implementing user authentication systems
- Securing REST or GraphQL APIs
- Adding OAuth2/social login
- Implementing role-based access control (RBAC)
- Designing session management
- Migrating authentication systems
- Debugging auth issues
- Implementing SSO or multi-tenancy

## Core Concepts

### 1. Authentication vs Authorization

**Authentication (AuthN)**: Who are you?

- Verifying identity (username/password, OAuth, biometrics)
- Issuing credentials (sessions, tokens)
- Managing login/logout

**Authorization (AuthZ)**: What can you do?

- Permission checking
- Role-based access control (RBAC)
- Resource ownership validation
- Policy enforcement

### 2. Authentication Strategies

**Session-Based:**

- Server stores session state
- Session ID in cookie
- Traditional, simple, stateful

**Token-Based (JWT):**

- Stateless, self-contained
- Scales horizontally
- Can store claims

**OAuth2/OpenID Connect:**

- Delegate authentication
- Social login (Google, GitHub)
- Enterprise SSO

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Never Store Plain Passwords**: Always hash with bcrypt/argon2
2. **Use HTTPS**: Encrypt data in transit
3. **Short-Lived Access Tokens**: 15-30 minutes max
4. **Secure Cookies**: httpOnly, secure, sameSite flags
5. **Validate All Input**: Email format, password strength
6. **Rate Limit Auth Endpoints**: Prevent brute force attacks
7. **Implement CSRF Protection**: For session-based auth
8. **Rotate Secrets Regularly**: JWT secrets, session secrets
9. **Log Security Events**: Login attempts, failed auth
10. **Use MFA When Possible**: Extra security layer

## Common Pitfalls

- **Weak Passwords**: Enforce strong password policies
- **JWT in localStorage**: Vulnerable to XSS, use httpOnly cookies
- **No Token Expiration**: Tokens should expire
- **Client-Side Auth Checks Only**: Always validate server-side
- **Insecure Password Reset**: Use secure tokens with expiration
- **No Rate Limiting**: Vulnerable to brute force
- **Trusting Client Data**: Always validate on server

<!-- chapter:end slug=auth-implementation-patterns -->

---

<!-- chapter:begin slug=bazel-build-optimization position=49 -->

## 49. bazel-build-optimization

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/bazel-build-optimization/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/bazel-build-optimization/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/bazel-build-optimization.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/bazel-build-optimization/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: bazel-build-optimization
description: Optimize Bazel builds for large-scale monorepos. Use when configuring Bazel, implementing remote execution, or optimizing build performance for enterprise codebases.
---

# Bazel Build Optimization

Production patterns for Bazel in large-scale monorepos.

## When to Use This Skill

- Setting up Bazel for monorepos
- Configuring remote caching/execution
- Optimizing build times
- Writing custom Bazel rules
- Debugging build issues
- Migrating to Bazel

## Core Concepts

### 1. Bazel Architecture

```
workspace/
├── WORKSPACE.bazel       # External dependencies
├── .bazelrc              # Build configurations
├── .bazelversion         # Bazel version
├── BUILD.bazel           # Root build file
├── apps/
│   └── web/
│       └── BUILD.bazel
├── libs/
│   └── utils/
│       └── BUILD.bazel
└── tools/
    └── bazel/
        └── rules/
```

### 2. Key Concepts

| Concept     | Description                            |
| ----------- | -------------------------------------- |
| **Target**  | Buildable unit (library, binary, test) |
| **Package** | Directory with BUILD file              |
| **Label**   | Target identifier `//path/to:target`   |
| **Rule**    | Defines how to build a target          |
| **Aspect**  | Cross-cutting build behavior           |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Use fine-grained targets** - Better caching
- **Pin dependencies** - Reproducible builds
- **Enable remote caching** - Share build artifacts
- **Use visibility wisely** - Enforce architecture
- **Write BUILD files per directory** - Standard convention

### Don'ts

- **Don't use glob for deps** - Explicit is better
- **Don't commit bazel-\* dirs** - Add to .gitignore
- **Don't skip WORKSPACE setup** - Foundation of build
- **Don't ignore build warnings** - Technical debt

<!-- chapter:end slug=bazel-build-optimization -->

---

<!-- chapter:begin slug=code-review-excellence position=50 -->

## 50. code-review-excellence

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/code-review-excellence/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/code-review-excellence/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/code-review-excellence.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: code-review-excellence
description: Master effective code review practices to provide constructive feedback, catch bugs early, and foster knowledge sharing while maintaining team morale. Use when reviewing pull requests, establishing review standards, or mentoring developers.
---

# Code Review Excellence

Transform code reviews from gatekeeping to knowledge sharing through constructive feedback, systematic analysis, and collaborative improvement.

## When to Use This Skill

- Reviewing pull requests and code changes
- Establishing code review standards for teams
- Mentoring junior developers through reviews
- Conducting architecture reviews
- Creating review checklists and guidelines
- Improving team collaboration
- Reducing code review cycle time
- Maintaining code quality standards

## Core Principles

### 1. The Review Mindset

**Goals of Code Review:**

- Catch bugs and edge cases
- Ensure code maintainability
- Share knowledge across team
- Enforce coding standards
- Improve design and architecture
- Build team culture

**Not the Goals:**

- Show off knowledge
- Nitpick formatting (use linters)
- Block progress unnecessarily
- Rewrite to your preference

### 2. Effective Feedback

**Good Feedback is:**

- Specific and actionable
- Educational, not judgmental
- Focused on the code, not the person
- Balanced (praise good work too)
- Prioritized (critical vs nice-to-have)

```markdown
❌ Bad: "This is wrong."
✅ Good: "This could cause a race condition when multiple users
access simultaneously. Consider using a mutex here."

❌ Bad: "Why didn't you use X pattern?"
✅ Good: "Have you considered the Repository pattern? It would
make this easier to test. Here's an example: [link]"

❌ Bad: "Rename this variable."
✅ Good: "[nit] Consider `userCount` instead of `uc` for
clarity. Not blocking if you prefer to keep it."
```

### 3. Review Scope

**What to Review:**

- Logic correctness and edge cases
- Security vulnerabilities
- Performance implications
- Test coverage and quality
- Error handling
- Documentation and comments
- API design and naming
- Architectural fit

**What Not to Review Manually:**

- Code formatting (use Prettier, Black, etc.)
- Import organization
- Linting violations
- Simple typos

## Review Process

### Phase 1: Context Gathering (2-3 minutes)

```markdown
Before diving into code, understand:

1. Read PR description and linked issue
2. Check PR size (>400 lines? Ask to split)
3. Review CI/CD status (tests passing?)
4. Understand the business requirement
5. Note any relevant architectural decisions
```

### Phase 2: High-Level Review (5-10 minutes)

```markdown
1. **Architecture & Design**
   - Does the solution fit the problem?
   - Are there simpler approaches?
   - Is it consistent with existing patterns?
   - Will it scale?

2. **File Organization**
   - Are new files in the right places?
   - Is code grouped logically?
   - Are there duplicate files?

3. **Testing Strategy**
   - Are there tests?
   - Do tests cover edge cases?
   - Are tests readable?
```

### Phase 3: Line-by-Line Review (10-20 minutes)

```markdown
For each file:

1. **Logic & Correctness**
   - Edge cases handled?
   - Off-by-one errors?
   - Null/undefined checks?
   - Race conditions?

2. **Security**
   - Input validation?
   - SQL injection risks?
   - XSS vulnerabilities?
   - Sensitive data exposure?

3. **Performance**
   - N+1 queries?
   - Unnecessary loops?
   - Memory leaks?
   - Blocking operations?

4. **Maintainability**
   - Clear variable names?
   - Functions doing one thing?
   - Complex code commented?
   - Magic numbers extracted?
```

### Phase 4: Summary & Decision (2-3 minutes)

```markdown
1. Summarize key concerns
2. Highlight what you liked
3. Make clear decision:
   - ✅ Approve
   - 💬 Comment (minor suggestions)
   - 🔄 Request Changes (must address)
4. Offer to pair if complex
```

## Review Techniques

### Technique 1: The Checklist Method

```markdown
## Security Checklist

- [ ] User input validated and sanitized
- [ ] SQL queries use parameterization
- [ ] Authentication/authorization checked
- [ ] Secrets not hardcoded
- [ ] Error messages don't leak info

## Performance Checklist

- [ ] No N+1 queries
- [ ] Database queries indexed
- [ ] Large lists paginated
- [ ] Expensive operations cached
- [ ] No blocking I/O in hot paths

## Testing Checklist

- [ ] Happy path tested
- [ ] Edge cases covered
- [ ] Error cases tested
- [ ] Test names are descriptive
- [ ] Tests are deterministic
```

### Technique 2: The Question Approach

Instead of stating problems, ask questions to encourage thinking:

```markdown
❌ "This will fail if the list is empty."
✅ "What happens if `items` is an empty array?"

❌ "You need error handling here."
✅ "How should this behave if the API call fails?"

❌ "This is inefficient."
✅ "I see this loops through all users. Have we considered
the performance impact with 100k users?"
```

### Technique 3: Suggest, Don't Command

````markdown
## Use Collaborative Language

❌ "You must change this to use async/await"
✅ "Suggestion: async/await might make this more readable:
`typescript
    async function fetchUser(id: string) {
        const user = await db.query('SELECT * FROM users WHERE id = ?', id);
        return user;
    }
    `
What do you think?"

❌ "Extract this into a function"
✅ "This logic appears in 3 places. Would it make sense to
extract it into a shared utility function?"
````

### Technique 4: Differentiate Severity

```markdown
Use labels to indicate priority:

🔴 [blocking] - Must fix before merge
🟡 [important] - Should fix, discuss if disagree
🟢 [nit] - Nice to have, not blocking
💡 [suggestion] - Alternative approach to consider
📚 [learning] - Educational comment, no action needed
🎉 [praise] - Good work, keep it up!

Example:
"🔴 [blocking] This SQL query is vulnerable to injection.
Please use parameterized queries."

"🟢 [nit] Consider renaming `data` to `userData` for clarity."

"🎉 [praise] Excellent test coverage! This will catch edge cases."
```

## Language-Specific Patterns

### Python Code Review

```python
# Check for Python-specific issues

# ❌ Mutable default arguments
def add_item(item, items=[]):  # Bug! Shared across calls
    items.append(item)
    return items

# ✅ Use None as default
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

# ❌ Catching too broad
try:
    result = risky_operation()
except:  # Catches everything, even KeyboardInterrupt!
    pass

# ✅ Catch specific exceptions
try:
    result = risky_operation()
except ValueError as e:
    logger.error(f"Invalid value: {e}")
    raise

# ❌ Using mutable class attributes
class User:
    permissions = []  # Shared across all instances!

# ✅ Initialize in __init__
class User:
    def __init__(self):
        self.permissions = []
```

### TypeScript/JavaScript Code Review

```typescript
// Check for TypeScript-specific issues

// ❌ Using any defeats type safety
function processData(data: any) {  // Avoid any
    return data.value;
}

// ✅ Use proper types
interface DataPayload {
    value: string;
}
function processData(data: DataPayload) {
    return data.value;
}

// ❌ Not handling async errors
async function fetchUser(id: string) {
    const response = await fetch(`/api/users/${id}`);
    return response.json();  // What if network fails?
}

// ✅ Handle errors properly
async function fetchUser(id: string): Promise<User> {
    try {
        const response = await fetch(`/api/users/${id}`);
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        return await response.json();
    } catch (error) {
        console.error('Failed to fetch user:', error);
        throw error;
    }
}

// ❌ Mutation of props
function UserProfile({ user }: Props) {
    user.lastViewed = new Date();  // Mutating prop!
    return <div>{user.name}</div>;
}

// ✅ Don't mutate props
function UserProfile({ user, onView }: Props) {
    useEffect(() => {
        onView(user.id);  // Notify parent to update
    }, [user.id]);
    return <div>{user.name}</div>;
}
```

## Advanced Review Patterns

### Pattern 1: Architectural Review

```markdown
When reviewing significant changes:

1. **Design Document First**
   - For large features, request design doc before code
   - Review design with team before implementation
   - Agree on approach to avoid rework

2. **Review in Stages**
   - First PR: Core abstractions and interfaces
   - Second PR: Implementation
   - Third PR: Integration and tests
   - Easier to review, faster to iterate

3. **Consider Alternatives**
   - "Have we considered using [pattern/library]?"
   - "What's the tradeoff vs. the simpler approach?"
   - "How will this evolve as requirements change?"
```

### Pattern 2: Test Quality Review

```typescript
// ❌ Poor test: Implementation detail testing
test('increments counter variable', () => {
    const component = render(<Counter />);
    const button = component.getByRole('button');
    fireEvent.click(button);
    expect(component.state.counter).toBe(1);  // Testing internal state
});

// ✅ Good test: Behavior testing
test('displays incremented count when clicked', () => {
    render(<Counter />);
    const button = screen.getByRole('button', { name: /increment/i });
    fireEvent.click(button);
    expect(screen.getByText('Count: 1')).toBeInTheDocument();
});

// Review questions for tests:
// - Do tests describe behavior, not implementation?
// - Are test names clear and descriptive?
// - Do tests cover edge cases?
// - Are tests independent (no shared state)?
// - Can tests run in any order?
```

### Pattern 3: Security Review

```markdown
## Security Review Checklist

### Authentication & Authorization

- [ ] Is authentication required where needed?
- [ ] Are authorization checks before every action?
- [ ] Is JWT validation proper (signature, expiry)?
- [ ] Are API keys/secrets properly secured?

### Input Validation

- [ ] All user inputs validated?
- [ ] File uploads restricted (size, type)?
- [ ] SQL queries parameterized?
- [ ] XSS protection (escape output)?

### Data Protection

- [ ] Passwords hashed (bcrypt/argon2)?
- [ ] Sensitive data encrypted at rest?
- [ ] HTTPS enforced for sensitive data?
- [ ] PII handled according to regulations?

### Common Vulnerabilities

- [ ] No eval() or similar dynamic execution?
- [ ] No hardcoded secrets?
- [ ] CSRF protection for state-changing operations?
- [ ] Rate limiting on public endpoints?
```

## Giving Difficult Feedback

### Pattern: The Sandwich Method (Modified)

```markdown
Traditional: Praise + Criticism + Praise (feels fake)

Better: Context + Specific Issue + Helpful Solution

Example:
"I noticed the payment processing logic is inline in the
controller. This makes it harder to test and reuse.

[Specific Issue]
The calculateTotal() function mixes tax calculation,
discount logic, and database queries, making it difficult
to unit test and reason about.

[Helpful Solution]
Could we extract this into a PaymentService class? That
would make it testable and reusable. I can pair with you
on this if helpful."
```

### Handling Disagreements

```markdown
When author disagrees with your feedback:

1. **Seek to Understand**
   "Help me understand your approach. What led you to
   choose this pattern?"

2. **Acknowledge Valid Points**
   "That's a good point about X. I hadn't considered that."

3. **Provide Data**
   "I'm concerned about performance. Can we add a benchmark
   to validate the approach?"

4. **Escalate if Needed**
   "Let's get [architect/senior dev] to weigh in on this."

5. **Know When to Let Go**
   If it's working and not a critical issue, approve it.
   Perfection is the enemy of progress.
```

## Best Practices

1. **Review Promptly**: Within 24 hours, ideally same day
2. **Limit PR Size**: 200-400 lines max for effective review
3. **Review in Time Blocks**: 60 minutes max, take breaks
4. **Use Review Tools**: GitHub, GitLab, or dedicated tools
5. **Automate What You Can**: Linters, formatters, security scans
6. **Build Rapport**: Emoji, praise, and empathy matter
7. **Be Available**: Offer to pair on complex issues
8. **Learn from Others**: Review others' review comments

## Common Pitfalls

- **Perfectionism**: Blocking PRs for minor style preferences
- **Scope Creep**: "While you're at it, can you also..."
- **Inconsistency**: Different standards for different people
- **Delayed Reviews**: Letting PRs sit for days
- **Ghosting**: Requesting changes then disappearing
- **Rubber Stamping**: Approving without actually reviewing
- **Bike Shedding**: Debating trivial details extensively

## Templates

### PR Review Comment Template

```markdown
## Summary

[Brief overview of what was reviewed]

## Strengths

- [What was done well]
- [Good patterns or approaches]

## Required Changes

🔴 [Blocking issue 1]
🔴 [Blocking issue 2]

## Suggestions

💡 [Improvement 1]
💡 [Improvement 2]

## Questions

❓ [Clarification needed on X]
❓ [Alternative approach consideration]

## Verdict

✅ Approve after addressing required changes
```

<!-- chapter:end slug=code-review-excellence -->

---

<!-- chapter:begin slug=debugging-strategies position=51 -->

## 51. debugging-strategies

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/debugging-strategies/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/debugging-strategies/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/debugging-strategies.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: debugging-strategies
description: Master systematic debugging techniques, profiling tools, and root cause analysis to efficiently track down bugs across any codebase or technology stack. Use when investigating bugs, performance issues, or unexpected behavior.
---

# Debugging Strategies

Transform debugging from frustrating guesswork into systematic problem-solving with proven strategies, powerful tools, and methodical approaches.

## When to Use This Skill

- Tracking down elusive bugs
- Investigating performance issues
- Understanding unfamiliar codebases
- Debugging production issues
- Analyzing crash dumps and stack traces
- Profiling application performance
- Investigating memory leaks
- Debugging distributed systems

## Core Principles

### 1. The Scientific Method

**1. Observe**: What's the actual behavior?
**2. Hypothesize**: What could be causing it?
**3. Experiment**: Test your hypothesis
**4. Analyze**: Did it prove/disprove your theory?
**5. Repeat**: Until you find the root cause

### 2. Debugging Mindset

**Don't Assume:**

- "It can't be X" - Yes it can
- "I didn't change Y" - Check anyway
- "It works on my machine" - Find out why

**Do:**

- Reproduce consistently
- Isolate the problem
- Keep detailed notes
- Question everything
- Take breaks when stuck

### 3. Rubber Duck Debugging

Explain your code and problem out loud (to a rubber duck, colleague, or yourself). Often reveals the issue.

## Systematic Debugging Process

### Phase 1: Reproduce

```markdown
## Reproduction Checklist

1. **Can you reproduce it?**
   - Always? Sometimes? Randomly?
   - Specific conditions needed?
   - Can others reproduce it?

2. **Create minimal reproduction**
   - Simplify to smallest example
   - Remove unrelated code
   - Isolate the problem

3. **Document steps**
   - Write down exact steps
   - Note environment details
   - Capture error messages
```

### Phase 2: Gather Information

```markdown
## Information Collection

1. **Error Messages**
   - Full stack trace
   - Error codes
   - Console/log output

2. **Environment**
   - OS version
   - Language/runtime version
   - Dependencies versions
   - Environment variables

3. **Recent Changes**
   - Git history
   - Deployment timeline
   - Configuration changes

4. **Scope**
   - Affects all users or specific ones?
   - All browsers or specific ones?
   - Production only or also dev?
```

### Phase 3: Form Hypothesis

```markdown
## Hypothesis Formation

Based on gathered info, ask:

1. **What changed?**
   - Recent code changes
   - Dependency updates
   - Infrastructure changes

2. **What's different?**
   - Working vs broken environment
   - Working vs broken user
   - Before vs after

3. **Where could this fail?**
   - Input validation
   - Business logic
   - Data layer
   - External services
```

### Phase 4: Test & Verify

```markdown
## Testing Strategies

1. **Binary Search**
   - Comment out half the code
   - Narrow down problematic section
   - Repeat until found

2. **Add Logging**
   - Strategic console.log/print
   - Track variable values
   - Trace execution flow

3. **Isolate Components**
   - Test each piece separately
   - Mock dependencies
   - Remove complexity

4. **Compare Working vs Broken**
   - Diff configurations
   - Diff environments
   - Diff data
```

## Debugging Tools

### JavaScript/TypeScript Debugging

```typescript
// Chrome DevTools Debugger
function processOrder(order: Order) {
  debugger; // Execution pauses here

  const total = calculateTotal(order);
  console.log("Total:", total);

  // Conditional breakpoint
  if (order.items.length > 10) {
    debugger; // Only breaks if condition true
  }

  return total;
}

// Console debugging techniques
console.log("Value:", value); // Basic
console.table(arrayOfObjects); // Table format
console.time("operation");
/* code */ console.timeEnd("operation"); // Timing
console.trace(); // Stack trace
console.assert(value > 0, "Value must be positive"); // Assertion

// Performance profiling
performance.mark("start-operation");
// ... operation code
performance.mark("end-operation");
performance.measure("operation", "start-operation", "end-operation");
console.log(performance.getEntriesByType("measure"));
```

**VS Code Debugger Configuration:**

```json
// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Program",
      "program": "${workspaceFolder}/src/index.ts",
      "preLaunchTask": "tsc: build - tsconfig.json",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "skipFiles": ["<node_internals>/**"]
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Tests",
      "program": "${workspaceFolder}/node_modules/jest/bin/jest",
      "args": ["--runInBand", "--no-cache"],
      "console": "integratedTerminal"
    }
  ]
}
```

### Python Debugging

```python
# Built-in debugger (pdb)
import pdb

def calculate_total(items):
    total = 0
    pdb.set_trace()  # Debugger starts here

    for item in items:
        total += item.price * item.quantity

    return total

# Breakpoint (Python 3.7+)
def process_order(order):
    breakpoint()  # More convenient than pdb.set_trace()
    # ... code

# Post-mortem debugging
try:
    risky_operation()
except Exception:
    import pdb
    pdb.post_mortem()  # Debug at exception point

# IPython debugging (ipdb)
from ipdb import set_trace
set_trace()  # Better interface than pdb

# Logging for debugging
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

def fetch_user(user_id):
    logger.debug(f'Fetching user: {user_id}')
    user = db.query(User).get(user_id)
    logger.debug(f'Found user: {user}')
    return user

# Profile performance
import cProfile
import pstats

cProfile.run('slow_function()', 'profile_stats')
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative')
stats.print_stats(10)  # Top 10 slowest
```

### Go Debugging

```go
// Delve debugger
// Install: go install github.com/go-delve/delve/cmd/dlv@latest
// Run: dlv debug main.go

import (
    "fmt"
    "runtime"
    "runtime/debug"
)

// Print stack trace
func debugStack() {
    debug.PrintStack()
}

// Panic recovery with debugging
func processRequest() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Panic:", r)
            debug.PrintStack()
        }
    }()

    // ... code that might panic
}

// Memory profiling
import _ "net/http/pprof"
// Visit http://localhost:6060/debug/pprof/

// CPU profiling
import (
    "os"
    "runtime/pprof"
)

f, _ := os.Create("cpu.prof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
// ... code to profile
```

## Advanced Debugging Techniques

### Technique 1: Binary Search Debugging

```bash
# Git bisect for finding regression
git bisect start
git bisect bad                    # Current commit is bad
git bisect good v1.0.0            # v1.0.0 was good

# Git checks out middle commit
# Test it, then:
git bisect good   # if it works
git bisect bad    # if it's broken

# Continue until bug found
git bisect reset  # when done
```

### Technique 2: Differential Debugging

Compare working vs broken:

```markdown
## What's Different?

| Aspect       | Working     | Broken         |
| ------------ | ----------- | -------------- |
| Environment  | Development | Production     |
| Node version | 18.16.0     | 18.15.0        |
| Data         | Empty DB    | 1M records     |
| User         | Admin       | Regular user   |
| Browser      | Chrome      | Safari         |
| Time         | During day  | After midnight |

Hypothesis: Time-based issue? Check timezone handling.
```

### Technique 3: Trace Debugging

```typescript
// Function call tracing
function trace(
  target: any,
  propertyKey: string,
  descriptor: PropertyDescriptor,
) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with args:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`${propertyKey} returned:`, result);
    return result;
  };

  return descriptor;
}

class OrderService {
  @trace
  calculateTotal(items: Item[]): number {
    return items.reduce((sum, item) => sum + item.price, 0);
  }
}
```

### Technique 4: Memory Leak Detection

```typescript
// Chrome DevTools Memory Profiler
// 1. Take heap snapshot
// 2. Perform action
// 3. Take another snapshot
// 4. Compare snapshots

// Node.js memory debugging
if (process.memoryUsage().heapUsed > 500 * 1024 * 1024) {
  console.warn("High memory usage:", process.memoryUsage());

  // Generate heap dump
  require("v8").writeHeapSnapshot();
}

// Find memory leaks in tests
let beforeMemory: number;

beforeEach(() => {
  beforeMemory = process.memoryUsage().heapUsed;
});

afterEach(() => {
  const afterMemory = process.memoryUsage().heapUsed;
  const diff = afterMemory - beforeMemory;

  if (diff > 10 * 1024 * 1024) {
    // 10MB threshold
    console.warn(`Possible memory leak: ${diff / 1024 / 1024}MB`);
  }
});
```

## Debugging Patterns by Issue Type

### Pattern 1: Intermittent Bugs

```markdown
## Strategies for Flaky Bugs

1. **Add extensive logging**
   - Log timing information
   - Log all state transitions
   - Log external interactions

2. **Look for race conditions**
   - Concurrent access to shared state
   - Async operations completing out of order
   - Missing synchronization

3. **Check timing dependencies**
   - setTimeout/setInterval
   - Promise resolution order
   - Animation frame timing

4. **Stress test**
   - Run many times
   - Vary timing
   - Simulate load
```

### Pattern 2: Performance Issues

```markdown
## Performance Debugging

1. **Profile first**
   - Don't optimize blindly
   - Measure before and after
   - Find bottlenecks

2. **Common culprits**
   - N+1 queries
   - Unnecessary re-renders
   - Large data processing
   - Synchronous I/O

3. **Tools**
   - Browser DevTools Performance tab
   - Lighthouse
   - Python: cProfile, line_profiler
   - Node: clinic.js, 0x
```

### Pattern 3: Production Bugs

```markdown
## Production Debugging

1. **Gather evidence**
   - Error tracking (Sentry, Bugsnag)
   - Application logs
   - User reports
   - Metrics/monitoring

2. **Reproduce locally**
   - Use production data (anonymized)
   - Match environment
   - Follow exact steps

3. **Safe investigation**
   - Don't change production
   - Use feature flags
   - Add monitoring/logging
   - Test fixes in staging
```

## Best Practices

1. **Reproduce First**: Can't fix what you can't reproduce
2. **Isolate the Problem**: Remove complexity until minimal case
3. **Read Error Messages**: They're usually helpful
4. **Check Recent Changes**: Most bugs are recent
5. **Use Version Control**: Git bisect, blame, history
6. **Take Breaks**: Fresh eyes see better
7. **Document Findings**: Help future you
8. **Fix Root Cause**: Not just symptoms

## Common Debugging Mistakes

- **Making Multiple Changes**: Change one thing at a time
- **Not Reading Error Messages**: Read the full stack trace
- **Assuming It's Complex**: Often it's simple
- **Debug Logging in Prod**: Remove before shipping
- **Not Using Debugger**: console.log isn't always best
- **Giving Up Too Soon**: Persistence pays off
- **Not Testing the Fix**: Verify it actually works

## Quick Debugging Checklist

```markdown
## When Stuck, Check:

- [ ] Spelling errors (typos in variable names)
- [ ] Case sensitivity (fileName vs filename)
- [ ] Null/undefined values
- [ ] Array index off-by-one
- [ ] Async timing (race conditions)
- [ ] Scope issues (closure, hoisting)
- [ ] Type mismatches
- [ ] Missing dependencies
- [ ] Environment variables
- [ ] File paths (absolute vs relative)
- [ ] Cache issues (clear cache)
- [ ] Stale data (refresh database)
```

<!-- chapter:end slug=debugging-strategies -->

---

<!-- chapter:begin slug=e2e-testing-patterns position=52 -->

## 52. e2e-testing-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/e2e-testing-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/e2e-testing-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/e2e-testing-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/e2e-testing-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: e2e-testing-patterns
description: Master end-to-end testing with Playwright and Cypress to build reliable test suites that catch bugs, improve confidence, and enable fast deployment. Use when implementing E2E tests, debugging flaky tests, or establishing testing standards.
---

# E2E Testing Patterns

Build reliable, fast, and maintainable end-to-end test suites that provide confidence to ship code quickly and catch regressions before users do.

## When to Use This Skill

- Implementing end-to-end test automation
- Debugging flaky or unreliable tests
- Testing critical user workflows
- Setting up CI/CD test pipelines
- Testing across multiple browsers
- Validating accessibility requirements
- Testing responsive designs
- Establishing E2E testing standards

## Core Concepts

### 1. E2E Testing Fundamentals

**What to Test with E2E:**

- Critical user journeys (login, checkout, signup)
- Complex interactions (drag-and-drop, multi-step forms)
- Cross-browser compatibility
- Real API integration
- Authentication flows

**What NOT to Test with E2E:**

- Unit-level logic (use unit tests)
- API contracts (use integration tests)
- Edge cases (too slow)
- Internal implementation details

### 2. Test Philosophy

**The Testing Pyramid:**

```
        /\
       /E2E\         ← Few, focused on critical paths
      /─────\
     /Integr\        ← More, test component interactions
    /────────\
   /Unit Tests\      ← Many, fast, isolated
  /────────────\
```

**Best Practices:**

- Test user behavior, not implementation
- Keep tests independent
- Make tests deterministic
- Optimize for speed
- Use data-testid, not CSS selectors

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Use Data Attributes**: `data-testid` or `data-cy` for stable selectors
2. **Avoid Brittle Selectors**: Don't rely on CSS classes or DOM structure
3. **Test User Behavior**: Click, type, see - not implementation details
4. **Keep Tests Independent**: Each test should run in isolation
5. **Clean Up Test Data**: Create and destroy test data in each test
6. **Use Page Objects**: Encapsulate page logic
7. **Meaningful Assertions**: Check actual user-visible behavior
8. **Optimize for Speed**: Mock when possible, parallel execution

```typescript
// ❌ Bad selectors
cy.get(".btn.btn-primary.submit-button").click();
cy.get("div > form > div:nth-child(2) > input").type("text");

// ✅ Good selectors
cy.getByRole("button", { name: "Submit" }).click();
cy.getByLabel("Email address").type("user@example.com");
cy.get('[data-testid="email-input"]').type("user@example.com");
```

## Common Pitfalls

- **Flaky Tests**: Use proper waits, not fixed timeouts
- **Slow Tests**: Mock external APIs, use parallel execution
- **Over-Testing**: Don't test every edge case with E2E
- **Coupled Tests**: Tests should not depend on each other
- **Poor Selectors**: Avoid CSS classes and nth-child
- **No Cleanup**: Clean up test data after each test
- **Testing Implementation**: Test user behavior, not internals

## Debugging Failing Tests

```typescript
// Playwright debugging
// 1. Run in headed mode
npx playwright test --headed

// 2. Run in debug mode
npx playwright test --debug

// 3. Use trace viewer
await page.screenshot({ path: 'screenshot.png' });
await page.video()?.saveAs('video.webm');

// 4. Add test.step for better reporting
test('checkout flow', async ({ page }) => {
    await test.step('Add item to cart', async () => {
        await page.goto('/products');
        await page.getByRole('button', { name: 'Add to Cart' }).click();
    });

    await test.step('Proceed to checkout', async () => {
        await page.goto('/cart');
        await page.getByRole('button', { name: 'Checkout' }).click();
    });
});

// 5. Inspect page state
await page.pause();  // Pauses execution, opens inspector
```

<!-- chapter:end slug=e2e-testing-patterns -->

---

<!-- chapter:begin slug=error-handling-patterns position=53 -->

## 53. error-handling-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/error-handling-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/error-handling-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/error-handling-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/error-handling-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: error-handling-patterns
description: Master error handling patterns across languages including exceptions, Result types, error propagation, and graceful degradation to build resilient applications. Use when implementing error handling, designing APIs, or improving application reliability.
---

# Error Handling Patterns

Build resilient applications with robust error handling strategies that gracefully handle failures and provide excellent debugging experiences.

## When to Use This Skill

- Implementing error handling in new features
- Designing error-resilient APIs
- Debugging production issues
- Improving application reliability
- Creating better error messages for users and developers
- Implementing retry and circuit breaker patterns
- Handling async/concurrent errors
- Building fault-tolerant distributed systems

## Core Concepts

### 1. Error Handling Philosophies

**Exceptions vs Result Types:**

- **Exceptions**: Traditional try-catch, disrupts control flow
- **Result Types**: Explicit success/failure, functional approach
- **Error Codes**: C-style, requires discipline
- **Option/Maybe Types**: For nullable values

**When to Use Each:**

- Exceptions: Unexpected errors, exceptional conditions
- Result Types: Expected errors, validation failures
- Panics/Crashes: Unrecoverable errors, programming bugs

### 2. Error Categories

**Recoverable Errors:**

- Network timeouts
- Missing files
- Invalid user input
- API rate limits

**Unrecoverable Errors:**

- Out of memory
- Stack overflow
- Programming bugs (null pointer, etc.)

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Fail Fast**: Validate input early, fail quickly
2. **Preserve Context**: Include stack traces, metadata, timestamps
3. **Meaningful Messages**: Explain what happened and how to fix it
4. **Log Appropriately**: Error = log, expected failure = don't spam logs
5. **Handle at Right Level**: Catch where you can meaningfully handle
6. **Clean Up Resources**: Use try-finally, context managers, defer
7. **Don't Swallow Errors**: Log or re-throw, don't silently ignore
8. **Type-Safe Errors**: Use typed errors when possible

```python
# Good error handling example
def process_order(order_id: str) -> Order:
    """Process order with comprehensive error handling."""
    try:
        # Validate input
        if not order_id:
            raise ValidationError("Order ID is required")

        # Fetch order
        order = db.get_order(order_id)
        if not order:
            raise NotFoundError("Order", order_id)

        # Process payment
        try:
            payment_result = payment_service.charge(order.total)
        except PaymentServiceError as e:
            # Log and wrap external service error
            logger.error(f"Payment failed for order {order_id}: {e}")
            raise ExternalServiceError(
                f"Payment processing failed",
                service="payment_service",
                details={"order_id": order_id, "amount": order.total}
            ) from e

        # Update order
        order.status = "completed"
        order.payment_id = payment_result.id
        db.save(order)

        return order

    except ApplicationError:
        # Re-raise known application errors
        raise
    except Exception as e:
        # Log unexpected errors
        logger.exception(f"Unexpected error processing order {order_id}")
        raise ApplicationError(
            "Order processing failed",
            code="INTERNAL_ERROR"
        ) from e
```

## Common Pitfalls

- **Catching Too Broadly**: `except Exception` hides bugs
- **Empty Catch Blocks**: Silently swallowing errors
- **Logging and Re-throwing**: Creates duplicate log entries
- **Not Cleaning Up**: Forgetting to close files, connections
- **Poor Error Messages**: "Error occurred" is not helpful
- **Returning Error Codes**: Use exceptions or Result types
- **Ignoring Async Errors**: Unhandled promise rejections

<!-- chapter:end slug=error-handling-patterns -->

---

<!-- chapter:begin slug=git-advanced-workflows position=54 -->

## 54. git-advanced-workflows

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/git-advanced-workflows/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/git-advanced-workflows/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/git-advanced-workflows.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/git-advanced-workflows/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: git-advanced-workflows
description: Master advanced Git workflows including rebasing, cherry-picking, bisect, worktrees, and reflog to maintain clean history and recover from any situation. Use when managing complex Git histories, collaborating on feature branches, or troubleshooting repository issues.
---

# Git Advanced Workflows

Master advanced Git techniques to maintain clean history, collaborate effectively, and recover from any situation with confidence.

## When to Use This Skill

- Cleaning up commit history before merging
- Applying specific commits across branches
- Finding commits that introduced bugs
- Working on multiple features simultaneously
- Recovering from Git mistakes or lost commits
- Managing complex branch workflows
- Preparing clean PRs for review
- Synchronizing diverged branches

## Core Concepts

### 1. Interactive Rebase

Interactive rebase is the Swiss Army knife of Git history editing.

**Common Operations:**

- `pick`: Keep commit as-is
- `reword`: Change commit message
- `edit`: Amend commit content
- `squash`: Combine with previous commit
- `fixup`: Like squash but discard message
- `drop`: Remove commit entirely

**Basic Usage:**

```bash
# Rebase last 5 commits
git rebase -i HEAD~5

# Rebase all commits on current branch
git rebase -i $(git merge-base HEAD main)

# Rebase onto specific commit
git rebase -i abc123
```

### 2. Cherry-Picking

Apply specific commits from one branch to another without merging entire branches.

```bash
# Cherry-pick single commit
git cherry-pick abc123

# Cherry-pick range of commits (exclusive start)
git cherry-pick abc123..def456

# Cherry-pick without committing (stage changes only)
git cherry-pick -n abc123

# Cherry-pick and edit commit message
git cherry-pick -e abc123
```

### 3. Git Bisect

Binary search through commit history to find the commit that introduced a bug.

```bash
# Start bisect
git bisect start

# Mark current commit as bad
git bisect bad

# Mark known good commit
git bisect good v1.0.0

# Git will checkout middle commit - test it
# Then mark as good or bad
git bisect good  # or: git bisect bad

# Continue until bug found
# When done
git bisect reset
```

**Automated Bisect:**

```bash
# Use script to test automatically
git bisect start HEAD v1.0.0
git bisect run ./test.sh

# test.sh should exit 0 for good, 1-127 (except 125) for bad
```

### 4. Worktrees

Work on multiple branches simultaneously without stashing or switching.

```bash
# List existing worktrees
git worktree list

# Add new worktree for feature branch
git worktree add ../project-feature feature/new-feature

# Add worktree and create new branch
git worktree add -b bugfix/urgent ../project-hotfix main

# Remove worktree
git worktree remove ../project-feature

# Prune stale worktrees
git worktree prune
```

### 5. Reflog

Your safety net - tracks all ref movements, even deleted commits.

```bash
# View reflog
git reflog

# View reflog for specific branch
git reflog show feature/branch

# Restore deleted commit
git reflog
# Find commit hash
git checkout abc123
git branch recovered-branch

# Restore deleted branch
git reflog
git branch deleted-branch abc123
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Always Use --force-with-lease**: Safer than --force, prevents overwriting others' work
2. **Rebase Only Local Commits**: Don't rebase commits that have been pushed and shared
3. **Descriptive Commit Messages**: Future you will thank present you
4. **Atomic Commits**: Each commit should be a single logical change
5. **Test Before Force Push**: Ensure history rewrite didn't break anything
6. **Keep Reflog Aware**: Remember reflog is your safety net for 90 days
7. **Branch Before Risky Operations**: Create backup branch before complex rebases

```bash
# Safe force push
git push --force-with-lease origin feature/branch

# Create backup before risky operation
git branch backup-branch
git rebase -i main
# If something goes wrong
git reset --hard backup-branch
```

## Common Pitfalls

- **Rebasing Public Branches**: Causes history conflicts for collaborators
- **Force Pushing Without Lease**: Can overwrite teammate's work
- **Losing Work in Rebase**: Resolve conflicts carefully, test after rebase
- **Forgetting Worktree Cleanup**: Orphaned worktrees consume disk space
- **Not Backing Up Before Experiment**: Always create safety branch
- **Bisect on Dirty Working Directory**: Commit or stash before bisecting

## Recovery Commands

```bash
# Abort operations in progress
git rebase --abort
git merge --abort
git cherry-pick --abort
git bisect reset

# Restore file to version from specific commit
git restore --source=abc123 path/to/file

# Undo last commit but keep changes
git reset --soft HEAD^

# Undo last commit and discard changes
git reset --hard HEAD^

# Recover deleted branch (within 90 days)
git reflog
git branch recovered-branch abc123
```

<!-- chapter:end slug=git-advanced-workflows -->

---

<!-- chapter:begin slug=monorepo-management position=55 -->

## 55. monorepo-management

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/monorepo-management/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/monorepo-management/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/monorepo-management.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/monorepo-management/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: monorepo-management
description: Master monorepo management with Turborepo, Nx, and pnpm workspaces to build efficient, scalable multi-package repositories with optimized builds and dependency management. Use when setting up monorepos, optimizing builds, or managing shared dependencies.
---

# Monorepo Management

Build efficient, scalable monorepos that enable code sharing, consistent tooling, and atomic changes across multiple packages and applications.

## When to Use This Skill

- Setting up new monorepo projects
- Migrating from multi-repo to monorepo
- Optimizing build and test performance
- Managing shared dependencies
- Implementing code sharing strategies
- Setting up CI/CD for monorepos
- Versioning and publishing packages
- Debugging monorepo-specific issues

## Core Concepts

### 1. Why Monorepos?

**Advantages:**

- Shared code and dependencies
- Atomic commits across projects
- Consistent tooling and standards
- Easier refactoring
- Simplified dependency management
- Better code visibility

**Challenges:**

- Build performance at scale
- CI/CD complexity
- Access control
- Large Git repository

### 2. Monorepo Tools

**Package Managers:**

- pnpm workspaces (recommended)
- npm workspaces
- Yarn workspaces

**Build Systems:**

- Turborepo (recommended for most)
- Nx (feature-rich, complex)
- Lerna (older, maintenance mode)

## Turborepo Setup

### Initial Setup

```bash
# Create new monorepo
npx create-turbo@latest my-monorepo
cd my-monorepo

# Structure:
# apps/
#   web/          - Next.js app
#   docs/         - Documentation site
# packages/
#   ui/           - Shared UI components
#   config/       - Shared configurations
#   tsconfig/     - Shared TypeScript configs
# turbo.json      - Turborepo configuration
# package.json    - Root package.json
```

### Configuration

```json
// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env.*local"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"]
    },
    "lint": {
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "type-check": {
      "dependsOn": ["^build"],
      "outputs": []
    }
  }
}
```

```json
// package.json (root)
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "test": "turbo run test",
    "lint": "turbo run lint",
    "format": "prettier --write \"**/*.{ts,tsx,md}\"",
    "clean": "turbo run clean && rm -rf node_modules"
  },
  "devDependencies": {
    "turbo": "^1.10.0",
    "prettier": "^3.0.0",
    "typescript": "^5.0.0"
  },
  "packageManager": "pnpm@8.0.0"
}
```

### Package Structure

```json
// packages/ui/package.json
{
  "name": "@repo/ui",
  "version": "0.0.0",
  "private": true,
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    },
    "./button": {
      "import": "./dist/button.js",
      "types": "./dist/button.d.ts"
    }
  },
  "scripts": {
    "build": "tsup src/index.ts --format esm,cjs --dts",
    "dev": "tsup src/index.ts --format esm,cjs --dts --watch",
    "lint": "eslint src/",
    "type-check": "tsc --noEmit"
  },
  "devDependencies": {
    "@repo/tsconfig": "workspace:*",
    "tsup": "^7.0.0",
    "typescript": "^5.0.0"
  },
  "dependencies": {
    "react": "^18.2.0"
  }
}
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Consistent Versioning**: Lock dependency versions across workspace
2. **Shared Configs**: Centralize ESLint, TypeScript, Prettier configs
3. **Dependency Graph**: Keep it acyclic, avoid circular dependencies
4. **Cache Effectively**: Configure inputs/outputs correctly
5. **Type Safety**: Share types between frontend/backend
6. **Testing Strategy**: Unit tests in packages, E2E in apps
7. **Documentation**: README in each package
8. **Release Strategy**: Use changesets for versioning

## Common Pitfalls

- **Circular Dependencies**: A depends on B, B depends on A
- **Phantom Dependencies**: Using deps not in package.json
- **Incorrect Cache Inputs**: Missing files in Turborepo inputs
- **Over-Sharing**: Sharing code that should be separate
- **Under-Sharing**: Duplicating code across packages
- **Large Monorepos**: Without proper tooling, builds slow down

## Publishing Packages

```bash
# Using Changesets
pnpm add -Dw @changesets/cli
pnpm changeset init

# Create changeset
pnpm changeset

# Version packages
pnpm changeset version

# Publish
pnpm changeset publish
```

```yaml
# .github/workflows/release.yml
- name: Create Release Pull Request or Publish
  uses: changesets/action@v1
  with:
    publish: pnpm release
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```

<!-- chapter:end slug=monorepo-management -->

---

<!-- chapter:begin slug=nx-workspace-patterns position=56 -->

## 56. nx-workspace-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/nx-workspace-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/nx-workspace-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/nx-workspace-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/nx-workspace-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: nx-workspace-patterns
description: Configure and optimize Nx monorepo workspaces. Use when setting up Nx, configuring project boundaries, optimizing build caching, or implementing affected commands.
---

# Nx Workspace Patterns

Production patterns for Nx monorepo management.

## When to Use This Skill

- Setting up new Nx workspaces
- Configuring project boundaries
- Optimizing CI with affected commands
- Implementing remote caching
- Managing dependencies between projects
- Migrating to Nx

## Core Concepts

### 1. Nx Architecture

```
workspace/
├── apps/              # Deployable applications
│   ├── web/
│   └── api/
├── libs/              # Shared libraries
│   ├── shared/
│   │   ├── ui/
│   │   └── utils/
│   └── feature/
│       ├── auth/
│       └── dashboard/
├── tools/             # Custom executors/generators
├── nx.json            # Nx configuration
└── workspace.json     # Project configuration
```

### 2. Library Types

| Type            | Purpose                          | Example             |
| --------------- | -------------------------------- | ------------------- |
| **feature**     | Smart components, business logic | `feature-auth`      |
| **ui**          | Presentational components        | `ui-buttons`        |
| **data-access** | API calls, state management      | `data-access-users` |
| **util**        | Pure functions, helpers          | `util-formatting`   |
| **shell**       | App bootstrapping                | `shell-web`         |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Use tags consistently** - Enforce with module boundaries
- **Enable caching early** - Significant CI savings
- **Keep libs focused** - Single responsibility
- **Use generators** - Ensure consistency
- **Document boundaries** - Help new developers

### Don'ts

- **Don't create circular deps** - Graph should be acyclic
- **Don't skip affected** - Test only what changed
- **Don't ignore boundaries** - Tech debt accumulates
- **Don't over-granularize** - Balance lib count

<!-- chapter:end slug=nx-workspace-patterns -->

---

<!-- chapter:begin slug=sql-optimization-patterns position=57 -->

## 57. sql-optimization-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/sql-optimization-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/sql-optimization-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/sql-optimization-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/sql-optimization-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: sql-optimization-patterns
description: Master SQL query optimization, indexing strategies, and EXPLAIN analysis to dramatically improve database performance and eliminate slow queries. Use when debugging slow queries, designing database schemas, or optimizing application performance.
---

# SQL Optimization Patterns

Transform slow database queries into lightning-fast operations through systematic optimization, proper indexing, and query plan analysis.

## When to Use This Skill

- Debugging slow-running queries
- Designing performant database schemas
- Optimizing application response times
- Reducing database load and costs
- Improving scalability for growing datasets
- Analyzing EXPLAIN query plans
- Implementing efficient indexes
- Resolving N+1 query problems

## Core Concepts

### 1. Query Execution Plans (EXPLAIN)

Understanding EXPLAIN output is fundamental to optimization.

**PostgreSQL EXPLAIN:**

```sql
-- Basic explain
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';

-- With actual execution stats
EXPLAIN ANALYZE
SELECT * FROM users WHERE email = 'user@example.com';

-- Verbose output with more details
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT u.*, o.order_total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > NOW() - INTERVAL '30 days';
```

**Key Metrics to Watch:**

- **Seq Scan**: Full table scan (usually slow for large tables)
- **Index Scan**: Using index (good)
- **Index Only Scan**: Using index without touching table (best)
- **Nested Loop**: Join method (okay for small datasets)
- **Hash Join**: Join method (good for larger datasets)
- **Merge Join**: Join method (good for sorted data)
- **Cost**: Estimated query cost (lower is better)
- **Rows**: Estimated rows returned
- **Actual Time**: Real execution time

### 2. Index Strategies

Indexes are the most powerful optimization tool.

**Index Types:**

- **B-Tree**: Default, good for equality and range queries
- **Hash**: Only for equality (=) comparisons
- **GIN**: Full-text search, array queries, JSONB
- **GiST**: Geometric data, full-text search
- **BRIN**: Block Range INdex for very large tables with correlation

```sql
-- Standard B-Tree index
CREATE INDEX idx_users_email ON users(email);

-- Composite index (order matters!)
CREATE INDEX idx_orders_user_status ON orders(user_id, status);

-- Partial index (index subset of rows)
CREATE INDEX idx_active_users ON users(email)
WHERE status = 'active';

-- Expression index
CREATE INDEX idx_users_lower_email ON users(LOWER(email));

-- Covering index (include additional columns)
CREATE INDEX idx_users_email_covering ON users(email)
INCLUDE (name, created_at);

-- Full-text search index
CREATE INDEX idx_posts_search ON posts
USING GIN(to_tsvector('english', title || ' ' || body));

-- JSONB index
CREATE INDEX idx_metadata ON events USING GIN(metadata);
```

### 3. Query Optimization Patterns

**Avoid SELECT \*:**

```sql
-- Bad: Fetches unnecessary columns
SELECT * FROM users WHERE id = 123;

-- Good: Fetch only what you need
SELECT id, email, name FROM users WHERE id = 123;
```

**Use WHERE Clause Efficiently:**

```sql
-- Bad: Function prevents index usage
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';

-- Good: Create functional index or use exact match
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
-- Then:
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';

-- Or store normalized data
SELECT * FROM users WHERE email = 'user@example.com';
```

**Optimize JOINs:**

```sql
-- Bad: Cartesian product then filter
SELECT u.name, o.total
FROM users u, orders o
WHERE u.id = o.user_id AND u.created_at > '2024-01-01';

-- Good: Filter before join
SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01';

-- Better: Filter both tables
SELECT u.name, o.total
FROM (SELECT * FROM users WHERE created_at > '2024-01-01') u
JOIN orders o ON u.id = o.user_id;
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Index Selectively**: Too many indexes slow down writes
2. **Monitor Query Performance**: Use slow query logs
3. **Keep Statistics Updated**: Run ANALYZE regularly
4. **Use Appropriate Data Types**: Smaller types = better performance
5. **Normalize Thoughtfully**: Balance normalization vs performance
6. **Cache Frequently Accessed Data**: Use application-level caching
7. **Connection Pooling**: Reuse database connections
8. **Regular Maintenance**: VACUUM, ANALYZE, rebuild indexes

```sql
-- Update statistics
ANALYZE users;
ANALYZE VERBOSE orders;

-- Vacuum (PostgreSQL)
VACUUM ANALYZE users;
VACUUM FULL users;  -- Reclaim space (locks table)

-- Reindex
REINDEX INDEX idx_users_email;
REINDEX TABLE users;
```

## Common Pitfalls

- **Over-Indexing**: Each index slows down INSERT/UPDATE/DELETE
- **Unused Indexes**: Waste space and slow writes
- **Missing Indexes**: Slow queries, full table scans
- **Implicit Type Conversion**: Prevents index usage
- **OR Conditions**: Can't use indexes efficiently
- **LIKE with Leading Wildcard**: `LIKE '%abc'` can't use index
- **Function in WHERE**: Prevents index usage unless functional index exists

## Monitoring Queries

```sql
-- Find slow queries (PostgreSQL)
SELECT query, calls, total_time, mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;

-- Find missing indexes (PostgreSQL)
SELECT
    schemaname,
    tablename,
    seq_scan,
    seq_tup_read,
    idx_scan,
    seq_tup_read / seq_scan AS avg_seq_tup_read
FROM pg_stat_user_tables
WHERE seq_scan > 0
ORDER BY seq_tup_read DESC
LIMIT 10;

-- Find unused indexes (PostgreSQL)
SELECT
    schemaname,
    tablename,
    indexname,
    idx_scan,
    idx_tup_read,
    idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;
```

<!-- chapter:end slug=sql-optimization-patterns -->

---

<!-- chapter:begin slug=turborepo-caching position=58 -->

## 58. turborepo-caching

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/developer-essentials/skills/turborepo-caching/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/developer-essentials/skills/turborepo-caching/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/turborepo-caching.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: turborepo-caching
description: Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.
---

# Turborepo Caching

Production patterns for Turborepo build optimization.

## When to Use This Skill

- Setting up new Turborepo projects
- Configuring build pipelines
- Implementing remote caching
- Optimizing CI/CD performance
- Migrating from other monorepo tools
- Debugging cache misses

## Core Concepts

### 1. Turborepo Architecture

```
Workspace Root/
├── apps/
│   ├── web/
│   │   └── package.json
│   └── docs/
│       └── package.json
├── packages/
│   ├── ui/
│   │   └── package.json
│   └── config/
│       └── package.json
├── turbo.json
└── package.json
```

### 2. Pipeline Concepts

| Concept        | Description                      |
| -------------- | -------------------------------- |
| **dependsOn**  | Tasks that must complete first   |
| **cache**      | Whether to cache outputs         |
| **outputs**    | Files to cache                   |
| **inputs**     | Files that affect cache key      |
| **persistent** | Long-running tasks (dev servers) |

## Templates

### Template 1: turbo.json Configuration

```json
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": [".env", ".env.local"],
  "globalEnv": ["NODE_ENV", "VERCEL_URL"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
      "env": ["API_URL", "NEXT_PUBLIC_*"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
    },
    "lint": {
      "outputs": [],
      "cache": true
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "clean": {
      "cache": false
    }
  }
}
```

### Template 2: Package-Specific Pipeline

```json
// apps/web/turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "extends": ["//"],
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"],
      "env": ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_ANALYTICS_ID"]
    },
    "test": {
      "outputs": ["coverage/**"],
      "inputs": ["src/**", "tests/**", "jest.config.js"]
    }
  }
}
```

### Template 3: Remote Caching with Vercel

```bash
# Login to Vercel
npx turbo login

# Link to Vercel project
npx turbo link

# Run with remote cache
turbo build --remote-only

# CI environment variables
TURBO_TOKEN=your-token
TURBO_TEAM=your-team
```

```yaml
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:

env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npx turbo build --filter='...[origin/main]'

      - name: Test
        run: npx turbo test --filter='...[origin/main]'
```

### Template 4: Self-Hosted Remote Cache

```typescript
// Custom remote cache server (Express)
import express from "express";
import { createReadStream, createWriteStream } from "fs";
import { mkdir } from "fs/promises";
import { join } from "path";

const app = express();
const CACHE_DIR = "./cache";

// Get artifact
app.get("/v8/artifacts/:hash", async (req, res) => {
  const { hash } = req.params;
  const team = req.query.teamId || "default";
  const filePath = join(CACHE_DIR, team, hash);

  try {
    const stream = createReadStream(filePath);
    stream.pipe(res);
  } catch {
    res.status(404).send("Not found");
  }
});

// Put artifact
app.put("/v8/artifacts/:hash", async (req, res) => {
  const { hash } = req.params;
  const team = req.query.teamId || "default";
  const dir = join(CACHE_DIR, team);
  const filePath = join(dir, hash);

  await mkdir(dir, { recursive: true });

  const stream = createWriteStream(filePath);
  req.pipe(stream);

  stream.on("finish", () => {
    res.json({
      urls: [`${req.protocol}://${req.get("host")}/v8/artifacts/${hash}`],
    });
  });
});

// Check artifact exists
app.head("/v8/artifacts/:hash", async (req, res) => {
  const { hash } = req.params;
  const team = req.query.teamId || "default";
  const filePath = join(CACHE_DIR, team, hash);

  try {
    await fs.access(filePath);
    res.status(200).end();
  } catch {
    res.status(404).end();
  }
});

app.listen(3000);
```

```json
// turbo.json for self-hosted cache
{
  "remoteCache": {
    "signature": false
  }
}
```

```bash
# Use self-hosted cache
turbo build --api="http://localhost:3000" --token="my-token" --team="my-team"
```

### Template 5: Filtering and Scoping

```bash
# Build specific package
turbo build --filter=@myorg/web

# Build package and its dependencies
turbo build --filter=@myorg/web...

# Build package and its dependents
turbo build --filter=...@myorg/ui

# Build changed packages since main
turbo build --filter='...[origin/main]'

# Build packages in directory
turbo build --filter='./apps/*'

# Combine filters
turbo build --filter=@myorg/web --filter=@myorg/docs

# Exclude package
turbo build --filter='!@myorg/docs'

# Include dependencies of changed
turbo build --filter='...[HEAD^1]...'
```

### Template 6: Advanced Pipeline Configuration

```json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"],
      "inputs": ["$TURBO_DEFAULT$", "!**/*.md", "!**/*.test.*"]
    },
    "test": {
      "dependsOn": ["^build"],
      "outputs": ["coverage/**"],
      "inputs": ["src/**", "tests/**", "*.config.*"],
      "env": ["CI", "NODE_ENV"]
    },
    "test:e2e": {
      "dependsOn": ["build"],
      "outputs": [],
      "cache": false
    },
    "deploy": {
      "dependsOn": ["build", "test", "lint"],
      "outputs": [],
      "cache": false
    },
    "db:generate": {
      "cache": false
    },
    "db:push": {
      "cache": false,
      "dependsOn": ["db:generate"]
    },
    "@myorg/web#build": {
      "dependsOn": ["^build", "@myorg/db#db:generate"],
      "outputs": [".next/**"],
      "env": ["NEXT_PUBLIC_*"]
    }
  }
}
```

### Template 7: Root package.json Setup

```json
{
  "name": "my-turborepo",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "build": "turbo build",
    "dev": "turbo dev",
    "lint": "turbo lint",
    "test": "turbo test",
    "clean": "turbo clean && rm -rf node_modules",
    "format": "prettier --write \"**/*.{ts,tsx,md}\"",
    "changeset": "changeset",
    "version-packages": "changeset version",
    "release": "turbo build --filter=./packages/* && changeset publish"
  },
  "devDependencies": {
    "turbo": "^1.10.0",
    "prettier": "^3.0.0",
    "@changesets/cli": "^2.26.0"
  },
  "packageManager": "npm@10.0.0"
}
```

## Debugging Cache

```bash
# Dry run to see what would run
turbo build --dry-run

# Verbose output with hashes
turbo build --verbosity=2

# Show task graph
turbo build --graph

# Force no cache
turbo build --force

# Show cache status
turbo build --summarize

# Debug specific task
TURBO_LOG_VERBOSITY=debug turbo build --filter=@myorg/web
```

## Best Practices

### Do's

- **Define explicit inputs** - Avoid cache invalidation
- **Use workspace protocol** - `"@myorg/ui": "workspace:*"`
- **Enable remote caching** - Share across CI and local
- **Filter in CI** - Build only affected packages
- **Cache build outputs** - Not source files

### Don'ts

- **Don't cache dev servers** - Use `persistent: true`
- **Don't include secrets in env** - Use runtime env vars
- **Don't ignore dependsOn** - Causes race conditions
- **Don't over-filter** - May miss dependencies

<!-- chapter:end slug=turborepo-caching -->

---

## Part: Dgx Spark Ops

---

<!-- chapter:begin slug=spark-environment-setup position=59 -->

## 59. spark-environment-setup

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/dgx-spark-ops/skills/spark-environment-setup/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-environment-setup/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/spark-environment-setup.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/container-workflow.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-environment-setup/references/container-workflow.md
  - `references/stack-matrix.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-environment-setup/references/stack-matrix.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: spark-environment-setup
description: Set up a working ML training/inference environment on NVIDIA DGX Spark (GB10, aarch64, CUDA 13). Use when installing PyTorch/Unsloth/TRL/vLLM on DGX Spark, hitting libcudart or wheel-ABI errors on aarch64, or choosing between NGC containers and bare pip installs.
---

# Spark Environment Setup

DGX Spark ships a GB10 Grace Blackwell chip: aarch64 CPU, SM121
GPU, 128GB unified memory, CUDA 13. This is a narrower and
younger platform than a standard x86 CUDA 12 box, so package
selection and ABI matching matter more than usual — the wheel
ecosystem for aarch64 + CUDA 13 is still filling in.

## When to Use This Skill

- Setting up a fresh Spark box for training or inference.
- Hitting an import error mentioning `libcudart`, a missing
  symbol, or a wheel that "installed fine but won't load."
- A framework install (PyTorch, Unsloth, TRL, vLLM, xformers)
  fails, hangs, or silently falls back to CPU.
- Deciding whether to use an NGC container or bare pip.
- Restoring a working setup after an OS reinstall or a
  base-image update, needing to re-verify from scratch.

Each of these accepts the same general fix: match the
container/wheel combination to CUDA 13 and SM121, don't fight
the ABI.

## Container-First Rule

Quick decision, before the detail below:

- Standard training/inference work → NGC PyTorch container.
- Unsloth-centric fine-tuning → Unsloth container (it ships
  the pinned Triton/xformers/transformers combination already
  validated for that path).
- Neither fits (custom system package, local IDE interpreter)
  → bare pip, following the exact sequence further down.

Default to a container. Use `nvcr.io/nvidia/pytorch:25.09-py3`
as the base for general work — the newest tag confirmed working
on this hardware; pull a newer blessed tag if locally available
rather than hard-blocking on `25.11-py3`. NGC's tag is dated, so
running it directly is fine:

```bash
docker run --runtime=nvidia --gpus all -it --rm \
  nvcr.io/nvidia/pytorch:25.09-py3
```

`unsloth/unsloth:dgxspark-latest` is a *moving* tag by
contrast — resolve and pin its digest before running it for
anything reproducible; the bare tag is a discovery step only,
not the default invocation. Full pull-inspect-pin sequence and
flag rationale/volume mounts for `finetuning/` run dirs:
`references/container-workflow.md`. Treat bare pip as the exception.

The reason for the container-first stance is pinning, not
convenience. Triton, xformers, and transformers versions
interact narrowly with GB10's SM121 target and CUDA 13; a
container locks all of them together against a combination
already validated on this hardware. Bare pip leaves that
resolution to you, one broken import at a time.

When bare pip is warranted, follow the NVIDIA playbook's
install sequence verbatim and in order:

```bash
pip install "transformers==5.13.1" "peft==0.19.1" "hf_transfer==0.1.9" "datasets==4.3.0" "trl==1.8.0"
pip install --no-deps "unsloth==2026.7.2" "unsloth_zoo==2026.7.2" "bitsandbytes==0.49.2"
pip install -U "torchao==0.17.0"
```

The second command's `--no-deps` flag is not optional —
letting pip re-resolve Unsloth's dependency tree on aarch64 is
a common way to pull in an incompatible torch or triton build.
The third line is not optional either: the NGC base image's
bundled `torchao` is too old for current `peft`'s LoRA-attach
path (`ImportError: ... torchao ... only versions above 0.16.0
are supported`) — a hard blocker, not a warning. Every `==` pin
above is load-bearing, taken from the dated known-good version
matrix in `references/stack-matrix.md` (its `Last verified` date
governs staleness) — an unpinned install resolves current PyPI
versions well outside what this Unsloth release supports.

Pull a fresh tag when a new blessed release is announced.
Rebuild locally from one of the two bases only when a project
needs an extra system package layered in — not to "upgrade" a
component the image already pins. Details on both paths:
`references/container-workflow.md`.

One more preflight: official DGX Spark playbooks have shipped
broken before. Check recent issues on
`github.com/NVIDIA/dgx-spark-playbooks` (and the other
resources in `references/stack-matrix.md`) before trusting a
recipe verbatim for a long run.

## The ABI Rule

The single most common failure on Spark is a CUDA 12/13 ABI
mismatch: a wheel built against `libcudart.so.12` loaded on a
system that only has `libcudart.so.13`. The install usually
succeeds; the failure surfaces later as a missing-symbol error
or a segfault that doesn't obviously point at CUDA.

Fix: pull wheels from `download.pytorch.org/whl/cu130` (the
cu130-tagged aarch64 builds), or use one of the containers
above, which already carry a matched build. Before chasing a
stack trace that mentions a CUDA symbol, check which CUDA tag
the installed wheel was built against:

```bash
python3 -c "import torch; print(torch.version.cuda)"
```

If that output doesn't start with `13`, the ABI mismatch is the
first thing to fix. NGC container builds (e.g.
`nvcr.io/nvidia/pytorch:25.09-py3`) build torch internally
against CUDA 13 with no `+cu130` wheel tag — `pip show torch`
won't say `cu130` there, and that absence alone is not a failure.

Typical symptoms:

- `ImportError: undefined symbol` referencing a CUDA runtime
  function.
- A segfault on the first `.cuda()` call, no useful traceback.
- A wheel that installs cleanly, then fails at import time —
  pip's resolver doesn't check CUDA ABI, only version constraints.
- Two "identical" environments behaving differently — usually one
  has a cu130 wheel, the other a cu121/cu124 leftover.

The fix is the same regardless of symptom: match the wheel's
CUDA tag to the system, or use a container that already does.

## Component Quick Table

Condensed status for the components most likely to come up.
Full table with wheel URLs, build flags, the sm_121 vs sm_121a
distinction, and the dated known-good version matrix:
`references/stack-matrix.md`.

| Component | Status |
|---|---|
| PyTorch | ✅ official cu130 aarch64 wheels |
| bitsandbytes | ✅ works out of the box |
| Triton | ✅ needs the `TRITON_PTXAS_PATH` parameter set |
| flash-attn | ❌ skip pip build; NGC bundles a working one — see `spark-training-gotchas` G2 |
| xformers | source build only (`TORCH_CUDA_ARCH_LIST=12.1`) |
| vLLM | nightly wheels only |
| TransformerEngine / NVFP4 train | container-only |

Everything else — Unsloth, Axolotl, TRL, PEFT — installs
cleanly through the container-first path above. LLaMA-Factory
and NeMo are fragile on Spark; check upstream issues first.

## Verification Commands

Confirm the environment can actually see the GPU before
running anything expensive:

```python
import torch
print(torch.cuda.is_available(), torch.version.cuda)
```

This call returns two values; the exact output format is one
line, `<bool> <cuda-version>`:

```text
True 13.0
```

If it prints `False` instead, don't jump straight to a wheel
reinstall — ABI mismatch is one cause among several:

| Hypothesis | Quick check |
|---|---|
| Runtime/flags | `nvidia-smi` fails in-container too |
| Device visibility | `echo $CUDA_VISIBLE_DEVICES` |
| Permissions | `ls -l /dev/nvidia*` |
| CUDA init state | wedged process; retry fresh shell/container |
| ABI mismatch (usual culprit) | `torch.version.cuda` not `13.x` |

Check `nvidia-smi` first — if it doesn't show the GPU, it's one
of the first three, not ABI. Reinstall a wheel only once ABI is
confirmed. Per-hypothesis detail: `references/stack-matrix.md`.
Run right after the container starts, before installing
project-specific packages.

One more check: if Triton kernel compilation fails once
training starts, set
`TRITON_PTXAS_PATH=/usr/local/cuda/bin/ptxas` and retry — see
`references/stack-matrix.md` for the full workaround list.

## Next Steps

A verified environment is only the starting point. See also:
`spark-training-gotchas` for failure preflights before a
training run, and `spark-memory-thermal-ops` for unified-memory
OOMs and thermal throttling during long ones.

<!-- chapter:end slug=spark-environment-setup -->

---

<!-- chapter:begin slug=spark-memory-thermal-ops position=60 -->

## 60. spark-memory-thermal-ops

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/dgx-spark-ops/skills/spark-memory-thermal-ops/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-memory-thermal-ops/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/spark-memory-thermal-ops.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `assets/thermal-sample.sh` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-memory-thermal-ops/assets/thermal-sample.sh
  - `references/uma-accounting.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-memory-thermal-ops/references/uma-accounting.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: spark-memory-thermal-ops
description: Manage unified memory and thermals during long-running ML jobs on NVIDIA DGX Spark. Use when planning memory headroom for a training run on GB10, when a job OOMs on unified memory, or when monitoring temperature and power during multi-hour training.
---

# Spark Memory & Thermal Ops

DGX Spark's GB10 chip has one 128GB unified
memory (UMA) pool shared by CPU and GPU, and a
sustained power ceiling well below its rated
figure. Both break discrete-GPU assumptions:
headroom isn't what `nvidia-smi` reports, and a
run that starts fast will slow down mid-job
with nothing misconfigured. This skill covers
planning memory headroom, working an actual
OOM, and watching thermals across a long job.
For launch-time failure modes (ABI mismatches,
flash-attn, playbook breakage), see
`spark-training-gotchas` — this skill assumes
the job starts.

## Common Issues Quick Reference

| Situation | Do this |
|---|---|
| Planning headroom before launch | Budget against `free -g`, not `nvidia-smi` — see UMA Memory Model |
| Job OOMs on unified memory | Work the OOM Ladder in order: flush, then batch/pack, then method downgrade |
| Throughput drops mid-run | Check the power/temp log before assuming a config bug — see Thermal Monitoring |
| Trainer + inference server both wanted | Run one at a time — see Concurrent Workloads |

## When to Use This Skill

- Sizing a training run against the 128GB pool
  before launch — will this model, method, and
  batch/pack combination fit.
- A run OOMs mid-load or mid-step and the
  remediation order matters — what to try first,
  second, third.
- Watching temperature and power during a
  multi-hour job, deciding whether a slowdown is
  thermal throttling or something else.
- Planning to run a trainer alongside an
  inference server (vLLM, Ollama) on the same box.

## UMA Memory Model

Spark has no separate GPU VRAM — the GPU and
CPU share one 128GB pool. Two consequences:

- **`nvidia-smi` and `cudaMemGetInfo`
  underreport pressure — or report nothing at
  all.** Both report CUDA-allocator-visible
  memory, not the pool's actual state — a box can
  show headroom in `nvidia-smi` and still OOM,
  because page-cache and mmap'd pages the
  allocator doesn't see consume the same pool. On
  some driver/setups, the memory query returns
  `[N/A], [N/A]` outright instead of a number — a
  script grepping for a numeric value there gets
  nothing, not a misleading undercount (see
  `spark-training-gotchas` gotcha G3).

- **Model load is a transient peak, not the
  steady state.** Loading safetensors weights
  mmaps the file, then copies into CUDA
  tensors — for a window during load, both the
  mmap'd pages and the CUDA copy count against
  the pool at once. A model that fits while
  training can still OOM during load if headroom
  was sized for the post-load footprint instead
  of this doubled transient.

Plan and diagnose with `free -g`, not
`nvidia-smi`:

```bash
free -g | awk 'NR==2 {print "free:", $4, "GB"}'
```

Rule of thumb: take that free figure, subtract a
few GB for OS/driver overhead, and budget against
the result — not the 128GB spec number.
The worksheet in `references/uma-accounting.md`
accepts parameter count, dtype, and method as
input, and returns a memory estimate to compare
against known anchors.

### Planning Sequence

Before launch, work through these in order:

1. Read `free -g`; subtract OS/driver overhead
   for the budget.
2. Estimate weights + optimizer + gradients +
   activations from `references/uma-accounting.md`.
3. Compare against the closest anchor (70B
   QLoRA, 27B LoRA, 9B full FT), not the
   estimate alone.
4. If the estimate is close to the budget, start
   with shorter packing or a smaller batch —
   cheaper than hitting the OOM Ladder mid-run.

### Example: Sizing a 70B QLoRA Run

A sanity check of the worksheet formula against
the ≈40GB anchor:

```python
params = 70e9
weights_gb = params * 0.5 / 1e9      # NF4, step 1
adapter_gb = 0.5                     # step 5, negligible
total_gb = weights_gb + adapter_gb   # + activations
print(f"{total_gb:.0f}GB before activations")
```

Weights alone land near the ≈40GB anchor — a plan
estimating far above that for the same model
class is a signal to recheck dtype and method.

## The OOM Ladder

When a job OOMs on unified memory, work this
ladder in order. Each step is more disruptive
than the last — don't skip ahead:
**reducing batch size is never step 1.**

1. **Flush the buffer cache.** Page cache from a
   previous run or a large dataset read often
   accounts for GB of the "missing" headroom.
   This costs nothing but a rerun and doesn't
   touch the job's configuration:

   ```bash
   sync; echo 3 > /proc/sys/vm/drop_caches
   ```

   Needs root; a between-run reset, not a
   mid-training step. See
   `spark-training-gotchas` (gotcha G3) for the
   full diagnostic behind this step.

2. **Reduce batch size or packing length.** Only
   after a flush fails to free enough headroom,
   cut batch size or packing length — the first
   step that changes what the run does. Prefer
   packing length first; it drives activation
   footprint more directly at long context.

3. **Downgrade the method: bf16 LoRA before
   QLoRA.** If flushing and shrinking batch/pack
   still OOM, drop the method a tier — bf16 LoRA
   is next, not the reverse. QLoRA's bitsandbytes
   dequantization buffers are transient CUDA-side
   allocations that can OOM before an equivalent
   bf16 LoRA run would, even though QLoRA's
   steady-state footprint is smaller. A QLoRA OOM
   is not proof the model doesn't fit.

Fall back further (smaller model, multi-Spark)
only after all three steps and the job still
won't fit.

## Thermal Monitoring

Multi-hour runs push into Spark's sustained
power ceiling, well under the rated figure —
expected platform behavior, not a symptom to
explain away:

- Sample temperature and power alongside the
  training logs, not after a slowdown is
  noticed — every 30-60 seconds correlates a
  throughput drop with a thermal event. Keep
  the CSV output format `assets/thermal-sample.sh`
  writes, so timestamps line up against the log:

  ```bash
  bash assets/thermal-sample.sh 30 thermal.log
  ```

- **A sustained ~100W power draw is the platform
  cap, not a configuration bug.** Don't re-tune
  batch size or precision to "fix" a plateau
  that's the box behaving normally under load.
  If temperature climbs while power stays flat
  under the rated 240W figure, that's the
  signature to recognize.

- Log throttle events explicitly instead of
  letting a run silently slow down unrecorded. A
  run whose per-step time doubles two hours in
  should show that in the log, correlated against
  the thermal sample at that timestamp. Full
  throttling diagnostics: `spark-training-gotchas`
  (gotcha G4).

## Concurrent Workloads

Because the 128GB pool is global, eviction
happens without either process's logs showing
an OOM:

- The one-heavy-job rule applies to **uncapped or
  near-capacity** workloads — an uncapped trainer
  and inference server (vLLM, Ollama) compete for
  the same pool. A small, capped workload doesn't:
  a <4GB LoRA fine-tune coexists fine alongside
  vLLM capped at `gpu-memory-utilization<=0.5` —
  check the other process's cap, not just its
  presence, before stopping it.

- Inference servers evict trainer pages silently
  under uncapped/near-capacity contention, and
  vice versa — neither logs an error, so a slow
  run or lost KV cache is a contention symptom to
  check for. Stop unrelated *uncapped* servers
  before a long or full-pool run.

Check for GPU-resident processes first:

```bash
ps aux | grep -E 'vllm|ollama|trl|axolotl' | grep -v grep
```

This procedure complements `spark-training-gotchas`
(gotchas G3, G4, G6) — that skill covers launch-time
failures; this one, the running job.

Memory math worksheets:
`references/uma-accounting.md`.

<!-- chapter:end slug=spark-memory-thermal-ops -->

---

<!-- chapter:begin slug=spark-training-gotchas position=61 -->

## 61. spark-training-gotchas

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/dgx-spark-ops/skills/spark-training-gotchas/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-training-gotchas/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/spark-training-gotchas.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `assets/preflight.sh` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-training-gotchas/assets/preflight.sh
  - `references/gotcha-checks.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dgx-spark-ops/skills/spark-training-gotchas/references/gotcha-checks.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: spark-training-gotchas
description: Preflight and diagnose the ten known failure modes for ML training on NVIDIA DGX Spark. Use when a training run on DGX Spark fails to start, OOMs below the 128GB limit, slows down mid-run, or before any multi-hour training job on GB10.
---

# Spark Training Gotchas

DGX Spark's GB10 chip (Grace Blackwell, SM121, 128GB unified
memory, aarch64) has ten recurring failure modes across
launch, memory, thermals, bandwidth, and precision. Each is
named G1–G10 so it can be checked by number — the numbering
is load-bearing for tooling that runs these checks. Read this
before a long run, not after hour six.

## When to Use This Skill

- A training run fails to start, with an import error or a
  segfault that doesn't point at the real cause.
- A run OOMs while `nvidia-smi` still shows headroom.
- Throughput degrades partway through a run that started fine.
- Before any multi-hour or multi-epoch job on GB10.
- Wiring two Sparks together, before picking a parallelism
  strategy.
- Choosing between FP8 and NVFP4 for a Spark-hosted run.

## Common Issues Quick Reference

| # | Symptom | Fix |
|---|---|---|
| G1 | undefined symbol / segfault | cu130 wheel or container |
| G2 | flash-attn wrong backend used | skip pip build; monkeypatch on NGC |
| G3 | OOM despite headroom | drop page cache |
| G4 | throughput drop / reboot | expect ~100W sustained cap |
| G5 | memory-bound step slow | budget 180–192 GB/s |
| G6 | cache evicted mid-run | one GPU server at a time |
| G7 | NVFP4 slower than FP8 | stay FP8 unless `sm_121a` |
| G8 | playbook fails outright | check upstream issues |
| G9 | env breaks after install | use a container |
| G10 | 2-Spark TP hangs | DDP/FSDP only, never TP |

## The Ten Gotchas

### G1: CUDA 12/13 ABI Mismatch

- **SYMPTOM:** `ImportError: undefined symbol` naming a CUDA
  function, or a segfault on the first `.cuda()` call.
- **CAUSE:** most PyPI wheels link `libcudart.so.12`; Spark
  ships CUDA 13. pip never checks CUDA ABI, so it surfaces
  only at import or first kernel launch.
- **CHECK:** `references/gotcha-checks.md` G1 — the wheel's
  CUDA build tag.
- **FIX:** reinstall from `download.pytorch.org/whl/cu130` or
  use a matched container.

### G2: flash-attn — Skip the pip Build, Watch Unsloth's Auto-Detect

- **SYMPTOM:** `pip install flash-attn` still fails/hangs.
  Unsloth may also silently train flash-attn over an
  explicitly requested SDPA.
- **CAUSE:** no aarch64/sm_121 wheel for bare pip — but NGC
  containers ship a working SM121 flash-attn, and Unsloth
  auto-prefers it, dropping `attn_implementation="sdpa"`.
- **CHECK:** `references/gotcha-checks.md` G2 — is flash-attn
  already present and working.
- **FIX:** bare pip — skip flash-attn, use SDPA (unchanged). On
  NGC — the only reliable override is the monkeypatch in
  `references/gotcha-checks.md` G2.

### G3: UMA OOM Below 128GB

- **SYMPTOM:** OOM during model load/training while
  `nvidia-smi` still reports free memory under the 128GB cap
  — or, on some setups, `[N/A]` outright instead of a number.
- **CAUSE:** mmap and the CUDA allocator double-count pages
  during safetensors load; QLoRA can OOM *earlier* than bf16
  since dequantization adds transient allocs.
- **CHECK:** `references/gotcha-checks.md` G3 — read `free -g`
  and `/proc/meminfo`, not `nvidia-smi`.
- **FIX:** drop the page cache with
  `sync; echo 3 > /proc/sys/vm/drop_caches` — needs root, a
  between-run reset, not a mid-training step.

### G4: Thermal Throttling

- **SYMPTOM:** throughput drops partway through a multi-hour
  run, or the box spontaneously reboots under sustained load.
- **CAUSE:** sustained power draw caps around 100W versus the
  240W rated figure; long runs push into that ceiling and
  throttle or, sometimes, reboot.
- **CHECK:** `references/gotcha-checks.md` G4 — sample
  `nvidia-smi --query-gpu=temperature.gpu,power.draw`.
- **FIX:** if power plateaus under 240W while temperature
  climbs, treat throttling as the cause; improve cooling or
  cap run length.

### G5: Bandwidth Ceiling

- **SYMPTOM:** memory-bound workloads, decode-heavy RL loops
  especially, plateau well below expected throughput.
- **CAUSE:** 273 GB/s is a spec ceiling, not sustained;
  measured bandwidth runs 180–192 GB/s.
- **CHECK:** `references/gotcha-checks.md` G5 — observed step
  time vs. the measured range, not spec.
- **FIX:** budget throughput from 180–192 GB/s; revise a plan
  built on the 273 GB/s figure.

### G6: Global UMA Resource Contention

- **SYMPTOM:** a process's KV cache/weights get evicted
  mid-run silently, no OOM in its own logs.
- **CAUSE:** unified memory is
  one global pool; an uncapped
  or near-capacity process
  competes with anything else
  and can evict it. A small,
  bounded workload doesn't — a
  <4GB LoRA coexists fine
  alongside vLLM capped at
  `gpu-memory-utilization<=0.5`.
- **CHECK:** `references/gotcha-checks.md`
  G6 — other GPU-resident
  processes and whether
  capped.
- **FIX:** the one-heavy-job
  rule applies to **uncapped or
  near-capacity** workloads —
  cap or stop unrelated servers
  first. A small, capped
  workload need not
  stop.

### G7: NVFP4 Slower Than FP8 on SM121

- **SYMPTOM:** switching an inference workload from FP8 to
  NVFP4 on Spark makes it slower, not faster.
- **CAUSE:** SM121 lacks `cvt.e2m1x2` unless kernels target
  `sm_121a`; NVFP4 runs ~32% slower without it.
- **CHECK:** `references/gotcha-checks.md` G7 — capability
  reports `(12, 1)`; does the build target `sm_121a`?
- **FIX:** stay on FP8 unless the build targets `sm_121a`.

### G8: Stale Official Playbooks

- **SYMPTOM:** following an official DGX Spark playbook still
  fails, with no local misconfiguration explaining it.
- **CAUSE:** official playbooks have shipped broken before;
  the stack moves faster than the docs.
- **CHECK:** `references/gotcha-checks.md` G8 — the playbook
  repo's recent issues.
- **FIX:** check `github.com/NVIDIA/dgx-spark-playbooks` issues
  before trusting a recipe for an expensive run.

### G9: Container-First, Not Bare Pip

- **SYMPTOM:** a bare-pip environment that worked yesterday
  breaks after an unrelated `pip install`, or two "identical"
  environments behave differently.
- **CAUSE:** bare pip lets Triton, xformers, and transformers
  drift independently; nothing pins them to GB10's SM121
  target.
- **CHECK:** `references/gotcha-checks.md`
  G9 — container or bare pip?
- **FIX:** prefer an NGC container (see `spark-environment-setup`
  for tag guidance) or Unsloth's container. If bare pip is
  unavoidable, follow the NVIDIA install order, including
  `--no-deps` on Unsloth.

### G10: Dual-Spark Is DDP/FSDP Only

- **SYMPTOM:** a tensor-parallel launch across two Sparks
  hangs, runs far slower than single-Spark, or errors out.
- **CAUSE:** ConnectX-7 is fast enough for gradient/parameter
  sync (DDP, FSDP) but too thin for TP's fine-grained traffic.
- **CHECK:** `references/gotcha-checks.md` G10 — the
  configured parallelism strategy.
- **FIX:** on a two-Spark setup, choose DDP or FSDP, never
  tensor parallelism — TP is single-node only here.

## Fast Triage

The cheapest checks to run before anything else:

```bash
python3 -c "import torch; print(torch.version.cuda)"  # expect 13.x (G1); NGC builds have no +cu130 tag — that's not a failure
```

```python
import torch; print(torch.cuda.get_device_capability())  # expect (12, 1) (G7)
```

```bash
{ [ -f /.dockerenv -o -f /run/.containerenv ] || grep -qE 'docker|containerd' /proc/1/cgroup; } 2>/dev/null && echo container || echo unknown  # G9
```

`assets/preflight.sh` runs G1, G3, G4, G7, G9 and produces one
output line per gotcha in a fixed format: G-number first, then
PASS/FAIL/WARN where automatable, SKIP when unavailable, or
`INFO:` for a raw reading (G3, G4). Full commands:
`references/gotcha-checks.md`. See also
`spark-environment-setup` for the environment assumed working.

<!-- chapter:end slug=spark-training-gotchas -->

---

## Part: Documentation Generation

---

<!-- chapter:begin slug=architecture-decision-records position=62 -->

## 62. architecture-decision-records

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/documentation-generation/skills/architecture-decision-records/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-generation/skills/architecture-decision-records/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/architecture-decision-records.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: architecture-decision-records
description: Write and maintain Architecture Decision Records (ADRs) following best practices for technical decision documentation. Use when documenting significant technical decisions, reviewing past architectural choices, or establishing decision processes.
---

# Architecture Decision Records

Comprehensive patterns for creating, maintaining, and managing Architecture Decision Records (ADRs) that capture the context and rationale behind significant technical decisions.

## When to Use This Skill

- Making significant architectural decisions
- Documenting technology choices
- Recording design trade-offs
- Onboarding new team members
- Reviewing historical decisions
- Establishing decision-making processes

## Core Concepts

### 1. What is an ADR?

An Architecture Decision Record captures:

- **Context**: Why we needed to make a decision
- **Decision**: What we decided
- **Consequences**: What happens as a result

### 2. When to Write an ADR

| Write ADR                  | Skip ADR               |
| -------------------------- | ---------------------- |
| New framework adoption     | Minor version upgrades |
| Database technology choice | Bug fixes              |
| API design patterns        | Implementation details |
| Security architecture      | Routine maintenance    |
| Integration patterns       | Configuration changes  |

### 3. ADR Lifecycle

```
Proposed → Accepted → Deprecated → Superseded
              ↓
           Rejected
```

## Templates

### Template 1: Standard ADR (MADR Format)

```markdown
# ADR-0001: Use PostgreSQL as Primary Database

## Status

Accepted

## Context

We need to select a primary database for our new e-commerce platform. The system
will handle:

- ~10,000 concurrent users
- Complex product catalog with hierarchical categories
- Transaction processing for orders and payments
- Full-text search for products
- Geospatial queries for store locator

The team has experience with MySQL, PostgreSQL, and MongoDB. We need ACID
compliance for financial transactions.

## Decision Drivers

- **Must have ACID compliance** for payment processing
- **Must support complex queries** for reporting
- **Should support full-text search** to reduce infrastructure complexity
- **Should have good JSON support** for flexible product attributes
- **Team familiarity** reduces onboarding time

## Considered Options

### Option 1: PostgreSQL

- **Pros**: ACID compliant, excellent JSON support (JSONB), built-in full-text
  search, PostGIS for geospatial, team has experience
- **Cons**: Slightly more complex replication setup than MySQL

### Option 2: MySQL

- **Pros**: Very familiar to team, simple replication, large community
- **Cons**: Weaker JSON support, no built-in full-text search (need
  Elasticsearch), no geospatial without extensions

### Option 3: MongoDB

- **Pros**: Flexible schema, native JSON, horizontal scaling
- **Cons**: No ACID for multi-document transactions (at decision time),
  team has limited experience, requires schema design discipline

## Decision

We will use **PostgreSQL 15** as our primary database.

## Rationale

PostgreSQL provides the best balance of:

1. **ACID compliance** essential for e-commerce transactions
2. **Built-in capabilities** (full-text search, JSONB, PostGIS) reduce
   infrastructure complexity
3. **Team familiarity** with SQL databases reduces learning curve
4. **Mature ecosystem** with excellent tooling and community support

The slight complexity in replication is outweighed by the reduction in
additional services (no separate Elasticsearch needed).

## Consequences

### Positive

- Single database handles transactions, search, and geospatial queries
- Reduced operational complexity (fewer services to manage)
- Strong consistency guarantees for financial data
- Team can leverage existing SQL expertise

### Negative

- Need to learn PostgreSQL-specific features (JSONB, full-text search syntax)
- Vertical scaling limits may require read replicas sooner
- Some team members need PostgreSQL-specific training

### Risks

- Full-text search may not scale as well as dedicated search engines
- Mitigation: Design for potential Elasticsearch addition if needed

## Implementation Notes

- Use JSONB for flexible product attributes
- Implement connection pooling with PgBouncer
- Set up streaming replication for read replicas
- Use pg_trgm extension for fuzzy search

## Related Decisions

- ADR-0002: Caching Strategy (Redis) - complements database choice
- ADR-0005: Search Architecture - may supersede if Elasticsearch needed

## References

- [PostgreSQL JSON Documentation](https://www.postgresql.org/docs/current/datatype-json.html)
- [PostgreSQL Full Text Search](https://www.postgresql.org/docs/current/textsearch.html)
- Internal: Performance benchmarks in `/docs/benchmarks/database-comparison.md`
```

### Template 2: Lightweight ADR

```markdown
# ADR-0012: Adopt TypeScript for Frontend Development

**Status**: Accepted
**Date**: 2024-01-15
**Deciders**: @alice, @bob, @charlie

## Context

Our React codebase has grown to 50+ components with increasing bug reports
related to prop type mismatches and undefined errors. PropTypes provide
runtime-only checking.

## Decision

Adopt TypeScript for all new frontend code. Migrate existing code incrementally.

## Consequences

**Good**: Catch type errors at compile time, better IDE support, self-documenting
code.

**Bad**: Learning curve for team, initial slowdown, build complexity increase.

**Mitigations**: TypeScript training sessions, allow gradual adoption with
`allowJs: true`.
```

### Template 3: Y-Statement Format

```markdown
# ADR-0015: API Gateway Selection

In the context of **building a microservices architecture**,
facing **the need for centralized API management, authentication, and rate limiting**,
we decided for **Kong Gateway**
and against **AWS API Gateway and custom Nginx solution**,
to achieve **vendor independence, plugin extensibility, and team familiarity with Lua**,
accepting that **we need to manage Kong infrastructure ourselves**.
```

### Template 4: ADR for Deprecation

```markdown
# ADR-0020: Deprecate MongoDB in Favor of PostgreSQL

## Status

Accepted (Supersedes ADR-0003)

## Context

ADR-0003 (2021) chose MongoDB for user profile storage due to schema flexibility
needs. Since then:

- MongoDB's multi-document transactions remain problematic for our use case
- Our schema has stabilized and rarely changes
- We now have PostgreSQL expertise from other services
- Maintaining two databases increases operational burden

## Decision

Deprecate MongoDB and migrate user profiles to PostgreSQL.

## Migration Plan

1. **Phase 1** (Week 1-2): Create PostgreSQL schema, dual-write enabled
2. **Phase 2** (Week 3-4): Backfill historical data, validate consistency
3. **Phase 3** (Week 5): Switch reads to PostgreSQL, monitor
4. **Phase 4** (Week 6): Remove MongoDB writes, decommission

## Consequences

### Positive

- Single database technology reduces operational complexity
- ACID transactions for user data
- Team can focus PostgreSQL expertise

### Negative

- Migration effort (~4 weeks)
- Risk of data issues during migration
- Lose some schema flexibility

## Lessons Learned

Document from ADR-0003 experience:

- Schema flexibility benefits were overestimated
- Operational cost of multiple databases was underestimated
- Consider long-term maintenance in technology decisions
```

### Template 5: Request for Comments (RFC) Style

```markdown
# RFC-0025: Adopt Event Sourcing for Order Management

## Summary

Propose adopting event sourcing pattern for the order management domain to
improve auditability, enable temporal queries, and support business analytics.

## Motivation

Current challenges:

1. Audit requirements need complete order history
2. "What was the order state at time X?" queries are impossible
3. Analytics team needs event stream for real-time dashboards
4. Order state reconstruction for customer support is manual

## Detailed Design

### Event Store
```

OrderCreated { orderId, customerId, items[], timestamp }
OrderItemAdded { orderId, item, timestamp }
OrderItemRemoved { orderId, itemId, timestamp }
PaymentReceived { orderId, amount, paymentId, timestamp }
OrderShipped { orderId, trackingNumber, timestamp }

```

### Projections

- **CurrentOrderState**: Materialized view for queries
- **OrderHistory**: Complete timeline for audit
- **DailyOrderMetrics**: Analytics aggregation

### Technology

- Event Store: EventStoreDB (purpose-built, handles projections)
- Alternative considered: Kafka + custom projection service

## Drawbacks

- Learning curve for team
- Increased complexity vs. CRUD
- Need to design events carefully (immutable once stored)
- Storage growth (events never deleted)

## Alternatives

1. **Audit tables**: Simpler but doesn't enable temporal queries
2. **CDC from existing DB**: Complex, doesn't change data model
3. **Hybrid**: Event source only for order state changes

## Unresolved Questions

- [ ] Event schema versioning strategy
- [ ] Retention policy for events
- [ ] Snapshot frequency for performance

## Implementation Plan

1. Prototype with single order type (2 weeks)
2. Team training on event sourcing (1 week)
3. Full implementation and migration (4 weeks)
4. Monitoring and optimization (ongoing)

## References

- [Event Sourcing by Martin Fowler](https://martinfowler.com/eaaDev/EventSourcing.html)
- [EventStoreDB Documentation](https://www.eventstore.com/docs)
```

## ADR Management

### Directory Structure

```
docs/
├── adr/
│   ├── README.md           # Index and guidelines
│   ├── template.md         # Team's ADR template
│   ├── 0001-use-postgresql.md
│   ├── 0002-caching-strategy.md
│   ├── 0003-mongodb-user-profiles.md  # [DEPRECATED]
│   └── 0020-deprecate-mongodb.md      # Supersedes 0003
```

### ADR Index (README.md)

```markdown
# Architecture Decision Records

This directory contains Architecture Decision Records (ADRs) for [Project Name].

## Index

| ADR                                   | Title                              | Status     | Date       |
| ------------------------------------- | ---------------------------------- | ---------- | ---------- |
| [0001](0001-use-postgresql.md)        | Use PostgreSQL as Primary Database | Accepted   | 2024-01-10 |
| [0002](0002-caching-strategy.md)      | Caching Strategy with Redis        | Accepted   | 2024-01-12 |
| [0003](0003-mongodb-user-profiles.md) | MongoDB for User Profiles          | Deprecated | 2023-06-15 |
| [0020](0020-deprecate-mongodb.md)     | Deprecate MongoDB                  | Accepted   | 2024-01-15 |

## Creating a New ADR

1. Copy `template.md` to `NNNN-title-with-dashes.md`
2. Fill in the template
3. Submit PR for review
4. Update this index after approval

## ADR Status

- **Proposed**: Under discussion
- **Accepted**: Decision made, implementing
- **Deprecated**: No longer relevant
- **Superseded**: Replaced by another ADR
- **Rejected**: Considered but not adopted
```

### Automation (adr-tools)

```bash
# Install adr-tools
brew install adr-tools

# Initialize ADR directory
adr init docs/adr

# Create new ADR
adr new "Use PostgreSQL as Primary Database"

# Supersede an ADR
adr new -s 3 "Deprecate MongoDB in Favor of PostgreSQL"

# Generate table of contents
adr generate toc > docs/adr/README.md

# Link related ADRs
adr link 2 "Complements" 1 "Is complemented by"
```

## Review Process

```markdown
## ADR Review Checklist

### Before Submission

- [ ] Context clearly explains the problem
- [ ] All viable options considered
- [ ] Pros/cons balanced and honest
- [ ] Consequences (positive and negative) documented
- [ ] Related ADRs linked

### During Review

- [ ] At least 2 senior engineers reviewed
- [ ] Affected teams consulted
- [ ] Security implications considered
- [ ] Cost implications documented
- [ ] Reversibility assessed

### After Acceptance

- [ ] ADR index updated
- [ ] Team notified
- [ ] Implementation tickets created
- [ ] Related documentation updated
```

## Best Practices

### Do's

- **Write ADRs early** - Before implementation starts
- **Keep them short** - 1-2 pages maximum
- **Be honest about trade-offs** - Include real cons
- **Link related decisions** - Build decision graph
- **Update status** - Deprecate when superseded

### Don'ts

- **Don't change accepted ADRs** - Write new ones to supersede
- **Don't skip context** - Future readers need background
- **Don't hide failures** - Rejected decisions are valuable
- **Don't be vague** - Specific decisions, specific consequences
- **Don't forget implementation** - ADR without action is waste

<!-- chapter:end slug=architecture-decision-records -->

---

<!-- chapter:begin slug=changelog-automation position=63 -->

## 63. changelog-automation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/documentation-generation/skills/changelog-automation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-generation/skills/changelog-automation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/changelog-automation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-generation/skills/changelog-automation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: changelog-automation
description: Automate changelog generation from commits, PRs, and releases following Keep a Changelog format. Use when setting up release workflows, generating release notes, or standardizing commit conventions.
---

# Changelog Automation

Patterns and tools for automating changelog generation, release notes, and version management following industry standards.

## When to Use This Skill

- Setting up automated changelog generation
- Implementing Conventional Commits
- Creating release note workflows
- Standardizing commit message formats
- Generating GitHub/GitLab release notes
- Managing semantic versioning

## Core Concepts

### 1. Keep a Changelog Format

```markdown
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Summary

This release introduces dark mode support and improves checkout performance
by 40%. It also includes important security updates.

## Highlights

### 🌙 Dark Mode

Users can now switch to dark mode from settings. The preference is
automatically saved and synced across devices.

### ⚡ Performance

- Checkout flow is 40% faster
- Reduced bundle size by 15%

## Breaking Changes

None in this release.

## Upgrade Guide

No special steps required. Standard deployment process applies.

## Known Issues

- Dark mode may flicker on initial load (fix scheduled for v2.1.1)

## Dependencies Updated

| Package | From    | To      | Reason                   |
| ------- | ------- | ------- | ------------------------ |
| react   | 18.2.0  | 18.3.0  | Performance improvements |
| lodash  | 4.17.20 | 4.17.21 | Security patch           |
```

## Commit Message Examples

```bash
# Feature with scope
feat(auth): add OAuth2 support for Google login

# Bug fix with issue reference
fix(checkout): resolve race condition in payment processing

Closes #123

# Breaking change
feat(api)!: change user endpoint response format

BREAKING CHANGE: The user endpoint now returns `userId` instead of `id`.
Migration guide: Update all API consumers to use the new field name.

# Multiple paragraphs
fix(database): handle connection timeouts gracefully

Previously, connection timeouts would cause the entire request to fail
without retry. This change implements exponential backoff with up to
3 retries before failing.

The timeout threshold has been increased from 5s to 10s based on p99
latency analysis.

Fixes #456
Reviewed-by: @alice
```

## Best Practices

### Do's

- **Follow Conventional Commits** - Enables automation
- **Write clear messages** - Future you will thank you
- **Reference issues** - Link commits to tickets
- **Use scopes consistently** - Define team conventions
- **Automate releases** - Reduce manual errors

### Don'ts

- **Don't mix changes** - One logical change per commit
- **Don't skip validation** - Use commitlint
- **Don't manual edit** - Generated changelogs only
- **Don't forget breaking changes** - Mark with `!` or footer
- **Don't ignore CI** - Validate commits in pipeline

<!-- chapter:end slug=changelog-automation -->

---

<!-- chapter:begin slug=openapi-spec-generation position=64 -->

## 64. openapi-spec-generation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/documentation-generation/skills/openapi-spec-generation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-generation/skills/openapi-spec-generation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/openapi-spec-generation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/code-first-and-tooling.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-generation/skills/openapi-spec-generation/references/code-first-and-tooling.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-generation/skills/openapi-spec-generation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: openapi-spec-generation
description: Generate and maintain OpenAPI 3.1 specifications from code, design-first specs, and validation patterns. Use when creating API documentation, generating SDKs, or ensuring API contract compliance.
---

# OpenAPI Spec Generation

Comprehensive patterns for creating, maintaining, and validating OpenAPI 3.1 specifications for RESTful APIs.

## When to Use This Skill

- Creating API documentation from scratch
- Generating OpenAPI specs from existing code
- Designing API contracts (design-first approach)
- Validating API implementations against specs
- Generating client SDKs from specs
- Setting up API documentation portals

## Core Concepts

### 1. OpenAPI 3.1 Structure

```yaml
openapi: 3.1.0
info:
  title: API Title
  version: 1.0.0
servers:
  - url: https://api.example.com/v1
paths:
  /resources:
    get: ...
components:
  schemas: ...
  securitySchemes: ...
```

### 2. Design Approaches

| Approach         | Description                  | Best For            |
| ---------------- | ---------------------------- | ------------------- |
| **Design-First** | Write spec before code       | New APIs, contracts |
| **Code-First**   | Generate spec from code      | Existing APIs       |
| **Hybrid**       | Annotate code, generate spec | Evolving APIs       |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Use $ref** - Reuse schemas, parameters, responses
- **Add examples** - Real-world values help consumers
- **Document errors** - All possible error codes
- **Version your API** - In URL or header
- **Use semantic versioning** - For spec changes

### Don'ts

- **Don't use generic descriptions** - Be specific
- **Don't skip security** - Define all schemes
- **Don't forget nullable** - Be explicit about null
- **Don't mix styles** - Consistent naming throughout
- **Don't hardcode URLs** - Use server variables

<!-- chapter:end slug=openapi-spec-generation -->

---

## Part: Documentation Standards

---

<!-- chapter:begin slug=hads position=65 -->

## 65. hads

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/documentation-standards/skills/hads/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/documentation-standards/skills/hads/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/hads.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: hads
description: Use when writing technical documentation that needs to be readable by both humans and AI models, converting existing docs to HADS format, validating a HADS document, or optimizing documentation for token-efficient AI consumption.
---

# HADS Claude Skill
**Version 1.0.0** · Human-AI Document Standard · 2026 · HADS 1.0.0

---

## AI READING INSTRUCTION

This skill teaches Claude how to read, generate, and validate HADS documents.
Read all `[SPEC]` blocks before responding to any HADS-related request.
Read `[NOTE]` blocks if you need context on intent or edge cases.

---

## 1. WHAT IS HADS

**[SPEC]**
- HADS = Human-AI Document Standard
- Convention for Markdown technical documentation
- Four block types: `**[SPEC]**`, `**[NOTE]**`, `**[BUG]**`, `**[?]**`
- Every HADS document requires: H1 title, version declaration, AI manifest
- AI manifest appears before first content section, tells AI what to read/skip
- File extension: `.md` — standard Markdown, no tooling required

---

## 2. BLOCK TYPES

**[SPEC]**
```
**[SPEC]**   Authoritative fact. Terse. Bullet lists, tables, code. AI reads always.
**[NOTE]**   Human context, history, examples. AI may skip.
**[BUG]**    Verified failure + fix. Required fields: symptom, cause, fix. Always read.
**[?]**      Unverified / inferred. Lower confidence. Always flagged.
```

Block tag rules:
- Bold, on its own line: `**[SPEC]**`
- Content follows immediately (no blank line between tag and content)
- Multiple blocks of different types allowed per section
- Titled BUG blocks allowed: `**[BUG] Short description**`
- No nesting of blocks inside blocks

---

## 3. REQUIRED DOCUMENT STRUCTURE

**[SPEC]**
```markdown
# Document Title
**Version X.Y.Z** · Author · Date · [metadata]

---

## AI READING INSTRUCTION

Read `[SPEC]` and `[BUG]` blocks for authoritative facts.
Read `[NOTE]` only if additional context is needed.
`[?]` blocks are unverified — treat with lower confidence.

---

## 1. First Section

**[SPEC]**
...
```

Required elements in order:
1. H1 title
2. `**Version X.Y.Z**` in header (first 20 lines)
3. AI manifest section before first content section
4. Content sections (H2), subsections (H3)

---

## 4. HOW CLAUDE READS HADS

**[SPEC]**
When encountering a HADS document:
1. Find and read the AI manifest first
2. Read all `[SPEC]` blocks — these are ground truth
3. Read all `[BUG]` blocks — always, before generating any code or config
4. Read `[NOTE]` blocks only if `[SPEC]` is insufficient to answer the query
5. Treat `[?]` content as hypothesis — note uncertainty in response

Token optimization: for large documents, scan section headings first, then read only `[SPEC]` and `[BUG]` blocks in relevant sections.

---

## 5. HOW CLAUDE GENERATES HADS

**[SPEC]**
When asked to write documentation in HADS format:

1. Start with header block (title, version, metadata)
2. Add AI manifest — always include, never skip
3. Organize content into numbered H2 sections
4. For each fact: write as `[SPEC]` — terse, bullet or table or code
5. For each "why" or context: write as `[NOTE]`
6. For each known failure mode with confirmed fix: write as `[BUG]`
7. For each unverified claim: write as `[?]`
8. End with changelog section

Content rules for `[SPEC]`:
- Prefer bullet lists over prose
- Prefer tables for multi-field facts
- Prefer code blocks for syntax, formats, examples
- Maximum 2 sentences of prose — if more needed, move to `[NOTE]`

Content rules for `[BUG]`:
- Always include: symptom, cause, fix
- Optional: affected versions, workaround
- Title on same line: `**[BUG] Short description**`

**[NOTE]**
When converting existing documentation to HADS: extract facts into `[SPEC]`, move narrative and history to `[NOTE]`, surface all known issues as `[BUG]`. Do not duplicate content between block types.

---

## 6. VALIDATION RULES

**[SPEC]**
A valid HADS document must have:
- H1 title
- `**Version X.Y.Z**` in first 20 lines
- AI manifest before first content section
- All block tags bold: `**[SPEC]**` not `[SPEC]` not *[SPEC]*
- `[BUG]` blocks contain at minimum symptom + fix

Validator: *(planned — not yet included in this release)*

---

## 7. EXAMPLE INTERACTIONS

**[SPEC]**

User: *"Write HADS documentation for this REST API"*
→ Generate full HADS document: header, manifest, sections with [SPEC]/[NOTE]/[BUG] blocks

User: *"Convert this README to HADS format"*
→ Restructure existing content into HADS blocks, preserve all facts, add manifest

User: *"Is this document valid HADS?"*
→ Check: H1 title, version, manifest, block tag formatting, BUG block completeness

User: *"Summarize this HADS document"*
→ Read only [SPEC] and [BUG] blocks, return structured summary

User: *"What does this API do?"* (HADS doc provided)
→ Read manifest, read [SPEC] blocks in relevant sections, answer directly

---

## 8. DESIGN INTENT

**[NOTE]**
HADS exists because AI models increasingly read documentation before humans do. The format optimizes for this reality without sacrificing human readability.

Key insight: the AI manifest is the core innovation. It lets even small (7B) models know what to read and what to skip — without requiring them to reason about document structure. Explicit is better than implicit for model consumption.

When generating HADS, think of `[SPEC]` as the API surface and `[NOTE]` as the comments. `[BUG]` blocks are the most valuable content — they represent hard-won knowledge that saves others from hitting the same wall.

---

## 9. QUICK REFERENCE

**[SPEC]**
```
Tag       | Bold format    | Reader  | Required content
----------|----------------|---------|------------------
[SPEC]    | **[SPEC]**     | AI      | Facts, terse
[NOTE]    | **[NOTE]**     | Human   | Context, narrative
[BUG]     | **[BUG] ...**  | Both    | Symptom + fix
[?]       | **[?]**        | Both    | Unverified claims
```

Manifest minimum:
```markdown
## AI READING INSTRUCTION
Read `[SPEC]` and `[BUG]` blocks for authoritative facts.
Read `[NOTE]` only if additional context is needed.
`[?]` blocks are unverified.
```

<!-- chapter:end slug=hads -->

---

## Part: NET Contribution

---

<!-- chapter:begin slug=dotnet-backend-patterns position=66 -->

## 66. dotnet-backend-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/dotnet-contribution/skills/dotnet-backend-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/dotnet-contribution/skills/dotnet-backend-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/dotnet-backend-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `assets/repository-template.cs` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dotnet-contribution/skills/dotnet-backend-patterns/assets/repository-template.cs
  - `assets/service-template.cs` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dotnet-contribution/skills/dotnet-backend-patterns/assets/service-template.cs
  - `references/dapper-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dotnet-contribution/skills/dotnet-backend-patterns/references/dapper-patterns.md
  - `references/ef-core-best-practices.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/dotnet-contribution/skills/dotnet-backend-patterns/references/ef-core-best-practices.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: dotnet-backend-patterns
description: Master C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.
---

# .NET Backend Development Patterns

Master C#/.NET patterns for building production-grade APIs, MCP servers, and enterprise backends with modern best practices (2024/2025).

## When to Use This Skill

- Developing new .NET Web APIs or MCP servers
- Reviewing C# code for quality and performance
- Designing service architectures with dependency injection
- Implementing caching strategies with Redis
- Writing unit and integration tests
- Optimizing database access with EF Core or Dapper
- Configuring applications with IOptions pattern
- Handling errors and implementing resilience patterns

## Core Concepts

### 1. Project Structure (Clean Architecture)

```
src/
├── Domain/                     # Core business logic (no dependencies)
│   ├── Entities/
│   ├── Interfaces/
│   ├── Exceptions/
│   └── ValueObjects/
├── Application/                # Use cases, DTOs, validation
│   ├── Services/
│   ├── DTOs/
│   ├── Validators/
│   └── Interfaces/
├── Infrastructure/             # External implementations
│   ├── Data/                   # EF Core, Dapper repositories
│   ├── Caching/                # Redis, Memory cache
│   ├── External/               # HTTP clients, third-party APIs
│   └── DependencyInjection/    # Service registration
└── Api/                        # Entry point
    ├── Controllers/            # Or MinimalAPI endpoints
    ├── Middleware/
    ├── Filters/
    └── Program.cs
```

### 2. Dependency Injection Patterns

```csharp
// Service registration by lifetime
public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddApplicationServices(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        // Scoped: One instance per HTTP request
        services.AddScoped<IProductService, ProductService>();
        services.AddScoped<IOrderService, OrderService>();

        // Singleton: One instance for app lifetime
        services.AddSingleton<ICacheService, RedisCacheService>();
        services.AddSingleton<IConnectionMultiplexer>(_ =>
            ConnectionMultiplexer.Connect(configuration["Redis:Connection"]!));

        // Transient: New instance every time
        services.AddTransient<IValidator<CreateOrderRequest>, CreateOrderValidator>();

        // Options pattern for configuration
        services.Configure<CatalogOptions>(configuration.GetSection("Catalog"));
        services.Configure<RedisOptions>(configuration.GetSection("Redis"));

        // Factory pattern for conditional creation
        services.AddScoped<IPriceCalculator>(sp =>
        {
            var options = sp.GetRequiredService<IOptions<PricingOptions>>().Value;
            return options.UseNewEngine
                ? sp.GetRequiredService<NewPriceCalculator>()
                : sp.GetRequiredService<LegacyPriceCalculator>();
        });

        // Keyed services (.NET 8+)
        services.AddKeyedScoped<IPaymentProcessor, StripeProcessor>("stripe");
        services.AddKeyedScoped<IPaymentProcessor, PayPalProcessor>("paypal");

        return services;
    }
}

// Usage with keyed services
public class CheckoutService
{
    public CheckoutService(
        [FromKeyedServices("stripe")] IPaymentProcessor stripeProcessor)
    {
        _processor = stripeProcessor;
    }
}
```

### 3. Async/Await Patterns

```csharp
// ✅ CORRECT: Async all the way down
public async Task<Product> GetProductAsync(string id, CancellationToken ct = default)
{
    return await _repository.GetByIdAsync(id, ct);
}

// ✅ CORRECT: Parallel execution with WhenAll
public async Task<(Stock, Price)> GetStockAndPriceAsync(
    string productId,
    CancellationToken ct = default)
{
    var stockTask = _stockService.GetAsync(productId, ct);
    var priceTask = _priceService.GetAsync(productId, ct);

    await Task.WhenAll(stockTask, priceTask);

    return (await stockTask, await priceTask);
}

// ✅ CORRECT: ConfigureAwait in libraries
public async Task<T> LibraryMethodAsync<T>(CancellationToken ct = default)
{
    var result = await _httpClient.GetAsync(url, ct).ConfigureAwait(false);
    return await result.Content.ReadFromJsonAsync<T>(ct).ConfigureAwait(false);
}

// ✅ CORRECT: ValueTask for hot paths with caching
public ValueTask<Product?> GetCachedProductAsync(string id)
{
    if (_cache.TryGetValue(id, out Product? product))
        return ValueTask.FromResult(product);

    return new ValueTask<Product?>(GetFromDatabaseAsync(id));
}

// ❌ WRONG: Blocking on async (deadlock risk)
var result = GetProductAsync(id).Result;  // NEVER do this
var result2 = GetProductAsync(id).GetAwaiter().GetResult(); // Also bad

// ❌ WRONG: async void (except event handlers)
public async void ProcessOrder() { }  // Exceptions are lost

// ❌ WRONG: Unnecessary Task.Run for already async code
await Task.Run(async () => await GetDataAsync());  // Wastes thread
```

### 4. Configuration with IOptions

```csharp
// Configuration classes
public class CatalogOptions
{
    public const string SectionName = "Catalog";

    public int DefaultPageSize { get; set; } = 50;
    public int MaxPageSize { get; set; } = 200;
    public TimeSpan CacheDuration { get; set; } = TimeSpan.FromMinutes(15);
    public bool EnableEnrichment { get; set; } = true;
}

public class RedisOptions
{
    public const string SectionName = "Redis";

    public string Connection { get; set; } = "localhost:6379";
    public string KeyPrefix { get; set; } = "mcp:";
    public int Database { get; set; } = 0;
}

// appsettings.json
{
    "Catalog": {
        "DefaultPageSize": 50,
        "MaxPageSize": 200,
        "CacheDuration": "00:15:00",
        "EnableEnrichment": true
    },
    "Redis": {
        "Connection": "localhost:6379",
        "KeyPrefix": "mcp:",
        "Database": 0
    }
}

// Registration
services.Configure<CatalogOptions>(configuration.GetSection(CatalogOptions.SectionName));
services.Configure<RedisOptions>(configuration.GetSection(RedisOptions.SectionName));

// Usage with IOptions (singleton, read once at startup)
public class CatalogService
{
    private readonly CatalogOptions _options;

    public CatalogService(IOptions<CatalogOptions> options)
    {
        _options = options.Value;
    }
}

// Usage with IOptionsSnapshot (scoped, re-reads on each request)
public class DynamicService
{
    private readonly CatalogOptions _options;

    public DynamicService(IOptionsSnapshot<CatalogOptions> options)
    {
        _options = options.Value;  // Fresh value per request
    }
}

// Usage with IOptionsMonitor (singleton, notified on changes)
public class MonitoredService
{
    private CatalogOptions _options;

    public MonitoredService(IOptionsMonitor<CatalogOptions> monitor)
    {
        _options = monitor.CurrentValue;
        monitor.OnChange(newOptions => _options = newOptions);
    }
}
```

### 5. Result Pattern (Avoiding Exceptions for Flow Control)

```csharp
// Generic Result type
public class Result<T>
{
    public bool IsSuccess { get; }
    public T? Value { get; }
    public string? Error { get; }
    public string? ErrorCode { get; }

    private Result(bool isSuccess, T? value, string? error, string? errorCode)
    {
        IsSuccess = isSuccess;
        Value = value;
        Error = error;
        ErrorCode = errorCode;
    }

    public static Result<T> Success(T value) => new(true, value, null, null);
    public static Result<T> Failure(string error, string? code = null) => new(false, default, error, code);

    public Result<TNew> Map<TNew>(Func<T, TNew> mapper) =>
        IsSuccess ? Result<TNew>.Success(mapper(Value!)) : Result<TNew>.Failure(Error!, ErrorCode);

    public async Task<Result<TNew>> MapAsync<TNew>(Func<T, Task<TNew>> mapper) =>
        IsSuccess ? Result<TNew>.Success(await mapper(Value!)) : Result<TNew>.Failure(Error!, ErrorCode);
}

// Usage in service
public async Task<Result<Order>> CreateOrderAsync(CreateOrderRequest request, CancellationToken ct)
{
    // Validation
    var validation = await _validator.ValidateAsync(request, ct);
    if (!validation.IsValid)
        return Result<Order>.Failure(
            validation.Errors.First().ErrorMessage,
            "VALIDATION_ERROR");

    // Business rule check
    var stock = await _stockService.CheckAsync(request.ProductId, request.Quantity, ct);
    if (!stock.IsAvailable)
        return Result<Order>.Failure(
            $"Insufficient stock: {stock.Available} available, {request.Quantity} requested",
            "INSUFFICIENT_STOCK");

    // Create order
    var order = await _repository.CreateAsync(request.ToEntity(), ct);

    return Result<Order>.Success(order);
}

// Usage in controller/endpoint
app.MapPost("/orders", async (
    CreateOrderRequest request,
    IOrderService orderService,
    CancellationToken ct) =>
{
    var result = await orderService.CreateOrderAsync(request, ct);

    return result.IsSuccess
        ? Results.Created($"/orders/{result.Value!.Id}", result.Value)
        : Results.BadRequest(new { error = result.Error, code = result.ErrorCode });
});
```

## Data Access Patterns

### Entity Framework Core

```csharp
// DbContext configuration
public class AppDbContext : DbContext
{
    public DbSet<Product> Products => Set<Product>();
    public DbSet<Order> Orders => Set<Order>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Apply all configurations from assembly
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);

        // Global query filters
        modelBuilder.Entity<Product>().HasQueryFilter(p => !p.IsDeleted);
    }
}

// Entity configuration
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
    public void Configure(EntityTypeBuilder<Product> builder)
    {
        builder.ToTable("Products");

        builder.HasKey(p => p.Id);
        builder.Property(p => p.Id).HasMaxLength(40);
        builder.Property(p => p.Name).HasMaxLength(200).IsRequired();
        builder.Property(p => p.Price).HasPrecision(18, 2);

        builder.HasIndex(p => p.Sku).IsUnique();
        builder.HasIndex(p => new { p.CategoryId, p.Name });

        builder.HasMany(p => p.OrderItems)
            .WithOne(oi => oi.Product)
            .HasForeignKey(oi => oi.ProductId);
    }
}

// Repository with EF Core
public class ProductRepository : IProductRepository
{
    private readonly AppDbContext _context;

    public async Task<Product?> GetByIdAsync(string id, CancellationToken ct = default)
    {
        return await _context.Products
            .AsNoTracking()
            .FirstOrDefaultAsync(p => p.Id == id, ct);
    }

    public async Task<IReadOnlyList<Product>> SearchAsync(
        ProductSearchCriteria criteria,
        CancellationToken ct = default)
    {
        var query = _context.Products.AsNoTracking();

        if (!string.IsNullOrWhiteSpace(criteria.SearchTerm))
            query = query.Where(p => EF.Functions.Like(p.Name, $"%{criteria.SearchTerm}%"));

        if (criteria.CategoryId.HasValue)
            query = query.Where(p => p.CategoryId == criteria.CategoryId);

        if (criteria.MinPrice.HasValue)
            query = query.Where(p => p.Price >= criteria.MinPrice);

        if (criteria.MaxPrice.HasValue)
            query = query.Where(p => p.Price <= criteria.MaxPrice);

        return await query
            .OrderBy(p => p.Name)
            .Skip((criteria.Page - 1) * criteria.PageSize)
            .Take(criteria.PageSize)
            .ToListAsync(ct);
    }
}
```

### Dapper for Performance

```csharp
public class DapperProductRepository : IProductRepository
{
    private readonly IDbConnection _connection;

    public async Task<Product?> GetByIdAsync(string id, CancellationToken ct = default)
    {
        const string sql = """
            SELECT Id, Name, Sku, Price, CategoryId, Stock, CreatedAt
            FROM Products
            WHERE Id = @Id AND IsDeleted = 0
            """;

        return await _connection.QueryFirstOrDefaultAsync<Product>(
            new CommandDefinition(sql, new { Id = id }, cancellationToken: ct));
    }

    public async Task<IReadOnlyList<Product>> SearchAsync(
        ProductSearchCriteria criteria,
        CancellationToken ct = default)
    {
        var sql = new StringBuilder("""
            SELECT Id, Name, Sku, Price, CategoryId, Stock, CreatedAt
            FROM Products
            WHERE IsDeleted = 0
            """);

        var parameters = new DynamicParameters();

        if (!string.IsNullOrWhiteSpace(criteria.SearchTerm))
        {
            sql.Append(" AND Name LIKE @SearchTerm");
            parameters.Add("SearchTerm", $"%{criteria.SearchTerm}%");
        }

        if (criteria.CategoryId.HasValue)
        {
            sql.Append(" AND CategoryId = @CategoryId");
            parameters.Add("CategoryId", criteria.CategoryId);
        }

        if (criteria.MinPrice.HasValue)
        {
            sql.Append(" AND Price >= @MinPrice");
            parameters.Add("MinPrice", criteria.MinPrice);
        }

        if (criteria.MaxPrice.HasValue)
        {
            sql.Append(" AND Price <= @MaxPrice");
            parameters.Add("MaxPrice", criteria.MaxPrice);
        }

        sql.Append(" ORDER BY Name OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY");
        parameters.Add("Offset", (criteria.Page - 1) * criteria.PageSize);
        parameters.Add("PageSize", criteria.PageSize);

        var results = await _connection.QueryAsync<Product>(
            new CommandDefinition(sql.ToString(), parameters, cancellationToken: ct));

        return results.ToList();
    }

    // Multi-mapping for related data
    public async Task<Order?> GetOrderWithItemsAsync(int orderId, CancellationToken ct = default)
    {
        const string sql = """
            SELECT o.*, oi.*, p.*
            FROM Orders o
            LEFT JOIN OrderItems oi ON o.Id = oi.OrderId
            LEFT JOIN Products p ON oi.ProductId = p.Id
            WHERE o.Id = @OrderId
            """;

        var orderDictionary = new Dictionary<int, Order>();

        await _connection.QueryAsync<Order, OrderItem, Product, Order>(
            new CommandDefinition(sql, new { OrderId = orderId }, cancellationToken: ct),
            (order, item, product) =>
            {
                if (!orderDictionary.TryGetValue(order.Id, out var existingOrder))
                {
                    existingOrder = order;
                    existingOrder.Items = new List<OrderItem>();
                    orderDictionary.Add(order.Id, existingOrder);
                }

                if (item != null)
                {
                    item.Product = product;
                    existingOrder.Items.Add(item);
                }

                return existingOrder;
            },
            splitOn: "Id,Id");

        return orderDictionary.Values.FirstOrDefault();
    }
}
```

## Caching Patterns

### Multi-Level Cache with Redis

```csharp
public class CachedProductService : IProductService
{
    private readonly IProductRepository _repository;
    private readonly IMemoryCache _memoryCache;
    private readonly IDistributedCache _distributedCache;
    private readonly ILogger<CachedProductService> _logger;

    private static readonly TimeSpan MemoryCacheDuration = TimeSpan.FromMinutes(1);
    private static readonly TimeSpan DistributedCacheDuration = TimeSpan.FromMinutes(15);

    public async Task<Product?> GetByIdAsync(string id, CancellationToken ct = default)
    {
        var cacheKey = $"product:{id}";

        // L1: Memory cache (in-process, fastest)
        if (_memoryCache.TryGetValue(cacheKey, out Product? cached))
        {
            _logger.LogDebug("L1 cache hit for {CacheKey}", cacheKey);
            return cached;
        }

        // L2: Distributed cache (Redis)
        var distributed = await _distributedCache.GetStringAsync(cacheKey, ct);
        if (distributed != null)
        {
            _logger.LogDebug("L2 cache hit for {CacheKey}", cacheKey);
            var product = JsonSerializer.Deserialize<Product>(distributed);

            // Populate L1
            _memoryCache.Set(cacheKey, product, MemoryCacheDuration);
            return product;
        }

        // L3: Database
        _logger.LogDebug("Cache miss for {CacheKey}, fetching from database", cacheKey);
        var fromDb = await _repository.GetByIdAsync(id, ct);

        if (fromDb != null)
        {
            var serialized = JsonSerializer.Serialize(fromDb);

            // Populate both caches
            await _distributedCache.SetStringAsync(
                cacheKey,
                serialized,
                new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = DistributedCacheDuration
                },
                ct);

            _memoryCache.Set(cacheKey, fromDb, MemoryCacheDuration);
        }

        return fromDb;
    }

    public async Task InvalidateAsync(string id, CancellationToken ct = default)
    {
        var cacheKey = $"product:{id}";

        _memoryCache.Remove(cacheKey);
        await _distributedCache.RemoveAsync(cacheKey, ct);

        _logger.LogInformation("Invalidated cache for {CacheKey}", cacheKey);
    }
}

// Stale-while-revalidate pattern
public class StaleWhileRevalidateCache<T>
{
    private readonly IDistributedCache _cache;
    private readonly TimeSpan _freshDuration;
    private readonly TimeSpan _staleDuration;

    public async Task<T?> GetOrCreateAsync(
        string key,
        Func<CancellationToken, Task<T>> factory,
        CancellationToken ct = default)
    {
        var cached = await _cache.GetStringAsync(key, ct);

        if (cached != null)
        {
            var entry = JsonSerializer.Deserialize<CacheEntry<T>>(cached)!;

            if (entry.IsStale && !entry.IsExpired)
            {
                // Return stale data immediately, refresh in background
                _ = Task.Run(async () =>
                {
                    var fresh = await factory(CancellationToken.None);
                    await SetAsync(key, fresh, CancellationToken.None);
                });
            }

            if (!entry.IsExpired)
                return entry.Value;
        }

        // Cache miss or expired
        var value = await factory(ct);
        await SetAsync(key, value, ct);
        return value;
    }

    private record CacheEntry<TValue>(TValue Value, DateTime CreatedAt)
    {
        public bool IsStale => DateTime.UtcNow - CreatedAt > _freshDuration;
        public bool IsExpired => DateTime.UtcNow - CreatedAt > _staleDuration;
    }
}
```

## Testing Patterns

### Unit Tests with xUnit and Moq

```csharp
public class OrderServiceTests
{
    private readonly Mock<IOrderRepository> _mockRepository;
    private readonly Mock<IStockService> _mockStockService;
    private readonly Mock<IValidator<CreateOrderRequest>> _mockValidator;
    private readonly OrderService _sut; // System Under Test

    public OrderServiceTests()
    {
        _mockRepository = new Mock<IOrderRepository>();
        _mockStockService = new Mock<IStockService>();
        _mockValidator = new Mock<IValidator<CreateOrderRequest>>();

        // Default: validation passes
        _mockValidator
            .Setup(v => v.ValidateAsync(It.IsAny<CreateOrderRequest>(), It.IsAny<CancellationToken>()))
            .ReturnsAsync(new ValidationResult());

        _sut = new OrderService(
            _mockRepository.Object,
            _mockStockService.Object,
            _mockValidator.Object);
    }

    [Fact]
    public async Task CreateOrderAsync_WithValidRequest_ReturnsSuccess()
    {
        // Arrange
        var request = new CreateOrderRequest
        {
            ProductId = "PROD-001",
            Quantity = 5,
            CustomerOrderCode = "ORD-2024-001"
        };

        _mockStockService
            .Setup(s => s.CheckAsync("PROD-001", 5, It.IsAny<CancellationToken>()))
            .ReturnsAsync(new StockResult { IsAvailable = true, Available = 10 });

        _mockRepository
            .Setup(r => r.CreateAsync(It.IsAny<Order>(), It.IsAny<CancellationToken>()))
            .ReturnsAsync(new Order { Id = 1, CustomerOrderCode = "ORD-2024-001" });

        // Act
        var result = await _sut.CreateOrderAsync(request);

        // Assert
        Assert.True(result.IsSuccess);
        Assert.NotNull(result.Value);
        Assert.Equal(1, result.Value.Id);

        _mockRepository.Verify(
            r => r.CreateAsync(It.Is<Order>(o => o.CustomerOrderCode == "ORD-2024-001"),
            It.IsAny<CancellationToken>()),
            Times.Once);
    }

    [Fact]
    public async Task CreateOrderAsync_WithInsufficientStock_ReturnsFailure()
    {
        // Arrange
        var request = new CreateOrderRequest { ProductId = "PROD-001", Quantity = 100 };

        _mockStockService
            .Setup(s => s.CheckAsync(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
            .ReturnsAsync(new StockResult { IsAvailable = false, Available = 5 });

        // Act
        var result = await _sut.CreateOrderAsync(request);

        // Assert
        Assert.False(result.IsSuccess);
        Assert.Equal("INSUFFICIENT_STOCK", result.ErrorCode);
        Assert.Contains("5 available", result.Error);

        _mockRepository.Verify(
            r => r.CreateAsync(It.IsAny<Order>(), It.IsAny<CancellationToken>()),
            Times.Never);
    }

    [Theory]
    [InlineData(0)]
    [InlineData(-1)]
    [InlineData(-100)]
    public async Task CreateOrderAsync_WithInvalidQuantity_ReturnsValidationError(int quantity)
    {
        // Arrange
        var request = new CreateOrderRequest { ProductId = "PROD-001", Quantity = quantity };

        _mockValidator
            .Setup(v => v.ValidateAsync(request, It.IsAny<CancellationToken>()))
            .ReturnsAsync(new ValidationResult(new[]
            {
                new ValidationFailure("Quantity", "Quantity must be greater than 0")
            }));

        // Act
        var result = await _sut.CreateOrderAsync(request);

        // Assert
        Assert.False(result.IsSuccess);
        Assert.Equal("VALIDATION_ERROR", result.ErrorCode);
    }
}
```

### Integration Tests with WebApplicationFactory

```csharp
public class ProductsApiTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    private readonly HttpClient _client;

    public ProductsApiTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory.WithWebHostBuilder(builder =>
        {
            builder.ConfigureServices(services =>
            {
                // Replace real database with in-memory
                services.RemoveAll<DbContextOptions<AppDbContext>>();
                services.AddDbContext<AppDbContext>(options =>
                    options.UseInMemoryDatabase("TestDb"));

                // Replace Redis with memory cache
                services.RemoveAll<IDistributedCache>();
                services.AddDistributedMemoryCache();
            });
        });

        _client = _factory.CreateClient();
    }

    [Fact]
    public async Task GetProduct_WithValidId_ReturnsProduct()
    {
        // Arrange
        using var scope = _factory.Services.CreateScope();
        var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

        context.Products.Add(new Product
        {
            Id = "TEST-001",
            Name = "Test Product",
            Price = 99.99m
        });
        await context.SaveChangesAsync();

        // Act
        var response = await _client.GetAsync("/api/products/TEST-001");

        // Assert
        response.EnsureSuccessStatusCode();
        var product = await response.Content.ReadFromJsonAsync<Product>();
        Assert.Equal("Test Product", product!.Name);
    }

    [Fact]
    public async Task GetProduct_WithInvalidId_Returns404()
    {
        // Act
        var response = await _client.GetAsync("/api/products/NONEXISTENT");

        // Assert
        Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
    }
}
```

## Best Practices

### DO

1. **Use async/await** all the way through the call stack
2. **Inject dependencies** through constructor injection
3. **Use IOptions<T>** for typed configuration
4. **Return Result types** instead of throwing exceptions for business logic
5. **Use CancellationToken** in all async methods
6. **Prefer Dapper** for read-heavy, performance-critical queries
7. **Use EF Core** for complex domain models with change tracking
8. **Cache aggressively** with proper invalidation strategies
9. **Write unit tests** for business logic, integration tests for APIs
10. **Use record types** for DTOs and immutable data

### DON'T

1. **Don't block on async** with `.Result` or `.Wait()`
2. **Don't use async void** except for event handlers
3. **Don't catch generic Exception** without re-throwing or logging
4. **Don't hardcode** configuration values
5. **Don't expose EF entities** directly in APIs (use DTOs)
6. **Don't forget** `AsNoTracking()` for read-only queries
7. **Don't ignore** CancellationToken parameters
8. **Don't create** `new HttpClient()` manually (use IHttpClientFactory)
9. **Don't mix** sync and async code unnecessarily
10. **Don't skip** validation at API boundaries

## Common Pitfalls

- **N+1 Queries**: Use `.Include()` or explicit joins
- **Memory Leaks**: Dispose IDisposable resources, use `using`
- **Deadlocks**: Don't mix sync and async, use ConfigureAwait(false) in libraries
- **Over-fetching**: Select only needed columns, use projections
- **Missing Indexes**: Check query plans, add indexes for common filters
- **Timeout Issues**: Configure appropriate timeouts for HTTP clients
- **Cache Stampede**: Use distributed locks for cache population

<!-- chapter:end slug=dotnet-backend-patterns -->

---

## Part: File Conversion

---

<!-- chapter:begin slug=file-conversion position=67 -->

## 67. file-conversion

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/file-conversion/skills/file-conversion/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/file-conversion/skills/file-conversion/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/file-conversion.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `scripts/convert.sh` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/file-conversion/skills/file-conversion/scripts/convert.sh

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: file-conversion
description: Convert files between formats — PDF to Word, HEIC to JPG, MP4 to MP3, CSV to JSON, EPUB to MOBI, and 999 total routes across images, video, audio, documents, data, fonts, ebooks, and archives. Free via changethisfile.com, no API key or signup. Use when the user needs a file converted to a different format.
---

# File Conversion (ChangeThisFile)

Convert files between 999 conversion routes using the free ChangeThisFile service. No account or API key required. Conversions run server-side (FFmpeg, LibreOffice, Calibre, 7-Zip, sharp, Ghostscript); files are deleted within 24 hours.

## Decision order

1. **If ChangeThisFile MCP tools are available** (`changethisfile:convert_file`, `changethisfile:list_conversions`) — use them directly. `convert_file` takes `source_url` OR `base64_content` + `source_format`, plus `target_format`, and returns a temporary download URL.
2. **Otherwise, use the bundled script** (requires network access to changethisfile.com):

```bash
scripts/convert.sh <input-file> <target-format> [output-file]
# e.g. scripts/convert.sh report.docx pdf
# prints the output file path on success
```

The script path is relative to this skill's directory. It base64-encodes the file, calls the hosted MCP endpoint over plain HTTPS, downloads the result, and writes it next to the input (or to `[output-file]`).

3. **Remote file (you have a URL, not a local file)** — skip the download/re-upload; one curl does it:

```bash
curl -sS -X POST https://changethisfile.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"convert_file","arguments":{"source_url":"<FILE_URL>","target_format":"pdf"}}}'
```

The response text contains a download URL — fetch it with `curl -o <output>`.

## Discovering supported routes

Ask before guessing if a conversion is exotic:

```bash
curl -sS -X POST https://changethisfile.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_conversions","arguments":{"source_format":"docx"}}}'
```

Omit `source_format` for a grouped summary of all 999 routes.

## Limits and errors

- Max input: **25 MB** (free path). Larger files: get a free API key (1,000 conversions/month) at https://changethisfile.com/docs/authentication and use `POST /v1/convert`.
- Rate limit: **5 conversions/minute per IP**. On "Rate limit exceeded", wait 60 seconds and retry once.
- "Unsupported conversion: X→Y" errors list the valid targets for that source format.
- Download URLs expire after 1 hour — download immediately, then work with the local file.

## Environment notes

- Needs outbound HTTPS to `changethisfile.com`. On claude.ai, the code-execution sandbox restricts egress by default — prefer the MCP connector there, or the user can allow the domain under Settings → Capabilities.
- Full docs: https://changethisfile.com/docs/mcp

<!-- chapter:end slug=file-conversion -->

---

## Part: Framework Migration

---

<!-- chapter:begin slug=angular-migration position=68 -->

## 68. angular-migration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/framework-migration/skills/angular-migration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/angular-migration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/angular-migration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/angular-migration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: angular-migration
description: Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.
---

# Angular Migration

Master AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.

## When to Use This Skill

- Migrating AngularJS (1.x) applications to Angular (2+)
- Running hybrid AngularJS/Angular applications
- Converting directives to components
- Modernizing dependency injection
- Migrating routing systems
- Updating to latest Angular versions
- Implementing Angular best practices

## Migration Strategies

### 1. Big Bang (Complete Rewrite)

- Rewrite entire app in Angular
- Parallel development
- Switch over at once
- **Best for:** Small apps, green field projects

### 2. Incremental (Hybrid Approach)

- Run AngularJS and Angular side-by-side
- Migrate feature by feature
- ngUpgrade for interop
- **Best for:** Large apps, continuous delivery

### 3. Vertical Slice

- Migrate one feature completely
- New features in Angular, maintain old in AngularJS
- Gradually replace
- **Best for:** Medium apps, distinct features

## Hybrid App Setup

```typescript
// main.ts - Bootstrap hybrid app
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { UpgradeModule } from "@angular/upgrade/static";
import { AppModule } from "./app/app.module";

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .then((platformRef) => {
    const upgrade = platformRef.injector.get(UpgradeModule);
    // Bootstrap AngularJS
    upgrade.bootstrap(document.body, ["myAngularJSApp"], { strictDi: true });
  });
```

```typescript
// app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { UpgradeModule } from "@angular/upgrade/static";

@NgModule({
  imports: [BrowserModule, UpgradeModule],
})
export class AppModule {
  constructor(private upgrade: UpgradeModule) {}

  ngDoBootstrap() {
    // Bootstrapped manually in main.ts
  }
}
```

## Component Migration

### AngularJS Controller → Angular Component

```javascript
// Before: AngularJS controller
angular
  .module("myApp")
  .controller("UserController", function ($scope, UserService) {
    $scope.user = {};

    $scope.loadUser = function (id) {
      UserService.getUser(id).then(function (user) {
        $scope.user = user;
      });
    };

    $scope.saveUser = function () {
      UserService.saveUser($scope.user);
    };
  });
```

```typescript
// After: Angular component
import { Component, OnInit } from "@angular/core";
import { UserService } from "./user.service";

@Component({
  selector: "app-user",
  template: `
    <div>
      <h2>{{ user.name }}</h2>
      <button (click)="saveUser()">Save</button>
    </div>
  `,
})
export class UserComponent implements OnInit {
  user: any = {};

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.loadUser(1);
  }

  loadUser(id: number) {
    this.userService.getUser(id).subscribe((user) => {
      this.user = user;
    });
  }

  saveUser() {
    this.userService.saveUser(this.user);
  }
}
```

### AngularJS Directive → Angular Component

```javascript
// Before: AngularJS directive
angular.module("myApp").directive("userCard", function () {
  return {
    restrict: "E",
    scope: {
      user: "=",
      onDelete: "&",
    },
    template: `
      <div class="card">
        <h3>{{ user.name }}</h3>
        <button ng-click="onDelete()">Delete</button>
      </div>
    `,
  };
});
```

```typescript
// After: Angular component
import { Component, Input, Output, EventEmitter } from "@angular/core";

@Component({
  selector: "app-user-card",
  template: `
    <div class="card">
      <h3>{{ user.name }}</h3>
      <button (click)="delete.emit()">Delete</button>
    </div>
  `,
})
export class UserCardComponent {
  @Input() user: any;
  @Output() delete = new EventEmitter<void>();
}

// Usage: <app-user-card [user]="user" (delete)="handleDelete()"></app-user-card>
```

## Service Migration

```javascript
// Before: AngularJS service
angular.module("myApp").factory("UserService", function ($http) {
  return {
    getUser: function (id) {
      return $http.get("/api/users/" + id);
    },
    saveUser: function (user) {
      return $http.post("/api/users", user);
    },
  };
});
```

```typescript
// After: Angular service
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";

@Injectable({
  providedIn: "root",
})
export class UserService {
  constructor(private http: HttpClient) {}

  getUser(id: number): Observable<any> {
    return this.http.get(`/api/users/${id}`);
  }

  saveUser(user: any): Observable<any> {
    return this.http.post("/api/users", user);
  }
}
```

## Dependency Injection Changes

### Downgrading Angular → AngularJS

```typescript
// Angular service
import { Injectable } from "@angular/core";

@Injectable({ providedIn: "root" })
export class NewService {
  getData() {
    return "data from Angular";
  }
}

// Make available to AngularJS
import { downgradeInjectable } from "@angular/upgrade/static";

angular.module("myApp").factory("newService", downgradeInjectable(NewService));

// Use in AngularJS
angular.module("myApp").controller("OldController", function (newService) {
  console.log(newService.getData());
});
```

### Upgrading AngularJS → Angular

```typescript
// AngularJS service
angular.module('myApp').factory('oldService', function() {
  return {
    getData: function() {
      return 'data from AngularJS';
    }
  };
});

// Make available to Angular
import { InjectionToken } from '@angular/core';

export const OLD_SERVICE = new InjectionToken<any>('oldService');

@NgModule({
  providers: [
    {
      provide: OLD_SERVICE,
      useFactory: (i: any) => i.get('oldService'),
      deps: ['$injector']
    }
  ]
})

// Use in Angular
@Component({...})
export class NewComponent {
  constructor(@Inject(OLD_SERVICE) private oldService: any) {
    console.log(this.oldService.getData());
  }
}
```

## Routing Migration

```javascript
// Before: AngularJS routing
angular.module("myApp").config(function ($routeProvider) {
  $routeProvider
    .when("/users", {
      template: "<user-list></user-list>",
    })
    .when("/users/:id", {
      template: "<user-detail></user-detail>",
    });
});
```

```typescript
// After: Angular routing
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";

const routes: Routes = [
  { path: "users", component: UserListComponent },
  { path: "users/:id", component: UserDetailComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=angular-migration -->

---

<!-- chapter:begin slug=database-migration position=69 -->

## 69. database-migration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/framework-migration/skills/database-migration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/database-migration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/database-migration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/database-migration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: database-migration
description: Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases, changing schemas, performing data transformations, or implementing zero-downtime deployment strategies.
---

# Database Migration

Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.

## When to Use This Skill

- Migrating between different ORMs
- Performing schema transformations
- Moving data between databases
- Implementing rollback procedures
- Zero-downtime deployments
- Database version upgrades
- Data model refactoring

## ORM Migrations

### Sequelize Migrations

```javascript
// migrations/20231201-create-users.js
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable("users", {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },
      email: {
        type: Sequelize.STRING,
        unique: true,
        allowNull: false,
      },
      createdAt: Sequelize.DATE,
      updatedAt: Sequelize.DATE,
    });
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable("users");
  },
};

// Run: npx sequelize-cli db:migrate
// Rollback: npx sequelize-cli db:migrate:undo
```

### TypeORM Migrations

```typescript
// migrations/1701234567-CreateUsers.ts
import { MigrationInterface, QueryRunner, Table } from "typeorm";

export class CreateUsers1701234567 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.createTable(
      new Table({
        name: "users",
        columns: [
          {
            name: "id",
            type: "int",
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "email",
            type: "varchar",
            isUnique: true,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
        ],
      }),
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.dropTable("users");
  }
}

// Run: npm run typeorm migration:run
// Rollback: npm run typeorm migration:revert
```

### Prisma Migrations

```prisma
// schema.prisma
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  createdAt DateTime @default(now())
}

// Generate migration: npx prisma migrate dev --name create_users
// Apply: npx prisma migrate deploy
```

## Schema Transformations

### Adding Columns with Defaults

```javascript
// Safe migration: add column with default
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.addColumn("users", "status", {
      type: Sequelize.STRING,
      defaultValue: "active",
      allowNull: false,
    });
  },

  down: async (queryInterface) => {
    await queryInterface.removeColumn("users", "status");
  },
};
```

### Renaming Columns (Zero Downtime)

```javascript
// Step 1: Add new column
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.addColumn("users", "full_name", {
      type: Sequelize.STRING,
    });

    // Copy data from old column
    await queryInterface.sequelize.query("UPDATE users SET full_name = name");
  },

  down: async (queryInterface) => {
    await queryInterface.removeColumn("users", "full_name");
  },
};

// Step 2: Update application to use new column

// Step 3: Remove old column
module.exports = {
  up: async (queryInterface) => {
    await queryInterface.removeColumn("users", "name");
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.addColumn("users", "name", {
      type: Sequelize.STRING,
    });
  },
};
```

### Changing Column Types

```javascript
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // For large tables, use multi-step approach

    // 1. Add new column
    await queryInterface.addColumn("users", "age_new", {
      type: Sequelize.INTEGER,
    });

    // 2. Copy and transform data
    await queryInterface.sequelize.query(`
      UPDATE users
      SET age_new = CAST(age AS INTEGER)
      WHERE age IS NOT NULL
    `);

    // 3. Drop old column
    await queryInterface.removeColumn("users", "age");

    // 4. Rename new column
    await queryInterface.renameColumn("users", "age_new", "age");
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.changeColumn("users", "age", {
      type: Sequelize.STRING,
    });
  },
};
```

## Data Transformations

### Complex Data Migration

```javascript
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // Get all records
    const [users] = await queryInterface.sequelize.query(
      "SELECT id, address_string FROM users",
    );

    // Transform each record
    for (const user of users) {
      const addressParts = user.address_string.split(",");

      await queryInterface.sequelize.query(
        `UPDATE users
         SET street = :street,
             city = :city,
             state = :state
         WHERE id = :id`,
        {
          replacements: {
            id: user.id,
            street: addressParts[0]?.trim(),
            city: addressParts[1]?.trim(),
            state: addressParts[2]?.trim(),
          },
        },
      );
    }

    // Drop old column
    await queryInterface.removeColumn("users", "address_string");
  },

  down: async (queryInterface, Sequelize) => {
    // Reconstruct original column
    await queryInterface.addColumn("users", "address_string", {
      type: Sequelize.STRING,
    });

    await queryInterface.sequelize.query(`
      UPDATE users
      SET address_string = CONCAT(street, ', ', city, ', ', state)
    `);

    await queryInterface.removeColumn("users", "street");
    await queryInterface.removeColumn("users", "city");
    await queryInterface.removeColumn("users", "state");
  },
};
```

## Rollback Strategies

### Transaction-Based Migrations

```javascript
module.exports = {
  up: async (queryInterface, Sequelize) => {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      await queryInterface.addColumn(
        "users",
        "verified",
        { type: Sequelize.BOOLEAN, defaultValue: false },
        { transaction },
      );

      await queryInterface.sequelize.query(
        "UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL",
        { transaction },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  },

  down: async (queryInterface) => {
    await queryInterface.removeColumn("users", "verified");
  },
};
```

### Checkpoint-Based Rollback

```javascript
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // Create backup table
    await queryInterface.sequelize.query(
      "CREATE TABLE users_backup AS SELECT * FROM users",
    );

    try {
      // Perform migration
      await queryInterface.addColumn("users", "new_field", {
        type: Sequelize.STRING,
      });

      // Verify migration
      const [result] = await queryInterface.sequelize.query(
        "SELECT COUNT(*) as count FROM users WHERE new_field IS NULL",
      );

      if (result[0].count > 0) {
        throw new Error("Migration verification failed");
      }

      // Drop backup
      await queryInterface.dropTable("users_backup");
    } catch (error) {
      // Restore from backup
      await queryInterface.sequelize.query("DROP TABLE users");
      await queryInterface.sequelize.query(
        "CREATE TABLE users AS SELECT * FROM users_backup",
      );
      await queryInterface.dropTable("users_backup");
      throw error;
    }
  },
};
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=database-migration -->

---

<!-- chapter:begin slug=dependency-upgrade position=70 -->

## 70. dependency-upgrade

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/framework-migration/skills/dependency-upgrade/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/dependency-upgrade/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/dependency-upgrade.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: dependency-upgrade
description: Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.
---

# Dependency Upgrade

Master major dependency version upgrades, compatibility analysis, staged upgrade strategies, and comprehensive testing approaches.

## When to Use This Skill

- Upgrading major framework versions
- Updating security-vulnerable dependencies
- Modernizing legacy dependencies
- Resolving dependency conflicts
- Planning incremental upgrade paths
- Testing compatibility matrices
- Automating dependency updates

## Semantic Versioning Review

```
MAJOR.MINOR.PATCH (e.g., 2.3.1)

MAJOR: Breaking changes
MINOR: New features, backward compatible
PATCH: Bug fixes, backward compatible

^2.3.1 = >=2.3.1 <3.0.0 (minor updates)
~2.3.1 = >=2.3.1 <2.4.0 (patch updates)
2.3.1 = exact version
```

## Dependency Analysis

### Audit Dependencies

```bash
# npm
npm outdated
npm audit
npm audit fix

# yarn
yarn outdated
yarn audit

# Check for major updates
npx npm-check-updates
npx npm-check-updates -u  # Update package.json
```

### Analyze Dependency Tree

```bash
# See why a package is installed
npm ls package-name
yarn why package-name

# Find duplicate packages
npm dedupe
yarn dedupe

# Visualize dependencies
npx madge --image graph.png src/
```

## Compatibility Matrix

```javascript
// compatibility-matrix.js
const compatibilityMatrix = {
  react: {
    "16.x": {
      "react-dom": "^16.0.0",
      "react-router-dom": "^5.0.0",
      "@testing-library/react": "^11.0.0",
    },
    "17.x": {
      "react-dom": "^17.0.0",
      "react-router-dom": "^5.0.0 || ^6.0.0",
      "@testing-library/react": "^12.0.0",
    },
    "18.x": {
      "react-dom": "^18.0.0",
      "react-router-dom": "^6.0.0",
      "@testing-library/react": "^13.0.0",
    },
  },
};

function checkCompatibility(packages) {
  // Validate package versions against matrix
}
```

## Staged Upgrade Strategy

### Phase 1: Planning

```bash
# 1. Identify current versions
npm list --depth=0

# 2. Check for breaking changes
# Read CHANGELOG.md and MIGRATION.md

# 3. Create upgrade plan
echo "Upgrade order:
1. TypeScript
2. React
3. React Router
4. Testing libraries
5. Build tools" > UPGRADE_PLAN.md
```

### Phase 2: Incremental Updates

```bash
# Don't upgrade everything at once!

# Step 1: Update TypeScript
npm install typescript@latest

# Test
npm run test
npm run build

# Step 2: Update React (one major version at a time)
npm install react@17 react-dom@17

# Test again
npm run test

# Step 3: Continue with other packages
npm install react-router-dom@6

# And so on...
```

### Phase 3: Validation

```javascript
// tests/compatibility.test.js
describe("Dependency Compatibility", () => {
  it("should have compatible React versions", () => {
    const reactVersion = require("react/package.json").version;
    const reactDomVersion = require("react-dom/package.json").version;

    expect(reactVersion).toBe(reactDomVersion);
  });

  it("should not have peer dependency warnings", () => {
    // Run npm ls and check for warnings
  });
});
```

## Breaking Change Handling

### Identifying Breaking Changes

```bash
# Check the changelog directly
curl https://raw.githubusercontent.com/facebook/react/master/CHANGELOG.md
```

### Codemod for Automated Fixes

```bash
# Run jscodeshift with transform URL
npx jscodeshift -t <transform-url> <path>

# Example: Rename unsafe lifecycle methods
npx jscodeshift -t https://raw.githubusercontent.com/reactjs/react-codemod/master/transforms/rename-unsafe-lifecycles.js src/

# For TypeScript files
npx jscodeshift -t https://raw.githubusercontent.com/reactjs/react-codemod/master/transforms/rename-unsafe-lifecycles.js --parser=tsx src/

# Dry run to preview changes
npx jscodeshift -t https://raw.githubusercontent.com/reactjs/react-codemod/master/transforms/rename-unsafe-lifecycles.js --dry src/
```

### Custom Migration Script

```javascript
// migration-script.js
const fs = require("fs");
const glob = require("glob");

glob("src/**/*.tsx", (err, files) => {
  files.forEach((file) => {
    let content = fs.readFileSync(file, "utf8");

    // Replace old API with new API
    content = content.replace(
      /componentWillMount/g,
      "UNSAFE_componentWillMount",
    );

    // Update imports
    content = content.replace(
      /import { Component } from 'react'/g,
      "import React, { Component } from 'react'",
    );

    fs.writeFileSync(file, content);
  });
});
```

## Testing Strategy

### Unit Tests

```javascript
// Ensure tests pass before and after upgrade
npm run test

// Update test utilities if needed
npm install @testing-library/react@latest
```

### Integration Tests

```javascript
// tests/integration/app.test.js
describe("App Integration", () => {
  it("should render without crashing", () => {
    render(<App />);
  });

  it("should handle navigation", () => {
    const { getByText } = render(<App />);
    fireEvent.click(getByText("Navigate"));
    expect(screen.getByText("New Page")).toBeInTheDocument();
  });
});
```

### Visual Regression Tests

```javascript
// visual-regression.test.js
describe("Visual Regression", () => {
  it("should match snapshot", () => {
    const { container } = render(<App />);
    expect(container.firstChild).toMatchSnapshot();
  });
});
```

### E2E Tests

```javascript
// cypress/e2e/app.cy.js
describe("E2E Tests", () => {
  it("should complete user flow", () => {
    cy.visit("/");
    cy.get('[data-testid="login"]').click();
    cy.get('input[name="email"]').type("user@example.com");
    cy.get('button[type="submit"]').click();
    cy.url().should("include", "/dashboard");
  });
});
```

## Automated Dependency Updates

### Renovate Configuration

```json
// renovate.json
{
  "extends": ["config:base"],
  "packageRules": [
    {
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    },
    {
      "matchUpdateTypes": ["major"],
      "automerge": false,
      "labels": ["major-update"]
    }
  ],
  "schedule": ["before 3am on Monday"],
  "timezone": "America/New_York"
}
```

### Dependabot Configuration

```yaml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5
    reviewers:
      - "team-leads"
    commit-message:
      prefix: "chore"
      include: "scope"
```

## Rollback Plan

```javascript
// rollback.sh
#!/bin/bash

# Save current state
git stash
git checkout -b upgrade-branch

# Attempt upgrade
npm install package@latest

# Run tests
if npm run test; then
  echo "Upgrade successful"
  git add package.json package-lock.json
  git commit -m "chore: upgrade package"
else
  echo "Upgrade failed, rolling back"
  git checkout main
  git branch -D upgrade-branch
  npm install  # Restore from package-lock.json
fi
```

## Common Upgrade Patterns

### Lock File Management

```bash
# npm
npm install --package-lock-only  # Update lock file only
npm ci  # Clean install from lock file

# yarn
yarn install --frozen-lockfile  # CI mode
yarn upgrade-interactive  # Interactive upgrades
```

### Peer Dependency Resolution

```bash
# npm 7+: strict peer dependencies
npm install --legacy-peer-deps  # Ignore peer deps

# npm 8+: override peer dependencies
npm install --force
```

### Workspace Upgrades

```bash
# Update all workspace packages
npm install --workspaces

# Update specific workspace
npm install package@latest --workspace=packages/app
```

<!-- chapter:end slug=dependency-upgrade -->

---

<!-- chapter:begin slug=react-modernization position=71 -->

## 71. react-modernization

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/framework-migration/skills/react-modernization/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/react-modernization/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/react-modernization.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/framework-migration/skills/react-modernization/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: react-modernization
description: Upgrade React applications to latest versions, migrate from class components to hooks, and adopt concurrent features. Use when modernizing React codebases, migrating to React Hooks, or upgrading to latest React versions.
---

# React Modernization

Master React version upgrades, class to hooks migration, concurrent features adoption, and codemods for automated transformation.

## When to Use This Skill

- Upgrading React applications to latest versions
- Migrating class components to functional components with hooks
- Adopting concurrent React features (Suspense, transitions)
- Applying codemods for automated refactoring
- Modernizing state management patterns
- Updating to TypeScript
- Improving performance with React 18+ features

## Version Upgrade Path

### React 16 → 17 → 18

**Breaking Changes by Version:**

**React 17:**

- Event delegation changes
- No event pooling
- Effect cleanup timing
- JSX transform (no React import needed)

**React 18:**

- Automatic batching
- Concurrent rendering
- Strict Mode changes (double invocation)
- New root API
- Suspense on server

## Class to Hooks Migration

### State Management

```javascript
// Before: Class component
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      name: "",
    };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

// After: Functional component with hooks
function Counter() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState("");

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
```

### Lifecycle Methods to Hooks

```javascript
// Before: Lifecycle methods
class DataFetcher extends React.Component {
  state = { data: null, loading: true };

  componentDidMount() {
    this.fetchData();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.id !== this.props.id) {
      this.fetchData();
    }
  }

  componentWillUnmount() {
    this.cancelRequest();
  }

  fetchData = async () => {
    const data = await fetch(`/api/${this.props.id}`);
    this.setState({ data, loading: false });
  };

  cancelRequest = () => {
    // Cleanup
  };

  render() {
    if (this.state.loading) return <div>Loading...</div>;
    return <div>{this.state.data}</div>;
  }
}

// After: useEffect hook
function DataFetcher({ id }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;

    const fetchData = async () => {
      try {
        const response = await fetch(`/api/${id}`);
        const result = await response.json();

        if (!cancelled) {
          setData(result);
          setLoading(false);
        }
      } catch (error) {
        if (!cancelled) {
          console.error(error);
        }
      }
    };

    fetchData();

    // Cleanup function
    return () => {
      cancelled = true;
    };
  }, [id]); // Re-run when id changes

  if (loading) return <div>Loading...</div>;
  return <div>{data}</div>;
}
```

### Context and HOCs to Hooks

```javascript
// Before: Context consumer and HOC
const ThemeContext = React.createContext();

class ThemedButton extends React.Component {
  static contextType = ThemeContext;

  render() {
    return (
      <button style={{ background: this.context.theme }}>
        {this.props.children}
      </button>
    );
  }
}

// After: useContext hook
function ThemedButton({ children }) {
  const { theme } = useContext(ThemeContext);

  return <button style={{ background: theme }}>{children}</button>;
}

// Before: HOC for data fetching
function withUser(Component) {
  return class extends React.Component {
    state = { user: null };

    componentDidMount() {
      fetchUser().then((user) => this.setState({ user }));
    }

    render() {
      return <Component {...this.props} user={this.state.user} />;
    }
  };
}

// After: Custom hook
function useUser() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser().then(setUser);
  }, []);

  return user;
}

function UserProfile() {
  const user = useUser();
  if (!user) return <div>Loading...</div>;
  return <div>{user.name}</div>;
}
```

## React 18 Concurrent Features

### New Root API

```javascript
// Before: React 17
import ReactDOM from "react-dom";

ReactDOM.render(<App />, document.getElementById("root"));

// After: React 18
import { createRoot } from "react-dom/client";

const root = createRoot(document.getElementById("root"));
root.render(<App />);
```

### Automatic Batching

```javascript
// React 18: All updates are batched
function handleClick() {
  setCount((c) => c + 1);
  setFlag((f) => !f);
  // Only one re-render (batched)
}

// Even in async:
setTimeout(() => {
  setCount((c) => c + 1);
  setFlag((f) => !f);
  // Still batched in React 18!
}, 1000);

// Opt out if needed
import { flushSync } from "react-dom";

flushSync(() => {
  setCount((c) => c + 1);
});
// Re-render happens here
setFlag((f) => !f);
// Another re-render
```

### Transitions

```javascript
import { useState, useTransition } from "react";

function SearchResults() {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    // Urgent: Update input immediately
    setQuery(e.target.value);

    // Non-urgent: Update results (can be interrupted)
    startTransition(() => {
      setResults(searchResults(e.target.value));
    });
  };

  return (
    <>
      <input value={query} onChange={handleChange} />
      {isPending && <Spinner />}
      <Results data={results} />
    </>
  );
}
```

### Suspense for Data Fetching

```javascript
import { Suspense } from "react";

// Resource-based data fetching (with React 18)
const resource = fetchProfileData();

function ProfilePage() {
  return (
    <Suspense fallback={<Loading />}>
      <ProfileDetails />
      <Suspense fallback={<Loading />}>
        <ProfileTimeline />
      </Suspense>
    </Suspense>
  );
}

function ProfileDetails() {
  // This will suspend if data not ready
  const user = resource.user.read();
  return <h1>{user.name}</h1>;
}

function ProfileTimeline() {
  const posts = resource.posts.read();
  return <Timeline posts={posts} />;
}
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=react-modernization -->

---

## Part: Frontend Mobile Development

---

<!-- chapter:begin slug=nextjs-app-router-patterns position=72 -->

## 72. nextjs-app-router-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/frontend-mobile-development/skills/nextjs-app-router-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/nextjs-app-router-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/nextjs-app-router-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/nextjs-app-router-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: nextjs-app-router-patterns
description: Master Next.js 14+ App Router with Server Components, streaming, parallel routes, and advanced data fetching. Use when building Next.js applications, implementing SSR/SSG, or optimizing React Server Components.
---

# Next.js App Router Patterns

Comprehensive patterns for Next.js 14+ App Router architecture, Server Components, and modern full-stack React development.

## When to Use This Skill

- Building new Next.js applications with App Router
- Migrating from Pages Router to App Router
- Implementing Server Components and streaming
- Setting up parallel and intercepting routes
- Optimizing data fetching and caching
- Building full-stack features with Server Actions

## Core Concepts

### 1. Rendering Modes

| Mode                  | Where        | When to Use                               |
| --------------------- | ------------ | ----------------------------------------- |
| **Server Components** | Server only  | Data fetching, heavy computation, secrets |
| **Client Components** | Browser      | Interactivity, hooks, browser APIs        |
| **Static**            | Build time   | Content that rarely changes               |
| **Dynamic**           | Request time | Personalized or real-time data            |
| **Streaming**         | Progressive  | Large pages, slow data sources            |

### 2. File Conventions

```
app/
├── layout.tsx       # Shared UI wrapper
├── page.tsx         # Route UI
├── loading.tsx      # Loading UI (Suspense)
├── error.tsx        # Error boundary
├── not-found.tsx    # 404 UI
├── route.ts         # API endpoint
├── template.tsx     # Re-mounted layout
├── default.tsx      # Parallel route fallback
└── opengraph-image.tsx  # OG image generation
```

## Quick Start

```typescript
// app/layout.tsx
import { Inter } from 'next/font/google'
import { Providers } from './providers'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: { default: 'My App', template: '%s | My App' },
  description: 'Built with Next.js App Router',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={inter.className}>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

// app/page.tsx - Server Component by default
async function getProducts() {
  const res = await fetch('https://api.example.com/products', {
    next: { revalidate: 3600 }, // ISR: revalidate every hour
  })
  return res.json()
}

export default async function HomePage() {
  const products = await getProducts()

  return (
    <main>
      <h1>Products</h1>
      <ProductGrid products={products} />
    </main>
  )
}
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Start with Server Components** - Add 'use client' only when needed
- **Colocate data fetching** - Fetch data where it's used
- **Use Suspense boundaries** - Enable streaming for slow data
- **Leverage parallel routes** - Independent loading states
- **Use Server Actions** - For mutations with progressive enhancement

### Don'ts

- **Don't pass serializable data** - Server → Client boundary limitations
- **Don't use hooks in Server Components** - No useState, useEffect
- **Don't fetch in Client Components** - Use Server Components or React Query
- **Don't over-nest layouts** - Each layout adds to the component tree
- **Don't ignore loading states** - Always provide loading.tsx or Suspense

<!-- chapter:end slug=nextjs-app-router-patterns -->

---

<!-- chapter:begin slug=react-native-architecture position=73 -->

## 73. react-native-architecture

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/frontend-mobile-development/skills/react-native-architecture/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/react-native-architecture/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/react-native-architecture.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/react-native-architecture/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: react-native-architecture
description: Build production React Native apps with Expo, navigation, native modules, offline sync, and cross-platform patterns. Use when developing mobile apps, implementing native integrations, or architecting React Native projects.
---

# React Native Architecture

Production-ready patterns for React Native development with Expo, including navigation, state management, native modules, and offline-first architecture.

## When to Use This Skill

- Starting a new React Native or Expo project
- Implementing complex navigation patterns
- Integrating native modules and platform APIs
- Building offline-first mobile applications
- Optimizing React Native performance
- Setting up CI/CD for mobile releases

## Core Concepts

### 1. Project Structure

```
src/
├── app/                    # Expo Router screens
│   ├── (auth)/            # Auth group
│   ├── (tabs)/            # Tab navigation
│   └── _layout.tsx        # Root layout
├── components/
│   ├── ui/                # Reusable UI components
│   └── features/          # Feature-specific components
├── hooks/                 # Custom hooks
├── services/              # API and native services
├── stores/                # State management
├── utils/                 # Utilities
└── types/                 # TypeScript types
```

### 2. Expo vs Bare React Native

| Feature            | Expo           | Bare RN        |
| ------------------ | -------------- | -------------- |
| Setup complexity   | Low            | High           |
| Native modules     | EAS Build      | Manual linking |
| OTA updates        | Built-in       | Manual setup   |
| Build service      | EAS            | Custom CI      |
| Custom native code | Config plugins | Direct access  |

## Quick Start

```bash
# Create new Expo project
npx create-expo-app@latest my-app -t expo-template-blank-typescript

# Install essential dependencies
npx expo install expo-router expo-status-bar react-native-safe-area-context
npx expo install @react-native-async-storage/async-storage
npx expo install expo-secure-store expo-haptics
```

```typescript
// app/_layout.tsx
import { Stack } from 'expo-router'
import { ThemeProvider } from '@/providers/ThemeProvider'
import { QueryProvider } from '@/providers/QueryProvider'

export default function RootLayout() {
  return (
    <QueryProvider>
      <ThemeProvider>
        <Stack screenOptions={{ headerShown: false }}>
          <Stack.Screen name="(tabs)" />
          <Stack.Screen name="(auth)" />
          <Stack.Screen name="modal" options={{ presentation: 'modal' }} />
        </Stack>
      </ThemeProvider>
    </QueryProvider>
  )
}
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use Expo** - Faster development, OTA updates, managed native code
- **FlashList over FlatList** - Better performance for long lists
- **Memoize components** - Prevent unnecessary re-renders
- **Use Reanimated** - 60fps animations on native thread
- **Test on real devices** - Simulators miss real-world issues

### Don'ts

- **Don't inline styles** - Use StyleSheet.create for performance
- **Don't fetch in render** - Use useEffect or React Query
- **Don't ignore platform differences** - Test on both iOS and Android
- **Don't store secrets in code** - Use environment variables
- **Don't skip error boundaries** - Mobile crashes are unforgiving

<!-- chapter:end slug=react-native-architecture -->

---

<!-- chapter:begin slug=react-state-management position=74 -->

## 74. react-state-management

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/frontend-mobile-development/skills/react-state-management/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/react-state-management/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/react-state-management.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/react-state-management/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: react-state-management
description: Master modern React state management with Redux Toolkit, Zustand, Jotai, and React Query. Use when setting up global state, managing server state, or choosing between state management solutions.
---

# React State Management

Comprehensive guide to modern React state management patterns, from local component state to global stores and server state synchronization.

## When to Use This Skill

- Setting up global state management in a React app
- Choosing between Redux Toolkit, Zustand, or Jotai
- Managing server state with React Query or SWR
- Implementing optimistic updates
- Debugging state-related issues
- Migrating from legacy Redux to modern patterns

## Core Concepts

### 1. State Categories

| Type             | Description                  | Solutions                     |
| ---------------- | ---------------------------- | ----------------------------- |
| **Local State**  | Component-specific, UI state | useState, useReducer          |
| **Global State** | Shared across components     | Redux Toolkit, Zustand, Jotai |
| **Server State** | Remote data, caching         | React Query, SWR, RTK Query   |
| **URL State**    | Route parameters, search     | React Router, nuqs            |
| **Form State**   | Input values, validation     | React Hook Form, Formik       |

### 2. Selection Criteria

```
Small app, simple state → Zustand or Jotai
Large app, complex state → Redux Toolkit
Heavy server interaction → React Query + light client state
Atomic/granular updates → Jotai
```

## Quick Start

### Zustand (Simplest)

```typescript
// store/useStore.ts
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'

interface AppState {
  user: User | null
  theme: 'light' | 'dark'
  setUser: (user: User | null) => void
  toggleTheme: () => void
}

export const useStore = create<AppState>()(
  devtools(
    persist(
      (set) => ({
        user: null,
        theme: 'light',
        setUser: (user) => set({ user }),
        toggleTheme: () => set((state) => ({
          theme: state.theme === 'light' ? 'dark' : 'light'
        })),
      }),
      { name: 'app-storage' }
    )
  )
)

// Usage in component
function Header() {
  const { user, theme, toggleTheme } = useStore()
  return (
    <header className={theme}>
      {user?.name}
      <button onClick={toggleTheme}>Toggle Theme</button>
    </header>
  )
}
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Colocate state** - Keep state as close to where it's used as possible
- **Use selectors** - Prevent unnecessary re-renders with selective subscriptions
- **Normalize data** - Flatten nested structures for easier updates
- **Type everything** - Full TypeScript coverage prevents runtime errors
- **Separate concerns** - Server state (React Query) vs client state (Zustand)

### Don'ts

- **Don't over-globalize** - Not everything needs to be in global state
- **Don't duplicate server state** - Let React Query manage it
- **Don't mutate directly** - Always use immutable updates
- **Don't store derived data** - Compute it instead
- **Don't mix paradigms** - Pick one primary solution per category

## Migration Guides

### From Legacy Redux to RTK

```typescript
// Before (legacy Redux)
const ADD_TODO = "ADD_TODO";
const addTodo = (text) => ({ type: ADD_TODO, payload: text });
function todosReducer(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [...state, { text: action.payload, completed: false }];
    default:
      return state;
  }
}

// After (Redux Toolkit)
const todosSlice = createSlice({
  name: "todos",
  initialState: [],
  reducers: {
    addTodo: (state, action: PayloadAction<string>) => {
      // Immer allows "mutations"
      state.push({ text: action.payload, completed: false });
    },
  },
});
```

<!-- chapter:end slug=react-state-management -->

---

<!-- chapter:begin slug=tailwind-design-system position=75 -->

## 75. tailwind-design-system

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/frontend-mobile-development/skills/tailwind-design-system/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/tailwind-design-system/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/tailwind-design-system.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/tailwind-design-system/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/frontend-mobile-development/skills/tailwind-design-system/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: tailwind-design-system
description: Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
---

# Tailwind Design System (v4)

Build production-ready design systems with Tailwind CSS v4, including CSS-first configuration, design tokens, component variants, responsive patterns, and accessibility.

> **Note**: This skill targets Tailwind CSS v4 (2024+). For v3 projects, refer to the [upgrade guide](https://tailwindcss.com/docs/upgrade-guide).

## When to Use This Skill

- Creating a component library with Tailwind v4
- Implementing design tokens and theming with CSS-first configuration
- Building responsive and accessible components
- Standardizing UI patterns across a codebase
- Migrating from Tailwind v3 to v4
- Setting up dark mode with native CSS features

## Key v4 Changes

| v3 Pattern                            | v4 Pattern                                                            |
| ------------------------------------- | --------------------------------------------------------------------- |
| `tailwind.config.ts`                  | `@theme` in CSS                                                       |
| `@tailwind base/components/utilities` | `@import "tailwindcss"`                                               |
| `darkMode: "class"`                   | `@custom-variant dark (&:where(.dark, .dark *))`                      |
| `theme.extend.colors`                 | `@theme { --color-*: value }`                                         |
| `require("tailwindcss-animate")`      | CSS `@keyframes` in `@theme` + `@starting-style` for entry animations |

## Quick Start

```css
/* app.css - Tailwind v4 CSS-first configuration */
@import "tailwindcss";

/* Define your theme with @theme */
@theme {
  /* Semantic color tokens using OKLCH for better color perception */
  --color-background: oklch(100% 0 0);
  --color-foreground: oklch(14.5% 0.025 264);

  --color-primary: oklch(14.5% 0.025 264);
  --color-primary-foreground: oklch(98% 0.01 264);

  --color-secondary: oklch(96% 0.01 264);
  --color-secondary-foreground: oklch(14.5% 0.025 264);

  --color-muted: oklch(96% 0.01 264);
  --color-muted-foreground: oklch(46% 0.02 264);

  --color-accent: oklch(96% 0.01 264);
  --color-accent-foreground: oklch(14.5% 0.025 264);

  --color-destructive: oklch(53% 0.22 27);
  --color-destructive-foreground: oklch(98% 0.01 264);

  --color-border: oklch(91% 0.01 264);
  --color-ring: oklch(14.5% 0.025 264);

  --color-card: oklch(100% 0 0);
  --color-card-foreground: oklch(14.5% 0.025 264);

  /* Ring offset for focus states */
  --color-ring-offset: oklch(100% 0 0);

  /* Radius tokens */
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;

  /* Animation tokens - keyframes inside @theme are output when referenced by --animate-* variables */
  --animate-fade-in: fade-in 0.2s ease-out;
  --animate-fade-out: fade-out 0.2s ease-in;
  --animate-slide-in: slide-in 0.3s ease-out;
  --animate-slide-out: slide-out 0.3s ease-in;

  @keyframes fade-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  @keyframes fade-out {
    from {
      opacity: 1;
    }
    to {
      opacity: 0;
    }
  }

  @keyframes slide-in {
    from {
      transform: translateY(-0.5rem);
      opacity: 0;
    }
    to {
      transform: translateY(0);
      opacity: 1;
    }
  }

  @keyframes slide-out {
    from {
      transform: translateY(0);
      opacity: 1;
    }
    to {
      transform: translateY(-0.5rem);
      opacity: 0;
    }
  }
}

/* Dark mode variant - use @custom-variant for class-based dark mode */
@custom-variant dark (&:where(.dark, .dark *));

/* Dark mode theme overrides */
.dark {
  --color-background: oklch(14.5% 0.025 264);
  --color-foreground: oklch(98% 0.01 264);

  --color-primary: oklch(98% 0.01 264);
  --color-primary-foreground: oklch(14.5% 0.025 264);

  --color-secondary: oklch(22% 0.02 264);
  --color-secondary-foreground: oklch(98% 0.01 264);

  --color-muted: oklch(22% 0.02 264);
  --color-muted-foreground: oklch(65% 0.02 264);

  --color-accent: oklch(22% 0.02 264);
  --color-accent-foreground: oklch(98% 0.01 264);

  --color-destructive: oklch(42% 0.15 27);
  --color-destructive-foreground: oklch(98% 0.01 264);

  --color-border: oklch(22% 0.02 264);
  --color-ring: oklch(83% 0.02 264);

  --color-card: oklch(14.5% 0.025 264);
  --color-card-foreground: oklch(98% 0.01 264);

  --color-ring-offset: oklch(14.5% 0.025 264);
}

/* Base styles */
@layer base {
  * {
    @apply border-border;
  }

  body {
    @apply bg-background text-foreground antialiased;
  }
}
```

## Core Concepts

### 1. Design Token Hierarchy

```
Brand Tokens (abstract)
    └── Semantic Tokens (purpose)
        └── Component Tokens (specific)

Example:
    oklch(45% 0.2 260) → --color-primary → bg-primary
```

### 2. Component Architecture

```
Base styles → Variants → Sizes → States → Overrides
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=tailwind-design-system -->

---

## Part: Game Development

---

<!-- chapter:begin slug=godot-gdscript-patterns position=76 -->

## 76. godot-gdscript-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/game-development/skills/godot-gdscript-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/game-development/skills/godot-gdscript-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/godot-gdscript-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/game-development/skills/godot-gdscript-patterns/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/game-development/skills/godot-gdscript-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: godot-gdscript-patterns
description: Master Godot 4 GDScript patterns including signals, scenes, state machines, and optimization. Use when building Godot games, implementing game systems, or learning GDScript best practices.
---

# Godot GDScript Patterns

Production patterns for Godot 4.x game development with GDScript, covering architecture, signals, scenes, and optimization.

## When to Use This Skill

- Building games with Godot 4
- Implementing game systems in GDScript
- Designing scene architecture
- Managing game state
- Optimizing GDScript performance
- Learning Godot best practices

## Core Concepts

### 1. Godot Architecture

```
Node: Base building block
├── Scene: Reusable node tree (saved as .tscn)
├── Resource: Data container (saved as .tres)
├── Signal: Event communication
└── Group: Node categorization
```

### 2. GDScript Basics

```gdscript
class_name Player
extends CharacterBody2D

# Signals
signal health_changed(new_health: int)
signal died

# Exports (Inspector-editable)
@export var speed: float = 200.0
@export var max_health: int = 100
@export_range(0, 1) var damage_reduction: float = 0.0
@export_group("Combat")
@export var attack_damage: int = 10
@export var attack_cooldown: float = 0.5

# Onready (initialized when ready)
@onready var sprite: Sprite2D = $Sprite2D
@onready var animation: AnimationPlayer = $AnimationPlayer
@onready var hitbox: Area2D = $Hitbox

# Private variables (convention: underscore prefix)
var _health: int
var _can_attack: bool = true

func _ready() -> void:
    _health = max_health

func _physics_process(delta: float) -> void:
    var direction := Input.get_vector("left", "right", "up", "down")
    velocity = direction * speed
    move_and_slide()

func take_damage(amount: int) -> void:
    var actual_damage := int(amount * (1.0 - damage_reduction))
    _health = max(_health - actual_damage, 0)
    health_changed.emit(_health)

    if _health <= 0:
        died.emit()
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=godot-gdscript-patterns -->

---

<!-- chapter:begin slug=unity-ecs-patterns position=77 -->

## 77. unity-ecs-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/game-development/skills/unity-ecs-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/game-development/skills/unity-ecs-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/unity-ecs-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/game-development/skills/unity-ecs-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: unity-ecs-patterns
description: Master Unity ECS (Entity Component System) with DOTS, Jobs, and Burst for high-performance game development. Use when building data-oriented games, optimizing performance, or working with large entity counts.
---

# Unity ECS Patterns

Production patterns for Unity's Data-Oriented Technology Stack (DOTS) including Entity Component System, Job System, and Burst Compiler.

## When to Use This Skill

- Building high-performance Unity games
- Managing thousands of entities efficiently
- Implementing data-oriented game systems
- Optimizing CPU-bound game logic
- Converting OOP game code to ECS
- Using Jobs and Burst for parallelization

## Core Concepts

### 1. ECS vs OOP

| Aspect      | Traditional OOP   | ECS/DOTS        |
| ----------- | ----------------- | --------------- |
| Data layout | Object-oriented   | Data-oriented   |
| Memory      | Scattered         | Contiguous      |
| Processing  | Per-object        | Batched         |
| Scaling     | Poor with count   | Linear scaling  |
| Best for    | Complex behaviors | Mass simulation |

### 2. DOTS Components

```
Entity: Lightweight ID (no data)
Component: Pure data (no behavior)
System: Logic that processes components
World: Container for entities
Archetype: Unique combination of components
Chunk: Memory block for same-archetype entities
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use ISystem over SystemBase** - Better performance
- **Burst compile everything** - Massive speedup
- **Batch structural changes** - Use ECB
- **Profile with Profiler** - Identify bottlenecks
- **Use Aspects** - Clean component grouping

### Don'ts

- **Don't use managed types** - Breaks Burst
- **Don't structural change in jobs** - Use ECB
- **Don't over-architect** - Start simple
- **Don't ignore chunk utilization** - Group similar entities
- **Don't forget disposal** - Native collections leak

<!-- chapter:end slug=unity-ecs-patterns -->

---

## Part: Hermes Tweet

---

<!-- chapter:begin slug=hermes-tweet position=78 -->

## 78. hermes-tweet

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/hermes-tweet/skills/hermes-tweet/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/hermes-tweet/skills/hermes-tweet/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/hermes-tweet.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/workflows.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/hermes-tweet/skills/hermes-tweet/references/workflows.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: hermes-tweet
description: >
  Install and operate Hermes Tweet, a Hermes Agent plugin for X/Twitter research,
  timeline reading, tweet analysis, and approval-gated tweet actions. Use this
  skill when installing Hermes Tweet, researching X/Twitter accounts, monitoring
  launch signals, investigating mentions, auditing giveaways, or preparing guarded
  tweet actions. Use proactively when a Hermes Agent workflow needs current
  X/Twitter context. Requires XQUIK_API_KEY for read and action tools.
license: MIT
metadata:
  version: "0.1.6"
  source: https://github.com/Xquik-dev/hermes-tweet
  homepage: https://github.com/Xquik-dev/hermes-tweet#readme
---

# Hermes Tweet

Hermes Tweet adds an X/Twitter toolset to Hermes Agent. It is useful for social
listening, account research, launch monitoring, support triage, giveaway audits,
and controlled publishing workflows where actions stay explicit.

## When to Use This Skill

Use this skill when the user wants to:

- Install Hermes Tweet into a Hermes Agent runtime
- Discover available X/Twitter read and action routes
- Read X/Twitter account, tweet, trend, monitor, or search data
- Summarize public signal before drafting responses or campaigns
- Keep account-changing actions gated behind explicit operator intent

## Setup

Install the package into the Hermes Python environment, then enable the plugin:

```bash
~/.hermes/hermes-agent/venv/bin/python -m pip install hermes-tweet
hermes plugins enable hermes-tweet
```

Set the API key on the Hermes runtime host:

```bash
export XQUIK_API_KEY="<your-key>"
export HERMES_TWEET_ENABLE_ACTIONS="false"
```

Keep `HERMES_TWEET_ENABLE_ACTIONS` false for read-first sessions. Set it to
`true` only for sessions that intentionally need posting, replies, DMs, follows,
webhooks, monitors, media changes, or other account-changing routes.

## Inputs

Ask for these inputs before selecting routes:

- Objective: research, monitoring, support triage, giveaway audit, or action prep
- Target: account handle, tweet URL, keyword, list, monitor, or trend
- Time window and freshness needs
- Whether any account-changing action is in scope
- Confirmation that the Hermes runtime has `XQUIK_API_KEY`

## Workflow

1. Search the bundled endpoint catalog with `tweet_explore` to find matching routes.
2. Read X/Twitter data through `tweet_read` after selecting a catalog route.
3. Execute account-changing routes with `tweet_action` only after explicit approval.
4. Keep API keys in environment variables or the Hermes runtime env file.
5. Do not paste credentials into prompts, issues, PR comments, or tool inputs.
6. Load [workflow patterns](references/workflows.md) when the user asks for a
   campaign, monitor, support, or giveaway workflow instead of a single read.

## Tool Model

| Tool | Purpose |
| --- | --- |
| `tweet_explore` | Search the bundled endpoint catalog without using the API key. |
| `tweet_read` | Call catalog-listed read-only endpoints when `XQUIK_API_KEY` is set. |
| `tweet_action` | Call action routes only when action gating is enabled. |

## Output Format

Return concise operational output:

```text
Summary:
- What was checked and why

Read routes:
- Catalog path, input, and result summary

Action plan:
- Proposed account-changing actions, each awaiting explicit approval

Next check:
- Follow-up route or monitoring cadence when useful
```

## Usage Examples

Research an account before drafting a reply:

```text
Use Hermes Tweet to inspect recent public context for @example before drafting a reply.
Keep actions disabled.
```

Monitor a launch keyword:

```text
Track X/Twitter mentions for "Example Launch" today.
Summarize themes and notable accounts. Do not post.
```

Prepare a guarded post:

```text
Draft a launch tweet and list the exact tweet_action call you would use.
Wait for approval before any action route.
```

Capture structured route notes:

```json
{
  "objective": "support-triage",
  "route": "/api/v1/x/search",
  "action_gate": "disabled",
  "approval_required": true
}
```

## Troubleshooting

- If only `tweet_explore` appears, configure `XQUIK_API_KEY` on the Hermes runtime
  host and reload or restart the active Hermes session.
- If action routes are unavailable, keep reading or set
  `HERMES_TWEET_ENABLE_ACTIONS=true` only for an approved action session.
- If a route does not match, use `tweet_explore` again and choose a catalog-listed
  path instead of guessing endpoints.

## Best Practices

- Treat Hermes Tweet as the Hermes-native X/Twitter layer, not a generic API wrapper.
- Keep research and monitoring workflows read-only by default.
- Use Desktop or gateway operator review before account-changing calls.
- Validate the exact catalog path before calling `tweet_read` or `tweet_action`.
- Restart gateway, cron, or long-running Hermes sessions after env changes.

## See Also

The social-publishing plugin complements Hermes Tweet for broad multi-platform
publishing. Hermes Tweet is focused on the Hermes Agent X/Twitter toolset and its
read-first, approval-gated operating model.

See the official guide at https://github.com/Xquik-dev/hermes-tweet#readme.

<!-- chapter:end slug=hermes-tweet -->

---

## Part: Hr Legal Compliance

---

<!-- chapter:begin slug=employment-contract-templates position=79 -->

## 79. employment-contract-templates

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/hr-legal-compliance/skills/employment-contract-templates/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/hr-legal-compliance/skills/employment-contract-templates/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/employment-contract-templates.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/hr-legal-compliance/skills/employment-contract-templates/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: employment-contract-templates
description: Create employment contracts, offer letters, and HR policy documents following legal best practices. Use when drafting employment agreements, creating HR policies, or standardizing employment documentation.
---

# Employment Contract Templates

Templates and patterns for creating legally sound employment documentation including contracts, offer letters, and HR policies.

## When to Use This Skill

- Drafting employment contracts
- Creating offer letters
- Writing employee handbooks
- Developing HR policies
- Standardizing employment documentation
- Onboarding documentation

## Core Concepts

### 1. Employment Document Types

| Document                | Purpose                 | When Used     |
| ----------------------- | ----------------------- | ------------- |
| **Offer Letter**        | Initial job offer       | Pre-hire      |
| **Employment Contract** | Formal agreement        | Hire          |
| **Employee Handbook**   | Policies & procedures   | Onboarding    |
| **NDA**                 | Confidentiality         | Before access |
| **Non-Compete**         | Competition restriction | Hire/Exit     |

### 2. Key Legal Considerations

```
Employment Relationship:
├── At-Will vs. Contract
├── Employee vs. Contractor
├── Full-Time vs. Part-Time
├── Exempt vs. Non-Exempt
└── Jurisdiction-Specific Requirements
```

**DISCLAIMER: These templates are for informational purposes only and do not constitute legal advice. Consult with qualified legal counsel before using any employment documents.**

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Consult legal counsel** - Employment law varies by jurisdiction
- **Keep copies signed** - Document all agreements
- **Update regularly** - Laws and policies change
- **Be clear and specific** - Avoid ambiguity
- **Train managers** - On policies and procedures

### Don'ts

- **Don't use generic templates** - Customize for your jurisdiction
- **Don't make promises** - That could create implied contracts
- **Don't discriminate** - In language or application
- **Don't forget at-will language** - Where applicable
- **Don't skip review** - Have legal counsel review all documents

<!-- chapter:end slug=employment-contract-templates -->

---

<!-- chapter:begin slug=gdpr-data-handling position=80 -->

## 80. gdpr-data-handling

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/hr-legal-compliance/skills/gdpr-data-handling/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/hr-legal-compliance/skills/gdpr-data-handling/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/gdpr-data-handling.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/hr-legal-compliance/skills/gdpr-data-handling/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: gdpr-data-handling
description: Implement GDPR-compliant data handling with consent management, data subject rights, and privacy by design. Use when building systems that process EU personal data, implementing privacy controls, or conducting GDPR compliance reviews.
---

# GDPR Data Handling

Practical implementation guide for GDPR-compliant data processing, consent management, and privacy controls.

## When to Use This Skill

- Building systems that process EU personal data
- Implementing consent management
- Handling data subject requests (DSRs)
- Conducting GDPR compliance reviews
- Designing privacy-first architectures
- Creating data processing agreements

## Core Concepts

### 1. Personal Data Categories

| Category               | Examples                    | Protection Level   |
| ---------------------- | --------------------------- | ------------------ |
| **Basic**              | Name, email, phone          | Standard           |
| **Sensitive (Art. 9)** | Health, religion, ethnicity | Explicit consent   |
| **Criminal (Art. 10)** | Convictions, offenses       | Official authority |
| **Children's**         | Under 16 data               | Parental consent   |

### 2. Legal Bases for Processing

```
Article 6 - Lawful Bases:
├── Consent: Freely given, specific, informed
├── Contract: Necessary for contract performance
├── Legal Obligation: Required by law
├── Vital Interests: Protecting someone's life
├── Public Interest: Official functions
└── Legitimate Interest: Balanced against rights
```

### 3. Data Subject Rights

```
Right to Access (Art. 15)      ─┐
Right to Rectification (Art. 16) │
Right to Erasure (Art. 17)       │ Must respond
Right to Restrict (Art. 18)      │ within 1 month
Right to Portability (Art. 20)   │
Right to Object (Art. 21)       ─┘
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Implementation Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices

### Do's

- **Minimize data collection** - Only collect what's needed
- **Document everything** - Processing activities, legal bases
- **Encrypt PII** - At rest and in transit
- **Implement access controls** - Need-to-know basis
- **Regular audits** - Verify compliance continuously

### Don'ts

- **Don't pre-check consent boxes** - Must be opt-in
- **Don't bundle consent** - Separate purposes separately
- **Don't retain indefinitely** - Define and enforce retention
- **Don't ignore DSARs** - 30-day response required
- **Don't transfer without safeguards** - SCCs or adequacy decisions

<!-- chapter:end slug=gdpr-data-handling -->

---

## Part: Incident Response

---

<!-- chapter:begin slug=incident-runbook-templates position=81 -->

## 81. incident-runbook-templates

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/incident-response/skills/incident-runbook-templates/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/incident-response/skills/incident-runbook-templates/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/incident-runbook-templates.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/incident-response/skills/incident-runbook-templates/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: incident-runbook-templates
description: Create structured incident response runbooks with step-by-step procedures, escalation paths, and recovery actions. Use this skill when building a service outage runbook for a payment processing system; creating database incident procedures covering connection pool exhaustion, replication lag, and disk space alerts; onboarding new on-call engineers who need step-by-step recovery guides written for a 3 AM brain; or standardizing escalation matrices across multiple engineering teams.
---

# Incident Runbook Templates

Production-ready templates for incident response runbooks covering detection, triage, mitigation, resolution, and communication.

## When to Use This Skill

- Creating incident response procedures
- Building service-specific runbooks
- Establishing escalation paths
- Documenting recovery procedures
- Responding to active incidents
- Onboarding on-call engineers

## Core Concepts

### 1. Incident Severity Levels

| Severity | Impact                     | Response Time     | Example                 |
| -------- | -------------------------- | ----------------- | ----------------------- |
| **SEV1** | Complete outage, data loss | 15 min            | Production down         |
| **SEV2** | Major degradation          | 30 min            | Critical feature broken |
| **SEV3** | Minor impact               | 2 hours           | Non-critical bug        |
| **SEV4** | Minimal impact             | Next business day | Cosmetic issue          |

### 2. Runbook Structure

```
1. Overview & Impact
2. Detection & Alerts
3. Initial Triage
4. Mitigation Steps
5. Root Cause Investigation
6. Resolution Procedures
7. Verification & Rollback
8. Communication Templates
9. Escalation Matrix
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's
- **Keep runbooks updated** - Review after every incident
- **Test runbooks regularly** - Game days, chaos engineering
- **Include rollback steps** - Always have an escape hatch
- **Document assumptions** - What must be true for steps to work
- **Link to dashboards** - Quick access during stress

### Don'ts
- **Don't assume knowledge** - Write for 3 AM brain
- **Don't skip verification** - Confirm each step worked
- **Don't forget communication** - Keep stakeholders informed
- **Don't work alone** - Escalate early
- **Don't skip postmortems** - Learn from every incident

## Troubleshooting

### Runbook steps work in staging but fail during a real incident

Steps often assume preconditions that are true in a healthy environment but not during an outage. For each command in your runbook, add a prerequisite check and a "what to do if this command fails" note:

```bash
# Step: Check pod status
kubectl get pods -n payments

# Prerequisites: kubectl configured, kubeconfig points to correct cluster
# If this fails: run `aws eks update-kubeconfig --name prod-cluster --region us-east-1`
# Expected output: pods in Running state
```

### On-call engineer panics and skips steps out of order

Add a numbered checklist at the top of the runbook that mirrors the section numbers, so responders can track progress under stress without reading the full document:

```markdown
## Quick Checklist
- [ ] 1. Declare incident severity and open war room
- [ ] 2. Check service health (Section 4.1)
- [ ] 3. Check recent deployments (Section 4.1)
- [ ] 4. Roll back if deploy is suspect (Section 4.1)
- [ ] 5. Post initial notification to #payments-incidents
- [ ] 6. Escalate if > 15 min unresolved
```

### Runbook is outdated — commands reference old cluster names or endpoints

Runbooks rot because they're updated manually. Include a "Last Verified" date and owner at the top, and add a CI check that validates all `curl` endpoints and `kubectl` context names are still valid:

```markdown
## Runbook Metadata
| Field | Value |
|---|---|
| Last verified | 2024-11-15 |
| Owner | @platform-team |
| Review cadence | After every SEV1/SEV2 |
```

### Stakeholder communication is delayed while engineers are heads-down

Assign a dedicated incident communicator role (separate from the incident commander) whose only job is to post status updates. Add a standing agenda in the communication template:

```
Update every 15 minutes (even if no new information):
- Current status (Investigating / Mitigating / Monitoring)
- Impact (what is broken, who is affected, % of traffic)
- What we are doing right now
- Next update in: 15 minutes
```

### Database runbook commands cause additional downtime when run incorrectly

Add explicit warnings before destructive SQL commands and require a dry-run output check before executing:

```sql
-- WARNING: This terminates active connections. Verify count first.
-- DRY RUN (check count before terminating):
SELECT count(*) FROM pg_stat_activity WHERE state = 'idle' AND query_start < now() - interval '10 minutes';

-- EXECUTE only after verifying count is reasonable (< 50):
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE state = 'idle' AND query_start < now() - interval '10 minutes';
```

## Related Skills

- `postmortem-writing` - After resolving an incident, use postmortem templates to capture root cause and preventive actions
- `on-call-handoff-patterns` - Structure shift handoffs so the incoming responder has full context on active incidents

<!-- chapter:end slug=incident-runbook-templates -->

---

<!-- chapter:begin slug=on-call-handoff-patterns position=82 -->

## 82. on-call-handoff-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/incident-response/skills/on-call-handoff-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/incident-response/skills/on-call-handoff-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/on-call-handoff-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/incident-response/skills/on-call-handoff-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: on-call-handoff-patterns
description: Master on-call shift handoffs with context transfer, escalation procedures, and documentation. Use this skill when transitioning on-call responsibilities between engineers and ensuring the incoming responder has full situational awareness, when writing a shift summary that captures active incidents, ongoing investigations, and recent changes, when handing off mid-incident so a fresh engineer can take over the incident commander role without losing context, when onboarding a new engineer to the on-call rotation for the first time, or when auditing and improving the quality of existing handoff processes across teams.
---

# On-Call Handoff Patterns

Effective patterns for on-call shift transitions, ensuring continuity, context transfer, and reliable incident response across shifts.

## When to Use This Skill

- Transitioning on-call responsibilities
- Writing shift handoff summaries
- Documenting ongoing investigations
- Establishing on-call rotation procedures
- Improving handoff quality
- Onboarding new on-call engineers

## Core Concepts

### 1. Handoff Components

| Component                  | Purpose                 |
| -------------------------- | ----------------------- |
| **Active Incidents**       | What's currently broken |
| **Ongoing Investigations** | Issues being debugged   |
| **Recent Changes**         | Deployments, configs    |
| **Known Issues**           | Workarounds in place    |
| **Upcoming Events**        | Maintenance, releases   |

### 2. Handoff Timing

```
Recommended: 30 min overlap between shifts

Outgoing:
├── 15 min: Write handoff document
└── 15 min: Sync call with incoming

Incoming:
├── 15 min: Review handoff document
├── 15 min: Sync call with outgoing
└── 5 min: Verify alerting setup
```

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Troubleshooting

**Incoming engineer misses a critical issue because the handoff document was incomplete.**
Use the outgoing checklist as a gate: do not mark handoff complete until every section has at least one entry (or an explicit "none"). Make incomplete handoffs a blameless postmortem action item.

**A 30-minute sync call is not possible due to timezone gaps.**
Fall back to the async quick handoff template (Template 2). Supplement with a short Loom or voice memo walking through the watch list. Ensure the incoming engineer has a direct contact method if they have follow-up questions.

**The incoming engineer inherits a mid-incident and is immediately overwhelmed.**
Use the incident handoff template (Template 3) specifically. The outgoing engineer should remain available on Slack for 15 minutes after handoff, even if off-call, to answer clarifying questions.

**On-call handoff documents are inconsistently formatted across teams.**
Adopt the shift handoff template organization-wide and store completed handoffs in a shared location (wiki, Notion, Confluence). Link each handoff from the on-call schedule entry in PagerDuty.

**Incoming engineer cannot verify their alerting is working before the outgoing engineer logs off.**
Add a standard step: outgoing engineer fires a test alert and confirms incoming engineer receives it in PagerDuty and Slack before ending the overlap window.

## Related Skills

- [incident-classification](../../skills/incident-classification/SKILL.md) — Classify and prioritize incidents that need to be included in the handoff document
- [postmortem-facilitation](../../skills/postmortem-facilitation/SKILL.md) — Turn resolved incidents from the shift into structured postmortems

<!-- chapter:end slug=on-call-handoff-patterns -->

---

<!-- chapter:begin slug=postmortem-writing position=83 -->

## 83. postmortem-writing

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/incident-response/skills/postmortem-writing/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/incident-response/skills/postmortem-writing/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/postmortem-writing.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/incident-response/skills/postmortem-writing/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: postmortem-writing
description: Write effective blameless postmortems with root cause analysis, timelines, and action items. Use when conducting incident reviews, writing postmortem documents, or improving incident response processes.
---

# Postmortem Writing

Comprehensive guide to writing effective, blameless postmortems that drive organizational learning and prevent incident recurrence.

## When to Use This Skill

- Conducting post-incident reviews
- Writing postmortem documents
- Facilitating blameless postmortem meetings
- Identifying root causes and contributing factors
- Creating actionable follow-up items
- Building organizational learning culture

## Core Concepts

### 1. Blameless Culture

| Blame-Focused            | Blameless                         |
| ------------------------ | --------------------------------- |
| "Who caused this?"       | "What conditions allowed this?"   |
| "Someone made a mistake" | "The system allowed this mistake" |
| Punish individuals       | Improve systems                   |
| Hide information         | Share learnings                   |
| Fear of speaking up      | Psychological safety              |

### 2. Postmortem Triggers

- SEV1 or SEV2 incidents
- Customer-facing outages > 15 minutes
- Data loss or security incidents
- Near-misses that could have been severe
- Novel failure modes
- Incidents requiring unusual intervention

## Quick Start

### Postmortem Timeline

```
Day 0: Incident occurs
Day 1-2: Draft postmortem document
Day 3-5: Postmortem meeting
Day 5-7: Finalize document, create tickets
Week 2+: Action item completion
Quarterly: Review patterns across incidents
```

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## References
- [Connection Pool Best Practices](internal-wiki/connection-pools)
- [Deployment Runbook](internal-wiki/deployment-runbook)
```

### Template 2: 5 Whys Analysis

```markdown
# 5 Whys Analysis: [Incident]

## Problem Statement

Payment service experienced 47-minute outage due to database connection exhaustion.

## Analysis

### Why #1: Why did the service fail?

**Answer**: Database connections were exhausted, causing all new requests to fail.

**Evidence**: Metrics showed connection count at 100/100 (max), with 500+ pending requests.

---

### Why #2: Why were database connections exhausted?

**Answer**: Each incoming request opened a new database connection instead of using the connection pool.

**Evidence**: Code diff shows direct `DriverManager.getConnection()` instead of pooled `DataSource`.

---

### Why #3: Why did the code bypass the connection pool?

**Answer**: A developer refactored the repository class and inadvertently changed the connection acquisition method.

**Evidence**: PR #1234 shows the change, made while fixing a different bug.

---

### Why #4: Why wasn't this caught in code review?

**Answer**: The reviewer focused on the functional change (the bug fix) and didn't notice the infrastructure change.

**Evidence**: Review comments only discuss business logic.

---

### Why #5: Why isn't there a safety net for this type of change?

**Answer**: We lack automated tests that verify connection pool behavior and lack documentation about our connection patterns.

**Evidence**: Test suite has no tests for connection handling; wiki has no article on database connections.

## Root Causes Identified

1. **Primary**: Missing automated tests for infrastructure behavior
2. **Secondary**: Insufficient documentation of architectural patterns
3. **Tertiary**: Code review checklist doesn't include infrastructure considerations

## Systemic Improvements

| Root Cause    | Improvement                       | Type       |
| ------------- | --------------------------------- | ---------- |
| Missing tests | Add infrastructure behavior tests | Prevention |
| Missing docs  | Document connection patterns      | Prevention |
| Review gaps   | Update review checklist           | Detection  |
| No canary     | Implement canary deployments      | Mitigation |
```

### Template 3: Quick Postmortem (Minor Incidents)

```markdown
# Quick Postmortem: [Brief Title]

**Date**: 2024-01-15 | **Duration**: 12 min | **Severity**: SEV3

## What Happened

API latency spiked to 5s due to cache miss storm after cache flush.

## Timeline

- 10:00 - Cache flush initiated for config update
- 10:02 - Latency alerts fire
- 10:05 - Identified as cache miss storm
- 10:08 - Enabled cache warming
- 10:12 - Latency normalized

## Root Cause

Full cache flush for minor config update caused thundering herd.

## Fix

- Immediate: Enabled cache warming
- Long-term: Implement partial cache invalidation (ENG-999)

## Lessons

Don't full-flush cache in production; use targeted invalidation.
```

## Facilitation Guide

### Running a Postmortem Meeting

```markdown
## Meeting Structure (60 minutes)

### 1. Opening (5 min)

- Remind everyone of blameless culture
- "We're here to learn, not to blame"
- Review meeting norms

### 2. Timeline Review (15 min)

- Walk through events chronologically
- Ask clarifying questions
- Identify gaps in timeline

### 3. Analysis Discussion (20 min)

- What failed?
- Why did it fail?
- What conditions allowed this?
- What would have prevented it?

### 4. Action Items (15 min)

- Brainstorm improvements
- Prioritize by impact and effort
- Assign owners and due dates

### 5. Closing (5 min)

- Summarize key learnings
- Confirm action item owners
- Schedule follow-up if needed

## Facilitation Tips

- Keep discussion on track
- Redirect blame to systems
- Encourage quiet participants
- Document dissenting views
- Time-box tangents
```

## Anti-Patterns to Avoid

| Anti-Pattern            | Problem                    | Better Approach                 |
| ----------------------- | -------------------------- | ------------------------------- |
| **Blame game**          | Shuts down learning        | Focus on systems                |
| **Shallow analysis**    | Doesn't prevent recurrence | Ask "why" 5 times               |
| **No action items**     | Waste of time              | Always have concrete next steps |
| **Unrealistic actions** | Never completed            | Scope to achievable tasks       |
| **No follow-up**        | Actions forgotten          | Track in ticketing system       |

## Best Practices

### Do's

- **Start immediately** - Memory fades fast
- **Be specific** - Exact times, exact errors
- **Include graphs** - Visual evidence
- **Assign owners** - No orphan action items
- **Share widely** - Organizational learning

### Don'ts

- **Don't name and shame** - Ever
- **Don't skip small incidents** - They reveal patterns
- **Don't make it a blame doc** - That kills learning
- **Don't create busywork** - Actions should be meaningful
- **Don't skip follow-up** - Verify actions completed

<!-- chapter:end slug=postmortem-writing -->

---

## Part: Java Script Type Script

---

<!-- chapter:begin slug=javascript-testing-patterns position=84 -->

## 84. javascript-testing-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/javascript-typescript/skills/javascript-testing-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/javascript-testing-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/javascript-testing-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/advanced-testing-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/javascript-testing-patterns/references/advanced-testing-patterns.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: javascript-testing-patterns
description: Implement comprehensive testing strategies using Jest, Vitest, and Testing Library for unit tests, integration tests, and end-to-end testing with mocking, fixtures, and test-driven development. Use when writing JavaScript/TypeScript tests, setting up test infrastructure, or implementing TDD/BDD workflows.
---

# JavaScript Testing Patterns

Comprehensive guide for implementing robust testing strategies in JavaScript/TypeScript applications using modern testing frameworks and best practices.

## When to Use This Skill

- Setting up test infrastructure for new projects
- Writing unit tests for functions and classes
- Creating integration tests for APIs and services
- Implementing end-to-end tests for user flows
- Mocking external dependencies and APIs
- Testing React, Vue, or other frontend components
- Implementing test-driven development (TDD)
- Setting up continuous testing in CI/CD pipelines

## Testing Frameworks

### Jest - Full-Featured Testing Framework

**Setup:**

```typescript
// jest.config.ts
import type { Config } from "jest";

const config: Config = {
  preset: "ts-jest",
  testEnvironment: "node",
  roots: ["<rootDir>/src"],
  testMatch: ["**/__tests__/**/*.ts", "**/?(*.)+(spec|test).ts"],
  collectCoverageFrom: [
    "src/**/*.ts",
    "!src/**/*.d.ts",
    "!src/**/*.interface.ts",
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },
  setupFilesAfterEnv: ["<rootDir>/src/test/setup.ts"],
};

export default config;
```

### Vitest - Fast, Vite-Native Testing

**Setup:**

```typescript
// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    globals: true,
    environment: "node",
    coverage: {
      provider: "v8",
      reporter: ["text", "json", "html"],
      exclude: ["**/*.d.ts", "**/*.config.ts", "**/dist/**"],
    },
    setupFiles: ["./src/test/setup.ts"],
  },
});
```

## Unit Testing Patterns

### Pattern 1: Testing Pure Functions

```typescript
// utils/calculator.ts
export function add(a: number, b: number): number {
  return a + b;
}

export function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error("Division by zero");
  }
  return a / b;
}

// utils/calculator.test.ts
import { describe, it, expect } from "vitest";
import { add, divide } from "./calculator";

describe("Calculator", () => {
  describe("add", () => {
    it("should add two positive numbers", () => {
      expect(add(2, 3)).toBe(5);
    });

    it("should add negative numbers", () => {
      expect(add(-2, -3)).toBe(-5);
    });

    it("should handle zero", () => {
      expect(add(0, 5)).toBe(5);
      expect(add(5, 0)).toBe(5);
    });
  });

  describe("divide", () => {
    it("should divide two numbers", () => {
      expect(divide(10, 2)).toBe(5);
    });

    it("should handle decimal results", () => {
      expect(divide(5, 2)).toBe(2.5);
    });

    it("should throw error when dividing by zero", () => {
      expect(() => divide(10, 0)).toThrow("Division by zero");
    });
  });
});
```

### Pattern 2: Testing Classes

```typescript
// services/user.service.ts
export class UserService {
  private users: Map<string, User> = new Map();

  create(user: User): User {
    if (this.users.has(user.id)) {
      throw new Error("User already exists");
    }
    this.users.set(user.id, user);
    return user;
  }

  findById(id: string): User | undefined {
    return this.users.get(id);
  }

  update(id: string, updates: Partial<User>): User {
    const user = this.users.get(id);
    if (!user) {
      throw new Error("User not found");
    }
    const updated = { ...user, ...updates };
    this.users.set(id, updated);
    return updated;
  }

  delete(id: string): boolean {
    return this.users.delete(id);
  }
}

// services/user.service.test.ts
import { describe, it, expect, beforeEach } from "vitest";
import { UserService } from "./user.service";

describe("UserService", () => {
  let service: UserService;

  beforeEach(() => {
    service = new UserService();
  });

  describe("create", () => {
    it("should create a new user", () => {
      const user = { id: "1", name: "John", email: "john@example.com" };
      const created = service.create(user);

      expect(created).toEqual(user);
      expect(service.findById("1")).toEqual(user);
    });

    it("should throw error if user already exists", () => {
      const user = { id: "1", name: "John", email: "john@example.com" };
      service.create(user);

      expect(() => service.create(user)).toThrow("User already exists");
    });
  });

  describe("update", () => {
    it("should update existing user", () => {
      const user = { id: "1", name: "John", email: "john@example.com" };
      service.create(user);

      const updated = service.update("1", { name: "Jane" });

      expect(updated.name).toBe("Jane");
      expect(updated.email).toBe("john@example.com");
    });

    it("should throw error if user not found", () => {
      expect(() => service.update("999", { name: "Jane" })).toThrow(
        "User not found",
      );
    });
  });
});
```

### Pattern 3: Testing Async Functions

```typescript
// services/api.service.ts
export class ApiService {
  async fetchUser(id: string): Promise<User> {
    const response = await fetch(`https://api.example.com/users/${id}`);
    if (!response.ok) {
      throw new Error("User not found");
    }
    return response.json();
  }

  async createUser(user: CreateUserDTO): Promise<User> {
    const response = await fetch("https://api.example.com/users", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(user),
    });
    return response.json();
  }
}

// services/api.service.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { ApiService } from "./api.service";

// Mock fetch globally
global.fetch = vi.fn();

describe("ApiService", () => {
  let service: ApiService;

  beforeEach(() => {
    service = new ApiService();
    vi.clearAllMocks();
  });

  describe("fetchUser", () => {
    it("should fetch user successfully", async () => {
      const mockUser = { id: "1", name: "John", email: "john@example.com" };

      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => mockUser,
      });

      const user = await service.fetchUser("1");

      expect(user).toEqual(mockUser);
      expect(fetch).toHaveBeenCalledWith("https://api.example.com/users/1");
    });

    it("should throw error if user not found", async () => {
      (fetch as any).mockResolvedValueOnce({
        ok: false,
      });

      await expect(service.fetchUser("999")).rejects.toThrow("User not found");
    });
  });

  describe("createUser", () => {
    it("should create user successfully", async () => {
      const newUser = { name: "John", email: "john@example.com" };
      const createdUser = { id: "1", ...newUser };

      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => createdUser,
      });

      const user = await service.createUser(newUser);

      expect(user).toEqual(createdUser);
      expect(fetch).toHaveBeenCalledWith(
        "https://api.example.com/users",
        expect.objectContaining({
          method: "POST",
          body: JSON.stringify(newUser),
        }),
      );
    });
  });
});
```

## Mocking Patterns

### Pattern 1: Mocking Modules

```typescript
// services/email.service.ts
import nodemailer from "nodemailer";

export class EmailService {
  private transporter = nodemailer.createTransport({
    host: process.env.SMTP_HOST,
    port: 587,
    auth: {
      user: process.env.SMTP_USER,
      pass: process.env.SMTP_PASS,
    },
  });

  async sendEmail(to: string, subject: string, html: string) {
    await this.transporter.sendMail({
      from: process.env.EMAIL_FROM,
      to,
      subject,
      html,
    });
  }
}

// services/email.service.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { EmailService } from "./email.service";

vi.mock("nodemailer", () => ({
  default: {
    createTransport: vi.fn(() => ({
      sendMail: vi.fn().mockResolvedValue({ messageId: "123" }),
    })),
  },
}));

describe("EmailService", () => {
  let service: EmailService;

  beforeEach(() => {
    service = new EmailService();
  });

  it("should send email successfully", async () => {
    await service.sendEmail(
      "test@example.com",
      "Test Subject",
      "<p>Test Body</p>",
    );

    expect(service["transporter"].sendMail).toHaveBeenCalledWith(
      expect.objectContaining({
        to: "test@example.com",
        subject: "Test Subject",
      }),
    );
  });
});
```

### Pattern 2: Dependency Injection for Testing

```typescript
// services/user.service.ts
export interface IUserRepository {
  findById(id: string): Promise<User | null>;
  create(user: User): Promise<User>;
}

export class UserService {
  constructor(private userRepository: IUserRepository) {}

  async getUser(id: string): Promise<User> {
    const user = await this.userRepository.findById(id);
    if (!user) {
      throw new Error("User not found");
    }
    return user;
  }

  async createUser(userData: CreateUserDTO): Promise<User> {
    // Business logic here
    const user = { id: generateId(), ...userData };
    return this.userRepository.create(user);
  }
}

// services/user.service.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { UserService, IUserRepository } from "./user.service";

describe("UserService", () => {
  let service: UserService;
  let mockRepository: IUserRepository;

  beforeEach(() => {
    mockRepository = {
      findById: vi.fn(),
      create: vi.fn(),
    };
    service = new UserService(mockRepository);
  });

  describe("getUser", () => {
    it("should return user if found", async () => {
      const mockUser = { id: "1", name: "John", email: "john@example.com" };
      vi.mocked(mockRepository.findById).mockResolvedValue(mockUser);

      const user = await service.getUser("1");

      expect(user).toEqual(mockUser);
      expect(mockRepository.findById).toHaveBeenCalledWith("1");
    });

    it("should throw error if user not found", async () => {
      vi.mocked(mockRepository.findById).mockResolvedValue(null);

      await expect(service.getUser("999")).rejects.toThrow("User not found");
    });
  });

  describe("createUser", () => {
    it("should create user successfully", async () => {
      const userData = { name: "John", email: "john@example.com" };
      const createdUser = { id: "1", ...userData };

      vi.mocked(mockRepository.create).mockResolvedValue(createdUser);

      const user = await service.createUser(userData);

      expect(user).toEqual(createdUser);
      expect(mockRepository.create).toHaveBeenCalled();
    });
  });
});
```

### Pattern 3: Spying on Functions

```typescript
// utils/logger.ts
export const logger = {
  info: (message: string) => console.log(`INFO: ${message}`),
  error: (message: string) => console.error(`ERROR: ${message}`),
};

// services/order.service.ts
import { logger } from "../utils/logger";

export class OrderService {
  async processOrder(orderId: string): Promise<void> {
    logger.info(`Processing order ${orderId}`);
    // Process order logic
    logger.info(`Order ${orderId} processed successfully`);
  }
}

// services/order.service.test.ts
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { OrderService } from "./order.service";
import { logger } from "../utils/logger";

describe("OrderService", () => {
  let service: OrderService;
  let loggerSpy: any;

  beforeEach(() => {
    service = new OrderService();
    loggerSpy = vi.spyOn(logger, "info");
  });

  afterEach(() => {
    loggerSpy.mockRestore();
  });

  it("should log order processing", async () => {
    await service.processOrder("123");

    expect(loggerSpy).toHaveBeenCalledWith("Processing order 123");
    expect(loggerSpy).toHaveBeenCalledWith("Order 123 processed successfully");
    expect(loggerSpy).toHaveBeenCalledTimes(2);
  });
});
```

## Integration Testing

Integration tests verify real database operations and HTTP endpoints using `supertest` and a test database instance. Always truncate tables in `beforeEach` and tear down in `afterAll`.

For full API integration test examples (supertest + PostgreSQL) and database repository integration tests, see [references/advanced-testing-patterns.md](references/advanced-testing-patterns.md).

## Frontend Testing with Testing Library

Test React components by rendering them and querying by role, placeholder, or test ID. Test hooks with `renderHook` + `act`. Prefer semantic queries (`getByRole`, `getByPlaceholderText`) over `data-testid`.

For complete React component test examples (UserForm, hooks with `renderHook`/`act`), see [references/advanced-testing-patterns.md](references/advanced-testing-patterns.md).

## Test Fixtures and Factories

Use `@faker-js/faker` to generate realistic test data factories. Factories accept optional `overrides` so tests can set only the fields they care about:

```typescript
// tests/fixtures/user.fixture.ts
import { faker } from "@faker-js/faker";

export function createUserFixture(overrides?: Partial<User>): User {
  return {
    id: faker.string.uuid(),
    name: faker.person.fullName(),
    email: faker.internet.email(),
    createdAt: faker.date.past(),
    ...overrides,
  };
}
```

For snapshot testing, coverage configuration, test organization patterns, promise testing, and timer mocking, see [references/advanced-testing-patterns.md](references/advanced-testing-patterns.md).

## Best Practices

1. **Follow AAA Pattern**: Arrange, Act, Assert
2. **One assertion per test**: Or logically related assertions
3. **Descriptive test names**: Should describe what is being tested
4. **Use beforeEach/afterEach**: For setup and teardown
5. **Mock external dependencies**: Keep tests isolated
6. **Test edge cases**: Not just happy paths
7. **Avoid implementation details**: Test behavior, not implementation
8. **Use test factories**: For consistent test data
9. **Keep tests fast**: Mock slow operations
10. **Write tests first (TDD)**: When possible
11. **Maintain test coverage**: Aim for 80%+ coverage
12. **Use TypeScript**: For type-safe tests
13. **Test error handling**: Not just success cases
14. **Use data-testid sparingly**: Prefer semantic queries
15. **Clean up after tests**: Prevent test pollution

<!-- chapter:end slug=javascript-testing-patterns -->

---

<!-- chapter:begin slug=modern-javascript-patterns position=85 -->

## 85. modern-javascript-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/javascript-typescript/skills/modern-javascript-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/modern-javascript-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/modern-javascript-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/modern-javascript-patterns/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/modern-javascript-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: modern-javascript-patterns
description: Master ES6+ features including async/await, destructuring, spread operators, arrow functions, promises, modules, iterators, generators, and functional programming patterns for writing clean, efficient JavaScript code. Use when refactoring legacy code, implementing modern patterns, or optimizing JavaScript applications.
---

# Modern JavaScript Patterns

Comprehensive guide for mastering modern JavaScript (ES6+) features, functional programming patterns, and best practices for writing clean, maintainable, and performant code.

## When to Use This Skill

- Refactoring legacy JavaScript to modern syntax
- Implementing functional programming patterns
- Optimizing JavaScript performance
- Writing maintainable and readable code
- Working with asynchronous operations
- Building modern web applications
- Migrating from callbacks to Promises/async-await
- Implementing data transformation pipelines

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Use const by default**: Only use let when reassignment is needed
2. **Prefer arrow functions**: Especially for callbacks
3. **Use template literals**: Instead of string concatenation
4. **Destructure objects and arrays**: For cleaner code
5. **Use async/await**: Instead of Promise chains
6. **Avoid mutating data**: Use spread operator and array methods
7. **Use optional chaining**: Prevent "Cannot read property of undefined"
8. **Use nullish coalescing**: For default values
9. **Prefer array methods**: Over traditional loops
10. **Use modules**: For better code organization
11. **Write pure functions**: Easier to test and reason about
12. **Use meaningful variable names**: Self-documenting code
13. **Keep functions small**: Single responsibility principle
14. **Handle errors properly**: Use try/catch with async/await
15. **Use strict mode**: `'use strict'` for better error catching

For common pitfalls (this binding, promise anti-patterns, memory leaks), see [references/advanced-patterns.md](references/advanced-patterns.md).

<!-- chapter:end slug=modern-javascript-patterns -->

---

<!-- chapter:begin slug=nodejs-backend-patterns position=86 -->

## 86. nodejs-backend-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/javascript-typescript/skills/nodejs-backend-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/nodejs-backend-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/nodejs-backend-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/nodejs-backend-patterns/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/nodejs-backend-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: nodejs-backend-patterns
description: Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices. Use when creating Node.js servers, REST APIs, GraphQL backends, or microservices architectures.
---

# Node.js Backend Patterns

Comprehensive guidance for building scalable, maintainable, and production-ready Node.js backend applications with modern frameworks, architectural patterns, and best practices.

## When to Use This Skill

- Building REST APIs or GraphQL servers
- Creating microservices with Node.js
- Implementing authentication and authorization
- Designing scalable backend architectures
- Setting up middleware and error handling
- Integrating databases (SQL and NoSQL)
- Building real-time applications with WebSockets
- Implementing background job processing

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Use TypeScript**: Type safety prevents runtime errors
2. **Implement proper error handling**: Use custom error classes
3. **Validate input**: Use libraries like Zod or Joi
4. **Use environment variables**: Never hardcode secrets
5. **Implement logging**: Use structured logging (Pino, Winston)
6. **Add rate limiting**: Prevent abuse
7. **Use HTTPS**: Always in production
8. **Implement CORS properly**: Don't use `*` in production
9. **Use dependency injection**: Easier testing and maintenance
10. **Write tests**: Unit, integration, and E2E tests
11. **Handle graceful shutdown**: Clean up resources
12. **Use connection pooling**: For databases
13. **Implement health checks**: For monitoring
14. **Use compression**: Reduce response size
15. **Monitor performance**: Use APM tools

## Testing Patterns

See `javascript-testing-patterns` skill for comprehensive testing guidance.

<!-- chapter:end slug=nodejs-backend-patterns -->

---

<!-- chapter:begin slug=typescript-advanced-types position=87 -->

## 87. typescript-advanced-types

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/javascript-typescript/skills/typescript-advanced-types/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/typescript-advanced-types/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/typescript-advanced-types.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/javascript-typescript/skills/typescript-advanced-types/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: typescript-advanced-types
description: Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.
---

# TypeScript Advanced Types

Comprehensive guidance for mastering TypeScript's advanced type system including generics, conditional types, mapped types, template literal types, and utility types for building robust, type-safe applications.

## When to Use This Skill

- Building type-safe libraries or frameworks
- Creating reusable generic components
- Implementing complex type inference logic
- Designing type-safe API clients
- Building form validation systems
- Creating strongly-typed configuration objects
- Implementing type-safe state management
- Migrating JavaScript codebases to TypeScript

## Core Concepts

### 1. Generics

**Purpose:** Create reusable, type-flexible components while maintaining type safety.

**Basic Generic Function:**

```typescript
function identity<T>(value: T): T {
  return value;
}

const num = identity<number>(42); // Type: number
const str = identity<string>("hello"); // Type: string
const auto = identity(true); // Type inferred: boolean
```

**Generic Constraints:**

```typescript
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(item: T): T {
  console.log(item.length);
  return item;
}

logLength("hello"); // OK: string has length
logLength([1, 2, 3]); // OK: array has length
logLength({ length: 10 }); // OK: object has length
// logLength(42);             // Error: number has no length
```

**Multiple Type Parameters:**

```typescript
function merge<T, U>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

const merged = merge({ name: "John" }, { age: 30 });
// Type: { name: string } & { age: number }
```

### 2. Conditional Types

**Purpose:** Create types that depend on conditions, enabling sophisticated type logic.

**Basic Conditional Type:**

```typescript
type IsString<T> = T extends string ? true : false;

type A = IsString<string>; // true
type B = IsString<number>; // false
```

**Extracting Return Types:**

```typescript
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getUser() {
  return { id: 1, name: "John" };
}

type User = ReturnType<typeof getUser>;
// Type: { id: number; name: string; }
```

**Distributive Conditional Types:**

```typescript
type ToArray<T> = T extends any ? T[] : never;

type StrOrNumArray = ToArray<string | number>;
// Type: string[] | number[]
```

**Nested Conditions:**

```typescript
type TypeName<T> = T extends string
  ? "string"
  : T extends number
    ? "number"
    : T extends boolean
      ? "boolean"
      : T extends undefined
        ? "undefined"
        : T extends Function
          ? "function"
          : "object";

type T1 = TypeName<string>; // "string"
type T2 = TypeName<() => void>; // "function"
```

### 3. Mapped Types

**Purpose:** Transform existing types by iterating over their properties.

**Basic Mapped Type:**

```typescript
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

interface User {
  id: number;
  name: string;
}

type ReadonlyUser = Readonly<User>;
// Type: { readonly id: number; readonly name: string; }
```

**Optional Properties:**

```typescript
type Partial<T> = {
  [P in keyof T]?: T[P];
};

type PartialUser = Partial<User>;
// Type: { id?: number; name?: string; }
```

**Key Remapping:**

```typescript
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

interface Person {
  name: string;
  age: number;
}

type PersonGetters = Getters<Person>;
// Type: { getName: () => string; getAge: () => number; }
```

**Filtering Properties:**

```typescript
type PickByType<T, U> = {
  [K in keyof T as T[K] extends U ? K : never]: T[K];
};

interface Mixed {
  id: number;
  name: string;
  age: number;
  active: boolean;
}

type OnlyNumbers = PickByType<Mixed, number>;
// Type: { id: number; age: number; }
```

### 4. Template Literal Types

**Purpose:** Create string-based types with pattern matching and transformation.

**Basic Template Literal:**

```typescript
type EventName = "click" | "focus" | "blur";
type EventHandler = `on${Capitalize<EventName>}`;
// Type: "onClick" | "onFocus" | "onBlur"
```

**String Manipulation:**

```typescript
type UppercaseGreeting = Uppercase<"hello">; // "HELLO"
type LowercaseGreeting = Lowercase<"HELLO">; // "hello"
type CapitalizedName = Capitalize<"john">; // "John"
type UncapitalizedName = Uncapitalize<"John">; // "john"
```

**Path Building:**

```typescript
type Path<T> = T extends object
  ? {
      [K in keyof T]: K extends string ? `${K}` | `${K}.${Path<T[K]>}` : never;
    }[keyof T]
  : never;

interface Config {
  server: {
    host: string;
    port: number;
  };
  database: {
    url: string;
  };
}

type ConfigPath = Path<Config>;
// Type: "server" | "database" | "server.host" | "server.port" | "database.url"
```

### 5. Utility Types

**Built-in Utility Types:**

```typescript
// Partial<T> - Make all properties optional
type PartialUser = Partial<User>;

// Required<T> - Make all properties required
type RequiredUser = Required<PartialUser>;

// Readonly<T> - Make all properties readonly
type ReadonlyUser = Readonly<User>;

// Pick<T, K> - Select specific properties
type UserName = Pick<User, "name" | "email">;

// Omit<T, K> - Remove specific properties
type UserWithoutPassword = Omit<User, "password">;

// Exclude<T, U> - Exclude types from union
type T1 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"

// Extract<T, U> - Extract types from union
type T2 = Extract<"a" | "b" | "c", "a" | "b">; // "a" | "b"

// NonNullable<T> - Exclude null and undefined
type T3 = NonNullable<string | null | undefined>; // string

// Record<K, T> - Create object type with keys K and values T
type PageInfo = Record<"home" | "about", { title: string }>;
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices

1. **Use `unknown` over `any`**: Enforce type checking
2. **Prefer `interface` for object shapes**: Better error messages
3. **Use `type` for unions and complex types**: More flexible
4. **Leverage type inference**: Let TypeScript infer when possible
5. **Create helper types**: Build reusable type utilities
6. **Use const assertions**: Preserve literal types
7. **Avoid type assertions**: Use type guards instead
8. **Document complex types**: Add JSDoc comments
9. **Use strict mode**: Enable all strict compiler options
10. **Test your types**: Use type tests to verify type behavior

## Type Testing

```typescript
// Type assertion tests
type AssertEqual<T, U> = [T] extends [U]
  ? [U] extends [T]
    ? true
    : false
  : false;

type Test1 = AssertEqual<string, string>; // true
type Test2 = AssertEqual<string, number>; // false
type Test3 = AssertEqual<string | number, string>; // false

// Expect error helper
type ExpectError<T extends never> = T;

// Example usage
type ShouldError = ExpectError<AssertEqual<string, number>>;
```

## Common Pitfalls

1. **Over-using `any`**: Defeats the purpose of TypeScript
2. **Ignoring strict null checks**: Can lead to runtime errors
3. **Too complex types**: Can slow down compilation
4. **Not using discriminated unions**: Misses type narrowing opportunities
5. **Forgetting readonly modifiers**: Allows unintended mutations
6. **Circular type references**: Can cause compiler errors
7. **Not handling edge cases**: Like empty arrays or null values

## Performance Considerations

- Avoid deeply nested conditional types
- Use simple types when possible
- Cache complex type computations
- Limit recursion depth in recursive types
- Use build tools to skip type checking in production

<!-- chapter:end slug=typescript-advanced-types -->

---

## Part: Kubernetes Operations

---

<!-- chapter:begin slug=gitops-workflow position=88 -->

## 88. gitops-workflow

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/kubernetes-operations/skills/gitops-workflow/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/gitops-workflow/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/gitops-workflow.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/argocd-setup.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/gitops-workflow/references/argocd-setup.md
  - `references/sync-policies.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/gitops-workflow/references/sync-policies.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: gitops-workflow
description: Implement GitOps workflows with ArgoCD and Flux for automated, declarative Kubernetes deployments with continuous reconciliation. Use when implementing GitOps practices, automating Kubernetes deployments, or setting up declarative infrastructure management.
---

# GitOps Workflow

Complete guide to implementing GitOps workflows with ArgoCD and Flux for automated Kubernetes deployments.

## Purpose

Implement declarative, Git-based continuous delivery for Kubernetes using ArgoCD or Flux CD, following OpenGitOps principles.

## When to Use This Skill

- Set up GitOps for Kubernetes clusters
- Automate application deployments from Git
- Implement progressive delivery strategies
- Manage multi-cluster deployments
- Configure automated sync policies
- Set up secret management in GitOps

## OpenGitOps Principles

1. **Declarative** - Entire system described declaratively
2. **Versioned and Immutable** - Desired state stored in Git
3. **Pulled Automatically** - Software agents pull desired state
4. **Continuously Reconciled** - Agents reconcile actual vs desired state

## ArgoCD Setup

### 1. Installation

```bash
# Create namespace
kubectl create namespace argocd

# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Get admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
```

**Reference:** See `references/argocd-setup.md` for detailed setup

### 2. Repository Structure

```
gitops-repo/
├── apps/
│   ├── production/
│   │   ├── app1/
│   │   │   ├── kustomization.yaml
│   │   │   └── deployment.yaml
│   │   └── app2/
│   └── staging/
├── infrastructure/
│   ├── ingress-nginx/
│   ├── cert-manager/
│   └── monitoring/
└── argocd/
    ├── applications/
    └── projects/
```

### 3. Create Application

```yaml
# argocd/applications/my-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/gitops-repo
    targetRevision: main
    path: apps/production/my-app
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
```

### 4. App of Apps Pattern

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: applications
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/gitops-repo
    targetRevision: main
    path: argocd/applications
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated: {}
```

## Flux CD Setup

### 1. Installation

```bash
# Install Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash

# Bootstrap Flux
flux bootstrap github \
  --owner=org \
  --repository=gitops-repo \
  --branch=main \
  --path=clusters/production \
  --personal
```

### 2. Create GitRepository

```yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/org/my-app
  ref:
    branch: main
```

### 3. Create Kustomization

```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./deploy
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app
```

## Sync Policies

### Auto-Sync Configuration

**ArgoCD:**

```yaml
syncPolicy:
  automated:
    prune: true # Delete resources not in Git
    selfHeal: true # Reconcile manual changes
    allowEmpty: false
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m
```

**Flux:**

```yaml
spec:
  interval: 1m
  prune: true
  wait: true
  timeout: 5m
```

**Reference:** See `references/sync-policies.md`

## Progressive Delivery

### Canary Deployment with ArgoCD Rollouts

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app
spec:
  replicas: 5
  strategy:
    canary:
      steps:
        - setWeight: 20
        - pause: { duration: 1m }
        - setWeight: 50
        - pause: { duration: 2m }
        - setWeight: 100
```

### Blue-Green Deployment

```yaml
strategy:
  blueGreen:
    activeService: my-app
    previewService: my-app-preview
    autoPromotionEnabled: false
```

## Secret Management

### External Secrets Operator

```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: SecretStore
  target:
    name: db-credentials
  data:
    - secretKey: password
      remoteRef:
        key: prod/db/password
```

### Sealed Secrets

```bash
# Encrypt secret
kubeseal --format yaml < secret.yaml > sealed-secret.yaml

# Commit sealed-secret.yaml to Git
```

## Best Practices

1. **Use separate repos or branches** for different environments
2. **Implement RBAC** for Git repositories
3. **Enable notifications** for sync failures
4. **Use health checks** for custom resources
5. **Implement approval gates** for production
6. **Keep secrets out of Git** (use External Secrets)
7. **Use App of Apps pattern** for organization
8. **Tag releases** for easy rollback
9. **Monitor sync status** with alerts
10. **Test changes** in staging first

## Troubleshooting

**Sync failures:**

```bash
argocd app get my-app
argocd app sync my-app --prune
```

**Out of sync status:**

```bash
argocd app diff my-app
argocd app sync my-app --force
```

## Related Skills

- `k8s-manifest-generator` - For creating manifests
- `helm-chart-scaffolding` - For packaging applications

<!-- chapter:end slug=gitops-workflow -->

---

<!-- chapter:begin slug=helm-chart-scaffolding position=89 -->

## 89. helm-chart-scaffolding

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/helm-chart-scaffolding.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (5), referenced from this skill's directory:
  - `assets/Chart.yaml.template` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/assets/Chart.yaml.template
  - `assets/values.yaml.template` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/assets/values.yaml.template
  - `references/chart-structure.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/references/chart-structure.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/references/details.md
  - `scripts/validate-chart.sh` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/helm-chart-scaffolding/scripts/validate-chart.sh

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: helm-chart-scaffolding
description: Design, organize, and manage Helm charts for templating and packaging Kubernetes applications with reusable configurations. Use when creating Helm charts, packaging Kubernetes applications, or implementing templated deployments.
---

# Helm Chart Scaffolding

Comprehensive guidance for creating, organizing, and managing Helm charts for packaging and deploying Kubernetes applications.

## Purpose

This skill provides step-by-step instructions for building production-ready Helm charts, including chart structure, templating patterns, values management, and validation strategies.

## When to Use This Skill

Use this skill when you need to:

- Create new Helm charts from scratch
- Package Kubernetes applications for distribution
- Manage multi-environment deployments with Helm
- Implement templating for reusable Kubernetes manifests
- Set up Helm chart repositories
- Follow Helm best practices and conventions

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Use semantic versioning** for chart and app versions
2. **Document all values** in values.yaml with comments
3. **Use template helpers** for repeated logic
4. **Validate charts** before packaging
5. **Pin dependency versions** explicitly
6. **Use conditions** for optional resources
7. **Follow naming conventions** (lowercase, hyphens)
8. **Include NOTES.txt** with usage instructions
9. **Add labels** consistently using helpers
10. **Test installations** in all environments

## Troubleshooting

**Template rendering errors:**

```bash
helm template my-app ./my-app --debug
```

**Dependency issues:**

```bash
helm dependency update
helm dependency list
```

**Installation failures:**

```bash
helm install my-app ./my-app --dry-run --debug
kubectl get events --sort-by='.lastTimestamp'
```


## Related Skills

- `k8s-manifest-generator` - For creating base Kubernetes manifests
- `gitops-workflow` - For automated Helm chart deployments

<!-- chapter:end slug=helm-chart-scaffolding -->

---

<!-- chapter:begin slug=k8s-manifest-generator position=90 -->

## 90. k8s-manifest-generator

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/k8s-manifest-generator.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (6), referenced from this skill's directory:
  - `assets/configmap-template.yaml` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/assets/configmap-template.yaml
  - `assets/deployment-template.yaml` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/assets/deployment-template.yaml
  - `assets/service-template.yaml` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/assets/service-template.yaml
  - `references/deployment-spec.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/references/deployment-spec.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/references/details.md
  - `references/service-spec.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-manifest-generator/references/service-spec.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: k8s-manifest-generator
description: Create production-ready Kubernetes manifests for Deployments, Services, ConfigMaps, and Secrets following best practices and security standards. Use when generating Kubernetes YAML manifests, creating K8s resources, or implementing production-grade Kubernetes configurations.
---

# Kubernetes Manifest Generator

Step-by-step guidance for creating production-ready Kubernetes manifests including Deployments, Services, ConfigMaps, Secrets, and PersistentVolumeClaims.

## Purpose

This skill provides comprehensive guidance for generating well-structured, secure, and production-ready Kubernetes manifests following cloud-native best practices and Kubernetes conventions.

## When to Use This Skill

Use this skill when you need to:

- Create new Kubernetes Deployment manifests
- Define Service resources for network connectivity
- Generate ConfigMap and Secret resources for configuration management
- Create PersistentVolumeClaim manifests for stateful workloads
- Follow Kubernetes best practices and naming conventions
- Implement resource limits, health checks, and security contexts
- Design manifests for multi-environment deployments

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices Summary

1. **Always set resource requests and limits** - Prevents resource starvation
2. **Implement health checks** - Ensures Kubernetes can manage your application
3. **Use specific image tags** - Avoid unpredictable deployments
4. **Apply security contexts** - Run as non-root, drop capabilities
5. **Use ConfigMaps and Secrets** - Separate config from code
6. **Label everything** - Enables filtering and organization
7. **Follow naming conventions** - Use standard Kubernetes labels
8. **Validate before applying** - Use dry-run and validation tools
9. **Version your manifests** - Keep in Git with version control
10. **Document with annotations** - Add context for other developers

## Troubleshooting

**Pods not starting:**

- Check image pull errors: `kubectl describe pod <pod-name>`
- Verify resource availability: `kubectl get nodes`
- Check events: `kubectl get events --sort-by='.lastTimestamp'`

**Service not accessible:**

- Verify selector matches pod labels: `kubectl get endpoints <service-name>`
- Check service type and port configuration
- Test from within cluster: `kubectl run debug --rm -it --image=busybox -- sh`

**ConfigMap/Secret not loading:**

- Verify names match in Deployment
- Check namespace
- Ensure resources exist: `kubectl get configmap,secret`

## Next Steps

After creating manifests:

1. Store in Git repository
2. Set up CI/CD pipeline for deployment
3. Consider using Helm or Kustomize for templating
4. Implement GitOps with ArgoCD or Flux
5. Add monitoring and observability

## Related Skills

- `helm-chart-scaffolding` - For templating and packaging
- `gitops-workflow` - For automated deployments
- `k8s-security-policies` - For advanced security configurations

<!-- chapter:end slug=k8s-manifest-generator -->

---

<!-- chapter:begin slug=k8s-security-policies position=91 -->

## 91. k8s-security-policies

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/kubernetes-operations/skills/k8s-security-policies/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-security-policies/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/k8s-security-policies.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `assets/network-policy-template.yaml` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-security-policies/assets/network-policy-template.yaml
  - `references/rbac-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/kubernetes-operations/skills/k8s-security-policies/references/rbac-patterns.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: k8s-security-policies
description: Implement Kubernetes security policies including NetworkPolicy, PodSecurityPolicy, and RBAC for production-grade security. Use when securing Kubernetes clusters, implementing network isolation, or enforcing pod security standards.
---

# Kubernetes Security Policies

Comprehensive guide for implementing NetworkPolicy, PodSecurityPolicy, RBAC, and Pod Security Standards in Kubernetes.

## Purpose

Implement defense-in-depth security for Kubernetes clusters using network policies, pod security standards, and RBAC.

## When to Use This Skill

- Implement network segmentation
- Configure pod security standards
- Set up RBAC for least-privilege access
- Create security policies for compliance
- Implement admission control
- Secure multi-tenant clusters

## Pod Security Standards

### 1. Privileged (Unrestricted)

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: privileged-ns
  labels:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/warn: privileged
```

### 2. Baseline (Minimally restrictive)

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: baseline-ns
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: baseline
```

### 3. Restricted (Most restrictive)

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: restricted-ns
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
```

## Network Policies

### Default Deny All

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
```

### Allow Frontend to Backend

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080
```

### Allow DNS

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: kube-system
      ports:
        - protocol: UDP
          port: 53
```

**Reference:** See `assets/network-policy-template.yaml`

## RBAC Configuration

### Role (Namespace-scoped)

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
```

### ClusterRole (Cluster-wide)

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-reader
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "watch", "list"]
```

### RoleBinding

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
  - kind: User
    name: jane
    apiGroup: rbac.authorization.k8s.io
  - kind: ServiceAccount
    name: default
    namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
```

**Reference:** See `references/rbac-patterns.md`

## Pod Security Context

### Restricted Pod

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: myapp:1.0
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
```

## Policy Enforcement with OPA Gatekeeper

### ConstraintTemplate

```yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        violation[{"msg": msg, "details": {"missing_labels": missing}}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("missing required labels: %v", [missing])
        }
```

### Constraint

```yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-app-label
spec:
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
  parameters:
    labels: ["app", "environment"]
```

## Service Mesh Security (Istio)

### PeerAuthentication (mTLS)

```yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT
```

### AuthorizationPolicy

```yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-frontend
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  action: ALLOW
  rules:
    - from:
        - source:
            principals: ["cluster.local/ns/production/sa/frontend"]
```

## Best Practices

1. **Implement Pod Security Standards** at namespace level
2. **Use Network Policies** for network segmentation
3. **Apply least-privilege RBAC** for all service accounts
4. **Enable admission control** (OPA Gatekeeper/Kyverno)
5. **Run containers as non-root**
6. **Use read-only root filesystem**
7. **Drop all capabilities** unless needed
8. **Implement resource quotas** and limit ranges
9. **Enable audit logging** for security events
10. **Regular security scanning** of images

## Compliance Frameworks

### CIS Kubernetes Benchmark

- Use RBAC authorization
- Enable audit logging
- Use Pod Security Standards
- Configure network policies
- Implement secrets encryption at rest
- Enable node authentication

### NIST Cybersecurity Framework

- Implement defense in depth
- Use network segmentation
- Configure security monitoring
- Implement access controls
- Enable logging and monitoring

## Troubleshooting

**NetworkPolicy not working:**

```bash
# Check if CNI supports NetworkPolicy
kubectl get nodes -o wide
kubectl describe networkpolicy <name>
```

**RBAC permission denied:**

```bash
# Check effective permissions
kubectl auth can-i list pods --as system:serviceaccount:default:my-sa
kubectl auth can-i '*' '*' --as system:serviceaccount:default:my-sa
```


## Related Skills

- `k8s-manifest-generator` - For creating secure manifests
- `gitops-workflow` - For automated policy deployment

<!-- chapter:end slug=k8s-security-policies -->

---

## Part: LLM Application Dev

---

<!-- chapter:begin slug=embedding-strategies position=92 -->

## 92. embedding-strategies

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/embedding-strategies/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/embedding-strategies/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/embedding-strategies.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/embedding-strategies/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: embedding-strategies
description: Select and optimize embedding models for semantic search and RAG applications. Use when choosing embedding models, implementing chunking strategies, or optimizing embedding quality for specific domains.
---

# Embedding Strategies

Guide to selecting and optimizing embedding models for vector search applications.

## When to Use This Skill

- Choosing embedding models for RAG
- Optimizing chunking strategies
- Fine-tuning embeddings for domains
- Comparing embedding model performance
- Reducing embedding dimensions
- Handling multilingual content

## Core Concepts

### 1. Embedding Model Comparison (2026)

| Model                      | Dimensions | Max Tokens | Best For                            |
| -------------------------- | ---------- | ---------- | ----------------------------------- |
| **voyage-3-large**         | 1024       | 32000      | Claude apps (Anthropic recommended) |
| **voyage-3**               | 1024       | 32000      | Claude apps, cost-effective         |
| **voyage-code-3**          | 1024       | 32000      | Code search                         |
| **voyage-finance-2**       | 1024       | 32000      | Financial documents                 |
| **voyage-law-2**           | 1024       | 32000      | Legal documents                     |
| **text-embedding-3-large** | 3072       | 8191       | OpenAI apps, high accuracy          |
| **text-embedding-3-small** | 1536       | 8191       | OpenAI apps, cost-effective         |
| **bge-large-en-v1.5**      | 1024       | 512        | Open source, local deployment       |
| **all-MiniLM-L6-v2**       | 384        | 256        | Fast, lightweight                   |
| **multilingual-e5-large**  | 1024       | 512        | Multi-language                      |

### 2. Embedding Pipeline

```
Document → Chunking → Preprocessing → Embedding Model → Vector
                ↓
        [Overlap, Size]  [Clean, Normalize]  [API/Local]
```

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Match model to use case**: Code vs prose vs multilingual
- **Chunk thoughtfully**: Preserve semantic boundaries
- **Normalize embeddings**: For cosine similarity search
- **Batch requests**: More efficient than one-by-one
- **Cache embeddings**: Avoid recomputing for static content
- **Use Voyage AI for Claude apps**: Recommended by Anthropic

### Don'ts

- **Don't ignore token limits**: Truncation loses information
- **Don't mix embedding models**: Incompatible vector spaces
- **Don't skip preprocessing**: Garbage in, garbage out
- **Don't over-chunk**: Lose important context
- **Don't forget metadata**: Essential for filtering and debugging

<!-- chapter:end slug=embedding-strategies -->

---

<!-- chapter:begin slug=hybrid-search-implementation position=93 -->

## 93. hybrid-search-implementation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/hybrid-search-implementation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/hybrid-search-implementation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/hybrid-search-implementation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/hybrid-search-implementation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: hybrid-search-implementation
description: Combine vector and keyword search for improved retrieval. Use when implementing RAG systems, building search engines, or when neither approach alone provides sufficient recall.
---

# Hybrid Search Implementation

Patterns for combining vector similarity and keyword-based search.

## When to Use This Skill

- Building RAG systems with improved recall
- Combining semantic understanding with exact matching
- Handling queries with specific terms (names, codes)
- Improving search for domain-specific vocabulary
- When pure vector search misses keyword matches

## Core Concepts

### 1. Hybrid Search Architecture

```
Query → ┬─► Vector Search ──► Candidates ─┐
        │                                  │
        └─► Keyword Search ─► Candidates ─┴─► Fusion ─► Results
```

### 2. Fusion Methods

| Method            | Description              | Best For        |
| ----------------- | ------------------------ | --------------- |
| **RRF**           | Reciprocal Rank Fusion   | General purpose |
| **Linear**        | Weighted sum of scores   | Tunable balance |
| **Cross-encoder** | Rerank with neural model | Highest quality |
| **Cascade**       | Filter then rerank       | Efficiency      |

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Tune weights empirically** - Test on your data
- **Use RRF for simplicity** - Works well without tuning
- **Add reranking** - Significant quality improvement
- **Log both scores** - Helps with debugging
- **A/B test** - Measure real user impact

### Don'ts

- **Don't assume one size fits all** - Different queries need different weights
- **Don't skip keyword search** - Handles exact matches better
- **Don't over-fetch** - Balance recall vs latency
- **Don't ignore edge cases** - Empty results, single word queries

<!-- chapter:end slug=hybrid-search-implementation -->

---

<!-- chapter:begin slug=langchain-architecture position=94 -->

## 94. langchain-architecture

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/langchain-architecture/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/langchain-architecture/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/langchain-architecture.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/langchain-architecture/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: langchain-architecture
description: Design LLM applications using LangChain 1.x and LangGraph for agents, memory, and tool integration. Use when building LangChain applications, implementing AI agents, or creating complex LLM workflows.
---

# LangChain & LangGraph Architecture

Master modern LangChain 1.x and LangGraph for building sophisticated LLM applications with agents, state management, memory, and tool integration.

## When to Use This Skill

- Building autonomous AI agents with tool access
- Implementing complex multi-step LLM workflows
- Managing conversation memory and state
- Integrating LLMs with external data sources and APIs
- Creating modular, reusable LLM application components
- Implementing document processing pipelines
- Building production-grade LLM applications

## Package Structure (LangChain 1.x)

```
langchain (1.2.x)         # High-level orchestration
langchain-core (1.2.x)    # Core abstractions (messages, prompts, tools)
langchain-community       # Third-party integrations
langgraph                 # Agent orchestration and state management
langchain-openai          # OpenAI integrations
langchain-anthropic       # Anthropic/Claude integrations
langchain-voyageai        # Voyage AI embeddings
langchain-pinecone        # Pinecone vector store
```

## Core Concepts

### 1. LangGraph Agents

LangGraph is the standard for building agents in 2026. It provides:

**Key Features:**

- **StateGraph**: Explicit state management with typed state
- **Durable Execution**: Agents persist through failures
- **Human-in-the-Loop**: Inspect and modify state at any point
- **Memory**: Short-term and long-term memory across sessions
- **Checkpointing**: Save and resume agent state

**Agent Patterns:**

- **ReAct**: Reasoning + Acting with `create_react_agent`
- **Plan-and-Execute**: Separate planning and execution nodes
- **Multi-Agent**: Supervisor routing between specialized agents
- **Tool-Calling**: Structured tool invocation with Pydantic schemas

### 2. State Management

LangGraph uses TypedDict for explicit state:

```python
from typing import Annotated, TypedDict
from langgraph.graph import MessagesState

# Simple message-based state
class AgentState(MessagesState):
    """Extends MessagesState with custom fields."""
    context: Annotated[list, "retrieved documents"]

# Custom state for complex agents
class CustomState(TypedDict):
    messages: Annotated[list, "conversation history"]
    context: Annotated[dict, "retrieved context"]
    current_step: str
    results: list
```

### 3. Memory Systems

Modern memory implementations:

- **ConversationBufferMemory**: Stores all messages (short conversations)
- **ConversationSummaryMemory**: Summarizes older messages (long conversations)
- **ConversationTokenBufferMemory**: Token-based windowing
- **VectorStoreRetrieverMemory**: Semantic similarity retrieval
- **LangGraph Checkpointers**: Persistent state across sessions

### 4. Document Processing

Loading, transforming, and storing documents:

**Components:**

- **Document Loaders**: Load from various sources
- **Text Splitters**: Chunk documents intelligently
- **Vector Stores**: Store and retrieve embeddings
- **Retrievers**: Fetch relevant documents

### 5. Callbacks & Tracing

LangSmith is the standard for observability:

- Request/response logging
- Token usage tracking
- Latency monitoring
- Error tracking
- Trace visualization

## Quick Start

### Modern ReAct Agent with LangGraph

```python
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
import ast
import operator

# Initialize LLM (Claude Sonnet 5 recommended)
llm = ChatAnthropic(model="claude-sonnet-5")

# Define tools with Pydantic schemas
@tool
def search_database(query: str) -> str:
    """Search internal database for information."""
    # Your database search logic
    return f"Results for: {query}"

@tool
def calculate(expression: str) -> str:
    """Safely evaluate a mathematical expression.

    Supports: +, -, *, /, **, %, parentheses
    Example: '(2 + 3) * 4' returns '20'
    """
    # Safe math evaluation using ast
    allowed_operators = {
        ast.Add: operator.add,
        ast.Sub: operator.sub,
        ast.Mult: operator.mul,
        ast.Div: operator.truediv,
        ast.Pow: operator.pow,
        ast.Mod: operator.mod,
        ast.USub: operator.neg,
    }

    def _eval(node):
        if isinstance(node, ast.Constant):
            return node.value
        elif isinstance(node, ast.BinOp):
            left = _eval(node.left)
            right = _eval(node.right)
            return allowed_operators[type(node.op)](left, right)
        elif isinstance(node, ast.UnaryOp):
            operand = _eval(node.operand)
            return allowed_operators[type(node.op)](operand)
        else:
            raise ValueError(f"Unsupported operation: {type(node)}")

    try:
        tree = ast.parse(expression, mode='eval')
        return str(_eval(tree.body))
    except Exception as e:
        return f"Error: {e}"

tools = [search_database, calculate]

# Create checkpointer for memory persistence
checkpointer = MemorySaver()

# Create ReAct agent
agent = create_react_agent(
    llm,
    tools,
    checkpointer=checkpointer
)

# Run agent with thread ID for memory
config = {"configurable": {"thread_id": "user-123"}}
result = await agent.ainvoke(
    {"messages": [("user", "Search for Python tutorials and calculate 25 * 4")]},
    config=config
)
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing Strategies

```python
import pytest
from unittest.mock import AsyncMock, patch

@pytest.mark.asyncio
async def test_agent_tool_selection():
    """Test agent selects correct tool."""
    with patch.object(llm, 'ainvoke') as mock_llm:
        mock_llm.return_value = AsyncMock(content="Using search_database")

        result = await agent.ainvoke({
            "messages": [("user", "search for documents")]
        })

        # Verify tool was called
        assert "search_database" in str(result)

@pytest.mark.asyncio
async def test_memory_persistence():
    """Test memory persists across invocations."""
    config = {"configurable": {"thread_id": "test-thread"}}

    # First message
    await agent.ainvoke(
        {"messages": [("user", "Remember: the code is 12345")]},
        config
    )

    # Second message should remember
    result = await agent.ainvoke(
        {"messages": [("user", "What was the code?")]},
        config
    )

    assert "12345" in result["messages"][-1].content
```

## Performance Optimization

### 1. Caching with Redis

```python
from langchain_community.cache import RedisCache
from langchain_core.globals import set_llm_cache
import redis

redis_client = redis.Redis.from_url("redis://localhost:6379")
set_llm_cache(RedisCache(redis_client))
```

### 2. Async Batch Processing

```python
import asyncio
from langchain_core.documents import Document

async def process_documents(documents: list[Document]) -> list:
    """Process documents in parallel."""
    tasks = [process_single(doc) for doc in documents]
    return await asyncio.gather(*tasks)

async def process_single(doc: Document) -> dict:
    """Process a single document."""
    chunks = text_splitter.split_documents([doc])
    embeddings = await embeddings_model.aembed_documents(
        [c.page_content for c in chunks]
    )
    return {"doc_id": doc.metadata.get("id"), "embeddings": embeddings}
```

### 3. Connection Pooling

```python
from langchain_pinecone import PineconeVectorStore
from pinecone import Pinecone

# Reuse Pinecone client
pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
index = pc.Index("my-index")

# Create vector store with existing index
vectorstore = PineconeVectorStore(index=index, embedding=embeddings)
```

<!-- chapter:end slug=langchain-architecture -->

---

<!-- chapter:begin slug=llm-evaluation position=95 -->

## 95. llm-evaluation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/llm-evaluation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/llm-evaluation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/llm-evaluation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/llm-evaluation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: llm-evaluation
description: Implement comprehensive evaluation strategies for LLM applications using automated metrics, human feedback, and benchmarking. Use when testing LLM performance, measuring AI application quality, or establishing evaluation frameworks.
---

# LLM Evaluation

Master comprehensive evaluation strategies for LLM applications, from automated metrics to human evaluation and A/B testing.

## When to Use This Skill

- Measuring LLM application performance systematically
- Comparing different models or prompts
- Detecting performance regressions before deployment
- Validating improvements from prompt changes
- Building confidence in production systems
- Establishing baselines and tracking progress over time
- Debugging unexpected model behavior

## Core Evaluation Types

### 1. Automated Metrics

Fast, repeatable, scalable evaluation using computed scores.

**Text Generation:**

- **BLEU**: N-gram overlap (translation)
- **ROUGE**: Recall-oriented (summarization)
- **METEOR**: Semantic similarity
- **BERTScore**: Embedding-based similarity
- **Perplexity**: Language model confidence

**Classification:**

- **Accuracy**: Percentage correct
- **Precision/Recall/F1**: Class-specific performance
- **Confusion Matrix**: Error patterns
- **AUC-ROC**: Ranking quality

**Retrieval (RAG):**

- **MRR**: Mean Reciprocal Rank
- **NDCG**: Normalized Discounted Cumulative Gain
- **Precision@K**: Relevant in top K
- **Recall@K**: Coverage in top K

### 2. Human Evaluation

Manual assessment for quality aspects difficult to automate.

**Dimensions:**

- **Accuracy**: Factual correctness
- **Coherence**: Logical flow
- **Relevance**: Answers the question
- **Fluency**: Natural language quality
- **Safety**: No harmful content
- **Helpfulness**: Useful to the user

### 3. LLM-as-Judge

Use stronger LLMs to evaluate weaker model outputs.

**Approaches:**

- **Pointwise**: Score individual responses
- **Pairwise**: Compare two responses
- **Reference-based**: Compare to gold standard
- **Reference-free**: Judge without ground truth

## Quick Start

```python
from dataclasses import dataclass
from typing import Callable
import numpy as np

@dataclass
class Metric:
    name: str
    fn: Callable

    @staticmethod
    def accuracy():
        return Metric("accuracy", calculate_accuracy)

    @staticmethod
    def bleu():
        return Metric("bleu", calculate_bleu)

    @staticmethod
    def bertscore():
        return Metric("bertscore", calculate_bertscore)

    @staticmethod
    def custom(name: str, fn: Callable):
        return Metric(name, fn)

class EvaluationSuite:
    def __init__(self, metrics: list[Metric]):
        self.metrics = metrics

    async def evaluate(self, model, test_cases: list[dict]) -> dict:
        results = {m.name: [] for m in self.metrics}

        for test in test_cases:
            prediction = await model.predict(test["input"])

            for metric in self.metrics:
                score = metric.fn(
                    prediction=prediction,
                    reference=test.get("expected"),
                    context=test.get("context")
                )
                results[metric.name].append(score)

        return {
            "metrics": {k: np.mean(v) for k, v in results.items()},
            "raw_scores": results
        }

# Usage
suite = EvaluationSuite([
    Metric.accuracy(),
    Metric.bleu(),
    Metric.bertscore(),
    Metric.custom("groundedness", check_groundedness)
])

test_cases = [
    {
        "input": "What is the capital of France?",
        "expected": "Paris",
        "context": "France is a country in Europe. Paris is its capital."
    },
]

results = await suite.evaluate(model=your_model, test_cases=test_cases)
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=llm-evaluation -->

---

<!-- chapter:begin slug=prompt-engineering-patterns position=96 -->

## 96. prompt-engineering-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/prompt-engineering-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (9), referenced from this skill's directory:
  - `assets/few-shot-examples.json` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/assets/few-shot-examples.json
  - `assets/prompt-template-library.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/assets/prompt-template-library.md
  - `references/chain-of-thought.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/references/chain-of-thought.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/references/details.md
  - `references/few-shot-learning.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/references/few-shot-learning.md
  - `references/prompt-optimization.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/references/prompt-optimization.md
  - `references/prompt-templates.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/references/prompt-templates.md
  - `references/system-prompts.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/references/system-prompts.md
  - `scripts/optimize-prompt.py` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/prompt-engineering-patterns/scripts/optimize-prompt.py

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: prompt-engineering-patterns
description: >-
  This skill should be used when the user asks to "optimize a prompt", "improve prompt
  performance", "design a prompt template", "write better prompts", "debug prompt issues", "use
  chain-of-thought", "structured prompting", "few-shot prompting", or wants to apply advanced
  prompt engineering patterns for production LLM applications.
---

# Prompt Engineering Patterns

Master advanced prompt engineering techniques to maximize LLM performance, reliability, and controllability.

## When to Use This Skill

- Designing complex prompts for production LLM applications
- Optimizing prompt performance and consistency
- Implementing structured reasoning patterns (chain-of-thought, tree-of-thought)
- Building few-shot learning systems with dynamic example selection
- Creating reusable prompt templates with variable interpolation
- Debugging and refining prompts that produce inconsistent outputs
- Implementing system prompts for specialized AI assistants
- Using structured outputs (JSON mode) for reliable parsing

## Core Capabilities

### 1. Few-Shot Learning

- Example selection strategies (semantic similarity, diversity sampling)
- Balancing example count with context window constraints
- Constructing effective demonstrations with input-output pairs
- Dynamic example retrieval from knowledge bases
- Handling edge cases through strategic example selection

### 2. Chain-of-Thought Prompting

- Step-by-step reasoning elicitation
- Zero-shot CoT with "Let's think step by step"
- Few-shot CoT with reasoning traces
- Self-consistency techniques (sampling multiple reasoning paths)
- Verification and validation steps

### 3. Structured Outputs

- JSON mode for reliable parsing
- Pydantic schema enforcement
- Type-safe response handling
- Error handling for malformed outputs

### 4. Prompt Optimization

- Iterative refinement workflows
- A/B testing prompt variations
- Measuring prompt performance metrics (accuracy, consistency, latency)
- Reducing token usage while maintaining quality
- Handling edge cases and failure modes

### 5. Template Systems

- Variable interpolation and formatting
- Conditional prompt sections
- Multi-turn conversation templates
- Role-based prompt composition
- Modular prompt components

### 6. System Prompt Design

- Setting model behavior and constraints
- Defining output formats and structure
- Establishing role and expertise
- Safety guidelines and content policies
- Context setting and background information

## Quick Start

```python
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field

# Define structured output schema
class SQLQuery(BaseModel):
    query: str = Field(description="The SQL query")
    explanation: str = Field(description="Brief explanation of what the query does")
    tables_used: list[str] = Field(description="List of tables referenced")

# Initialize model with structured output
llm = ChatAnthropic(model="claude-sonnet-5")
structured_llm = llm.with_structured_output(SQLQuery)

# Create prompt template
prompt = ChatPromptTemplate.from_messages([
    ("system", """You are an expert SQL developer. Generate efficient, secure SQL queries.
    Always use parameterized queries to prevent SQL injection.
    Explain your reasoning briefly."""),
    ("user", "Convert this to SQL: {query}")
])

# Create chain
chain = prompt | structured_llm

# Use
result = await chain.ainvoke({
    "query": "Find all users who registered in the last 30 days"
})
print(result.query)
print(result.explanation)
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Be Specific**: Vague prompts produce inconsistent results
2. **Show, Don't Tell**: Examples are more effective than descriptions
3. **Use Structured Outputs**: Enforce schemas with Pydantic for reliability
4. **Test Extensively**: Evaluate on diverse, representative inputs
5. **Iterate Rapidly**: Small changes can have large impacts
6. **Monitor Performance**: Track metrics in production
7. **Version Control**: Treat prompts as code with proper versioning
8. **Document Intent**: Explain why prompts are structured as they are

## Common Pitfalls

- **Over-engineering**: Starting with complex prompts before trying simple ones
- **Example pollution**: Using examples that don't match the target task
- **Context overflow**: Exceeding token limits with excessive examples
- **Ambiguous instructions**: Leaving room for multiple interpretations
- **Ignoring edge cases**: Not testing on unusual or boundary inputs
- **No error handling**: Assuming outputs will always be well-formed
- **Hardcoded values**: Not parameterizing prompts for reuse

## Success Metrics

Track these KPIs for your prompts:

- **Accuracy**: Correctness of outputs
- **Consistency**: Reproducibility across similar inputs
- **Latency**: Response time (P50, P95, P99)
- **Token Usage**: Average tokens per request
- **Success Rate**: Percentage of valid, parseable outputs
- **User Satisfaction**: Ratings and feedback

<!-- chapter:end slug=prompt-engineering-patterns -->

---

<!-- chapter:begin slug=rag-implementation position=97 -->

## 97. rag-implementation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/rag-implementation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/rag-implementation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/rag-implementation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/rag-implementation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: rag-implementation
description: Build Retrieval-Augmented Generation (RAG) systems for LLM applications with vector databases and semantic search. Use when implementing knowledge-grounded AI, building document Q&A systems, or integrating LLMs with external knowledge bases.
---

# RAG Implementation

Master Retrieval-Augmented Generation (RAG) to build LLM applications that provide accurate, grounded responses using external knowledge sources.

## When to Use This Skill

- Building Q&A systems over proprietary documents
- Creating chatbots with current, factual information
- Implementing semantic search with natural language queries
- Reducing hallucinations with grounded responses
- Enabling LLMs to access domain-specific knowledge
- Building documentation assistants
- Creating research tools with source citation

## Core Components

### 1. Vector Databases

**Purpose**: Store and retrieve document embeddings efficiently

**Options:**

- **Pinecone**: Managed, scalable, serverless
- **Weaviate**: Open-source, hybrid search, GraphQL
- **Milvus**: High performance, on-premise
- **Chroma**: Lightweight, easy to use, local development
- **Qdrant**: Fast, filtered search, Rust-based
- **pgvector**: PostgreSQL extension, SQL integration

### 2. Embeddings

**Purpose**: Convert text to numerical vectors for similarity search

**Models (2026):**
| Model | Dimensions | Best For |
|-------|------------|----------|
| **voyage-3-large** | 1024 | Claude apps (Anthropic recommended) |
| **voyage-code-3** | 1024 | Code search |
| **text-embedding-3-large** | 3072 | OpenAI apps, high accuracy |
| **text-embedding-3-small** | 1536 | OpenAI apps, cost-effective |
| **bge-large-en-v1.5** | 1024 | Open source, local deployment |
| **multilingual-e5-large** | 1024 | Multi-language support |

### 3. Retrieval Strategies

**Approaches:**

- **Dense Retrieval**: Semantic similarity via embeddings
- **Sparse Retrieval**: Keyword matching (BM25, TF-IDF)
- **Hybrid Search**: Combine dense + sparse with weighted fusion
- **Multi-Query**: Generate multiple query variations
- **HyDE**: Generate hypothetical documents for better retrieval

### 4. Reranking

**Purpose**: Improve retrieval quality by reordering results

**Methods:**

- **Cross-Encoders**: BERT-based reranking (ms-marco-MiniLM)
- **Cohere Rerank**: API-based reranking
- **Maximal Marginal Relevance (MMR)**: Diversity + relevance
- **LLM-based**: Use LLM to score relevance

## Quick Start with LangGraph

```python
from langgraph.graph import StateGraph, START, END
from langchain_anthropic import ChatAnthropic
from langchain_voyageai import VoyageAIEmbeddings
from langchain_pinecone import PineconeVectorStore
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_text_splitters import RecursiveCharacterTextSplitter
from typing import TypedDict, Annotated

class RAGState(TypedDict):
    question: str
    context: list[Document]
    answer: str

# Initialize components
llm = ChatAnthropic(model="claude-sonnet-5")
embeddings = VoyageAIEmbeddings(model="voyage-3-large")
vectorstore = PineconeVectorStore(index_name="docs", embedding=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# RAG prompt
rag_prompt = ChatPromptTemplate.from_template(
    """Answer based on the context below. If you cannot answer, say so.

    Context:
    {context}

    Question: {question}

    Answer:"""
)

async def retrieve(state: RAGState) -> RAGState:
    """Retrieve relevant documents."""
    docs = await retriever.ainvoke(state["question"])
    return {"context": docs}

async def generate(state: RAGState) -> RAGState:
    """Generate answer from context."""
    context_text = "\n\n".join(doc.page_content for doc in state["context"])
    messages = rag_prompt.format_messages(
        context=context_text,
        question=state["question"]
    )
    response = await llm.ainvoke(messages)
    return {"answer": response.content}

# Build RAG graph
builder = StateGraph(RAGState)
builder.add_node("retrieve", retrieve)
builder.add_node("generate", generate)
builder.add_edge(START, "retrieve")
builder.add_edge("retrieve", "generate")
builder.add_edge("generate", END)

rag_chain = builder.compile()

# Use
result = await rag_chain.ainvoke({"question": "What are the main features?"})
print(result["answer"])
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=rag-implementation -->

---

<!-- chapter:begin slug=similarity-search-patterns position=98 -->

## 98. similarity-search-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/similarity-search-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/similarity-search-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/similarity-search-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/similarity-search-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: similarity-search-patterns
description: Implement efficient similarity search with vector databases. Use when building semantic search, implementing nearest neighbor queries, or optimizing retrieval performance.
---

# Similarity Search Patterns

Patterns for implementing efficient similarity search in production systems.

## When to Use This Skill

- Building semantic search systems
- Implementing RAG retrieval
- Creating recommendation engines
- Optimizing search latency
- Scaling to millions of vectors
- Combining semantic and keyword search

## Core Concepts

### 1. Distance Metrics

| Metric             | Formula            | Best For              |
| ------------------ | ------------------ | --------------------- | --- | -------------- |
| **Cosine**         | 1 - (A·B)/(‖A‖‖B‖) | Normalized embeddings |
| **Euclidean (L2)** | √Σ(a-b)²           | Raw embeddings        |
| **Dot Product**    | A·B                | Magnitude matters     |
| **Manhattan (L1)** | Σ                  | a-b                   |     | Sparse vectors |

### 2. Index Types

```
┌─────────────────────────────────────────────────┐
│                 Index Types                      │
├─────────────┬───────────────┬───────────────────┤
│    Flat     │     HNSW      │    IVF+PQ         │
│ (Exact)     │ (Graph-based) │ (Quantized)       │
├─────────────┼───────────────┼───────────────────┤
│ O(n) search │ O(log n)      │ O(√n)             │
│ 100% recall │ ~95-99%       │ ~90-95%           │
│ Small data  │ Medium-Large  │ Very Large        │
└─────────────┴───────────────┴───────────────────┘
```

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Use appropriate index** - HNSW for most cases
- **Tune parameters** - ef_search, nprobe for recall/speed
- **Implement hybrid search** - Combine with keyword search
- **Monitor recall** - Measure search quality
- **Pre-filter when possible** - Reduce search space

### Don'ts

- **Don't skip evaluation** - Measure before optimizing
- **Don't over-index** - Start with flat, scale up
- **Don't ignore latency** - P99 matters for UX
- **Don't forget costs** - Vector storage adds up

<!-- chapter:end slug=similarity-search-patterns -->

---

<!-- chapter:begin slug=vector-index-tuning position=99 -->

## 99. vector-index-tuning

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-application-dev/skills/vector-index-tuning/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/vector-index-tuning/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/vector-index-tuning.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-application-dev/skills/vector-index-tuning/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: vector-index-tuning
description: Optimize vector index performance for latency, recall, and memory. Use when tuning HNSW parameters, selecting quantization strategies, or scaling vector search infrastructure.
---

# Vector Index Tuning

Guide to optimizing vector indexes for production performance.

## When to Use This Skill

- Tuning HNSW parameters
- Implementing quantization
- Optimizing memory usage
- Reducing search latency
- Balancing recall vs speed
- Scaling to billions of vectors

## Core Concepts

### 1. Index Type Selection

```
Data Size           Recommended Index
────────────────────────────────────────
< 10K vectors  →    Flat (exact search)
10K - 1M       →    HNSW
1M - 100M      →    HNSW + Quantization
> 100M         →    IVF + PQ or DiskANN
```

### 2. HNSW Parameters

| Parameter          | Default | Effect                                               |
| ------------------ | ------- | ---------------------------------------------------- |
| **M**              | 16      | Connections per node, ↑ = better recall, more memory |
| **efConstruction** | 100     | Build quality, ↑ = better index, slower build        |
| **efSearch**       | 50      | Search quality, ↑ = better recall, slower search     |

### 3. Quantization Types

```
Full Precision (FP32): 4 bytes × dimensions
Half Precision (FP16): 2 bytes × dimensions
INT8 Scalar:           1 byte × dimensions
Product Quantization:  ~32-64 bytes total
Binary:                dimensions/8 bytes
```

## Templates and detailed worked examples

Full template library and detailed worked examples live in `references/details.md`. Read that file when you need the concrete templates.

## Best Practices

### Do's

- **Benchmark with real queries** - Synthetic may not represent production
- **Monitor recall continuously** - Can degrade with data drift
- **Start with defaults** - Tune only when needed
- **Use quantization** - Significant memory savings
- **Consider tiered storage** - Hot/cold data separation

### Don'ts

- **Don't over-optimize early** - Profile first
- **Don't ignore build time** - Index updates have cost
- **Don't forget reindexing** - Plan for maintenance
- **Don't skip warming** - Cold indexes are slow

<!-- chapter:end slug=vector-index-tuning -->

---

## Part: LLM Finetuning

---

<!-- chapter:begin slug=checkpoint-promotion position=100 -->

## 100. checkpoint-promotion

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/checkpoint-promotion/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/checkpoint-promotion/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/checkpoint-promotion.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/gate-templates.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/checkpoint-promotion/references/gate-templates.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: checkpoint-promotion
description: Gate fine-tuned checkpoints with drift budgets, paired comparison, and forgetting checks before promotion. Use after a training run produces a checkpoint, when deciding whether a tuned model ships, or when a promoted model needs re-gating against updated goldens.
---

# Checkpoint Promotion

The Phase 5 gate for the whole
plugin: a checkpoint that trains
cleanly and beats its task metric
still doesn't ship without
clearing all four stages below.
`eval-harness-first` built the
suite re-run here — this skill is
where that suite's baseline
decides something.

**Input:** a trained checkpoint,
`eval/baseline-<model>.json` from
`eval-harness-first`, and the
frozen `eval/drift-suite.yaml`.
**Output format:**
`promotion-report.md` — the
four-stage evidence plus a
terminal `PROMOTE` or `REJECT`
verdict that `/finetune` Phase 5
and `/promote-checkpoint` consume
directly.

## The Four-Stage Gate

Each stage gates the next — a
failure at stage 2 means stage 3
doesn't run. Stages 2 and 3 share
one expensive inference pass, so
running them concurrently and
applying gate order at verdict
time is licensed on a
**deterministic** arena (nothing
saved by serializing); a
judge-based arena should still
wait for stage 2 first — that's
where the real savings are.

1. **Data-quality gate.** Before
   any eval touches the
   checkpoint: dedup the training
   set, check for eval-goldens
   leakage (the exact failure
   `trace-to-training-data`'s
   Hygiene section exists to
   prevent), and scan for label
   noise. A checkpoint trained on
   leaked goldens invalidates
   every later stage.
2. **Held-out + frozen
   capability-drift suite.**
   Re-run `eval-harness-first`'s
   `eval/drift-suite.yaml` —
   MMLU/GSM8K/IFEval plus 200–500
   domain-adjacent items — against
   the checkpoint and diff against
   `baseline-<model>.json` per
   benchmark against the Drift
   Budget table below.
3. **Paired arena vs. base.**
   Position-randomized judge,
   checkpoint vs. base model, same
   prompts — or the deterministic
   paired-comparison variant in
   `references/gate-templates.md`
   when every grader in the
   harness is deterministic (no
   LLM-judge; position
   randomization N/A there).
   **A holdout win that
   loses the live arena does not
   ship** — stage-2 numbers and
   stage-3 judgments must agree; a
   win on frozen goldens and a
   loss in paired comparison is a
   real signal, not a discrepancy
   to explain away.
4. **Canary.** 5–10% stratified
   rollout with auto-rollback for
   any checkpoint reaching
   production traffic. **Local-only
   users stop at stage 3** —
   skipping stage 4 for a local
   deployment is the correct
   stopping point, not a shortcut.

### Drift Budget

| Drift (pts) | Verdict |
|---|---|
| ≤1 | Noise — proceed |
| 2–5 | Rerun with seed variation before deciding |
| >5 | **HARD FAIL** — no exception for task gains |

The >5pt row governs regardless
of the others: a checkpoint that
gained 8 points on the target
task and lost 6 points of general
capability still fails here —
task improvement never buys back
a drift-budget breach.

**Item count derives from the
budget, not convenience:** the
strict n for a half-width under
half the 5pt hard-fail threshold
is ~1,300 at typical accuracy
(p≈0.7); n=200 is a pragmatic
floor (±6pt half-width at that
same p, n=50 ±13pt) — report the
half-width with every verdict,
and treat a margin smaller than
it as `REJECT (uncertain)`, not
PASS/HARD FAIL. Full math and a
5-run cautionary example:
`references/gate-templates.md`.

**RERUN is not a verdict.** A
2–5pt drift only ever produces a
`PROMOTE` or `REJECT` after the
seed-variation rerun completes —
`PROMOTE` requires landing back
at ≤1pt (noise); any rerun still
>1pt — 2–5pt band or >5pt breach
alike — resolves stage 2 to a
hard `REJECT`. No report may
reach the Verdict section with
stage 2 still showing `RERUN`.

## Catastrophic Forgetting

Unmanaged LoRA fine-tuning loses
real general capability, and
stage 2 is what catches it:

- **~43% knowledge loss
  unmanaged** — no replay, no
  regularization.
- **~10% with basic management**
  — some replay or a conservative
  LR.
- **~3% with replay + EWC** — the
  disciplined case.
- **10–30% general-data replay
  mix is the standard
  mitigation** — blend general-
  domain data into training
  rather than target-task data
  alone.

If a checkpoint hits the >5pt
hard fail in stage 2, work this
escalation ladder in order — the
one canonical order this skill
and `references/gate-templates.md`
both point to:

1. **Adjust the replay-mix
   fraction — swap rows, don't
   add them** (adding confounds
   fraction with total optimizer
   steps). Dose is not monotonic
   at small-run scale (<~100
   steps) — re-check drift after
   any swap.
2. **Lower the learning rate.**
3. **Fewer epochs.**
4. **A smaller LoRA rank** — the
   same rank/LR levers
   `lora-qlora-recipes` and
   `preference-optimization` tune
   for the training run, applied
   here in reverse.

This order is a default, not a
law: **remediation guidance from
a single before/after run pair
is a hypothesis** — label it
low-confidence once any lever
produces a reversal, and prefer
a seed-variation repeat over
trusting the next rung blindly.
A lever that clears the drift
breach but drops a
success-criterion metric below
target is a two-sided tradeoff
for a human, not a reason to
keep descending the ladder. Full
reasoning and the 5-run
trajectory behind both caveats:
`references/gate-templates.md`.

**Disclose drift-suite
instruction reuse.** A replay row
copying the drift harness's exact
instruction phrasing (not just
disjoint source items) makes that
benchmark's post-replay score an
upper bound — flag it
instruction-familiar, or re-probe
with a paraphrase, before
treating a near-budget pass as
clean.

## The Verdict

`promotion-report.md` covers all
four stages as sections and
**must end with a terminal
verdict: `PROMOTE` or `REJECT`**,
the evidence that produced it,
and exactly one top remediation
when the verdict is `REJECT`.
Template: `references/gate-templates.md`.
The terminal contract other
skills parse:

```
## Verdict

REJECT

Evidence: domain-adjacent drift
suite dropped 6.2pt (threshold:
>5pt hard fail) despite +8pt on
the target task.

Top remediation: swap the
replay-mix fraction from 10%
toward 20%, holding step count
constant.
```

- **REJECT is a result, not an
  error.** A checkpoint that
  fails stage 2's drift budget or
  stage 3's arena comparison did
  its job. Don't treat a REJECT
  as a failed run needing a rerun
  of this skill; it's the correct
  output of a working gate.
- **One remediation, not a
  menu.** Evidence sections may
  list everything observed; the
  verdict section names the
  single highest-leverage fix per
  the escalation ladder above. A
  report that hedges across three
  possible fixes hasn't done the
  prioritization this skill
  exists to do.
- **No auto-retraining.** This
  skill produces a verdict and a
  report, not a re-triggered
  training run. A `REJECT` hands
  the remediation back to a human
  decision at
  `finetuning-method-selection` or
  the relevant training skill.

## Related Skills

- `eval-harness-first` — owns the
  drift suite and baseline this
  skill re-runs and diffs
  against; no `baseline-<model>.json`
  means nothing to gate against.
- `quantized-export` — the only
  valid next step after a
  `PROMOTE` verdict.
- `preference-optimization` and
  `lora-qlora-recipes` — own the
  LR and rank levers in the
  Catastrophic Forgetting
  escalation path; this skill
  diagnoses the breach, those
  skills own the config that
  caused it.
- `dataset-curation` — owns the
  replay-mix construction recipe
  the escalation ladder's first
  rung applies.

Complete `promotion-report.md`
template with all four stages,
the drift-suite scoring table,
the paired-arena protocol (item
count, position randomization,
win-rate threshold), and a
replay-mix configuration example:
`references/gate-templates.md`.

<!-- chapter:end slug=checkpoint-promotion -->

---

<!-- chapter:begin slug=dataset-curation position=101 -->

## 101. dataset-curation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/dataset-curation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/dataset-curation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/dataset-curation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/formats-and-templates.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/dataset-curation/references/formats-and-templates.md
  - `references/synthetic-data.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/dataset-curation/references/synthetic-data.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: dataset-curation
description: Prepare, format, and validate datasets for supervised fine-tuning and preference training. Use when converting raw data into training format, applying chat templates, configuring sequence packing, generating synthetic training data, or writing a dataset card before a run.
---

# Dataset Curation

This skill assumes `finetuning-method-selection`
already routed here — the next step is preparing
data, not choosing a method. What follows: format
selection by target method, the template/packing
mechanics behind the most common silent training
failures, rules for mixing in synthetic data
without collapse, and the dataset card that closes
out Phase 2 before a run starts.

**Input:** raw examples (demonstrations, preference
judgments, or task prompts) plus a routing decision
from `finetuning-method-selection`.
**Output format:** a formatted, packed, validated
JSONL dataset plus a completed dataset card — the
Phase 2 artifact `/finetune` checks before launching
training.

## Format Selection

| Method | Shape | Rows |
|---|---|---|
| SFT, single-turn | Instruct (`instruction`/`response` or `prompt`/`completion`) | ~1,000+ floor |
| SFT, multi-turn | Conversation / ChatML `messages` list | ~1,000+ floor |
| DPO / ORPO | Preference pair (`prompt`, `chosen`, `rejected`) | Method-dependent, see `preference-optimization` |
| KTO | Unpaired (`prompt`, `completion`, `label`) | Method-dependent, see `preference-optimization` |
| GRPO / RLVR | Prompt-only (`prompt` + verifier metadata) | Method-dependent, see `grpo-rlvr-training` |

- **~1,000+ rows is the recommended floor for SFT**,
  not a target. Below it, a handful of low-quality
  or duplicate examples can dominate the gradient;
  above it, **quality over quantity** — a smaller
  verified, deduplicated set beats a larger noisy one.
- The ChatML shape, for orientation; the other four
  formats plus a ShareGPT conversion note live in
  `references/formats-and-templates.md`:

  ```json
  {"messages": [
    {"role": "user", "content": "..."},
    {"role": "assistant", "content": "..."}
  ]}
  ```

## Chat Templates and Loss Masking

Apply the target model's chat template **before**
any concatenation or packing, never after — packing
raw text and templating the packed blob afterward
corrupts turn boundaries, landing role markers in
the wrong place relative to each example.

- **Train on assistant responses only.** Mask the
  loss (`-100` in the labels tensor) over system/user
  turns and the template's own role markers — only
  assistant-turn content tokens contribute to loss.
- **Template/tokenizer mismatches are a top silent
  failure mode.** A model trained against one chat
  template but served or evaluated with a different
  one degrades without erroring. Verify the same
  template string used in training is applied at
  inference and eval time.
- **Keep the dataset in `messages` shape** and let
  the trainer template and mask it
  (`assistant_only_loss=True` in current TRL) —
  pre-rendering to a flat text field destroys the
  turn boundaries masking needs. Full code sketch:
  `references/formats-and-templates.md`. Sanity-check
  before training — decode only unmasked positions;
  expect only assistant text:

  ```python
  keep = batch["labels"][0] != -100
  print(tokenizer.decode(batch["input_ids"][0][keep]))
  ```

## Packing

**Without packing, 40–70% of compute is spent on
padding** — variable-length examples batched at a
fixed sequence length waste the gap between each
example's length and the batch's max. Packing
concatenates multiple examples into one sequence
up to the max length, cutting most of that waste.

- **Packing changes batch semantics.** A packed
  sequence can contain several original examples, so
  "steps per epoch" and any LR schedule keyed to
  example count shift once packing is on — recompute
  schedule milestones against packed-sequence count.
- **MANDATORY: decode and manually inspect 5–10
  packed sequences before scaling to a full run.**
  Confirm example boundaries land where expected,
  template markers are intact per sub-example, and
  the loss mask is still assistant-only within each
  packed sequence. Not optional — packing bugs are
  silent (the loss curve looks normal) and only
  surface in eval quality, hours later:

  ```python
  for seq in packed_dataset.select(range(10)):
      print(tokenizer.decode(seq["input_ids"]))
  ```

## Synthetic Data Rules

- **Keep ≥25% real data as a collapse guard.**
  Training on a growing share of model-generated
  data without a real-data floor drives measurable
  quality collapse over successive generations —
  25% real is the minimum that holds the line.
  **General-domain replay rows
  count toward this floor** —
  "real" means "not generated
  for this task from this
  student," not "human-authored."
  An all-synthetic-by-construction
  dataset can meet the ≥25% floor
  through replay alone (see
  `references/synthetic-data.md`'s
  Replay-Mix Construction recipe);
  state which rows count as "real"
  in the dataset card rather than
  leaving the floor structurally
  unmeetable.
- **Magpie and rejection sampling are the
  workhorses.** Magpie extracts prompts from the
  model's own template prior; rejection sampling
  generates several candidates per prompt and keeps
  only the ones a filter passes. Both beat naive
  single-shot generation.
- **Targeted, student-aware generation beats static
  generation by 1.3–2x sample efficiency** — aiming
  at the student's actual failure modes hits a
  quality bar with fewer filtered examples.
- **Typical accept rates after filtering run
  10–30%.** Plan volume accordingly — a 10,000-row
  target at 15% accept needs ~65,000+ raw generations.
- Generation-method ranking, filter funnel, replay-
  mix construction, and distillation pattern:
  `references/synthetic-data.md`.

## The Dataset Card

Every dataset that reaches training gets a card —
the required Phase 2 artifact `/finetune` checks
before launching. The card is not free-form
documentation; it MUST carry these fields:

- **Provenance** — where every row came from (real
  source(s), synthetic method(s), or both),
  traceable to `trace-to-training-data` output.
- **Counts** — total rows, and rows per split
  (train/eval/held-out) if split.
- **Synthetic/real ratio** — the measured ratio,
  checked against the ≥25% real floor above.
- **Dedup method** — exact-match, semantic
  (embedding threshold), or both; see the filter
  funnel in `references/synthetic-data.md`.
- **Template used** — the exact chat template
  string/identifier, kept consistent through
  inference and eval — this is what ties an
  `eval-harness-first` run back to the checkpoint.
- **Packing config** — whether packing was used,
  max sequence length, and confirmation the
  5–10-sequence manual inspection above was done.

A dataset missing any of these six fields isn't
ready for `/finetune` — the card is a gate, not a
summary written after the fact.

### Phase 2 Exit Checklist

Before handing off to `/finetune`, confirm:

1. Format matches the method (table above).
2. Template applied before concatenation.
3. Loss masked to assistant turns only.
4. 5–10 packed sequences decoded and read.
5. ≥25% real data in the final mix.
6. Dataset card complete — all six fields.

## References

- `references/formats-and-templates.md` — JSONL
  examples per format, current-TRL masking code,
  and the ShareGPT conversion note.
- `references/synthetic-data.md` — generation-method
  ranking, filter funnel, replay-mix construction,
  and teacher→student distillation pattern.

Related skills: `finetuning-method-selection` routes
here; `lora-qlora-recipes`, `vision-sft`, and
`preference-optimization` consume the datasets this
skill produces; `trace-to-training-data` is the
provenance source for graded-trajectory datasets;
`eval-harness-first` grades the resulting checkpoint.

<!-- chapter:end slug=dataset-curation -->

---

<!-- chapter:begin slug=eval-harness-first position=102 -->

## 102. eval-harness-first

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/eval-harness-first/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/eval-harness-first/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/eval-harness-first.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/grader-templates.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/eval-harness-first/references/grader-templates.md
  - `references/judge-calibration.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/eval-harness-first/references/judge-calibration.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: eval-harness-first
description: Build the evaluation harness that gates every fine-tuning run — golden sets, per-failure-mode graders, judge calibration, and base-model baselines. Use when starting a fine-tuning effort, when converting traces into an eval set, or when calibrating a judge against human labels.
---

# Eval Harness First

The Phase 0 gate for the whole plugin:
`finetuning-method-selection` and every downstream
skill assume this harness exists before a training
config gets written. The harness is not a run-end
side artifact — it is the data-curation engine. The
same labeled traces that build the goldens feed
training data, minus an explicit holdout.

**Input:** production/agent traces if they exist, or
a task spec if they don't, plus labelers willing to
grade ≥100 examples.
**Output format:** the `eval/` directory below —
goldens, graders, drift suite, and the base-model
baseline that later phases gate on.

## The Gate

No eval harness, no fine-tune. Skip to a training
config and there is nothing to measure against,
nothing to catch regressions, and no labeled data
to train on. The flywheel:

1. **Collect traces** — production/agent spans, or
   synthetic tasks if none exist yet.
2. **Error analysis** — open coding on ≥100 traces,
   axial coding into 4–8 failure buckets.
3. **One grader per bucket** — deterministic first;
   calibrated LLM-judge only for genuinely
   subjective criteria.
4. **Prioritize** by frequency × severity × value.
5. **The labeled traces feed dataset curation, minus
   an explicit holdout.** Every `eval/goldens.jsonl`
   ID stays excluded from training data by ID.
6. **Train.**
7. **Re-run the same harness** on the checkpoint —
   not a different, looser one.
8. **Drift detection feeds back to step 2** — new
   production failure modes re-open error analysis.

Steps 2–4 build the harness; steps 5–8 are why it
must exist first — it is both the training data
source and the checkpoint's exit gate.

## Building Goldens

- **From traces, when they exist:** run error
  analysis — open coding on ≥100 real traces (read
  them, tag failures in your own words, no fixed
  taxonomy yet), then axial coding to collapse those
  tags into 4–8 named failure buckets. Fewer than 4
  means the coding pass was too shallow; more than 8
  means buckets need merging. **Exception:**
  single-failure-surface tasks (e.g. strict-schema
  extraction) may land at 1–2 buckets with per-field
  sub-metrics inside one grader — don't invent
  artificial splits with no evidence behind them.
- **Synthetic, when traces don't exist yet:**
  dimension-based generation — enumerate the axes
  that matter (task type, difficulty, edge case,
  persona) and sample the cross-product; free-
  generated prompts cluster around whatever's
  easiest to write.
- **Goldens are versioned like code** — commit
  `eval/goldens.jsonl`, diff it in review, tag it per
  release. It doubles as the CI regression suite.

## Graders

One grader per failure bucket from error analysis —
not one for the whole eval set. A single blended
score hides which bucket regressed.

- **Deterministic first.** Regex, schema validation,
  or execution checks are cheaper, reproducible, and
  need no calibration.
- **LLM-judge only for genuinely subjective
  criteria** — tone, faithfulness, "which response
  is better" — where no deterministic check can
  express it.
- **Binary pass/fail over Likert.** A 1–5 or 1–10
  scale is noisier to calibrate and harder to apply
  consistently; collapse to pass/fail.
- **Drift-suite MMLU-style scoring: prefer logprob
  over generate-and-extract** — a tight token budget
  makes generate-and-extract parse-brittle for models
  that preamble, conflating format compliance with
  the knowledge being measured. Templates for all
  four grader shapes and this scoring note:
  `references/grader-templates.md`.

## Judge Calibration Is a Prerequisite

Any bucket routed to an LLM-judge needs calibration
before its verdicts count for anything beyond
exploration — a hard prerequisite, not a
nice-to-have. **N/A when no bucket routes to a
judge** — an all-deterministic harness has nothing
to calibrate; state that rather than leaving this
section unaddressed.

- Label ≥100 items, split **train**/**dev**/**sealed
  test** (report once, no re-touching after).
- Report **TPR and TNR**, not one blended accuracy
  number — a judge can hit 90% by always saying
  "pass" on a skewed set.
- **Pin the judge to a fixed model snapshot** and
  recalibrate on judge-model change, quarterly
  regardless.
- **The judge must come from a different model family
  than the model under test.**
- A judge that misses the agreed TPR/TNR bar ships
  **advisory-only** — flags for human review, never
  gates a promotion. Full protocol, bias correction,
  and recalibration checklist:
  `references/judge-calibration.md`.

## The Baseline

Before Phase 1 (method selection) starts, run the
full harness — goldens plus the capability-drift
suite — against the unmodified base model. This is
the number every later checkpoint gets compared
against.

`eval/baseline-<model>.json` is the gate token. No
baseline file, no comparison basis for
`checkpoint-promotion` — a checkpoint that "looks
better" against nothing measured isn't a finding.

## Directory Contract

```
eval/
├── goldens.jsonl          # labeled traces + synthetic goldens, versioned
├── graders/                # one module per failure bucket
│   ├── schema_compliance.py
│   ├── exact_match.py
│   └── rubric_judge.py
├── drift-suite.yaml        # frozen benchmarks + 200-500 domain-adjacent items
└── baseline-<model>.json   # gate token: harness + drift suite vs the base model
runs/
└── <run-id>/
    └── results.json         # per-run harness output, one per checkpoint
```

`eval/` persists across runs and lives outside
`runs/` — the fixed measuring stick, not a run
artifact. `runs/` is disposable; `eval/` is not.
Never let a run script write into `eval/`. **Canonical
location:** every per-trace `results.json` — the
Phase 0 baseline included — lives at
`runs/<run-id>/results.json`, never under
`eval/runs/...`; an instruction requesting the
latter is wrong, not this contract.

### Phase 0 Exit Checklist

Before `finetuning-method-selection`, confirm:

1. ≥100 traces open-coded; 4–8 failure buckets (N/A
   floor for synthetic goldens on a single-failure-
   surface task — see the Building Goldens exception;
   bucket count then comes from post-baseline error
   analysis instead).
2. `eval/goldens.jsonl` committed and versioned.
3. One grader per bucket, deterministic first.
4. Judges calibrated — TPR/TNR, snapshot pinned,
   different family (**N/A when no bucket routes to
   an LLM-judge**; state that explicitly).
5. `eval/drift-suite.yaml` frozen.
6. `eval/baseline-<model>.json` written.

Missing any of the six (or its stated N/A)? Not
Phase 0 complete — `/finetune` checks the baseline
file before a run.

## Related Skills

General-purpose evaluation guidance (dashboards, A/B
testing, non-fine-tuning harnesses) lives in the
`llm-application-dev` plugin's `llm-evaluation`
skill — this skill covers only the fine-tuning
coupling: goldens that double as training data, and
the baseline that gates a checkpoint.

- `finetuning-method-selection` — routes here first.
- `dataset-curation` — formats these traces into
  training rows.
- `trace-to-training-data` — turns graded traces into
  training examples.
- `checkpoint-promotion` — consumes
  `baseline-<model>.json`, re-runs this harness on
  each candidate checkpoint.

## References

- `references/grader-templates.md` — runnable grader
  examples per shape, plus a `drift-suite.yaml`
  example and MMLU logprob-scoring note.
- `references/judge-calibration.md` — the
  calibration protocol, including the all-
  deterministic N/A path.

<!-- chapter:end slug=eval-harness-first -->

---

<!-- chapter:begin slug=finetuning-method-selection position=103 -->

## 103. finetuning-method-selection

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/finetuning-method-selection/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/finetuning-method-selection/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/finetuning-method-selection.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/memory-math.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/finetuning-method-selection/references/memory-math.md
  - `references/model-catalog.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/finetuning-method-selection/references/model-catalog.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: finetuning-method-selection
description: Decide whether to fine-tune at all, and route to the right method (SFT, DPO/ORPO/KTO, GRPO/RLVR, continued pretraining) and base model. Use when starting any fine-tuning effort, when unsure whether RAG or prompting would suffice, or when choosing between preference-optimization and reinforcement methods.
---

# Fine-Tuning Method Selection

This is the router skill for the fine-tuning
lifecycle: it decides whether fine-tuning is the
right tool at all, and if so, which method and
which base-model size class. Every other skill
in this plugin assumes this routing already
happened — start here before opening
`lora-qlora-recipes`, `preference-optimization`,
or `grpo-rlvr-training`.

## When to Use This Skill

- Starting any fine-tuning effort, before a
  framework or base model has been chosen.
- Unsure whether RAG or prompt engineering would
  solve the problem more cheaply than training.
- Choosing between preference optimization (DPO
  family) and a reinforcement method (GRPO/RLVR)
  for the same underlying task.
- Sizing a candidate model/method combination
  before committing to a run.

## Quick Reference

| Situation | Route |
|---|---|
| Facts change often (prices, docs, news) | RAG, not fine-tuning |
| Desired behavior still being figured out | Prompt engineering |
| Stable domain knowledge, ≥500MB text | CPT then SFT — see Off-Ramps First |
| Have input/output demonstrations | SFT — see `lora-qlora-recipes` |
| Have preference pairs or thumbs-up/down | DPO/ORPO/KTO — see `preference-optimization` |
| Have a verifiable pass/fail signal | GRPO+RLVR — see `grpo-rlvr-training` |
| No eval harness yet | Stop — see `eval-harness-first` |

## Off-Ramps First

Most requests that sound like "fine-tune this"
are served better and cheaper elsewhere. Check
these off-ramps before opening a training run:

- **Knowledge-bound and volatile** (the gap is
  facts that change — prices, docs, current
  events): route to RAG, not fine-tuning. A
  fine-tuned model bakes in a snapshot; volatile
  facts go stale immediately.
- **Behavior-bound and shifting** (the desired
  behavior is still being figured out, or
  changes per request): route to prompt
  engineering. Fine-tuning locks in a behavior;
  don't lock in one that hasn't stabilized yet.
- **Stable, dense domain knowledge**: this is
  where continued pretraining (CPT) enters, sized
  by how much domain text exists:

| Domain text volume | Route |
|---|---|
| <10MB | RAG only |
| 10MB–500MB | RAG + fine-tune |
| 500MB–10GB | CPT, then SFT |
| >10GB | CPT required |

CPT learning rate ≈ **10% of the pretraining
LR**. CPT is guidance-only in this plugin —
sizing and LR guidance live here, but this
plugin does not execute a CPT run.

## Method Router

Once the off-ramps are ruled out, this is the
full decision tree (verbatim from the research
this plugin is built on):

```
New FACTS?  volatile → RAG | stable+dense → CPT (LR ~10% of pretrain) → SFT
New BEHAVIOR? shifting → prompt-engineering | stable:
  demos → SFT (LoRA/QLoRA, all-linear, α=2r)
  preference pairs → DPO (SimPO if length-bias, ORPO if memory-bound)
  unpaired 👍/👎 → KTO
  verifiable success → RLVR + GRPO (DAPO/GSPO/Dr.GRPO per failure mode)
Deploy: FP8 (Hopper+) | NVFP4 (Blackwell scale) | AWQ (older) | GGUF+imatrix (edge)
BEFORE ANY OF THIS: the eval harness must exist first.
```

Read the tree top-down: answer "new facts or new
behavior," then follow the branch that matches
the data shape in hand (demos, preference pairs,
thumbs up/down, or verifiable success/failure).
The data shape picks the method — not the other
way around.

### Worked Routing Examples

- *"Users want the assistant to follow our
  support macros exactly."* Behavior is stable
  and demonstrable from transcripts → demos →
  **SFT**.
- *"We have pairs of good/bad responses from
  reviewer thumbs-up/down, unpaired."* → unpaired
  signal → **KTO**, not DPO (DPO needs paired
  preferences).
- *"The model can already solve some of these
  math problems and we can grade correctness
  automatically."* → verifiable success signal →
  **GRPO+RLVR**, and only after confirming the
  model succeeds at least sometimes (see Key
  Routing Facts below).
- *"We want the model to know this week's
  pricing page."* → volatile facts → **RAG**, no
  training run at all.

## Key Routing Facts

- **Loss-function choice is low-leverage.** A
  240-H100-run study found method choice worth
  ~1 percentage point versus ~50 points for model
  scale, and zero of 20 DPO variants beat vanilla
  DPO. Don't spend a routing decision agonizing
  over DPO-variant selection — spend it on
  getting the data shape and scale right.
- **DPO is for taste, GRPO+RLVR is for
  reasoning.** Preference pairs that encode a
  subjective judgment (tone, style, "which answer
  is better") route to DPO. Tasks with a
  verifiable pass/fail signal (math, code, tool
  calls) route to GRPO+RLVR instead.
- **RL is not the fix for a model that never
  succeeds.** GRPO and other RL methods sharpen
  an existing capability — they don't teach one
  from zero. If the model doesn't yet understand
  the task or output format, run SFT first; only
  bring in RL once the model succeeds at least
  sometimes.

### Common Routing Mistakes

- Reaching for fine-tuning to fix facts that
  change weekly — that's a RAG problem, and
  fine-tuning will just go stale faster than the
  source data does.
- Picking a DPO variant before checking whether
  the actual bottleneck is data quality or model
  scale — variant choice is the ~1pp lever, not
  the ~50pp one.
- Starting an RL run on a model that fails every
  rollout — route to SFT first so RL has
  something to sharpen.
- Treating CPT as the default for "the model
  doesn't know our domain" — check the data
  volume thresholds first; under 500MB, RAG or
  RAG+fine-tune iterates faster than a CPT run.

## Model Selection

Base-model choice is size-class first, family
second, and it goes stale fast — so it lives in
exactly one place: `references/model-catalog.md`.
That file is the only place in this plugin (and
in the DGX Spark ops plugin) that names a base
model family. Neither this skill nor
`references/memory-math.md` names one; both
describe models by size class only (for example,
"8B-class LoRA," not a model name).

The catalog is dated on purpose — model rankings
turn over quarterly. It carries a "last verified"
date and a refresh checklist. Before trusting a
row, check that date; if stale, work the refresh
checklist in the catalog before recommending a
model from it.

**Precedence when the catalog and a method skill
disagree:** the catalog's per-row Notes column
states hardware/size-class *feasibility*, not a
method recommendation — `lora-qlora-recipes`'s
LoRA vs QLoRA vs Full FT table (routed by task
shape) governs the actual method choice.

## Memory Feasibility

Before committing to a method, size it: total
memory ≈ **params × dtype bytes + optimizer
state + gradients + activations**. Work each
term for the chosen dtype and method (full
fine-tune, LoRA, or QLoRA) — worked worksheets
and size-class examples live in
`references/memory-math.md`.

On DGX Spark specifically, unified-memory
behavior breaks the naive estimate (transient
load peaks, `nvidia-smi` underreporting, thermal
throttling on long runs). Once the
`dgx-spark-ops` plugin is installed, defer
Spark-specific feasibility calls to its
`spark-memory-thermal-ops` skill rather than
re-deriving them here.

## Related Skills

Once this skill has picked a method, hand off to
the skill that executes it:

- `lora-qlora-recipes` — SFT via LoRA/QLoRA
- `preference-optimization` — DPO, ORPO, KTO
- `grpo-rlvr-training` — GRPO with verifiable
  rewards

No method is selected before the eval harness
exists — see `eval-harness-first`.

<!-- chapter:end slug=finetuning-method-selection -->

---

<!-- chapter:begin slug=grpo-rlvr-training position=104 -->

## 104. grpo-rlvr-training

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/grpo-rlvr-training/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/grpo-rlvr-training/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/grpo-rlvr-training.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/grpo-memory.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/grpo-rlvr-training/references/grpo-memory.md
  - `references/reward-functions.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/grpo-rlvr-training/references/reward-functions.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: grpo-rlvr-training
description: Train reasoning and verifiable-task behavior with GRPO and reinforcement learning from verifiable rewards (RLVR). Use when task success is algorithmically checkable (math, code, tool calls, structured output), when designing GRPO reward functions, or when a GRPO run diverges or reward-hacks.
---

# GRPO & RLVR Training

This skill assumes `finetuning-method-selection`
already routed here because the target behavior
has a verifiable pass/fail signal — not
demonstrations (`lora-qlora-recipes`) or
preference pairs (`preference-optimization`).
What follows is when RL is the right tool, the
reference recipe, the mandatory reward-inspection
gate, and how to pick a GRPO variant when the
base recipe misbehaves.

**Input:** a routing decision (RLVR via GRPO)
plus a verifier (code executor, test suite,
schema checker, or grader) for the target task.
**Output format:** a validated GRPO config — the
kwarg values in `references/grpo-memory.md` and
the reward functions in
`references/reward-functions.md`, not free-form
advice — that `llm-finetuning-training-engineer`
consumes directly.

## When RL Applies

GRPO+RLVR only pays off when task success is
**algorithmically checkable** — a unit test
passes, a parser accepts the output, a tool call
matches an expected schema, a math answer matches
a ground truth. If grading the output requires
human judgment or a subjective rubric, that's an
eval-harness and judge-calibration problem first
— see `eval-harness-first` — not a reason to skip
straight to RL.

Before opening a GRPO run, confirm the model can
**sometimes** succeed on the target task already.
RL sharpens an existing capability by reweighting
toward the samples that already work; it does not
install a capability from zero.

- **The model never succeeds, even at low
  temperature across many samples:** the gap is
  format or task understanding, not policy
  refinement. Route back to SFT first
  (`lora-qlora-recipes`) and only return to this
  skill once the base success rate is nonzero.
- **The model succeeds sometimes,
  inconsistently:** this is the GRPO sweet spot —
  proceed to The Recipe below.

The standing rule for the whole plugin: **DPO for
taste, GRPO for reasoning.** If the signal is a
preference between two acceptable outputs, that's
`preference-optimization`, not this skill.

## The Recipe

The reference recipe is TRL's `GRPOTrainer` with
vLLM-backed generation:

```python
from trl import GRPOConfig, GRPOTrainer

grpo_args = GRPOConfig(
    output_dir="./outputs-grpo",
    use_vllm=True,
    vllm_mode="colocate",       # single GPU; "server" for multi-GPU
    num_generations=8,          # floor — fewer starves the group-relative baseline
    learning_rate=5e-7,         # settled range for GRPO
    beta=0.01,                  # KL coefficient vs the reference policy
    per_device_train_batch_size=8,
    gradient_accumulation_steps=4,
    bf16=True,
    logging_steps=10,
    seed=3407,
)

trainer = GRPOTrainer(
    model=SFT_CHECKPOINT,
    args=grpo_args,
    reward_funcs=[format_reward, correctness_reward],   # references/reward-functions.md
    train_dataset=prompts,       # prompt-only — GRPO generates its own completions
    processing_class=tokenizer,
)

trainer.train()
```

- **`vllm_mode="colocate"`** runs generation and
  training on the same GPU — the default for a
  single-GPU box.
- **`vllm_mode="server"`** points at a separate
  vLLM server process and is the multi-GPU path —
  generation and training don't compete for the
  same device.
- **`num_generations` ≥ 8** is a floor, not a
  suggestion: GRPO's advantage estimate is
  relative to the group mean, and fewer than 8
  samples per prompt produces a noisy baseline.
- **Reward is composite** — a format reward (did
  the output parse / match the required
  structure) plus a correctness reward (did the
  answer verify). A well-formed-but-wrong answer
  and a malformed one should not score
  identically; correctness alone loses that
  signal.
- **`learning_rate=5e-7`** and **`beta=0.01`** are
  the settled starting point; deviate only after
  the base run is stable and reward-inspected
  (below).

Memory sizing for this recipe by target size
class: `references/grpo-memory.md`.

## The Inspection Rule

**Run the reward function against 50–100 sampled
outputs and manually read the results before
starting the actual training run.** This is a
gate, not a one-time sanity check.

If the reward function's judgment disagrees with
a human reading of that sample, fix the reward
function first. Training against an uninspected
reward, or tuning hyperparameters to compensate
for one silently scoring the wrong thing, is how
a run reward-hacks: the model optimizes cleanly
toward the wrong target, and that doesn't surface
as a training-loop bug.

This inspection is a Phase 1 gate input for
`/finetune` — the same 50–100-sample read that
catches a broken reward function here is what that
command checks for before it lets a GRPO brief
proceed.

Complete reward function implementations to
inspect against — exact-match, schema-validation,
unit-test-execution, a length-penalty wrapper, and
a rubric-as-reward judge pattern:
`references/reward-functions.md`.

## Variant Selection

The base recipe above is the default. Reach for a
variant only when a specific failure mode shows
up, not preemptively:

| Failure mode | Variant | Why |
|---|---|---|
| Entropy collapse / degenerate long chain-of-thought | **DAPO** | Decouples clip bounds and relaxes the KL penalty that over-regularizes exploration on long reasoning traces |
| Reward or output length trends up regardless of quality | **Dr.GRPO** | Removes GRPO's length-normalization bias so reward tracks correctness, not completion length |
| Training a mixture-of-experts model | **GSPO** | Moves the importance-sampling ratio to the sequence level instead of per-token — per-token ratios are unstable on MoE routing, so GSPO is required here, not optional |

Start with plain GRPO. Watch for the specific
symptom — collapsing entropy on long CoT, a
length-reward correlation, or MoE instability —
and only then swap in the matching variant above.
Don't pre-select a variant before the base recipe
has actually shown the failure mode.

## VLM RL Is Reference-Only

Vision-language RL is **not executed by this
plugin in v1** — it's documented here for
context, not as a runnable path. Tooling is
fragmented across ms-swift and EasyR1-derived
forks with no one-line TRL command yet, and naive
text-only GRPO applied to a VLM tends to
reward-hack by optimizing the text-reasoning trace
while ignoring the image — the model learns to
sound right without looking at the input. A VLM
RL run is a research spike outside this skill's
supported recipe, not a variant of The Recipe
above.

## References

- `references/reward-functions.md` — complete
  Python reward functions (exact-match
  correctness, schema validation, unit-test
  execution, a length-penalty wrapper, and a
  rubric-as-reward judge pattern) to inspect under
  The Inspection Rule before any training run.
- `references/grpo-memory.md` — memory sizing by
  target size class, vLLM sleep-mode and
  optimizer-state tactics, Unsloth's long-context
  RL chunking, and the DGX Spark bandwidth caveat
  for decode-heavy rollouts.

Related skills: `finetuning-method-selection`
routes here once a verifiable pass/fail signal
exists; `preference-optimization` is the sibling
skill for preference pairs rather than verifiable
rewards; `eval-harness-first` covers judge
calibration for any reward that isn't purely
code-checkable. On DGX Spark, defer to the
`dgx-spark-ops` plugin's skills, when installed,
for the memory/thermal remediation ladder this
skill's memory table doesn't cover.

<!-- chapter:end slug=grpo-rlvr-training -->

---

<!-- chapter:begin slug=lora-qlora-recipes position=105 -->

## 105. lora-qlora-recipes

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/lora-qlora-recipes/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/lora-qlora-recipes/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/lora-qlora-recipes.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/hyperparameters.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/lora-qlora-recipes/references/hyperparameters.md
  - `references/unsloth-trl-mapping.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/lora-qlora-recipes/references/unsloth-trl-mapping.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: lora-qlora-recipes
description: Configure LoRA and QLoRA supervised fine-tuning with current best-practice hyperparameters. Use when writing or reviewing a LoRA/QLoRA training configuration, choosing rank/alpha/target modules, or deciding between LoRA, QLoRA, and full fine-tuning.
---

# LoRA & QLoRA Recipes

This skill assumes the routing decision already
happened — `finetuning-method-selection` should
have already pointed here because the data shape
is demonstrations (SFT), not preference pairs or
a verifiable reward signal. What follows is the
current best-practice recipe for configuring the
adapter itself: which modules to target, how to
size rank and alpha, what learning rate to use,
and when QLoRA buys real headroom versus when it
just adds risk. Dataset preparation and quality
checks are a separate concern — see
`dataset-curation`.

**Input:** a routing decision (SFT via LoRA/
QLoRA) plus a target size class.
**Output format:** a validated adapter config —
the kwarg values below, not free-form advice —
that `llm-finetuning-training-engineer` consumes
directly when it generates a runnable script.

## The Reference Recipe

The reference recipe is "LoRA Without Regret"
(Thinking Machines/Schulman, 2025-09), now the
settled convention for LoRA/QLoRA SFT.

### Target Modules

Target **all-linear** modules, not just
attention:

```python
target_modules = [
    "q_proj", "k_proj", "v_proj", "o_proj",   # attention
    "gate_proj", "up_proj", "down_proj",      # MLP — matters most
]
```

The MLP layers (`gate_proj`, `up_proj`,
`down_proj`) matter most — attention-only
targeting was the older, weaker convention.
Dropping modules to save memory is a Failure
Mode below, not a valid optimization.

### Alpha and Learning Rate

- **`lora_alpha = 2 * r`** is the settled
  convention (NeurIPS 2025 "intruder dimensions"
  result). Don't hand-tune alpha independently of
  rank — derive it from rank every time.
- **LoRA learning rate ≈ 10x the equivalent
  full-fine-tune LR.** For QLoRA specifically,
  **2e-4** is the standard starting point. Full
  hyperparameter tables and worked examples:
  `references/hyperparameters.md`.

### Rank by Task

Rank is task-shaped, not a single global default:

| Task | Rank |
|---|---|
| RL (GRPO/RLVR adapters) | 1–32 |
| General default | 16–32 |
| SFT at scale | up to ~256 |

Higher rank isn't automatically better — it
raises capacity to memorize as fast as it raises
capacity to generalize. Start at the row matching
the task, and only move up a row if the lower
rank measurably underfits on held-out eval, not
as a default hedge.

### Effective Batch Size

Keep **effective batch size under 32**. This
recipe was validated at that scale — pushing
effective batch higher is an untested
extrapolation, not a free throughput win.

## Unsloth Defaults

Unsloth is the reference implementation this
plugin assumes as the default fast path — except
for messages-shaped conversational SFT with
`assistant_only_loss=True`, where Unsloth
2026.7.x's compiled trainer has no messages-shaped
path at all and the plain-TRL escape hatch
(`references/unsloth-trl-mapping.md`) is the
default for that combination, not a rare-regression
fallback. Its out-of-the-box defaults, and why
each one is set that way:

- **`lora_dropout=0`** — the optimized kernel
  path assumes zero dropout; setting a nonzero
  value forfeits the fused-kernel speedup.
- **`bias="none"`** — bias terms add adapter
  parameters for negligible quality gain at this
  rank range.
- **`use_gradient_checkpointing="unsloth"`** —
  Unsloth's checkpointing variant, not vanilla HF
  checkpointing; saves roughly **30% VRAM** over
  no checkpointing.
- **`optim="adamw_8bit"`** — 8-bit AdamW cuts
  optimizer-state memory with negligible quality
  impact at LoRA/QLoRA adapter scale.
- **`random_state`** fixed — pins LoRA
  initialization for reproducibility across runs;
  treat it like any other seed, not a tunable.

These show up together on the `get_peft_model`
call:

```python
model = FastLanguageModel.get_peft_model(
    model,
    r=32,
    target_modules=target_modules,
    lora_alpha=64,               # 2 * r
    lora_dropout=0,
    bias="none",
    use_gradient_checkpointing="unsloth",
    random_state=3407,
)
```

Exact kwarg names and their plain-TRL/PEFT
equivalents, plus a full worked config including
`SFTConfig`: `references/unsloth-trl-mapping.md`
and `references/hyperparameters.md`.

## LoRA vs QLoRA vs Full FT

| Situation | Default choice |
|---|---|
| Adapting behavior on demonstrations | LoRA |
| Base model doesn't fit in bf16 at target rank | QLoRA |
| Injecting dense new domain knowledge | Full FT (see `finetuning-method-selection`) |
| Unsure which one | LoRA — upgrade to QLoRA only if memory forces it |

- **QLoRA** = NF4-quantized frozen base weights +
  BF16 adapters. This is what makes a 65B-class
  model trainable on 48GB — the quantized base
  is the memory win, not the adapter itself.
- **Full fine-tuning is not a default.** Reserve
  it for dense knowledge injection where the goal
  is changing what the model knows at the weight
  level, not adapting a behavior. For everything
  else in this skill's scope, LoRA or QLoRA is
  the starting assumption.
- **On DGX Spark, QLoRA can OOM before an
  equivalent bf16 LoRA run would**, even though
  QLoRA's steady-state footprint is smaller —
  bitsandbytes dequantization buffers are
  transient CUDA-side allocations that spike
  during load. A QLoRA OOM is not proof the model
  doesn't fit; the `dgx-spark-ops` plugin's
  `spark-memory-thermal-ops` skill covers the
  full OOM remediation ladder (bf16 LoRA is the
  next thing to try, not a further QLoRA
  shrink).

## Failure Modes

- **fp16 divergence on non-BF16 GPUs.** Training
  in fp16 on hardware that doesn't have solid
  BF16 support is a known source of loss spikes
  and silent divergence. Force `bf16=True`
  wherever the hardware supports it; don't fall
  back to fp16 as if it were equivalent. Check
  hardware support before picking a dtype:

  ```bash
  python -c "import torch; print(torch.cuda.is_bf16_supported())"
  ```

- **Rank too high on a small dataset overfits.**
  A rank picked for "SFT at scale" (up to ~256)
  on a dataset that doesn't have scale behind it
  memorizes rather than generalizes. Match rank
  to the Rank by Task table above, not to the
  largest number available.
- **Removing target modules to save memory costs
  quality for negligible savings.** The adapter
  parameters on `gate_proj`/`up_proj`/`down_proj`
  are a small fraction of total model size — cutting
  them barely moves memory but measurably hurts
  quality. If memory is tight, move to QLoRA or
  reduce rank/batch/pack length before trimming
  target modules.

All three failure modes share a pattern: they
look like a training-loop bug (loss spikes,
plateaus, memorization) but are actually a
config choice that contradicts the reference
recipe above. Check configuration against this
skill before debugging the training loop itself.

## References

- `references/hyperparameters.md` — full rank/
  alpha/LR tables by task type, rsLoRA notes,
  batch/packing interactions, and a complete
  worked Unsloth config block.
- `references/unsloth-trl-mapping.md` — every
  Unsloth kwarg mapped to its TRL/PEFT
  equivalent, current TRL API notes, and the
  escape-hatch rule for when to drop back to
  plain TRL.

Related skills: `finetuning-method-selection`
routes here; `dataset-curation` covers the data
side this skill doesn't; `llm-finetuning-training-engineer`
is the downstream consumer of the config this
skill produces.

<!-- chapter:end slug=lora-qlora-recipes -->

---

<!-- chapter:begin slug=preference-optimization position=106 -->

## 106. preference-optimization

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/preference-optimization/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/preference-optimization/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/preference-optimization.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/method-configs.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/preference-optimization/references/method-configs.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: preference-optimization
description: Align a fine-tuned model with preference data using DPO, ORPO, KTO, or SimPO. Use when preference pairs or thumbs-up/down feedback exist, when choosing between preference-optimization methods, or when a DPO run needs hyperparameters or debugging.
---

# Preference Optimization

This skill assumes `finetuning-method-selection`
already routed here because the data shape is
preference pairs or unpaired thumbs-up/down
feedback, not demonstrations (that's
`lora-qlora-recipes`) or a verifiable reward
signal (that's `grpo-rlvr-training`). What
follows is method selection among the DPO family,
the evidence for how much that selection actually
matters, the production training pattern, and how
to build the pairs in the first place.

**Input:** a routing decision (preference
optimization) plus preference pairs or unpaired
feedback, usually from an SFT checkpoint.
**Output format:** a validated method choice plus
a config — the kwarg values in
`references/method-configs.md`, not free-form
advice — that `llm-finetuning-training-engineer`
consumes directly.

## Method Selection

| Data shape | Method | Key parameters |
|---|---|---|
| Preference pairs, default case | **DPO** | β=0.1, LR 5e-7–1e-6, 1–2 epochs |
| Memory-bound or no SFT checkpoint | **ORPO** | reference-free, fused SFT+preference in one loss |
| Unpaired thumbs-up/down | **KTO** | binary label per example, no pairing needed |
| Length bias observed, sweep budget available | **SimPO** | reference-free; see sweep grid below |

- **DPO is the safe default.** Use β=0.1 and a
  learning rate of 5e-7 to 1e-6 for 1–2 epochs.
  This LR is *lower* than the SFT LR that produced
  the checkpoint being aligned — porting an SFT-
  scale LR into a DPO run is the most common
  misconfiguration here, not an edge case.
- **ORPO** routes in when memory is the
  constraint, or when there's no separate SFT
  checkpoint to start from — it's reference-free
  and fuses the SFT and preference objectives into
  one loss, skipping the separate SFT pass and the
  reference-model memory cost DPO carries.
- **KTO** routes in when feedback is unpaired
  binary signal (thumbs-up/down) rather than
  matched preference pairs — don't force unpaired
  feedback into synthetic pairs to use DPO instead.
- **SimPO** fixes DPO's length bias but only pays
  off with disciplined sweeping — its published
  gains are a ceiling reported under a tuned sweep,
  not a baseline any single config will reproduce.
  Route here only when there's sweep budget; use
  DPO instead if there isn't.
- **Classic RLHF (reward model + PPO) is retired**
  outside frontier labs. Don't reach for it in a
  production pipeline — every method above is
  cheaper and better-supported for the same data
  shapes.

### Worked Examples

- *"We have an SFT checkpoint and clean paired
  preference data, no length-bias complaints yet."*
  → default case → **DPO** at β=0.1.
- *"Reviewers click thumbs-up/down per response;
  nothing is paired."* → unpaired signal →
  **KTO**, not DPO — don't synthesize pairs to
  force DPO onto unpaired data.
- *"GPU budget doesn't cover a separate SFT pass
  plus a DPO reference model."* → memory-bound,
  no separate checkpoint → **ORPO**.
- *"DPO output favors longer answers regardless of
  quality, and there's time to run a sweep."* →
  length bias plus sweep budget → **SimPO**. Skip
  it if the sweep budget isn't actually there.

## The Low-Leverage Truth

A 2026 240-H100-run study (arXiv 2603.19335) is
the load-bearing evidence behind the table above:
**loss-function choice is worth roughly 1
percentage point of leverage, model scale is
worth roughly 50.** Zero of 20 DPO variants tested
beat vanilla DPO. Rankings also **invert with
scale** — a variant that wins in a small pilot can
lose at deployment size.

Two practical consequences:

- Don't spend a routing decision agonizing over
  DPO-variant bake-offs. The table above is
  sufficient; deeper variant selection is
  low-leverage compared to data quality and scale.
- **Validate at deployment scale before trusting a
  ranking.** A method comparison run on a small
  pilot model doesn't transfer to the production
  size class — re-check the winner once scale
  changes.

This is also why the Method Selection table above
is deliberately short: it encodes the ~1pp lever,
not a ranking of DPO variants that the same study
shows doesn't hold up across scale. Treat any
variant-selection advice that isn't in that table
— including advice that claims a specific variant
"wins" — as unproven until it's been validated at
the target deployment size.

## Production Pattern: Iterative On-Policy DPO

A single offline DPO pass on a static preference
dataset is a starting point, not the production
pattern. The policy drifts away from the
distribution the pairs were sampled from as
training proceeds, and a static dataset goes stale
against that drift. Production pipelines run DPO
iteratively and on-policy instead:

1. Sample completions from the current policy
   checkpoint.
2. Score or rank the completions (reward model,
   judge, or task grader).
3. Run a DPO pass using the current checkpoint as
   the reference model.
4. The resulting checkpoint becomes both the new
   policy *and* the new reference for the next
   round.

Repeat. Each round's reference model is the prior
round's output, not a fixed initial checkpoint —
that's what keeps the preference signal on-policy
instead of scoring against an increasingly stale
distribution.

A single-pass DPO run is still a reasonable first
iteration — it just isn't the whole pipeline. Plan
for at least one more round once the first
checkpoint exists, rather than treating pass one
as the finished artifact.

## Pair Construction

Build DPO/ORPO pairs from **same-task
passing-vs-failing trajectories** — two attempts
at the same underlying task, not unrelated
best-and-worst examples pulled from different
tasks. Within that trajectory set, select the
rejected member at **μ−2σ of the reward
distribution, never the minimum**. Naive
best-vs-worst pair construction (max reward vs.
absolute minimum) degrades as scale increases; the
μ−2σ selection is more robust to the same scale
sensitivity the low-leverage study surfaced above.

```
sorted_by_reward = sort(trajectories, key=reward)
chosen   = sorted_by_reward[-1]                # highest reward
mu, sigma = mean(rewards), stdev(rewards)
rejected = closest(sorted_by_reward, mu - 2 * sigma)
# NOT sorted_by_reward[0] — the absolute minimum
# is the naive best-vs-worst construction that
# degrades as scale increases.
```

For the mechanics of turning graded traces into
these pairs — including rejection sampling and
judge-scored delta selection — see
`trace-to-training-data`.

## References

Complete TRL config blocks per method —
`DPOConfig`, `ORPOConfig`, `KTOConfig`, and the
SimPO sweep grid — plus Unsloth wrappers and a
catastrophic-forgetting note live in
`references/method-configs.md`. Those configs use
the same current-TRL API conventions established
in `lora-qlora-recipes`'s
`references/unsloth-trl-mapping.md`
(`processing_class`, not `tokenizer=`).

`references/method-configs.md` also carries the
catastrophic-forgetting note: a too-high learning
rate is the usual cause when a preference-tuned
checkpoint loses general capability, and the fix
is almost always to drop the LR toward the low end
of the range in the Method Selection table above
before reaching for any other remediation.

Related skills: `finetuning-method-selection`
routes here once preference pairs or unpaired
feedback exist; `lora-qlora-recipes` produces the
SFT checkpoint DPO/KTO/SimPO align (ORPO's
fused path can skip it); `trace-to-training-data`
converts passing/failing trajectories into the
pairs this skill's Pair Construction section
consumes.

<!-- chapter:end slug=preference-optimization -->

---

<!-- chapter:begin slug=quantized-export position=107 -->

## 107. quantized-export

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/quantized-export/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/quantized-export/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/quantized-export.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/export-commands.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/quantized-export/references/export-commands.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: quantized-export
description: Export a promoted fine-tuned model in the right deployment format — merged safetensors, LoRA-only, GGUF with imatrix, or FP8. Use after a checkpoint passes promotion, when choosing a quantization format for a target device, or when an exported model fails its smoke test.
---

# Quantized Export

The last stop after `checkpoint-promotion`
hands off a `PROMOTE` verdict: a checkpoint
that cleared the four-stage gate still isn't
deployed until it's exported in the right
format for its target runtime and proven to
still work post-export. A `REJECT` verdict
never reaches this skill — export starts only
from a promoted checkpoint.

**Input:** a promoted checkpoint (or LoRA
adapter) plus the target deployment surface —
GPU class, serving stack, and whether
long-context/code/math workloads are in
scope.
**Output format:** an exported artifact in
the chosen format plus a smoke-test diff
report comparing 3–5 golden outputs
pre-export and post-export.

## Format Map

Pick format by hardware and deployment shape,
not by habit — the wrong pick either wastes
throughput headroom or breaks silently on
specific workloads (see Workload Overrides).

- **FP8 is the default on Hopper-class GPUs
  and newer.** It preserves near-bf16 quality
  at roughly half the memory, and it's the
  safe first choice whenever the target GPU
  supports it and no edge-device constraint
  applies.
- **AWQ INT4 targets older GPUs** that predate
  FP8 hardware support. **GPTQ is superseded
  for new deployments** — don't reach for it
  on a fresh export; AWQ has better accuracy
  retention at the same bit width and wider
  current tooling support.
- **GGUF with Q4_K_M quantization, built from
  an imatrix, is the edge/llama.cpp format.**
  Use it for local or CPU-adjacent
  deployment, not for GPU-serving
  throughput — it optimizes for footprint,
  not tokens/sec on a datacenter GPU.
- **NVFP4 is for Blackwell-at-scale
  deployments only — and explicitly NOT on
  GB10.** NVFP4 on SM121 (GB10) runs **~32%
  slower than FP8** because the hardware
  lacks a native `cvt.e2m1x2` path unless the
  kernel is compiled `sm_121a`. Choosing
  NVFP4 on a GB10 target is a regression, not
  an upgrade — pick FP8 there instead.
- **Merged vs. LoRA-only is a separate axis
  from quant format.** A merged export folds
  the adapter into the base weights: larger
  artifact, no base-model dependency at serve
  time. LoRA-only keeps the adapter separate:
  much smaller artifact, but the serving stack
  must load the exact same base model
  alongside it — a mismatched or
  wrong-revision base silently changes
  outputs. Pick merged when artifact
  portability matters more than storage; pick
  LoRA-only when disk footprint or multi-adapter
  serving matters more.

### Worked Picks

The core format-selection tradeoff, read as a
lookup table for common scenarios:

| Target | Workload | Format |
|---|---|---|
| Datacenter GPU | generic chat | FP8 |
| Datacenter GPU | long-context/code/math | FP8 or W8A8 — never INT4 |
| Older GPU generation | generic | AWQ INT4 |
| Edge device / laptop | llama.cpp serving | GGUF Q4_K_M + imatrix |
| GB10 | any workload | FP8 via vLLM nightly, or GGUF via llama.cpp locally — skip NVFP4 |

```yaml
# quick decision snippet — see the table above for the full map
hopper_or_newer: fp8
older_gpu: awq-int4
edge_llama_cpp: gguf-q4_k_m+imatrix
gb10_any_workload: fp8-vllm-nightly   # never nvfp4 on GB10
```

## Workload Overrides

The Format Map above is a default, not a rule
that survives every workload. **Long-context,
code, and math workloads break at INT4** —
quantization error compounds across long
sequences and precise token-level reasoning in
ways that don't show up on short, generic
prompts. For any of these three workload
classes, **stay on FP8 or W8A8** even if the
target hardware would otherwise justify INT4
on cost grounds.

- Don't validate this override with MMLU or
  similar broad-knowledge benchmarks — they
  don't stress the failure mode. **Measure
  with the actual task evals** — the goldens
  and graders from `eval-harness-first`, run
  through the exported artifact — because
  INT4 degradation on long-context, code, or
  math shows up as task-specific failures
  (dropped context, broken syntax, arithmetic
  errors) well before it moves a knowledge
  benchmark.
- If a task eval regresses after an INT4
  export on one of these three workload
  classes, the fix is switching format, not
  re-tuning the quantization recipe — AWQ
  and GPTQ variants at the same bit width
  share the same compounding-error failure
  mode on these workloads.

## The Smoke Test

Export bugs are silent at the file level — a
malformed export still produces a
loadable artifact, so file-existence checks
prove nothing. **The smoke test is
mandatory for every export, with no
exception for a format that "should just
work":**

1. **Load the exported artifact in its actual
   target runtime** — vLLM for FP8/AWQ,
   llama.cpp for GGUF, not a quick
   sanity load in a different framework than
   the one that will serve it in production.
2. **Run 3–5 golden prompts through it** —
   pull these from the same `eval/goldens.jsonl`
   `eval-harness-first` maintains, not a fresh
   ad hoc set.
3. **Compare each output against the
   pre-export generation** for the same
   prompt, same deterministic sampling
   settings — greedy decoding (temperature 0)
   and a fixed seed, persisted and reused
   between the pre- and post-export runs, not
   just nominally identical config. **For a
   lossless export, byte match is the gate —
   any diff is a bug.** For a **lossy**
   (quantized) export, byte match is expected
   to fail; the gate is task-grader verdict
   agreement instead — see
   `references/export-commands.md`'s
   Smoke-Test Script Skeleton.

Run this as a gate, not a manual check:

```bash
python smoke_test.py "$EXPORT_PATH" \
    eval/goldens.jsonl pre-export-outputs.jsonl
# non-zero exit on any pre/post mismatch
```

### Failure Signatures

What export bugs actually look like, not a
clean pass/fail flag:

- **Template mismatch** presents as garbled or
  run-on output — the chat template baked
  into the export doesn't match the one the
  checkpoint was trained and evaluated
  against, so turn boundaries or special
  tokens land in the wrong place.
- **Wrong quantization applied to `lm_head`**
  presents as off-template or semantically
  nonsensical output that still looks
  fluent — the output head lost precision it
  needed even though the rest of the network
  quantized cleanly.

Never ship an export that skipped this step —
a checkpoint's `PROMOTE` verdict says the
un-exported checkpoint is good; it says
nothing about the export pipeline. Re-run on
any quant-method or runtime version bump, not
only after the first export. Runnable command
sequences for every format plus the
smoke-test script skeleton:
`references/export-commands.md`.

## Related Skills

- `checkpoint-promotion` — the only valid
  upstream source for this skill. A checkpoint
  without a `PROMOTE` verdict doesn't reach
  export.
- `eval-harness-first` — owns the
  `eval/goldens.jsonl` this skill's smoke test
  draws its 3–5 prompts from, and the task
  evals the Workload Overrides section
  requires for long-context/code/math
  validation.
- `finetuning-method-selection` — its
  `references/model-catalog.md` is the place
  to check hardware-class assumptions (which
  GPU generations a base model targets) before
  picking a format off the Format Map above.

**Spark users:** on GB10, GGUF via llama.cpp
works well for local serving, and FP8 serving
via vLLM nightly builds is the other proven
path — NVFP4 is the one format to avoid there
(see the Format Map exception above). Once the
`dgx-spark-ops` plugin is installed, defer
Spark-specific serving and thermal questions to
its skills rather than re-deriving them here.

<!-- chapter:end slug=quantized-export -->

---

<!-- chapter:begin slug=trace-to-training-data position=108 -->

## 108. trace-to-training-data

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/trace-to-training-data/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/trace-to-training-data/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/trace-to-training-data.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/conversion-recipes.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/trace-to-training-data/references/conversion-recipes.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: trace-to-training-data
description: Convert evaluation traces and production logs into SFT examples and preference pairs. Use when graded traces or failure examples exist and need to become training data, when applying rejection sampling to model outputs, or when building DPO pairs from passing and failing runs.
---

# Trace To Training Data

This skill assumes `eval-harness-first`
already graded the traces being
converted here — goldens, graders,
and `runs/<run-id>/results.json`
all exist before conversion
starts. This is the flywheel edge
that skill names in its own flow:
"the same labeled traces become
the training set." Conversion
happens here; grading already
happened upstream.

**Input:** graded traces —
`eval/goldens.jsonl` plus
`runs/<run-id>/results.json`, each
row carrying a `task_id`, a
`verdict` from the grader, and a
`reward` when the task supports a
scalar score (judge score,
execution partial-credit, or an
RLVR verifier):

```json
{"task_id": "t-042", "trace_id": "t-042-a3",
 "messages": [{"role": "user", "content": "..."}],
 "verdict": "pass", "reward": 0.91,
 "grader": "exact_match"}
```

**Output format:** rows shaped
exactly like `dataset-curation`'s
Format Selection table — SFT
`messages` rows or DPO
`prompt`/`chosen`/`rejected`
pairs — so this skill's output is
that skill's input with no
reshaping step in between.

## The Principle

The eval harness already did the
labeling work: every trace in
`results.json` carries a verdict,
and often a reward, before this
skill ever touches it. Converting
a graded trace into a training
row is mechanical — pick a shape
from `dataset-curation`'s table,
map fields, write JSONL.
**Curation is the work that
remains** — which traces clear a
quality bar, which pairs are
informative, and which rows must
never enter the training set at
all.

Treat any conversion step that
requires re-judging a trace as a
sign the harness is missing a
grader, not a gap this skill
should paper over. A trace with
no verdict or reward isn't
convertible yet — route it back
to `eval-harness-first` first,
don't hand-label it here to
unblock conversion.

## SFT From Traces

- **Keep the top-reward fraction
  of successful trajectories**,
  not every passing one. Rank
  passing traces by reward and
  take a fraction (the
  Agent-lightning pattern) rather
  than every trace that merely
  cleared the pass bar — a trace
  that barely passed is a weaker
  SFT signal than one that scored
  well above threshold.
- **Expert-corrected failures
  become gold SFT examples
  directly** (the Langfuse
  pattern) — when a human edits a
  failing trace's output into a
  correct one, that correction
  needs no reward threshold; a
  human already validated it.
  Route corrections straight into
  the SFT set.
- **Step-level masking beats
  whole-trajectory discard for
  multi-step traces.** When only
  some steps in a multi-step
  trajectory are bad, mask the
  loss on the bad steps and keep
  the good ones, rather than
  discarding the whole trajectory.
  SRFT reports 32.2% vs. 30.9% on
  SWE-bench for step-level critic
  masking over trajectory discard
  — a real, if modest, gap from
  the finer-grained cut.

## Preference Pairs From Traces

- **Build pairs from
  passing-vs-failing trajectories
  on the SAME task**, never from
  unrelated best- and
  worst-scoring traces pulled
  across different tasks —
  cross-task pairs teach the
  model to prefer one task over
  another, not one response over
  another.
- **Select the rejected member at
  μ−2σ of the reward distribution
  for that task, never the
  absolute minimum.**
  `preference-optimization`'s
  Pair Construction section owns
  the full selection formula;
  this skill supplies the graded
  trajectories it consumes.
- **Judge-scored delta selection
  cuts pair volume without
  cutting signal.** Score each
  candidate pair by
  chosen-minus-rejected judge
  delta and keep only the
  highest-delta subset — the top
  5k of a 16.5k candidate pool
  matched the full pool's
  downstream result. Build the
  full candidate set first, then
  filter by delta; don't cap
  generation at 5k up front.

## Hygiene

- **Scan for secrets and PII before any row ships,
  and redact what's found.** Traces sourced from
  production logs can carry credentials, API keys,
  tokens, or customer data — run a secret/PII scan
  over every SFT and DPO row and redact matches;
  conversion fails closed (the row is dropped, not
  shipped with the raw content) if sensitive fields
  remain after redaction. Never commit secrets.
- **Eval goldens must never leak
  into training data.** Hold
  every `eval/goldens.jsonl` ID
  out of every converted SFT and
  DPO set — a trace that also
  appears as a golden trains on
  the exact item the checkpoint
  gets graded against later,
  silently inflating every
  subsequent eval run.
- **Dedup against the training
  set**, not just within the
  newly converted rows —
  exact-match or
  embedding-similarity, matching
  `dataset-curation`'s dedup
  method field, run against
  whatever training data already
  exists before this batch merges
  in.
- **Provenance goes into the
  dataset card.** Every converted
  row must trace back to its
  source `run_id` and `trace_id`
  — `dataset-curation`'s
  Provenance field checks for
  exactly this link back to
  `trace-to-training-data`
  output; a row with no traceable
  source isn't ready to merge.

## Related Skills

- `eval-harness-first` — produces
  the graded traces this skill
  converts; a trace with no
  verdict or reward isn't
  convertible yet, route it back
  there before conversion.
- `dataset-curation` — owns the
  target formats and the dataset
  card this skill's provenance
  data feeds; converted rows must
  match its Format Selection
  table field names exactly, not
  an approximation of them.
- `preference-optimization` —
  consumes the DPO pairs this
  skill builds and owns the full
  μ−2σ rejection-selection
  formula referenced above.

Worked JSONL-to-JSONL conversions
— graded trace to SFT row, trace
pair to DPO pair, correction to
SFT row, the rejection-sampling
loop, and the goldens-holdout
check — live in
`references/conversion-recipes.md`.

<!-- chapter:end slug=trace-to-training-data -->

---

<!-- chapter:begin slug=vision-sft position=109 -->

## 109. vision-sft

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/llm-finetuning/skills/vision-sft/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/vision-sft/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/vision-sft.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/collators-and-pitfalls.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/llm-finetuning/skills/vision-sft/references/collators-and-pitfalls.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: vision-sft
description: Fine-tune vision-language models (VLMs) with supervised learning on image+text data. Use when adapting a VLM to a visual domain or task, configuring frozen-vision-tower LoRA, or debugging a VLM fine-tune that trains without learning.
---

# Vision-Language SFT

This skill assumes `finetuning-method-selection`
already routed here: the data shape is
image+text demonstrations, not preference pairs
or a verifiable reward signal, and the base is a
vision-language model rather than a text-only
one. `lora-qlora-recipes` covers the text-only
LoRA/QLoRA recipe this skill specializes for the
vision tower and projector; read that skill first
if the LoRA fundamentals (rank, alpha, target
modules) aren't already familiar.

**Input:** an image+text dataset and a VLM base
model already picked from the model catalog.
**Output format:** a validated adapter config —
which components are frozen, LoRA target modules,
and a `min_pixels`/`max_pixels` budget — that
`llm-finetuning-training-engineer` consumes
directly when it generates a runnable script.

## Quick Reference

| Situation | Default |
|---|---|
| Adapting behavior on familiar images | Frozen tower+projector, LoRA r=8–16, α=16–32 |
| Visual domain shift | Unfreeze last-6 ViT layers, vision LR 5–10x lower |
| Doesn't fit in bf16 at target rank | QLoRA — frozen vision tower only |
| `fast_inference=True` | `finetune_vision_layers=False` |
| Loss normal, eval not improving | Check the Two Silent Killers below first |

## The Consensus Recipe

Freeze the vision tower and the projector. Put
LoRA on the LLM only, all-linear (the same
attention + MLP target list as text-only SFT —
see `lora-qlora-recipes`), at **r=8–16,
α=16–32**. This is the settled default for
adapting a VLM's behavior without disturbing how
it sees.

- **The vision tower and projector stay frozen by
  default.** They already encode a general visual
  representation; retraining them is rarely
  necessary and adds risk without adding
  capability for most tasks.
- **LoRA rank runs lower than the text-only
  general default** (r=8–16 here vs r=16–32 for
  text-only SFT) because the LLM-only adapter is
  adapting behavior, not injecting new visual
  knowledge.
- **QLoRA is permitted only with a frozen vision
  tower.** Quantizing the base while also
  unfreezing and training vision layers is
  unsupported and unstable — treat this as a hard
  pairing rule, not a tunable. If the vision tower
  needs to unfreeze, drop QLoRA and use bf16 LoRA
  instead.

```python
# freeze tower + projector; LoRA on LLM only
for name, param in model.named_parameters():
    if "vision_tower" in name or "projector" in name:
        param.requires_grad = False

target_modules = [
    "q_proj", "k_proj", "v_proj", "o_proj",
    "gate_proj", "up_proj", "down_proj",
]  # LLM-only, all-linear — r=8-16, alpha=16-32
```

## When to Unfreeze

Unfreezing vision layers is a deliberate
escalation, not a default decision — reach
for it only when the domain shift is
visual, not textual.

- **Unfreeze only for visual domain
  shift.** If the task is teaching new
  behavior on images the tower already
  understands (charts, everyday photos),
  the frozen-tower recipe above is
  sufficient. Unfreeze when the visual
  domain itself is unfamiliar to the
  tower — satellite imagery, medical
  scans, dense technical diagrams — and
  the frozen-tower recipe plateaus.
- **Last-6 ViT layers is the sweet
  spot.** Unfreezing the final six
  vision-transformer layers (not the
  whole tower) measured **+1.7pt DocVQA
  at ~1.75x training cost** over the
  frozen baseline. Treat six layers as
  the ceiling worth paying for; going
  further spends compute without a
  matched result.
- **Vision LR must run 5–10x lower than
  the LLM LR when unfrozen.** The vision
  tower's pretrained representation is
  more fragile than the LLM's adapter;
  the same LR for both risks overwriting
  the visual representation faster than
  the LLM adapter can compensate.
- **High LoRA rank on the patch-
  embedding layer risks NaN.** If patch
  embedding is in the unfrozen set, keep
  its rank low and watch early-step loss
  closely — one of the most fragile
  places to apply LoRA in a VLM.

## The Two Silent Killers

Both produce a run that trains without error and
without learning: the loss curve looks normal,
the model doesn't improve, and neither throws an
exception — both need an explicit pre-training
check, not just a clean training log.

- **Image-tag/count mismatch.** Every image
  placeholder token in the templated text must
  map 1:1 to a media item actually passed to the
  collator. A mismatch (one placeholder, zero or
  two images attached; or an image with no
  placeholder) doesn't error in most collators —
  it silently misaligns image and text, and the
  model "trains but learns nothing." Validate the
  1:1 placeholder-to-media mapping before training
  starts, on every example, not just a sample.
  Full validation-checklist detail:
  `references/collators-and-pitfalls.md`.
- **`min_pixels`/`max_pixels` resolution budget.**
  This pair is the single most consequential
  hyperparameter for quality and memory in VLM
  SFT — more than rank, alpha, or LR. Too low
  silently downsamples images below what the task
  needs (small document text becomes unreadable
  even though training "succeeds"); too high blows
  the activation memory budget or forces too small
  a batch to train stably. Set it deliberately per
  dataset, don't leave it at a framework default.

## Unsloth Specifics

- **`UnslothVisionDataCollator`** is the collator
  Unsloth expects for VLM SFT — it handles the
  image-tag alignment and per-architecture
  processor contract described in
  `references/collators-and-pitfalls.md`. Don't
  substitute a text-only collator for VLM data.
- **`finetune_vision_layers=False` is required
  when `fast_inference=True`.** vLLM cannot serve
  LoRA adapters on vision layers, so a fast-
  inference setup that also unfreezes vision
  layers fails at serve time even if training
  succeeds. If the recipe calls for unfreezing the
  last-6 ViT layers (see When to Unfreeze above),
  fast inference is off the table for that run —
  choose one or the other, not both.

## Model Choice

Base VLM choice is out of scope for this skill —
it lives in one place, the model catalog at
`finetuning-method-selection`'s
`references/model-catalog.md`. This skill and its
references describe recipes by architecture
family only, never by recommending one model over
another.

VLM reinforcement learning (VLM-GRPO) is
reference-only in this plugin — the fragmented
tooling and reward-hacking failure modes specific
to VLM-RL are covered in `grpo-rlvr-training`,
not here. This skill's scope stops at supervised
fine-tuning.

## Failure Modes

The recurring mistake across every section above
is treating a clean loss curve as proof the run
is healthy. A normal-looking curve is consistent
with **both** a working run **and** either silent
killer, since the model trains on *something*
either way — just not the aligned image-text
signal when a killer is present. A flat eval score
next to a normal loss curve means re-run the
checklist in `references/collators-and-pitfalls.md`
before touching any hyperparameter.

## References

- `references/collators-and-pitfalls.md` — per-
  architecture collator table, dataset-format
  examples with image placeholders, a pre-
  training validation checklist, and the two-
  stage projector-alignment recipe as an advanced
  pattern.

Related skills: `finetuning-method-selection`
routes here; `lora-qlora-recipes` covers the
text-only LoRA fundamentals this skill
specializes; `grpo-rlvr-training` covers VLM-RL
(reference-only); `dataset-curation` covers
image+text dataset preparation this skill doesn't.

<!-- chapter:end slug=vision-sft -->

---

## Part: Machine Learning Ops

---

<!-- chapter:begin slug=ml-pipeline-workflow position=110 -->

## 110. ml-pipeline-workflow

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/machine-learning-ops/skills/ml-pipeline-workflow/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/machine-learning-ops/skills/ml-pipeline-workflow/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/ml-pipeline-workflow.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: ml-pipeline-workflow
description: Build end-to-end MLOps pipelines from data preparation through model training, validation, and production deployment. Use when creating ML pipelines, implementing MLOps practices, or automating model training and deployment workflows.
---

# ML Pipeline Workflow

Complete end-to-end MLOps pipeline orchestration from data preparation through model deployment.

## Overview

This skill provides comprehensive guidance for building production ML pipelines that handle the full lifecycle: data ingestion → preparation → training → validation → deployment → monitoring.

## When to Use This Skill

- Building new ML pipelines from scratch
- Designing workflow orchestration for ML systems
- Implementing data → model → deployment automation
- Setting up reproducible training workflows
- Creating DAG-based ML orchestration
- Integrating ML components into production systems

## What This Skill Provides

### Core Capabilities

1. **Pipeline Architecture**
   - End-to-end workflow design
   - DAG orchestration patterns (Airflow, Dagster, Kubeflow)
   - Component dependencies and data flow
   - Error handling and retry strategies

2. **Data Preparation**
   - Data validation and quality checks
   - Feature engineering pipelines
   - Data versioning and lineage
   - Train/validation/test splitting strategies

3. **Model Training**
   - Training job orchestration
   - Hyperparameter management
   - Experiment tracking integration
   - Distributed training patterns

4. **Model Validation**
   - Validation frameworks and metrics
   - A/B testing infrastructure
   - Performance regression detection
   - Model comparison workflows

5. **Deployment Automation**
   - Model serving patterns
   - Canary deployments
   - Blue-green deployment strategies
   - Rollback mechanisms

### Reference Documentation

See the `references/` directory for detailed guides:

- **data-preparation.md** - Data cleaning, validation, and feature engineering
- **model-training.md** - Training workflows and best practices
- **model-validation.md** - Validation strategies and metrics
- **model-deployment.md** - Deployment patterns and serving architectures

### Assets and Templates

The `assets/` directory contains:

- **pipeline-dag.yaml.template** - DAG template for workflow orchestration
- **training-config.yaml** - Training configuration template
- **validation-checklist.md** - Pre-deployment validation checklist

## Usage Patterns

### Basic Pipeline Setup

```python
# 1. Define pipeline stages
stages = [
    "data_ingestion",
    "data_validation",
    "feature_engineering",
    "model_training",
    "model_validation",
    "model_deployment"
]

# 2. Configure dependencies
# See assets/pipeline-dag.yaml.template for full example
```

### Production Workflow

1. **Data Preparation Phase**
   - Ingest raw data from sources
   - Run data quality checks
   - Apply feature transformations
   - Version processed datasets

2. **Training Phase**
   - Load versioned training data
   - Execute training jobs
   - Track experiments and metrics
   - Save trained models

3. **Validation Phase**
   - Run validation test suite
   - Compare against baseline
   - Generate performance reports
   - Approve for deployment

4. **Deployment Phase**
   - Package model artifacts
   - Deploy to serving infrastructure
   - Configure monitoring
   - Validate production traffic

## Best Practices

### Pipeline Design

- **Modularity**: Each stage should be independently testable
- **Idempotency**: Re-running stages should be safe
- **Observability**: Log metrics at every stage
- **Versioning**: Track data, code, and model versions
- **Failure Handling**: Implement retry logic and alerting

### Data Management

- Use data validation libraries (Great Expectations, TFX)
- Version datasets with DVC or similar tools
- Document feature engineering transformations
- Maintain data lineage tracking

### Model Operations

- Separate training and serving infrastructure
- Use model registries (MLflow, Weights & Biases)
- Implement gradual rollouts for new models
- Monitor model performance drift
- Maintain rollback capabilities

### Deployment Strategies

- Start with shadow deployments
- Use canary releases for validation
- Implement A/B testing infrastructure
- Set up automated rollback triggers
- Monitor latency and throughput

## Integration Points

### Orchestration Tools

- **Apache Airflow**: DAG-based workflow orchestration
- **Dagster**: Asset-based pipeline orchestration
- **Kubeflow Pipelines**: Kubernetes-native ML workflows
- **Prefect**: Modern dataflow automation

### Experiment Tracking

- MLflow for experiment tracking and model registry
- Weights & Biases for visualization and collaboration
- TensorBoard for training metrics

### Deployment Platforms

- AWS SageMaker for managed ML infrastructure
- Google Vertex AI for GCP deployments
- Azure ML for Azure cloud
- OCI Data Science for Oracle Cloud Infrastructure deployments
- Kubernetes + KServe for cloud-agnostic serving

## Progressive Disclosure

Start with the basics and gradually add complexity:

1. **Level 1**: Simple linear pipeline (data → train → deploy)
2. **Level 2**: Add validation and monitoring stages
3. **Level 3**: Implement hyperparameter tuning
4. **Level 4**: Add A/B testing and gradual rollouts
5. **Level 5**: Multi-model pipelines with ensemble strategies

## Common Patterns

### Batch Training Pipeline

```yaml
# See assets/pipeline-dag.yaml.template
stages:
  - name: data_preparation
    dependencies: []
  - name: model_training
    dependencies: [data_preparation]
  - name: model_evaluation
    dependencies: [model_training]
  - name: model_deployment
    dependencies: [model_evaluation]
```

### Real-time Feature Pipeline

```python
# Stream processing for real-time features
# Combined with batch training
# See references/data-preparation.md
```

### Continuous Training

```python
# Automated retraining on schedule
# Triggered by data drift detection
# See references/model-training.md
```

## Troubleshooting

### Common Issues

- **Pipeline failures**: Check dependencies and data availability
- **Training instability**: Review hyperparameters and data quality
- **Deployment issues**: Validate model artifacts and serving config
- **Performance degradation**: Monitor data drift and model metrics

### Debugging Steps

1. Check pipeline logs for each stage
2. Validate input/output data at boundaries
3. Test components in isolation
4. Review experiment tracking metrics
5. Inspect model artifacts and metadata

## Next Steps

After setting up your pipeline:

1. Explore **hyperparameter-tuning** skill for optimization
2. Learn **experiment-tracking-setup** for MLflow/W&B
3. Review **model-deployment-patterns** for serving strategies
4. Implement monitoring with observability tools

## Related Skills

- **experiment-tracking-setup**: MLflow and Weights & Biases integration
- **hyperparameter-tuning**: Automated hyperparameter optimization
- **model-deployment-patterns**: Advanced deployment strategies

<!-- chapter:end slug=ml-pipeline-workflow -->

---

<!-- chapter:begin slug=recsys-pipeline-architect position=111 -->

## 111. recsys-pipeline-architect

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/machine-learning-ops/skills/recsys-pipeline-architect/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/machine-learning-ops/skills/recsys-pipeline-architect/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/recsys-pipeline-architect.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: recsys-pipeline-architect
description: Design composable recommendation, ranking, and feed pipelines using the six-stage Source→Hydrator→Filter→Scorer→Selector→SideEffect framework popularized by xAI's open-sourced X For You algorithm. Use when building any system that picks "the top K items for a (user, context)" — content feeds, search ranking, RAG rerankers, task prioritizers, notification triage, ad selection.
---

# Recsys Pipeline Architect

A spec-and-scaffold skill for building composable recommendation, ranking, and feed pipelines. Encodes the six-stage pattern popularized by xAI's open-sourced [For You algorithm](https://github.com/xai-org/x-algorithm) (Apache 2.0) and applies it to any "top K for (user, context)" problem.

## Overview

Most "recommendation systems" in production aren't exotic ML — they're *pipelines*: fetch candidates from one or more sources, enrich them with metadata, drop the ineligible, score the rest, sort and pick the top K, then fire async side effects. The pattern is universal. The scoring function and the items change; the pipeline shape doesn't.

This skill is an independent reimplementation of the pattern (MIT) — no code copied from the original.

## When to Use This Skill

- Building any system that returns "the top K items for a user/context"
- Designing or refactoring a personalized feed (content, search results, notifications)
- Wrapping an LLM/ML scorer in proper pipeline plumbing (sources, hydration, filters, side effects)
- Adding multi-action prediction with tunable weights (instead of a single relevance score)
- Building a RAG retrieval reranker (cheap retrieval → expensive rerank)
- Designing a task prioritizer or alert triage system

## The Six-Stage Framework

| # | Stage | Job | Parallel? |
|---|---|---|---|
| 1 | **Source** | Fetch candidates from one or more origins | Yes — multiple sources run in parallel |
| 2 | **Hydrator** | Enrich candidates with metadata needed for filtering and scoring | Yes — independent hydrators run in parallel |
| 3 | **Filter** | Drop ineligible candidates (blocked, expired, duplicate, ineligible) | Sequential — each filter sees fewer items |
| 4 | **Scorer** | Assign each surviving candidate one or more scores | Sequential — later scorers see earlier scores |
| 5 | **Selector** | Sort by final score, return top K | Single op |
| 6 | **SideEffect** | Cache, log, emit events, update served-history | Async — must never block the response |

### Why this exact order

- Sources before hydration: know what candidates exist before paying to enrich
- Hydration before filtering: many filters need metadata the source didn't provide
- Filtering before scoring: scoring is the expensive stage — drop the ineligible first
- Scorer chain (not single scorer): real systems compose ML scoring + diversity reranking + business rules
- Selector after scoring: keeps scoring deterministic and cacheable
- SideEffects last and async: side effects must never block the user response

## Workflow When Invoked

Walk the user through eight steps:

1. **Clarify the use case** (one round, three questions only if missing): items being ranked, input context, language/runtime
2. **Identify the candidate sources** (usually in-network + out-of-network, but single-source also valid)
3. **List required hydrations** — for each filter and scorer, what data does it need that the source didn't provide?
4. **List the filters** — cheap before expensive, universal before user-specific (duplicate, self, age, block/mute, previously-served, eligibility)
5. **Design the scorer chain** — primary ML/heuristic → combiner (multi-action with weights) → diversity → business rules
6. **Selector** — sort descending by final score, take top K (or stratified mix)
7. **SideEffects** — cache served IDs, emit impression events, update counters, log analytics; all fire-and-forget
8. **Generate the scaffold** in the user's stack

## Key Trade-offs to Surface

Never default silently on these — they are product decisions disguised as technical ones.

### 1. Single score vs multi-action prediction

- **Single score:** train one model to predict relevance. To change behavior → retrain.
- **Multi-action:** predict `P(action)` for many actions (`P(read)`, `P(like)`, `P(share)`, `P(skip)`, `P(report)`), combine with weights at serving time. To change behavior → change weights. No retraining.

The X For You algorithm uses multi-action with both positive and negative weights. Recommend multi-action when the user expects to tune frequently.

### 2. Candidate isolation vs joint scoring

- **Isolated:** each candidate scored independently. Deterministic, cacheable.
- **Joint:** candidates attend to each other during scoring (e.g., transformer over the whole batch). More expressive but non-deterministic across batches.

Default to isolation. Joint only when there's a specific reason (e.g., explicit batch-aware diversity).

### 3. Online vs offline batch

- **Request-time (online):** pipeline runs on each request. Latency budget: 100–300ms.
- **Pre-computed (offline batch):** pipeline runs periodically, results cached. Lower latency, lower freshness.
- **Hybrid:** candidate retrieval offline, ranking online.

## Hard Rules

1. **Do not invent benchmark numbers.** "How fast is this?" → "depends on workload, run it yourself."
2. **Attribution discipline.** Attribute the pattern as "popularized by xAI's open-sourced For You algorithm" / `github.com/xai-org/x-algorithm` (Apache 2.0).
3. **No trademark use.** Don't name the user's artifact "X-like" or use "For You" branding. Use neutral names: "candidate pipeline", "feed pipeline", "ranking pipeline".
4. **Surface trade-offs.** Multi-action vs single, isolation vs joint, online vs offline — never default silently.
5. **The generated scaffold must run.** No pseudocode passing as code.
6. **Filter order matters.** Cheap before expensive. Universal before user-specific.
7. **Side effects never block.** Wrap in fire-and-forget patterns (goroutines / promises without await / asyncio tasks).

## Anti-Patterns

- ❌ Scoring before filtering (wastes compute on candidates that will be dropped)
- ❌ Synchronous side effects (cache writes / impression emits blocking the response)
- ❌ A single "relevance" score when the product needs multi-objective tuning
- ❌ Joint scoring as default (non-deterministic, uncacheable, doesn't compose with reranking)
- ❌ Pseudocode "for illustration" — the scaffold must actually run

## Common Use Cases

### Content feed (Strapi v5 plugin, TypeScript)

User has a CMS with 50k articles, wants a personalized "for you" feed. Walk through 8 steps → generate a Strapi plugin scaffold with multi-action scoring, author diversity, standard filters, async side-effect lane.

### RAG retrieval reranker (Python async)

User's RAG returns top-50 chunks from a vector DB, wants to rerank with a more expensive scorer and return top-5. Single-source pipeline with a scorer chain (cheap retrieval + expensive rerank).

### Task prioritizer (FastAPI service)

User has a queue of incoming task suggestions, wants to rank by "what should this user work on next" considering their past patterns. Items reversed (tasks instead of content), same shape applies.

### Notification triage (offline-batch job)

User wants a daily digest that picks the top 10 from the last 24h queue. Offline-batch pipeline. Source = queue, filters = age/dedup/eligibility, scorer = urgency × user-affinity, selector = top 10, side effect = email send (still async).

## Upstream

This skill is a single-file adapter for the upstream repository, which ships 5 load-on-demand reference docs and 3 runnable example scaffolds (Strapi v5 / Go / Python — every one green on its test suite, 9/9 tests total).

- **Upstream:** https://github.com/mturac/recsys-pipeline-architect
- **Release:** v0.1.0 (MIT)
- **References:** interfaces in 4 languages (TS/Go/Python/Rust), multi-action scoring, candidate isolation, filter cookbook (12 patterns), scorer cookbook
- **Cross-platform install:** `npx skills add mturac/recsys-pipeline-architect`

<!-- chapter:end slug=recsys-pipeline-architect -->

---

## Part: Observability Monitoring

---

<!-- chapter:begin slug=distributed-tracing position=112 -->

## 112. distributed-tracing

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/observability-monitoring/skills/distributed-tracing/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/distributed-tracing/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/distributed-tracing.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/distributed-tracing/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: distributed-tracing
description: Implement distributed tracing with Jaeger and Tempo to track requests across microservices and identify performance bottlenecks. Use when debugging microservices, analyzing request flows, or implementing observability for distributed systems.
---

# Distributed Tracing

Implement distributed tracing with Jaeger and Tempo for request flow visibility across microservices.

## Purpose

Track requests across distributed systems to understand latency, dependencies, and failure points.

## When to Use

- Debug latency issues
- Understand service dependencies
- Identify bottlenecks
- Trace error propagation
- Analyze request paths

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Sample appropriately** (1-10% in production)
2. **Add meaningful tags** (user_id, request_id)
3. **Propagate context** across all service boundaries
4. **Log exceptions** in spans
5. **Use consistent naming** for operations
6. **Monitor tracing overhead** (<1% CPU impact)
7. **Set up alerts** for trace errors
8. **Implement distributed context** (baggage)
9. **Use span events** for important milestones
10. **Document instrumentation** standards

## Integration with Logging

### Correlated Logs

```python
import logging
from opentelemetry import trace

logger = logging.getLogger(__name__)

def process_request():
    span = trace.get_current_span()
    trace_id = span.get_span_context().trace_id

    logger.info(
        "Processing request",
        extra={"trace_id": format(trace_id, '032x')}
    )
```

## Troubleshooting

**No traces appearing:**

- Check collector endpoint
- Verify network connectivity
- Check sampling configuration
- Review application logs

**High latency overhead:**

- Reduce sampling rate
- Use batch span processor
- Check exporter configuration


## Related Skills

- `prometheus-configuration` - For metrics
- `grafana-dashboards` - For visualization
- `slo-implementation` - For latency SLOs

<!-- chapter:end slug=distributed-tracing -->

---

<!-- chapter:begin slug=grafana-dashboards position=113 -->

## 113. grafana-dashboards

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/observability-monitoring/skills/grafana-dashboards/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/grafana-dashboards/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/grafana-dashboards.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: grafana-dashboards
description: Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visualizing metrics, or creating operational observability interfaces.
---

# Grafana Dashboards

Create and manage production-ready Grafana dashboards for comprehensive system observability.

## Purpose

Design effective Grafana dashboards for monitoring applications, infrastructure, and business metrics.

## When to Use

- Visualize Prometheus metrics
- Create custom dashboards
- Implement SLO dashboards
- Monitor infrastructure
- Track business KPIs

## Dashboard Design Principles

### 1. Hierarchy of Information

```
┌─────────────────────────────────────┐
│  Critical Metrics (Big Numbers)     │
├─────────────────────────────────────┤
│  Key Trends (Time Series)           │
├─────────────────────────────────────┤
│  Detailed Metrics (Tables/Heatmaps) │
└─────────────────────────────────────┘
```

### 2. RED Method (Services)

- **Rate** - Requests per second
- **Errors** - Error rate
- **Duration** - Latency/response time

### 3. USE Method (Resources)

- **Utilization** - % time resource is busy
- **Saturation** - Queue length/wait time
- **Errors** - Error count

## Dashboard Structure

### API Monitoring Dashboard

```json
{
  "dashboard": {
    "title": "API Monitoring",
    "tags": ["api", "production"],
    "timezone": "browser",
    "refresh": "30s",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "sum(rate(http_requests_total[5m])) by (service)",
            "legendFormat": "{{service}}"
          }
        ],
        "gridPos": { "x": 0, "y": 0, "w": 12, "h": 8 }
      },
      {
        "title": "Error Rate %",
        "type": "graph",
        "targets": [
          {
            "expr": "(sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))) * 100",
            "legendFormat": "Error Rate"
          }
        ],
        "alert": {
          "conditions": [
            {
              "evaluator": { "params": [5], "type": "gt" },
              "operator": { "type": "and" },
              "query": { "params": ["A", "5m", "now"] },
              "type": "query"
            }
          ]
        },
        "gridPos": { "x": 12, "y": 0, "w": 12, "h": 8 }
      },
      {
        "title": "P95 Latency",
        "type": "graph",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))",
            "legendFormat": "{{service}}"
          }
        ],
        "gridPos": { "x": 0, "y": 8, "w": 24, "h": 8 }
      }
    ]
  }
}
```

**Reference:** See `assets/api-dashboard.json`

## Panel Types

### 1. Stat Panel (Single Value)

```json
{
  "type": "stat",
  "title": "Total Requests",
  "targets": [
    {
      "expr": "sum(http_requests_total)"
    }
  ],
  "options": {
    "reduceOptions": {
      "values": false,
      "calcs": ["lastNotNull"]
    },
    "orientation": "auto",
    "textMode": "auto",
    "colorMode": "value"
  },
  "fieldConfig": {
    "defaults": {
      "thresholds": {
        "mode": "absolute",
        "steps": [
          { "value": 0, "color": "green" },
          { "value": 80, "color": "yellow" },
          { "value": 90, "color": "red" }
        ]
      }
    }
  }
}
```

### 2. Time Series Graph

```json
{
  "type": "graph",
  "title": "CPU Usage",
  "targets": [
    {
      "expr": "100 - (avg by (instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)"
    }
  ],
  "yaxes": [
    { "format": "percent", "max": 100, "min": 0 },
    { "format": "short" }
  ]
}
```

### 3. Table Panel

```json
{
  "type": "table",
  "title": "Service Status",
  "targets": [
    {
      "expr": "up",
      "format": "table",
      "instant": true
    }
  ],
  "transformations": [
    {
      "id": "organize",
      "options": {
        "excludeByName": { "Time": true },
        "indexByName": {},
        "renameByName": {
          "instance": "Instance",
          "job": "Service",
          "Value": "Status"
        }
      }
    }
  ]
}
```

### 4. Heatmap

```json
{
  "type": "heatmap",
  "title": "Latency Heatmap",
  "targets": [
    {
      "expr": "sum(rate(http_request_duration_seconds_bucket[5m])) by (le)",
      "format": "heatmap"
    }
  ],
  "dataFormat": "tsbuckets",
  "yAxis": {
    "format": "s"
  }
}
```

## Variables

### Query Variables

```json
{
  "templating": {
    "list": [
      {
        "name": "namespace",
        "type": "query",
        "datasource": "Prometheus",
        "query": "label_values(kube_pod_info, namespace)",
        "refresh": 1,
        "multi": false
      },
      {
        "name": "service",
        "type": "query",
        "datasource": "Prometheus",
        "query": "label_values(kube_service_info{namespace=\"$namespace\"}, service)",
        "refresh": 1,
        "multi": true
      }
    ]
  }
}
```

### Use Variables in Queries

```
sum(rate(http_requests_total{namespace="$namespace", service=~"$service"}[5m]))
```

## Alerts in Dashboards

```json
{
  "alert": {
    "name": "High Error Rate",
    "conditions": [
      {
        "evaluator": {
          "params": [5],
          "type": "gt"
        },
        "operator": { "type": "and" },
        "query": {
          "params": ["A", "5m", "now"]
        },
        "reducer": { "type": "avg" },
        "type": "query"
      }
    ],
    "executionErrorState": "alerting",
    "for": "5m",
    "frequency": "1m",
    "message": "Error rate is above 5%",
    "noDataState": "no_data",
    "notifications": [{ "uid": "slack-channel" }]
  }
}
```

## Dashboard Provisioning

**dashboards.yml:**

```yaml
apiVersion: 1

providers:
  - name: "default"
    orgId: 1
    folder: "General"
    type: file
    disableDeletion: false
    updateIntervalSeconds: 10
    allowUiUpdates: true
    options:
      path: /etc/grafana/dashboards
```

## Common Dashboard Patterns

### Infrastructure Dashboard

**Key Panels:**

- CPU utilization per node
- Memory usage per node
- Disk I/O
- Network traffic
- Pod count by namespace
- Node status

**Reference:** See `assets/infrastructure-dashboard.json`

### Database Dashboard

**Key Panels:**

- Queries per second
- Connection pool usage
- Query latency (P50, P95, P99)
- Active connections
- Database size
- Replication lag
- Slow queries

**Reference:** See `assets/database-dashboard.json`

### Application Dashboard

**Key Panels:**

- Request rate
- Error rate
- Response time (percentiles)
- Active users/sessions
- Cache hit rate
- Queue length

## Best Practices

1. **Start with templates** (Grafana community dashboards)
2. **Use consistent naming** for panels and variables
3. **Group related metrics** in rows
4. **Set appropriate time ranges** (default: Last 6 hours)
5. **Use variables** for flexibility
6. **Add panel descriptions** for context
7. **Configure units** correctly
8. **Set meaningful thresholds** for colors
9. **Use consistent colors** across dashboards
10. **Test with different time ranges**

## Dashboard as Code

### Terraform Provisioning

```hcl
resource "grafana_dashboard" "api_monitoring" {
  config_json = file("${path.module}/dashboards/api-monitoring.json")
  folder      = grafana_folder.monitoring.id
}

resource "grafana_folder" "monitoring" {
  title = "Production Monitoring"
}
```

### Ansible Provisioning

```yaml
- name: Deploy Grafana dashboards
  copy:
    src: "{{ item }}"
    dest: /etc/grafana/dashboards/
  with_fileglob:
    - "dashboards/*.json"
  notify: restart grafana
```


## Related Skills

- `prometheus-configuration` - For metric collection
- `slo-implementation` - For SLO dashboards

<!-- chapter:end slug=grafana-dashboards -->

---

<!-- chapter:begin slug=prometheus-configuration position=114 -->

## 114. prometheus-configuration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/observability-monitoring/skills/prometheus-configuration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/prometheus-configuration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/prometheus-configuration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/prometheus-configuration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: prometheus-configuration
description: Set up Prometheus for comprehensive metric collection, storage, and monitoring of infrastructure and applications. Use when implementing metrics collection, setting up monitoring infrastructure, or configuring alerting systems.
---

# Prometheus Configuration

Complete guide to Prometheus setup, metric collection, scrape configuration, and recording rules.

## Purpose

Configure Prometheus for comprehensive metric collection, alerting, and monitoring of infrastructure and applications.

## When to Use

- Set up Prometheus monitoring
- Configure metric scraping
- Create recording rules
- Design alert rules
- Implement service discovery

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Use consistent naming** for metrics (prefix_name_unit)
2. **Set appropriate scrape intervals** (15-60s typical)
3. **Use recording rules** for expensive queries
4. **Implement high availability** (multiple Prometheus instances)
5. **Configure retention** based on storage capacity
6. **Use relabeling** for metric cleanup
7. **Monitor Prometheus itself**
8. **Implement federation** for large deployments
9. **Use Thanos/Cortex** for long-term storage
10. **Document custom metrics**

## Troubleshooting

**Check scrape targets:**

```bash
curl http://localhost:9090/api/v1/targets
```

**Check configuration:**

```bash
curl http://localhost:9090/api/v1/status/config
```

**Test query:**

```bash
curl 'http://localhost:9090/api/v1/query?query=up'
```


## Related Skills

- `grafana-dashboards` - For visualization
- `slo-implementation` - For SLO monitoring
- `distributed-tracing` - For request tracing

<!-- chapter:end slug=prometheus-configuration -->

---

<!-- chapter:begin slug=slo-implementation position=115 -->

## 115. slo-implementation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/observability-monitoring/skills/slo-implementation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/slo-implementation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/slo-implementation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/observability-monitoring/skills/slo-implementation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: slo-implementation
description: Define and implement Service Level Indicators (SLIs) and Service Level Objectives (SLOs) with error budgets and alerting. Use when establishing reliability targets, implementing SRE practices, or measuring service performance.
---

# SLO Implementation

Framework for defining and implementing Service Level Indicators (SLIs), Service Level Objectives (SLOs), and error budgets.

## Purpose

Implement measurable reliability targets using SLIs, SLOs, and error budgets to balance reliability with innovation velocity.

## When to Use

- Define service reliability targets
- Measure user-perceived reliability
- Implement error budgets
- Create SLO-based alerts
- Track reliability goals

## SLI/SLO/SLA Hierarchy

```
SLA (Service Level Agreement)
  ↓ Contract with customers
SLO (Service Level Objective)
  ↓ Internal reliability target
SLI (Service Level Indicator)
  ↓ Actual measurement
```

## Defining SLIs

### Common SLI Types

#### 1. Availability SLI

```promql
# Successful requests / Total requests
sum(rate(http_requests_total{status!~"5.."}[28d]))
/
sum(rate(http_requests_total[28d]))
```

#### 2. Latency SLI

```promql
# Requests below latency threshold / Total requests
sum(rate(http_request_duration_seconds_bucket{le="0.5"}[28d]))
/
sum(rate(http_request_duration_seconds_count[28d]))
```

#### 3. Durability SLI

```
# Successful writes / Total writes
sum(storage_writes_successful_total)
/
sum(storage_writes_total)
```

**Reference:** See `references/slo-definitions.md`

## Setting SLO Targets

### Availability SLO Examples

| SLO %  | Downtime/Month | Downtime/Year |
| ------ | -------------- | ------------- |
| 99%    | 7.2 hours      | 3.65 days     |
| 99.9%  | 43.2 minutes   | 8.76 hours    |
| 99.95% | 21.6 minutes   | 4.38 hours    |
| 99.99% | 4.32 minutes   | 52.56 minutes |

### Choose Appropriate SLOs

**Consider:**

- User expectations
- Business requirements
- Current performance
- Cost of reliability
- Competitor benchmarks

**Example SLOs:**

```yaml
slos:
  - name: api_availability
    target: 99.9
    window: 28d
    sli: |
      sum(rate(http_requests_total{status!~"5.."}[28d]))
      /
      sum(rate(http_requests_total[28d]))

  - name: api_latency_p95
    target: 99
    window: 28d
    sli: |
      sum(rate(http_request_duration_seconds_bucket{le="0.5"}[28d]))
      /
      sum(rate(http_request_duration_seconds_count[28d]))
```

## Error Budget Calculation

### Error Budget Formula

```
Error Budget = 1 - SLO Target
```

**Example:**

- SLO: 99.9% availability
- Error Budget: 0.1% = 43.2 minutes/month
- Current Error: 0.05% = 21.6 minutes/month
- Remaining Budget: 50%

### Error Budget Policy

```yaml
error_budget_policy:
  - remaining_budget: 100%
    action: Normal development velocity
  - remaining_budget: 50%
    action: Consider postponing risky changes
  - remaining_budget: 10%
    action: Freeze non-critical changes
  - remaining_budget: 0%
    action: Feature freeze, focus on reliability
```

**Reference:** See `references/error-budget.md`

## SLO Implementation

### Prometheus Recording Rules

```yaml
# SLI Recording Rules
groups:
  - name: sli_rules
    interval: 30s
    rules:
      # Availability SLI
      - record: sli:http_availability:ratio
        expr: |
          sum(rate(http_requests_total{status!~"5.."}[28d]))
          /
          sum(rate(http_requests_total[28d]))

      # Latency SLI (requests < 500ms)
      - record: sli:http_latency:ratio
        expr: |
          sum(rate(http_request_duration_seconds_bucket{le="0.5"}[28d]))
          /
          sum(rate(http_request_duration_seconds_count[28d]))

  - name: slo_rules
    interval: 5m
    rules:
      # SLO compliance (1 = meeting SLO, 0 = violating)
      - record: slo:http_availability:compliance
        expr: sli:http_availability:ratio >= bool 0.999

      - record: slo:http_latency:compliance
        expr: sli:http_latency:ratio >= bool 0.99

      # Error budget remaining (percentage)
      - record: slo:http_availability:error_budget_remaining
        expr: |
          (sli:http_availability:ratio - 0.999) / (1 - 0.999) * 100

      # Error budget burn rate
      - record: slo:http_availability:burn_rate_5m
        expr: |
          (1 - (
            sum(rate(http_requests_total{status!~"5.."}[5m]))
            /
            sum(rate(http_requests_total[5m]))
          )) / (1 - 0.999)
```

### SLO Alerting Rules

```yaml
groups:
  - name: slo_alerts
    interval: 1m
    rules:
      # Fast burn: 14.4x rate, 1 hour window
      # Consumes 2% error budget in 1 hour
      - alert: SLOErrorBudgetBurnFast
        expr: |
          slo:http_availability:burn_rate_1h > 14.4
          and
          slo:http_availability:burn_rate_5m > 14.4
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Fast error budget burn detected"
          description: "Error budget burning at {{ $value }}x rate"

      # Slow burn: 6x rate, 6 hour window
      # Consumes 5% error budget in 6 hours
      - alert: SLOErrorBudgetBurnSlow
        expr: |
          slo:http_availability:burn_rate_6h > 6
          and
          slo:http_availability:burn_rate_30m > 6
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Slow error budget burn detected"
          description: "Error budget burning at {{ $value }}x rate"

      # Error budget exhausted
      - alert: SLOErrorBudgetExhausted
        expr: slo:http_availability:error_budget_remaining < 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "SLO error budget exhausted"
          description: "Error budget remaining: {{ $value }}%"
```

## SLO Dashboard

**Grafana Dashboard Structure:**

```
┌────────────────────────────────────┐
│ SLO Compliance (Current)           │
│ ✓ 99.95% (Target: 99.9%)          │
├────────────────────────────────────┤
│ Error Budget Remaining: 65%        │
│ ████████░░ 65%                     │
├────────────────────────────────────┤
│ SLI Trend (28 days)                │
│ [Time series graph]                │
├────────────────────────────────────┤
│ Burn Rate Analysis                 │
│ [Burn rate by time window]         │
└────────────────────────────────────┘
```

**Example Queries:**

```promql
# Current SLO compliance
sli:http_availability:ratio * 100

# Error budget remaining
slo:http_availability:error_budget_remaining

# Days until error budget exhausted (at current burn rate)
(slo:http_availability:error_budget_remaining / 100)
*
28
/
(1 - sli:http_availability:ratio) * (1 - 0.999)
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=slo-implementation -->

---

## Part: Payment Processing

---

<!-- chapter:begin slug=billing-automation position=116 -->

## 116. billing-automation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/payment-processing/skills/billing-automation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/billing-automation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/billing-automation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/billing-automation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: billing-automation
description: Build automated billing systems for recurring payments, invoicing, subscription lifecycle, and dunning management. Use when implementing subscription billing, automating invoicing, or managing recurring payment systems.
---

# Billing Automation

Master automated billing systems including recurring billing, invoice generation, dunning management, proration, and tax calculation.

## When to Use This Skill

- Implementing SaaS subscription billing
- Automating invoice generation and delivery
- Managing failed payment recovery (dunning)
- Calculating prorated charges for plan changes
- Handling sales tax, VAT, and GST
- Processing usage-based billing
- Managing billing cycles and renewals

## Core Concepts

### 1. Billing Cycles

**Common Intervals:**

- Monthly (most common for SaaS)
- Annual (discounted long-term)
- Quarterly
- Weekly
- Custom (usage-based, per-seat)

### 2. Subscription States

```
trial → active → past_due → canceled
              → paused → resumed
```

### 3. Dunning Management

Automated process to recover failed payments through:

- Retry schedules
- Customer notifications
- Grace periods
- Account restrictions

### 4. Proration

Adjusting charges when:

- Upgrading/downgrading mid-cycle
- Adding/removing seats
- Changing billing frequency

## Quick Start

```python
from billing import BillingEngine, Subscription

# Initialize billing engine
billing = BillingEngine()

# Create subscription
subscription = billing.create_subscription(
    customer_id="cus_123",
    plan_id="plan_pro_monthly",
    billing_cycle_anchor=datetime.now(),
    trial_days=14
)

# Process billing cycle
billing.process_billing_cycle(subscription.id)
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=billing-automation -->

---

<!-- chapter:begin slug=paypal-integration position=117 -->

## 117. paypal-integration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/payment-processing/skills/paypal-integration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/paypal-integration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/paypal-integration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/paypal-integration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: paypal-integration
description: Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-commerce checkout flows.
---

# PayPal Integration

Master PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows.

## When to Use This Skill

- Integrating PayPal as a payment option
- Implementing express checkout flows
- Setting up recurring billing with PayPal
- Processing refunds and payment disputes
- Handling PayPal webhooks (IPN)
- Supporting international payments
- Implementing PayPal subscriptions

## Core Concepts

### 1. Payment Products

**PayPal Checkout**

- One-time payments
- Express checkout experience
- Guest and PayPal account payments

**PayPal Subscriptions**

- Recurring billing
- Subscription plans
- Automatic renewals

**PayPal Payouts**

- Send money to multiple recipients
- Marketplace and platform payments

### 2. Integration Methods

**Client-Side (JavaScript SDK)**

- Smart Payment Buttons
- Hosted payment flow
- Minimal backend code

**Server-Side (REST API)**

- Full control over payment flow
- Custom checkout UI
- Advanced features

### 3. IPN (Instant Payment Notification)

- Webhook-like payment notifications
- Asynchronous payment updates
- Verification required

## Quick Start

```javascript
// Frontend - PayPal Smart Buttons
<div id="paypal-button-container"></div>

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&currency=USD"></script>
<script>
  paypal.Buttons({
    createOrder: function(data, actions) {
      return actions.order.create({
        purchase_units: [{
          amount: {
            value: '25.00'
          }
        }]
      });
    },
    onApprove: function(data, actions) {
      return actions.order.capture().then(function(details) {
        // Payment successful
        console.log('Transaction completed by ' + details.payer.name.given_name);

        // Send to backend for verification
        fetch('/api/paypal/capture', {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({orderID: data.orderID})
        });
      });
    }
  }).render('#paypal-button-container');
</script>
```

```python
# Backend - Verify and capture order
from paypalrestsdk import Payment
import paypalrestsdk

paypalrestsdk.configure({
    "mode": "sandbox",  # or "live"
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
})

def capture_paypal_order(order_id):
    """Capture a PayPal order."""
    payment = Payment.find(order_id)

    if payment.execute({"payer_id": payment.payer.payer_info.payer_id}):
        # Payment successful
        return {
            'status': 'success',
            'transaction_id': payment.id,
            'amount': payment.transactions[0].amount.total
        }
    else:
        # Payment failed
        return {
            'status': 'failed',
            'error': payment.error
        }
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing

```python
# Use sandbox credentials
SANDBOX_CLIENT_ID = "..."
SANDBOX_SECRET = "..."

# Test accounts
# Create test buyer and seller accounts at developer.paypal.com

def test_payment_flow():
    """Test complete payment flow."""
    client = PayPalClient(SANDBOX_CLIENT_ID, SANDBOX_SECRET, mode='sandbox')

    # Create order
    order = client.create_order(10.00)
    assert 'id' in order

    # Get approval URL
    approval_url = next((link['href'] for link in order['links'] if link['rel'] == 'approve'), None)
    assert approval_url is not None

    # After approval (manual step with test account)
    # Capture order
    # captured = client.capture_order(order['id'])
    # assert captured['status'] == 'COMPLETED'
```

<!-- chapter:end slug=paypal-integration -->

---

<!-- chapter:begin slug=pci-compliance position=118 -->

## 118. pci-compliance

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/payment-processing/skills/pci-compliance/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/pci-compliance/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/pci-compliance.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/pci-compliance/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: pci-compliance
description: Implement PCI DSS compliance requirements for secure handling of payment card data and payment systems. Use when securing payment processing, achieving PCI compliance, or implementing payment card security measures.
---

# PCI Compliance

Master PCI DSS (Payment Card Industry Data Security Standard) compliance for secure payment processing and handling of cardholder data.

## When to Use This Skill

- Building payment processing systems
- Handling credit card information
- Implementing secure payment flows
- Conducting PCI compliance audits
- Reducing PCI compliance scope
- Implementing tokenization and encryption
- Preparing for PCI DSS assessments

## PCI DSS Requirements (12 Core Requirements)

### Build and Maintain Secure Network

1. Install and maintain firewall configuration
2. Don't use vendor-supplied defaults for passwords

### Protect Cardholder Data

3. Protect stored cardholder data
4. Encrypt transmission of cardholder data across public networks

### Maintain Vulnerability Management

5. Protect systems against malware
6. Develop and maintain secure systems and applications

### Implement Strong Access Control

7. Restrict access to cardholder data by business need-to-know
8. Identify and authenticate access to system components
9. Restrict physical access to cardholder data

### Monitor and Test Networks

10. Track and monitor all access to network resources and cardholder data
11. Regularly test security systems and processes

### Maintain Information Security Policy

12. Maintain a policy that addresses information security

## Compliance Levels

**Level 1**: > 6 million transactions/year (annual ROC required)
**Level 2**: 1-6 million transactions/year (annual SAQ)
**Level 3**: 20,000-1 million e-commerce transactions/year
**Level 4**: < 20,000 e-commerce or < 1 million total transactions

## Data Minimization (Never Store)

```python
# NEVER STORE THESE
PROHIBITED_DATA = {
    'full_track_data': 'Magnetic stripe data',
    'cvv': 'Card verification code/value',
    'pin': 'PIN or PIN block'
}

# CAN STORE (if encrypted)
ALLOWED_DATA = {
    'pan': 'Primary Account Number (card number)',
    'cardholder_name': 'Name on card',
    'expiration_date': 'Card expiration',
    'service_code': 'Service code'
}

class PaymentData:
    """Safe payment data handling."""

    def __init__(self):
        self.prohibited_fields = ['cvv', 'cvv2', 'cvc', 'pin']

    def sanitize_log(self, data):
        """Remove sensitive data from logs."""
        sanitized = data.copy()

        # Mask PAN
        if 'card_number' in sanitized:
            card = sanitized['card_number']
            sanitized['card_number'] = f"{card[:6]}{'*' * (len(card) - 10)}{card[-4:]}"

        # Remove prohibited data
        for field in self.prohibited_fields:
            sanitized.pop(field, None)

        return sanitized

    def validate_no_prohibited_storage(self, data):
        """Ensure no prohibited data is being stored."""
        for field in self.prohibited_fields:
            if field in data:
                raise SecurityError(f"Attempting to store prohibited field: {field}")
```

## Tokenization

### Using Payment Processor Tokens

```python
import stripe

class TokenizedPayment:
    """Handle payments using tokens (no card data on server)."""

    @staticmethod
    def create_payment_method_token(card_details):
        """Create token from card details (client-side only)."""
        # THIS SHOULD ONLY BE DONE CLIENT-SIDE WITH STRIPE.JS
        # NEVER send card details to your server

        """
        // Frontend JavaScript
        const stripe = Stripe('pk_...');

        const {token, error} = await stripe.createToken({
            card: {
                number: '4242424242424242',
                exp_month: 12,
                exp_year: 2024,
                cvc: '123'
            }
        });

        // Send token.id to server (NOT card details)
        """
        pass

    @staticmethod
    def charge_with_token(token_id, amount):
        """Charge using token (server-side)."""
        # Your server only sees the token, never the card number
        stripe.api_key = "sk_..."

        charge = stripe.Charge.create(
            amount=amount,
            currency="usd",
            source=token_id,  # Token instead of card details
            description="Payment"
        )

        return charge

    @staticmethod
    def store_payment_method(customer_id, payment_method_token):
        """Store payment method as token for future use."""
        stripe.Customer.modify(
            customer_id,
            source=payment_method_token
        )

        # Store only customer_id and payment_method_id in your database
        # NEVER store actual card details
        return {
            'customer_id': customer_id,
            'has_payment_method': True
            # DO NOT store: card number, CVV, etc.
        }
```

### Custom Tokenization (Advanced)

```python
import secrets
from cryptography.fernet import Fernet

class TokenVault:
    """Secure token vault for card data (if you must store it)."""

    def __init__(self, encryption_key):
        self.cipher = Fernet(encryption_key)
        self.vault = {}  # In production: use encrypted database

    def tokenize(self, card_data):
        """Convert card data to token."""
        # Generate secure random token
        token = secrets.token_urlsafe(32)

        # Encrypt card data
        encrypted = self.cipher.encrypt(json.dumps(card_data).encode())

        # Store token -> encrypted data mapping
        self.vault[token] = encrypted

        return token

    def detokenize(self, token):
        """Retrieve card data from token."""
        encrypted = self.vault.get(token)
        if not encrypted:
            raise ValueError("Token not found")

        # Decrypt
        decrypted = self.cipher.decrypt(encrypted)
        return json.loads(decrypted.decode())

    def delete_token(self, token):
        """Remove token from vault."""
        self.vault.pop(token, None)
```

## Encryption

### Data at Rest

```python
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

class EncryptedStorage:
    """Encrypt data at rest using AES-256-GCM."""

    def __init__(self, encryption_key):
        """Initialize with 256-bit key."""
        self.key = encryption_key  # Must be 32 bytes

    def encrypt(self, plaintext):
        """Encrypt data."""
        # Generate random nonce
        nonce = os.urandom(12)

        # Encrypt
        aesgcm = AESGCM(self.key)
        ciphertext = aesgcm.encrypt(nonce, plaintext.encode(), None)

        # Return nonce + ciphertext
        return nonce + ciphertext

    def decrypt(self, encrypted_data):
        """Decrypt data."""
        # Extract nonce and ciphertext
        nonce = encrypted_data[:12]
        ciphertext = encrypted_data[12:]

        # Decrypt
        aesgcm = AESGCM(self.key)
        plaintext = aesgcm.decrypt(nonce, ciphertext, None)

        return plaintext.decode()

# Usage
storage = EncryptedStorage(os.urandom(32))
encrypted_pan = storage.encrypt("4242424242424242")
# Store encrypted_pan in database
```

### Data in Transit

```python
# Always use TLS 1.2 or higher
# Flask/Django example
app.config['SESSION_COOKIE_SECURE'] = True  # HTTPS only
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'Strict'

# Enforce HTTPS
from flask_talisman import Talisman
Talisman(app, force_https=True)
```

## Additional patterns and templates

More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.

<!-- chapter:end slug=pci-compliance -->

---

<!-- chapter:begin slug=stripe-integration position=119 -->

## 119. stripe-integration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/payment-processing/skills/stripe-integration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/stripe-integration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/stripe-integration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/payment-processing/skills/stripe-integration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: stripe-integration
description: Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.
---

# Stripe Integration

Master Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.

## When to Use This Skill

- Implementing payment processing in web/mobile applications
- Setting up subscription billing systems
- Handling one-time payments and recurring charges
- Processing refunds and disputes
- Managing customer payment methods
- Implementing SCA (Strong Customer Authentication) for European payments
- Building marketplace payment flows with Stripe Connect

## Core Concepts

### 1. Payment Flows

**Checkout Sessions**

- Recommended for most integrations
- Supports all UI paths:
  - Stripe-hosted checkout page
  - Embedded checkout form
  - Custom UI with Elements (Payment Element, Express Checkout Element) using `ui_mode='custom'`
- Provides built-in checkout capabilities (line items, discounts, tax, shipping, address collection, saved payment methods, and checkout lifecycle events)
- Lower integration and maintenance burden than Payment Intents

**Payment Intents (Bespoke control)**

- You calculate the final amount with taxes, discounts, subscriptions, and currency conversion yourself.
- More complex implementation and long-term maintenance burden
- Requires Stripe.js for PCI compliance

**Setup Intents (Save Payment Methods)**

- Collect payment method without charging
- Used for subscriptions and future payments
- Requires customer confirmation

### 2. Webhooks

**Critical Events:**

- `payment_intent.succeeded`: Payment completed
- `payment_intent.payment_failed`: Payment failed
- `customer.subscription.updated`: Subscription changed
- `customer.subscription.deleted`: Subscription canceled
- `charge.refunded`: Refund processed
- `invoice.payment_succeeded`: Subscription payment successful

### 3. Subscriptions

**Components:**

- **Product**: What you're selling
- **Price**: How much and how often
- **Subscription**: Customer's recurring payment
- **Invoice**: Generated for each billing cycle

### 4. Customer Management

- Create and manage customer records
- Store multiple payment methods
- Track customer metadata
- Manage billing details

## Quick Start

```python
import stripe

stripe.api_key = "sk_test_..."

# Create a checkout session
session = stripe.checkout.Session.create(
    line_items=[{
        'price_data': {
            'currency': 'usd',
            'product_data': {
                'name': 'Premium Subscription',
            },
            'unit_amount': 2000,  # $20.00
            'recurring': {
                'interval': 'month',
            },
        },
        'quantity': 1,
    }],
    mode='subscription',
    success_url='https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}',
    cancel_url='https://yourdomain.com/cancel'
)

# Redirect user to session.url
print(session.url)
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing

```python
# Use test mode keys
stripe.api_key = "sk_test_..."

# Test card numbers
TEST_CARDS = {
    'success': '4242424242424242',
    'declined': '4000000000000002',
    '3d_secure': '4000002500003155',
    'insufficient_funds': '4000000000009995'
}

def test_payment_flow():
    """Test complete payment flow."""
    # Create test customer
    customer = stripe.Customer.create(
        email="test@example.com"
    )

    # Create payment intent
    intent = stripe.PaymentIntent.create(
        amount=1000,
        automatic_payment_methods={
            'enabled': True
        },
        currency='usd',
        customer=customer.id
    )

    # Confirm with test card
    confirmed = stripe.PaymentIntent.confirm(
        intent.id,
        payment_method='pm_card_visa'  # Test payment method
    )

    assert confirmed.status == 'succeeded'
```

<!-- chapter:end slug=stripe-integration -->

---

## Part: Plugin Eval

---

<!-- chapter:begin slug=evaluation-methodology position=120 -->

## 120. evaluation-methodology

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/plugin-eval/skills/evaluation-methodology/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/plugin-eval/skills/evaluation-methodology/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/evaluation-methodology.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/rubrics.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/plugin-eval/skills/evaluation-methodology/references/rubrics.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: evaluation-methodology
description: "PluginEval quality methodology — dimensions, rubrics, statistical methods, and scoring formulas. Use this skill when understanding how plugin quality is measured, when interpreting a low score on a specific dimension, when deciding how to improve a skill's triggering accuracy or orchestration fitness, when calibrating scoring thresholds for your marketplace, or when explaining quality badges to external partners like Neon."
---

# Evaluation Methodology

This document is the authoritative reference for how PluginEval measures plugin and skill quality.
It covers the three evaluation layers, all ten scoring dimensions, the composite formula, badge
thresholds, anti-pattern flags, Elo ranking, and actionable improvement tips.

Related: [Full rubric anchors](references/rubrics.md)

---

## The Three Evaluation Layers

PluginEval stacks three complementary layers. Each layer produces a score between 0.0 and 1.0 for
each applicable dimension, and later layers override or blend with earlier ones according to
per-dimension blend weights.

### Layer 1 — Static Analysis

**Speed:** < 2 seconds. No LLM calls. Deterministic.

The static analyzer (`layers/static.py`) runs six sub-checks directly against the parsed SKILL.md:

| Sub-check | What it measures |
|---|---|
| `frontmatter_quality` | Name presence, description length, trigger-phrase quality |
| `orchestration_wiring` | Output/input documentation, code block count, orchestrator anti-pattern |
| `progressive_disclosure` | Line count vs. sweet-spot (200–600 lines), references/ and assets/ bonuses |
| `structural_completeness` | Heading density, code blocks, examples section, troubleshooting section |
| `token_efficiency` | MUST/NEVER/ALWAYS density, duplicate-line repetition ratio |
| `ecosystem_coherence` | Cross-references to other skills/agents, "related"/"see also" mentions |

These six sub-checks feed directly into six of the ten final dimensions (via `STATIC_TO_DIMENSION`
mapping). The remaining four dimensions — `output_quality`, `scope_calibration`,
`robustness`, and part of `triggering_accuracy` — receive no static contribution and rely
entirely on Layer 2 and/or Layer 3.

**Anti-pattern penalty** is applied multiplicatively to the Layer 1 score:

```
penalty = max(0.5, 1.0 − 0.05 × anti_pattern_count)
```

Each additional detected anti-pattern reduces the score by 5%, flooring at 50%.

### Layer 2 — LLM Judge

**Speed:** 30–90 seconds. One or more LLM calls (Sonnet by default). Non-deterministic.

The `eval-judge` agent reads the SKILL.md and any `references/` files, then scores four
dimensions using anchored rubrics (see [references/rubrics.md](references/rubrics.md)):

1. **Triggering accuracy** — F1 score derived from 10 mental test prompts
2. **Orchestration fitness** — Worker purity assessment (0–1 rubric)
3. **Output quality** — Simulates 3 realistic tasks; assesses instruction quality
4. **Scope calibration** — Judges depth and breadth relative to the skill's category

The judge returns a structured JSON object (no markdown fences) that the eval engine merges
into the composite. When `judges > 1`, scores are averaged and Cohen's kappa is reported as
an inter-judge agreement metric.

### Layer 3 — Monte Carlo Simulation

**Speed:** 5–20 minutes. N=50 simulated Agent SDK invocations (default). Statistical.

Monte Carlo runs `N` real prompts through the skill and records:

- **Activation rate** — Fraction of prompts that triggered the skill
- **Output consistency** — Coefficient of variation (CV) across quality scores
- **Failure rate** — Error/crash fraction with Clopper-Pearson exact CIs
- **Token efficiency** — Median token count, IQR, outlier count

The Layer 3 composite formula:

```
mc_score = 0.40 × activation_rate
         + 0.30 × (1 − min(1.0, CV))
         + 0.20 × (1 − failure_rate)
         + 0.10 × efficiency_norm
```

where `efficiency_norm = max(0, 1 − median_tokens / 8000)`.

---

## Composite Scoring Formula

The final score is a weighted blend across all three layers for each dimension, then summed:

```
composite = Σ(dimension_weight × blended_dimension_score) × 100 × anti_pattern_penalty
```

### Dimension Weights

| Dimension | Weight | Why it matters |
|---|---|---|
| `triggering_accuracy` | 0.25 | A skill that never fires — or fires incorrectly — has no value |
| `orchestration_fitness` | 0.20 | Skills must be pure workers; supervisor logic belongs in agents |
| `output_quality` | 0.15 | Correct, complete output is the primary deliverable |
| `scope_calibration` | 0.12 | Neither a stub nor a bloated monster |
| `progressive_disclosure` | 0.10 | SKILL.md is lean; detail lives in references/ |
| `token_efficiency` | 0.06 | Minimal context waste per invocation |
| `robustness` | 0.05 | Handles edge cases without crashing |
| `structural_completeness` | 0.03 | Correct sections in the right order |
| `code_template_quality` | 0.02 | Working, copy-paste-ready examples |
| `ecosystem_coherence` | 0.02 | Cross-references; no duplication with siblings |

### Layer Blend Weights

Each dimension draws from different layers at different ratios. With all three layers active
(`--depth deep` or `certify`):

| Dimension | Static | Judge | Monte Carlo |
|---|---|---|---|
| `triggering_accuracy` | 0.15 | 0.25 | 0.60 |
| `orchestration_fitness` | 0.10 | 0.70 | 0.20 |
| `output_quality` | 0.00 | 0.40 | 0.60 |
| `scope_calibration` | 0.30 | 0.55 | 0.15 |
| `progressive_disclosure` | 0.80 | 0.20 | 0.00 |
| `token_efficiency` | 0.40 | 0.10 | 0.50 |
| `robustness` | 0.00 | 0.20 | 0.80 |
| `structural_completeness` | 0.90 | 0.10 | 0.00 |
| `code_template_quality` | 0.30 | 0.70 | 0.00 |
| `ecosystem_coherence` | 0.85 | 0.15 | 0.00 |

At `--depth standard` (static + judge only), blends are renormalized to drop the Monte Carlo
column. At `--depth quick` (static only), all weight falls on Layer 1.

### Blended Score Calculation

For a given depth, the blended score for dimension `d` is:

```
blended[d] = Σ( layer_weight[d][layer] × layer_score[d][layer] )
             ─────────────────────────────────────────────────────
             Σ( layer_weight[d][layer] for available layers )
```

This normalization ensures that skipping Monte Carlo at standard depth doesn't artificially
deflate scores.

---

## Interpreting Dimension Scores

Each dimension score is a float in `[0.0, 1.0]`. The CLI converts it to a letter grade:

| Grade | Score range | Meaning |
|---|---|---|
| A | 0.90 – 1.00 | Excellent — no meaningful improvement needed |
| B | 0.80 – 0.89 | Good — minor gaps only |
| C | 0.70 – 0.79 | Adequate — one or two clear improvement areas |
| D | 0.60 – 0.69 | Marginal — needs targeted work |
| F | < 0.60 | Failing — significant remediation required |

When reading a report, focus first on the lowest-graded dimension that has the highest weight.
A D in `triggering_accuracy` (weight 0.25) costs far more than a D in `ecosystem_coherence`
(weight 0.02).

**Confidence intervals** appear in the report when Layer 2 or Layer 3 ran. Narrow CIs (± < 5
points) indicate stable scores. Wide CIs suggest inconsistency — often caused by an ambiguous
description or instructions that work for some prompt styles but not others.

---

## Quality Badges

Badges require both a composite score threshold AND an Elo threshold (when Elo is available).
The `Badge.from_scores()` logic checks composite first, then Elo if provided:

| Badge | Composite | Elo | Meaning |
|---|---|---|---|
| Platinum ★★★★★ | ≥ 90 | ≥ 1600 | Reference quality — suitable for gold corpus |
| Gold ★★★★ | ≥ 80 | ≥ 1500 | Production ready |
| Silver ★★★ | ≥ 70 | ≥ 1400 | Functional, has improvement opportunities |
| Bronze ★★ | ≥ 60 | ≥ 1300 | Minimum viable — not yet recommended for users |
| — | < 60 | any | Does not meet minimum bar |

The Elo threshold is skipped when Elo has not been computed (i.e., at quick or standard depth
without `certify`). A skill can earn a badge on composite score alone in those cases.

---

## Anti-Pattern Flags

The static analyzer detects five anti-patterns. Each carries a severity multiplier that feeds
into the penalty formula.

### OVER_CONSTRAINED

**Trigger:** More than 15 occurrences of MUST, ALWAYS, or NEVER in the SKILL.md.

**Problem:** Overly prescriptive instructions reduce model flexibility, increase token overhead,
and signal that the author is trying to micromanage every output rather than providing
principled guidance.

**Fix:** Audit every MUST/ALWAYS/NEVER. Replace directive language with explanatory framing
where possible. Reserve hard constraints for genuine safety or correctness requirements. Target
fewer than 10 such directives per 100 lines.

### EMPTY_DESCRIPTION

**Trigger:** The frontmatter `description` field is fewer than 20 characters after stripping.

**Problem:** Without a meaningful description, the Claude Code plugin system cannot determine
when to invoke the skill. The skill becomes invisible to autonomous invocation.

**Fix:** Write a description of at least 60–120 characters that includes:
- A "Use this skill when..." or "Use when..." trigger clause
- Two or more concrete contexts separated by commas or "or"

### MISSING_TRIGGER

**Trigger:** The description does not contain "use when", "use this skill when",
"use proactively", or "trigger when" (case-insensitive).

**Problem:** Even a long description is useless for autonomous invocation if it doesn't
include a clear trigger signal. The system's routing model needs an explicit cue.

**Fix:** Prepend "Use this skill when..." to the description, followed by specific scenarios.
Example: "Use this skill when measuring plugin quality, interpreting score reports, or
explaining badge thresholds to a team."

### BLOATED_SKILL

**Trigger:** SKILL.md exceeds 800 lines AND the skill has no `references/` directory.

**Problem:** A monolithic SKILL.md forces the entire document into context on every invocation,
wasting tokens on content only needed in edge cases.

**Fix:** Create a `references/` directory and move supporting material there:
- Detailed rubrics → `references/rubrics.md`
- Extended examples → `references/examples.md`
- Configuration reference → `references/config.md`

The SKILL.md should link to these files with `[text](references/filename.md)` so the model
can fetch them on demand.

### ORPHAN_REFERENCE

**Trigger:** SKILL.md contains a markdown link `[text](references/filename)` where
`filename` does not exist in the `references/` directory.

**Problem:** Dead links waste tokens on context that will never resolve and confuse the model.

**Fix:** Either create the missing reference file or remove the dead link.

### DEAD_CROSS_REF

**Trigger:** SKILL.md references another skill or agent by relative path and that path
cannot be resolved from the skills/ directory.

**Problem:** Broken ecosystem links undermine the plugin's coherence score and may cause
the model to attempt navigation to non-existent files.

**Fix:** Verify the referenced skill exists. Update the path or remove the reference.

---

## Elo Ranking

PluginEval uses an Elo/Bradley-Terry rating system to rank a skill against the gold corpus.

**Starting rating:** 1500 (the corpus median by convention).

**K-factor:** 32 (standard for moderate-stakes ratings).

**Expected score formula** (standard Elo):

```
E(A vs B) = 1 / (1 + 10^((B_rating − A_rating) / 400))
```

**Rating update after each matchup:**

```
new_rating = old_rating + 32 × (actual_score − expected_score)
```

where `actual_score` is 1.0 for a win, 0.5 for a draw, 0.0 for a loss.

**Confidence intervals** are computed via 500-sample bootstrap, reported as 95% CI.
**Corpus percentile** reflects pairwise win rate against the gold corpus.
**Position bias check:** Pairs are evaluated in both orders; disagreements are flagged.

The `plugin-eval init` command builds the corpus index from a plugins directory:

```bash
plugin-eval init ./plugins --corpus-dir ~/.plugineval/corpus
```

---

## CLI Reference

### Score a skill (quick static analysis only)

```bash
plugin-eval score ./path/to/skill --depth quick
```

Returns Layer 1 results in < 2 seconds. Useful for fast feedback during authoring.

### Score with LLM judge (default)

```bash
plugin-eval score ./path/to/skill
```

Runs static + LLM judge (standard depth). Takes 30–90 seconds.

### Score with full output as JSON

```bash
plugin-eval score ./path/to/skill --output json
```

Emits structured JSON including `composite.score`, `composite.dimensions`, and
`layers[0].anti_patterns`. Suitable for CI integration:

```bash
plugin-eval score ./path/to/skill --depth quick --output json --threshold 70
# exits with code 1 if score < 70
```

### Full certification (all three layers + Elo)

```bash
plugin-eval certify ./path/to/skill
```

Runs static + LLM judge + Monte Carlo (50 simulations) + Elo ranking. Takes 15–20 minutes.
Assigns a quality badge. Use before publishing a skill to the marketplace.

### Head-to-head comparison

```bash
plugin-eval compare ./skill-a ./skill-b
```

Evaluates both skills at quick depth and prints a dimension-by-dimension comparison table.
Useful for deciding between two implementations or measuring improvement before/after a
rewrite.

### Initialize corpus for Elo

```bash
plugin-eval init ./plugins
```

Builds the local corpus index at `~/.plugineval/corpus`. Required before Elo ranking works.

### Scripting the Composite Formula

Reproduce the composite score offline (pre-commit hook, CI gate):

```python
def composite_score(dimension_scores: dict, anti_pattern_count: int = 0) -> float:
    """Replicate the PluginEval composite formula."""
    WEIGHTS = {
        "triggering_accuracy":    0.25,
        "orchestration_fitness":  0.20,
        "output_quality":         0.15,
        "scope_calibration":      0.12,
        "progressive_disclosure": 0.10,
        "token_efficiency":       0.06,
        "robustness":             0.05,
        "structural_completeness":0.03,
        "code_template_quality":  0.02,
        "ecosystem_coherence":    0.02,
    }
    raw = sum(WEIGHTS[d] * s for d, s in dimension_scores.items())
    penalty = max(0.5, 1.0 - 0.05 * anti_pattern_count)
    return round(raw * 100 * penalty, 2)

# Example: a skill with a weak triggering score
scores = {
    "triggering_accuracy":    0.65,  # D — needs description work
    "orchestration_fitness":  0.85,
    "output_quality":         0.80,
    # … fill in remaining 7 dimensions …
}
# composite_score(scores, anti_pattern_count=1) → ~76.5
```

### JSON Output Format

Top-level shape of `--output json`:

```json
{
  "composite": { "score": 76.5, "badge": "Silver", "elo": null },
  "dimensions": {
    "triggering_accuracy": { "score": 0.65, "grade": "D", "ci_low": 0.60, "ci_high": 0.70 },
    "orchestration_fitness": { "score": 0.85, "grade": "B", "ci_low": 0.80, "ci_high": 0.90 }
  },
  "layers": [
    { "name": "static", "duration_ms": 1243, "anti_patterns": ["OVER_CONSTRAINED"] },
    { "name": "judge", "duration_ms": 48200, "judges": 1, "kappa": null }
  ]
}
```

Parse `composite.score` in CI to gate deployments:

```bash
score=$(plugin-eval score ./my-skill --output json | python3 -c "import sys,json; print(json.load(sys.stdin)['composite']['score'])")
if (( $(echo "$score < 70" | bc -l) )); then
  echo "Quality gate failed: score $score < 70"
  exit 1
fi
```

---

## Tips for Improving a Skill's Score

Work through dimensions in weight order. The largest gains come from fixing the top-weighted
dimensions first.

### Which Dimension to Improve First

Use this table when a score report shows multiple D/F grades and you need to prioritize effort.

| Dimension | Weight | Typical fix effort | Score impact / hour | Fix first if… |
|---|---|---|---|---|
| `triggering_accuracy` | 0.25 | Low — description rewrite | High | Score < 70 overall |
| `orchestration_fitness` | 0.20 | Medium — restructure sections | High | Skill mixes worker + supervisor logic |
| `output_quality` | 0.15 | Medium — add examples | Medium | Judge score < 0.70 |
| `scope_calibration` | 0.12 | Low — move content to references/ | Medium | File is < 100 or > 800 lines |
| `progressive_disclosure` | 0.10 | Low — create references/ dir | Medium | No references/ directory exists |
| `token_efficiency` | 0.06 | Low — reduce MUST/ALWAYS/NEVER | Low | Anti-pattern count ≥ 3 |
| `robustness` | 0.05 | Low — add Troubleshooting section | Low | No edge-case handling documented |
| `structural_completeness` | 0.03 | Very low — add headings/code blocks | Low | Fewer than 4 H2 headings |
| `code_template_quality` | 0.02 | Very low — add language tags | Very low | Code blocks missing language tags |
| `ecosystem_coherence` | 0.02 | Very low — add Related section | Very low | No cross-references at all |

**Rule of thumb:** Fix `triggering_accuracy` before anything else — at weight 0.25 it delivers
more composite-score gain per hour than all low-weight dimensions combined.

### Triggering Accuracy (weight 0.25)

- Include "Use this skill when..." followed by 3–4 comma-separated specific contexts.
- Add "proactively" if the skill should auto-activate without an explicit user request.
- Mental test: write 5 prompts that should trigger it and 5 that should not — does
  your description discriminate? If not, add or tighten the context phrases.

### Orchestration Fitness (weight 0.20)

- Document what the skill *receives* and what it *returns* — not what it orchestrates.
- Avoid "orchestrate", "coordinate", "dispatch", "manage workflow" in SKILL.md.
- Include an "Output format" section and 2+ code blocks showing concrete worker behavior.

### Output Quality (weight 0.15)

- Give specific, actionable instructions — not just goals.
- Cover at least one edge case explicitly (empty input, malformed data, etc.).
- Include an examples section showing representative inputs and expected outputs.
- The more concrete the instructions, the higher the judge will score this dimension.

### Scope Calibration (weight 0.12)

- Target 200–600 lines. Below 100 is a stub; above 800 without `references/` is bloat.
- Move background reading, extended examples, and reference tables to `references/`.
- Very narrow skills should be merged with a sibling; very broad ones should be split.

### Progressive Disclosure (weight 0.10)

- Add a `references/` directory (earns 0.15–0.25 bonus) and keep SKILL.md focused on
  the execution path. An `assets/` directory adds a further bonus.

### Token Efficiency (weight 0.06)

- Audit MUST/ALWAYS/NEVER count. Target < 1 per 10 lines.
- Consolidate near-duplicate bullet points and repeated-structure tables.

### Robustness (weight 0.05)

- Add a "Troubleshooting" or "Edge Cases" section covering at least 3 failure modes.
- State what the skill returns when it cannot complete its task.

### Structural Completeness (weight 0.03)

- Ensure at least 4 H2/H3 headings, 3 code blocks, an Examples section, and a Troubleshooting section.

### Code Template Quality (weight 0.02)

- All code blocks must be syntactically valid and copy-paste ready with language tags.

### Ecosystem Coherence (weight 0.02)

- Add a "## Related" section listing sibling skills or agents with relative paths.
- Avoid duplicating content that already exists in another skill — link to it instead.

---

## Troubleshooting

### "Score is much lower than expected after adding content"

The anti-pattern penalty compounds. Run with `--output json` and inspect
`layers[0].anti_patterns`. If you have 5+ anti-patterns, the multiplier can reduce your
score to 75% of its raw value regardless of how good the content is. Fix the flags first.

### "triggering_accuracy is low despite a detailed description"

The `_description_pushiness` scorer looks for specific syntactic patterns, not just length.
Verify your description contains the phrase "Use this skill when" or "Use when" (exact
phrasing matters — it's a regex match). Also check that you have multiple use cases separated
by commas or "or" to earn the specificity bonus.

### "LLM judge scores vary significantly between runs"

This is expected for ambiguous skills. The judge generates 10 mental test prompts
non-deterministically. Improve score stability by tightening the description and adding
concrete examples. When `judges > 1`, averaged scores will be more stable. Use
`--depth deep` with `certify` which runs Monte Carlo to get statistically-bounded scores.

### "progressive_disclosure score is low even though the file is the right length"

Check whether the file is in the 200–600 line sweet spot. Files shorter than 100 lines
score only 0.20 on this sub-check. Also confirm that `references/` files are not empty —
the scorer checks for non-empty reference files, not just the directory.

### "compare shows my rewrite scores lower than the original"

Quick depth (`--depth quick`) only runs static analysis. If the rewrite moved content to
`references/` and shortened SKILL.md significantly, static scores for structural completeness
may drop even though overall quality improved. Run `--depth standard` for a fairer comparison
that includes the LLM judge's assessment of content quality.

---

## References

- [Full Rubric Anchors — all 4 judge dimensions](references/rubrics.md)

### Related Agents

- **eval-judge** (`../../agents/eval-judge.md`) — the LLM judge that scores Layer 2 dimensions
  (`triggering_accuracy`, `orchestration_fitness`, `output_quality`, `scope_calibration`).
  Invoke directly when you need to re-run only the judge layer or inspect its reasoning.
- **eval-orchestrator** (`../../agents/eval-orchestrator.md`) — the top-level orchestrator that
  sequences all three layers, merges results, assigns badges, and writes the final report.
  Invoke when running a full certification pass or comparing two skills head-to-head.

<!-- chapter:end slug=evaluation-methodology -->

---

## Part: PPTX Deck Creation

---

<!-- chapter:begin slug=pptx-deck-context position=121 -->

## 121. pptx-deck-context

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/pptx-deck-creation/skills/pptx-deck-context/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-deck-context/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/pptx-deck-context.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/design-profiles.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-deck-context/references/design-profiles.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: pptx-deck-context
description: "Use when preparing the narrative, sources, and design context for a new editable PPTX deck."
---

# PPTX Deck Context

Prepare the deck before coordinates or PPTX objects are authored. This skill owns the business narrative, source lineage, and design lock.

## Decision sequence

1. Confirm audience, decision, slide count, language, sources, and brand requirements.
2. Use the user-selected narrative framework. If none is specified, offer `mckinsey`, `scqa`, `pyramid`, `mece`, `action-title`, `assertion-evidence`, `exec-summary-first`, or `custom`; do not choose silently.
3. Assign stable source IDs and plan a `source_ref` for every metric, quotation, chart value, and factual claim.
4. Choose a documented design direction. Prefer a user brand guide, then read-only reference-deck evidence, then a reusable profile from `references/design-profiles.md`.
5. Record the framework, assumptions, source manifest, palette, typography, spacing, and signature elements in `summary` before authoring slides.

## Rules

- One slide should communicate one message, with an action-style title where the framework calls for it.
- Treat design references as design evidence, not content or asset sources.
- Do not copy external fonts, images, icons, or logos without recorded licensing evidence.
- Translate design signals into explicit fills, typography, spacing, and bboxes; do not rely on an automatic layout engine.
- Keep long source material concise. Ask for a summary or decision-relevant excerpt instead of turning a deck spec into a document dump.

See `references/design-profiles.md` for reusable profile guidance.

<!-- chapter:end slug=pptx-deck-context -->

---

<!-- chapter:begin slug=pptx-quality-gates position=122 -->

## 122. pptx-quality-gates

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/pptx-deck-creation/skills/pptx-quality-gates/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-quality-gates/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/pptx-quality-gates.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/audit-checklist.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-quality-gates/references/audit-checklist.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: pptx-quality-gates
description: "Use when validating or repairing an editable PPTX deck for geometry, accessibility, native editability, source lineage, and OOXML package integrity."
---

# PPTX Quality Gates

Use this skill before delivering a generated PPTX. Treat deterministic failures as repair work, not exceptions.

## Workflow

1. Confirm the spec, builder, PPTX, source manifest, and audit paths.
2. Apply `references/audit-checklist.md` to the coordinate contract before building.
3. Reopen the PPTX and compare slide count, actual bounds, hidden slides, and requested geometry with the layout tree.
4. For production decks, run `pptx-reference-deck-analysis/scripts/validate_package.py` and save the JSON report.
5. Check document language, slide titles, meaningful-image alt text, reading order, table headers, and source references.
6. When a compatible renderer is already available, inspect previews for clipping, font fallback, contrast, crop, and hierarchy. Do not add a renderer dependency.
7. Repair the spec or task-local builder, rebuild, and rerun the same checks.

## Required artifacts

Keep the spec, PPTX, build record, geometry audit, accessibility audit, package report, and source manifest together. Report any documented exception with slide ID, object ID, owner, reason, and review date.

## Pass criteria

Zero content collisions, text overflows, unsafe content bounds, invalid positive geometry, and package-integrity errors. Meaningful slide content must remain native editable objects; images support rather than replace it.

See `references/audit-checklist.md` for the complete checklist.

<!-- chapter:end slug=pptx-quality-gates -->

---

<!-- chapter:begin slug=pptx-reference-deck-analysis position=123 -->

## 123. pptx-reference-deck-analysis

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/pptx-reference-deck-analysis.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (7), referenced from this skill's directory:
  - `references/ooxml-parsing.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/references/ooxml-parsing.md
  - `references/reference-deck-analysis-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/references/reference-deck-analysis-patterns.md
  - `references/reference-deck-analysis.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/references/reference-deck-analysis.md
  - `requirements.txt` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/requirements.txt
  - `scripts/inspect.py` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/scripts/inspect.py
  - `scripts/unpack.py` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/scripts/unpack.py
  - `scripts/validate_package.py` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-reference-deck-analysis/scripts/validate_package.py

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: pptx-reference-deck-analysis
description: "Use when analyzing a reference PPTX for read-only structure, theme, typography, layout rhythm, diagnostics, derived template catalogs, or safe OOXML package inspection."
---

# PPTX Reference Deck Analysis

Inspect a reference deck as design evidence. This skill never copies, clones, or mutates a source deck.

## Contract

Implement required extraction on demand with a small task-local `python-pptx` script. Capture only the information required for the new deck:

- compact prompt context: slide count and size, text summaries, shape counts, styles, brand signals, template use, and layout rhythm;
- full extraction: `summary`, slides, and read-only `layout_tree` evidence;
- folder diagnostics: one result per deck plus a manifest;
- style-master analysis: colors, fonts, size distribution, master/layout use, and flow patterns;
- derived template catalog: zero-based source indices, layout roles, usable regions, placeholders, visual structures, and constraints.

## Rules

- Keep the source deck read-only and independently author every target-slide coordinate.
- Use the bundled OOXML utilities only for raw themes, relationships, notes, comments, animations, media, masters, or layouts that high-level extraction cannot expose.
- Record inspected parts and parsing exceptions in the analysis manifest.
- Do not use extracted content, fonts, images, or proprietary assets in a generated deck without explicit permission and license evidence.

## OOXML package inspection

Install `defusedxml` from `requirements.txt` before using the bundled utilities.

1. Run `scripts/inspect.py <deck.pptx>` for a compact JSON report of slide order, text, theme tokens, relationships, notes, comments, animations, and media.
2. Run `scripts/validate_package.py <deck.pptx> --output <report.json>` for malformed XML, broken internal relationships, content-type gaps, duplicate layout links, and orphaned parts.
3. Run `scripts/unpack.py <deck.pptx> <output-dir>` only when raw-package evidence is necessary.
4. Resolve relationship targets relative to the `.rels` owner; never infer slide order from filenames.

### Safety

- Never modify a supplied deck or blindly copy package parts into a new deck.
- Run the scripts from a trusted workspace; they reject path traversal, symlinks, oversized members, and archive bombs.
- Parse untrusted XML with `defusedxml`; do not enable entity expansion, DTD loading, or network access.
- Treat theme colors as tokens unless fully resolved against the color scheme.

See `references/reference-deck-analysis.md` for output shapes, `references/reference-deck-analysis-patterns.md` for documentation-only patterns, and `references/ooxml-parsing.md` for package part maps.

<!-- chapter:end slug=pptx-reference-deck-analysis -->

---

<!-- chapter:begin slug=pptx-slide-specification position=124 -->

## 124. pptx-slide-specification

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/pptx-deck-creation/skills/pptx-slide-specification/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-slide-specification/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/pptx-slide-specification.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/layout-contract.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-slide-specification/references/layout-contract.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: pptx-slide-specification
description: "Use when authoring or repairing a coordinate-explicit JSON specification for an editable PPTX deck."
---

# PPTX Slide Specification

Author final coordinates directly in `layout_tree`. No renderer may decide placement, shrink text, or infer layout after the audit.

## Required contract

- The root JSON contains `summary` and `slides`.
- Every slide has a stable `id`, a message-led `title`, an accessibility reading order, and a complete `layout_tree`.
- A layout tree declares slide size, root group, id-keyed groups and objects, final inch bboxes, styles, z-indexes, and classifications.
- Every meaningful object has `id`, `kind`, `role`, `classification`, `content`, `style`, `bbox`, and `z_index`.
- Production `summary` contains an explicit `layout_policy` (safe margin, content bottom, footer top, minimum gap) and accessibility metadata.

## Authoring rules

1. Use stable readable IDs, absolute groups, and positive inch dimensions.
2. Keep normal content inside the safe margin and above the footer rail. Only background `layout_design` objects may be full bleed.
3. Use native `text`, `shape`, `line`, `table`, and `image` objects. Recreate labels and values from any supporting visual as native objects.
4. Give meaningful images alt text. Record `source_ref` for sourced claims.
5. Keep content text at 9 pt or greater; shorten, resize, or split dense content before reducing type.
6. Use shared grids, consistent gaps, explicit color, explicit font size, and an intentional z-order.

## Build contract

A task-local builder starts from a blank slide layout and maps all bboxes with `Inches(...)`. Explicitly set wrapping, disabled auto-size, text insets, anchors, alignment, fonts, colors, line settings, image aspect ratio, and hidden-slide state. Reject zero or negative geometry before adding an object.

See `references/layout-contract.md` for the compact schema and repair guidance.

<!-- chapter:end slug=pptx-slide-specification -->

---

<!-- chapter:begin slug=pptx-visual-assets position=125 -->

## 125. pptx-visual-assets

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/pptx-deck-creation/skills/pptx-visual-assets/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-visual-assets/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/pptx-visual-assets.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/asset-guidance.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/pptx-deck-creation/skills/pptx-visual-assets/references/asset-guidance.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: pptx-visual-assets
description: "Use when selecting and placing approved supporting icons, images, SVGs, diagrams, or infographics in an editable PPTX deck."
---

# PPTX Visual Assets

Use visual assets to support a slide's message, never to flatten or replace editable content.

## Workflow

1. Select the asset type only when it improves comprehension: icon, image, SVG, diagram, or infographic.
2. Confirm the local asset path, source, usage rights, and concise alt text before placement.
3. Add the asset with a final inch bbox, deliberate z-index, and `content` or `layout_design` classification.
4. Preserve aspect ratio and check that no asset covers readable text or leaves essential information locked in an image.

## Rules

- Use simple, legible icons alongside text labels.
- Place captions beside images rather than over them.
- Use true SVG sources only when they are clean vectors; never wrap a raster image in SVG and call it editable.
- Recreate essential labels, legends, values, and process steps with native PowerPoint objects.
- If rights, provenance, or a suitable asset are unavailable, omit the asset and report the gap. Never add a placeholder as a finished visual.
- Record provider or source details in the source manifest. Never request secrets in chat.

See `references/asset-guidance.md` for licensing, placement, and SVG constraints.

<!-- chapter:end slug=pptx-visual-assets -->

---

## Part: Protect MCP

---

<!-- chapter:begin slug=protect-mcp-setup position=126 -->

## 126. protect-mcp-setup

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/protect-mcp/skills/protect-mcp-setup/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/protect-mcp/skills/protect-mcp-setup/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/protect-mcp-setup.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: protect-mcp-setup
description: Configure Cedar policy enforcement and Ed25519 signed receipts for Claude Code tool calls. Use when setting up projects that need cryptographic audit trails, policy-gated tool execution, or compliance-ready evidence of agent actions.
---

# protect-mcp — Policy Enforcement + Signed Receipts

Cryptographic governance for every Claude Code tool call. Each invocation is
evaluated against a Cedar policy and produces an Ed25519-signed receipt that
anyone can verify offline.

## Overview

Claude Code runs powerful tools: `Bash`, `Edit`, `Write`, `WebFetch`. By default
there is no audit trail, no policy enforcement, and no way to prove what was
decided after the fact. `protect-mcp` closes all three gaps:

- **Cedar policies** (AWS's open authorization engine) evaluate every tool call
  before execution. Cedar deny is authoritative.
- **Ed25519 receipts** record each decision with its inputs, the policy that
  governed it, and the outcome. Receipts are hash-chained.
- **Offline verification** via `npx @veritasacta/verify`. No server, no account,
  no trust in the operator.

## Problem

AI agents make decisions that affect money, safety, and rights. The Claude Code
session log records what happened, but the log is:

- Mutable — anyone with access can edit it
- Unsigned — there is no way to prove integrity
- Operator-bound — verification requires trusting whoever holds the log

For compliance contexts (finance, healthcare, regulated research), this is not
sufficient. You need tamper-evident evidence that can be verified by third
parties without trusting you.

## Solution

Add `protect-mcp` to your Claude Code project:

```bash
# 1. Install the plugin (adds hooks + skill to your project)
claude plugin install wshobson/agents/protect-mcp

# 2. Configure hooks in .claude/settings.json (see below)

# 3. Start the receipt-signing server (runs locally, no external calls)
npx protect-mcp@latest serve --enforce

# 4. Use Claude Code normally. Every tool call is now policy-evaluated
#    and produces a signed receipt in ./receipts/
```

## Hook Configuration

Add the following to your project's `.claude/settings.json`:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hook": {
          "type": "command",
          "command": "npx protect-mcp@latest evaluate --policy ./protect.cedar --tool \"$TOOL_NAME\" --input \"$TOOL_INPUT\" || exit 2"
        }
      }
    ],
    "PostToolUse": [
      {
        "matcher": ".*",
        "hook": {
          "type": "command",
          "command": "npx protect-mcp@latest sign --tool \"$TOOL_NAME\" --input \"$TOOL_INPUT\" --output \"$TOOL_OUTPUT\" --receipts ./receipts/"
        }
      }
    ]
  }
}
```

### What each hook does

**PreToolUse** — Runs BEFORE the tool executes. Evaluates the tool call against
your Cedar policy file. If Cedar returns `deny`, the hook exits with code 2 and
Claude Code blocks the tool call entirely.

**PostToolUse** — Runs AFTER the tool completes. Signs a receipt containing the
tool name, input hash, output hash, decision, policy digest, and timestamp.
Writes the receipt to `./receipts/<timestamp>.json`.

## Cedar Policy File

Create `./protect.cedar` at the project root:

```cedar
// Allow read-only tools by default
permit (
    principal,
    action in [Action::"Read", Action::"Glob", Action::"Grep", Action::"WebFetch"],
    resource
);

// Require explicit allow for destructive tools
permit (
    principal,
    action == Action::"Bash",
    resource
) when {
    // Allow safe commands only
    context.command_pattern in ["git", "npm", "ls", "cat", "echo", "pwd", "test"]
};

// Never allow recursive deletion
forbid (
    principal,
    action == Action::"Bash",
    resource
) when {
    context.command_pattern == "rm -rf"
};

// Require confirmation for writes outside the project
forbid (
    principal,
    action in [Action::"Edit", Action::"Write"],
    resource
) when {
    context.path_starts_with != "."
};
```

## Verification

Verify a single receipt:

```bash
npx @veritasacta/verify receipts/2026-04-15T10-30-00Z.json
# Exit 0 = valid
# Exit 1 = tampered
# Exit 2 = malformed
```

Verify the entire chain:

```bash
npx @veritasacta/verify receipts/*.json
```

Use the plugin's slash commands from within Claude Code:

```
/verify-receipt receipts/latest.json
/audit-chain ./receipts/ --last 20
```

## Receipt Format

Each receipt is a JSON file with this structure:

```json
{
  "receipt_id": "rec_8f92a3b1",
  "receipt_version": "1.0",
  "issuer_id": "claude-code-protect-mcp",
  "event_time": "2026-04-15T10:30:00.000Z",
  "tool_name": "Bash",
  "input_hash": "sha256:a3f8...",
  "decision": "allow",
  "policy_id": "autoresearch-safe",
  "policy_digest": "sha256:b7e2...",
  "parent_receipt_id": "rec_3d1ab7c2",
  "public_key": "4437ca56815c0516...",
  "signature": "4cde814b7889e987..."
}
```

- **Ed25519** signatures (RFC 8032)
- **JCS canonicalization** (RFC 8785) before signing
- **Hash-chained** to the previous receipt via `parent_receipt_id`
- **Offline verifiable** — no network call, no vendor lookup

## Why This Matters

| Before | After |
|--------|-------|
| "Trust me, the agent only read files" | Cryptographically provable: every Read logged and signed |
| "The log shows it happened" | The receipt proves it happened, and no one can edit it |
| "You'd have to audit our system" | Anyone can verify every receipt offline |
| "Logs might be different by now" | Ed25519 signatures lock the record at signing time |

## Standards

- **Ed25519** — RFC 8032 (digital signatures)
- **JCS** — RFC 8785 (deterministic JSON canonicalization)
- **Cedar** — AWS's open authorization policy language
- **IETF draft** — [draft-farley-acta-signed-receipts](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/)

## Related

- **npm**: [protect-mcp](https://www.npmjs.com/package/protect-mcp)
- **Verify CLI**: [@veritasacta/verify](https://www.npmjs.com/package/@veritasacta/verify)
- **Source**: [github.com/ScopeBlind/scopeblind-gateway](https://github.com/ScopeBlind/scopeblind-gateway)
- **Protocol**: [veritasacta.com](https://veritasacta.com)
- **Integrations**: Microsoft Agent Governance Toolkit (PR #667), AWS cedar-policy/cedar-for-agents (PR #64)

<!-- chapter:end slug=protect-mcp-setup -->

---

## Part: Python Development

---

<!-- chapter:begin slug=async-python-patterns position=127 -->

## 127. async-python-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/async-python-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/async-python-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/async-python-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/async-python-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: async-python-patterns
description: Master Python asyncio, concurrent programming, and async/await patterns for high-performance applications. Use when building async APIs, concurrent systems, or I/O-bound applications requiring non-blocking operations.
---

# Async Python Patterns

Comprehensive guidance for implementing asynchronous Python applications using asyncio, concurrent programming patterns, and async/await for building high-performance, non-blocking systems.

## When to Use This Skill

- Building async web APIs (FastAPI, aiohttp, Sanic)
- Implementing concurrent I/O operations (database, file, network)
- Creating web scrapers with concurrent requests
- Developing real-time applications (WebSocket servers, chat systems)
- Processing multiple independent tasks simultaneously
- Building microservices with async communication
- Optimizing I/O-bound workloads
- Implementing async background tasks and queues

## Sync vs Async Decision Guide

Before adopting async, consider whether it's the right choice for your use case.

| Use Case | Recommended Approach |
|----------|---------------------|
| Many concurrent network/DB calls | `asyncio` |
| CPU-bound computation | `multiprocessing` or thread pool |
| Mixed I/O + CPU | Offload CPU work with `asyncio.to_thread()` |
| Simple scripts, few connections | Sync (simpler, easier to debug) |
| Web APIs with high concurrency | Async frameworks (FastAPI, aiohttp) |

**Key Rule:** Stay fully sync or fully async within a call path. Mixing creates hidden blocking and complexity.

## Core Concepts

### 1. Event Loop

The event loop is the heart of asyncio, managing and scheduling asynchronous tasks.

**Key characteristics:**

- Single-threaded cooperative multitasking
- Schedules coroutines for execution
- Handles I/O operations without blocking
- Manages callbacks and futures

### 2. Coroutines

Functions defined with `async def` that can be paused and resumed.

**Syntax:**

```python
async def my_coroutine():
    result = await some_async_operation()
    return result
```

### 3. Tasks

Scheduled coroutines that run concurrently on the event loop.

### 4. Futures

Low-level objects representing eventual results of async operations.

### 5. Async Context Managers

Resources that support `async with` for proper cleanup.

### 6. Async Iterators

Objects that support `async for` for iterating over async data sources.

## Quick Start

```python
import asyncio

async def main():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

# Python 3.7+
asyncio.run(main())
```

## Fundamental Patterns

### Pattern 1: Basic Async/Await

```python
import asyncio

async def fetch_data(url: str) -> dict:
    """Fetch data from URL asynchronously."""
    await asyncio.sleep(1)  # Simulate I/O
    return {"url": url, "data": "result"}

async def main():
    result = await fetch_data("https://api.example.com")
    print(result)

asyncio.run(main())
```

### Pattern 2: Concurrent Execution with gather()

```python
import asyncio
from typing import List

async def fetch_user(user_id: int) -> dict:
    """Fetch user data."""
    await asyncio.sleep(0.5)
    return {"id": user_id, "name": f"User {user_id}"}

async def fetch_all_users(user_ids: List[int]) -> List[dict]:
    """Fetch multiple users concurrently."""
    tasks = [fetch_user(uid) for uid in user_ids]
    results = await asyncio.gather(*tasks)
    return results

async def main():
    user_ids = [1, 2, 3, 4, 5]
    users = await fetch_all_users(user_ids)
    print(f"Fetched {len(users)} users")

asyncio.run(main())
```

### Pattern 3: Task Creation and Management

```python
import asyncio

async def background_task(name: str, delay: int):
    """Long-running background task."""
    print(f"{name} started")
    await asyncio.sleep(delay)
    print(f"{name} completed")
    return f"Result from {name}"

async def main():
    # Create tasks
    task1 = asyncio.create_task(background_task("Task 1", 2))
    task2 = asyncio.create_task(background_task("Task 2", 1))

    # Do other work
    print("Main: doing other work")
    await asyncio.sleep(0.5)

    # Wait for tasks
    result1 = await task1
    result2 = await task2

    print(f"Results: {result1}, {result2}")

asyncio.run(main())
```

### Pattern 4: Error Handling in Async Code

```python
import asyncio
from typing import List, Optional

async def risky_operation(item_id: int) -> dict:
    """Operation that might fail."""
    await asyncio.sleep(0.1)
    if item_id % 3 == 0:
        raise ValueError(f"Item {item_id} failed")
    return {"id": item_id, "status": "success"}

async def safe_operation(item_id: int) -> Optional[dict]:
    """Wrapper with error handling."""
    try:
        return await risky_operation(item_id)
    except ValueError as e:
        print(f"Error: {e}")
        return None

async def process_items(item_ids: List[int]):
    """Process multiple items with error handling."""
    tasks = [safe_operation(iid) for iid in item_ids]
    results = await asyncio.gather(*tasks, return_exceptions=True)

    # Filter out failures
    successful = [r for r in results if r is not None and not isinstance(r, Exception)]
    failed = [r for r in results if isinstance(r, Exception)]

    print(f"Success: {len(successful)}, Failed: {len(failed)}")
    return successful

asyncio.run(process_items([1, 2, 3, 4, 5, 6]))
```

### Pattern 5: Timeout Handling

```python
import asyncio

async def slow_operation(delay: int) -> str:
    """Operation that takes time."""
    await asyncio.sleep(delay)
    return f"Completed after {delay}s"

async def with_timeout():
    """Execute operation with timeout."""
    try:
        result = await asyncio.wait_for(slow_operation(5), timeout=2.0)
        print(result)
    except asyncio.TimeoutError:
        print("Operation timed out")

asyncio.run(with_timeout())
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Common Pitfalls

### 1. Forgetting await

```python
# Wrong - returns coroutine object, doesn't execute
result = async_function()

# Correct
result = await async_function()
```

### 2. Blocking the Event Loop

```python
# Wrong - blocks event loop
import time
async def bad():
    time.sleep(1)  # Blocks!

# Correct
async def good():
    await asyncio.sleep(1)  # Non-blocking
```

### 3. Not Handling Cancellation

```python
async def cancelable_task():
    """Task that handles cancellation."""
    try:
        while True:
            await asyncio.sleep(1)
            print("Working...")
    except asyncio.CancelledError:
        print("Task cancelled, cleaning up...")
        # Perform cleanup
        raise  # Re-raise to propagate cancellation
```

### 4. Mixing Sync and Async Code

```python
# Wrong - can't call async from sync directly
def sync_function():
    result = await async_function()  # SyntaxError!

# Correct
def sync_function():
    result = asyncio.run(async_function())
```

## Testing Async Code

```python
import asyncio
import pytest

# Using pytest-asyncio
@pytest.mark.asyncio
async def test_async_function():
    """Test async function."""
    result = await fetch_data("https://api.example.com")
    assert result is not None

@pytest.mark.asyncio
async def test_with_timeout():
    """Test with timeout."""
    with pytest.raises(asyncio.TimeoutError):
        await asyncio.wait_for(slow_operation(5), timeout=1.0)
```

<!-- chapter:end slug=async-python-patterns -->

---

<!-- chapter:begin slug=python-anti-patterns position=128 -->

## 128. python-anti-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-anti-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-anti-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-anti-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-anti-patterns
description: Use this skill when reviewing Python code for common anti-patterns to avoid. Use as a checklist when reviewing code, before finalizing implementations, or when debugging issues that might stem from known bad practices.
---

# Python Anti-Patterns Checklist

A reference checklist of common mistakes and anti-patterns in Python code. Review this before finalizing implementations to catch issues early.

## When to Use This Skill

- Reviewing code before merge
- Debugging mysterious issues
- Teaching or learning Python best practices
- Establishing team coding standards
- Refactoring legacy code

**Note:** This skill focuses on what to avoid. For guidance on positive patterns and architecture, see the `python-design-patterns` skill.

## Infrastructure Anti-Patterns

### Scattered Timeout/Retry Logic

```python
# BAD: Timeout logic duplicated everywhere
def fetch_user(user_id):
    try:
        return requests.get(url, timeout=30)
    except Timeout:
        logger.warning("Timeout fetching user")
        return None

def fetch_orders(user_id):
    try:
        return requests.get(url, timeout=30)
    except Timeout:
        logger.warning("Timeout fetching orders")
        return None
```

**Fix:** Centralize in decorators or client wrappers.

```python
# GOOD: Centralized retry logic
@retry(stop=stop_after_attempt(3), wait=wait_exponential())
def http_get(url: str) -> Response:
    return requests.get(url, timeout=30)
```

### Double Retry

```python
# BAD: Retrying at multiple layers
@retry(max_attempts=3)  # Application retry
def call_service():
    return client.request()  # Client also has retry configured!
```

**Fix:** Retry at one layer only. Know your infrastructure's retry behavior.

### Hard-Coded Configuration

```python
# BAD: Secrets and config in code
DB_HOST = "prod-db.example.com"
API_KEY = "sk-12345"

def connect():
    return psycopg.connect(f"host={DB_HOST}...")
```

**Fix:** Use environment variables with typed settings.

```python
# GOOD
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    db_host: str = Field(alias="DB_HOST")
    api_key: str = Field(alias="API_KEY")

settings = Settings()
```

## Architecture Anti-Patterns

### Exposed Internal Types

```python
# BAD: Leaking ORM model to API
@app.get("/users/{id}")
def get_user(id: str) -> UserModel:  # SQLAlchemy model
    return db.query(UserModel).get(id)
```

**Fix:** Use DTOs/response models.

```python
# GOOD
@app.get("/users/{id}")
def get_user(id: str) -> UserResponse:
    user = db.query(UserModel).get(id)
    return UserResponse.from_orm(user)
```

### Mixed I/O and Business Logic

```python
# BAD: SQL embedded in business logic
def calculate_discount(user_id: str) -> float:
    user = db.query("SELECT * FROM users WHERE id = ?", user_id)
    orders = db.query("SELECT * FROM orders WHERE user_id = ?", user_id)
    # Business logic mixed with data access
    if len(orders) > 10:
        return 0.15
    return 0.0
```

**Fix:** Repository pattern. Keep business logic pure.

```python
# GOOD
def calculate_discount(user: User, orders: list[Order]) -> float:
    # Pure business logic, easily testable
    if len(orders) > 10:
        return 0.15
    return 0.0
```

## Error Handling Anti-Patterns

### Bare Exception Handling

```python
# BAD: Swallowing all exceptions
try:
    process()
except Exception:
    pass  # Silent failure - bugs hidden forever
```

**Fix:** Catch specific exceptions. Log or handle appropriately.

```python
# GOOD
try:
    process()
except ConnectionError as e:
    logger.warning("Connection failed, will retry", error=str(e))
    raise
except ValueError as e:
    logger.error("Invalid input", error=str(e))
    raise BadRequestError(str(e))
```

### Ignored Partial Failures

```python
# BAD: Stops on first error
def process_batch(items):
    results = []
    for item in items:
        result = process(item)  # Raises on error - batch aborted
        results.append(result)
    return results
```

**Fix:** Capture both successes and failures.

```python
# GOOD
def process_batch(items) -> BatchResult:
    succeeded = {}
    failed = {}
    for idx, item in enumerate(items):
        try:
            succeeded[idx] = process(item)
        except Exception as e:
            failed[idx] = e
    return BatchResult(succeeded, failed)
```

### Missing Input Validation

```python
# BAD: No validation
def create_user(data: dict):
    return User(**data)  # Crashes deep in code on bad input
```

**Fix:** Validate early at API boundaries.

```python
# GOOD
def create_user(data: dict) -> User:
    validated = CreateUserInput.model_validate(data)
    return User.from_input(validated)
```

## Resource Anti-Patterns

### Unclosed Resources

```python
# BAD: File never closed
def read_file(path):
    f = open(path)
    return f.read()  # What if this raises?
```

**Fix:** Use context managers.

```python
# GOOD
def read_file(path):
    with open(path) as f:
        return f.read()
```

### Blocking in Async

```python
# BAD: Blocks the entire event loop
async def fetch_data():
    time.sleep(1)  # Blocks everything!
    response = requests.get(url)  # Also blocks!
```

**Fix:** Use async-native libraries.

```python
# GOOD
async def fetch_data():
    await asyncio.sleep(1)
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
```

## Type Safety Anti-Patterns

### Missing Type Hints

```python
# BAD: No types
def process(data):
    return data["value"] * 2
```

**Fix:** Annotate all public functions.

```python
# GOOD
def process(data: dict[str, int]) -> int:
    return data["value"] * 2
```

### Untyped Collections

```python
# BAD: Generic list without type parameter
def get_users() -> list:
    ...
```

**Fix:** Use type parameters.

```python
# GOOD
def get_users() -> list[User]:
    ...
```

## Testing Anti-Patterns

### Only Testing Happy Paths

```python
# BAD: Only tests success case
def test_create_user():
    user = service.create_user(valid_data)
    assert user.id is not None
```

**Fix:** Test error conditions and edge cases.

```python
# GOOD
def test_create_user_success():
    user = service.create_user(valid_data)
    assert user.id is not None

def test_create_user_invalid_email():
    with pytest.raises(ValueError, match="Invalid email"):
        service.create_user(invalid_email_data)

def test_create_user_duplicate_email():
    service.create_user(valid_data)
    with pytest.raises(ConflictError):
        service.create_user(valid_data)
```

### Over-Mocking

```python
# BAD: Mocking everything
def test_user_service():
    mock_repo = Mock()
    mock_cache = Mock()
    mock_logger = Mock()
    mock_metrics = Mock()
    # Test doesn't verify real behavior
```

**Fix:** Use integration tests for critical paths. Mock only external services.

## Quick Review Checklist

Before finalizing code, verify:

- [ ] No scattered timeout/retry logic (centralized)
- [ ] No double retry (app + infrastructure)
- [ ] No hard-coded configuration or secrets
- [ ] No exposed internal types (ORM models, protobufs)
- [ ] No mixed I/O and business logic
- [ ] No bare `except Exception: pass`
- [ ] No ignored partial failures in batches
- [ ] No missing input validation
- [ ] No unclosed resources (using context managers)
- [ ] No blocking calls in async code
- [ ] All public functions have type hints
- [ ] Collections have type parameters
- [ ] Error paths are tested
- [ ] Edge cases are covered

## Common Fixes Summary

| Anti-Pattern | Fix |
|-------------|-----|
| Scattered retry logic | Centralized decorators |
| Hard-coded config | Environment variables + pydantic-settings |
| Exposed ORM models | DTO/response schemas |
| Mixed I/O + logic | Repository pattern |
| Bare except | Catch specific exceptions |
| Batch stops on error | Return BatchResult with successes/failures |
| No validation | Validate at boundaries with Pydantic |
| Unclosed resources | Context managers |
| Blocking in async | Async-native libraries |
| Missing types | Type annotations on all public APIs |
| Only happy path tests | Test errors and edge cases |

<!-- chapter:end slug=python-anti-patterns -->

---

<!-- chapter:begin slug=python-background-jobs position=129 -->

## 129. python-background-jobs

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-background-jobs/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-background-jobs/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-background-jobs.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-background-jobs/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-background-jobs
description: Python background job patterns including task queues, workers, and event-driven architecture. Use when implementing async task processing, job queues, long-running operations, or decoupling work from request/response cycles.
---

# Python Background Jobs & Task Queues

Decouple long-running or unreliable work from request/response cycles. Return immediately to the user while background workers handle the heavy lifting asynchronously.

## When to Use This Skill

- Processing tasks that take longer than a few seconds
- Sending emails, notifications, or webhooks
- Generating reports or exporting data
- Processing uploads or media transformations
- Integrating with unreliable external services
- Building event-driven architectures

## Core Concepts

### 1. Task Queue Pattern

API accepts request, enqueues a job, returns immediately with a job ID. Workers process jobs asynchronously.

### 2. Idempotency

Tasks may be retried on failure. Design for safe re-execution.

### 3. Job State Machine

Jobs transition through states: pending → running → succeeded/failed.

### 4. At-Least-Once Delivery

Most queues guarantee at-least-once delivery. Your code must handle duplicates.

## Quick Start

This skill uses Celery for examples, a widely adopted task queue. Alternatives like RQ, Dramatiq, and cloud-native solutions (AWS SQS, GCP Tasks) are equally valid choices.

```python
from celery import Celery

app = Celery("tasks", broker="redis://localhost:6379")

@app.task
def send_email(to: str, subject: str, body: str) -> None:
    # This runs in a background worker
    email_client.send(to, subject, body)

# In your API handler
send_email.delay("user@example.com", "Welcome!", "Thanks for signing up")
```

## Fundamental Patterns

### Pattern 1: Return Job ID Immediately

For operations exceeding a few seconds, return a job ID and process asynchronously.

```python
from uuid import uuid4
from dataclasses import dataclass
from enum import Enum
from datetime import datetime

class JobStatus(Enum):
    PENDING = "pending"
    RUNNING = "running"
    SUCCEEDED = "succeeded"
    FAILED = "failed"

@dataclass
class Job:
    id: str
    status: JobStatus
    created_at: datetime
    started_at: datetime | None = None
    completed_at: datetime | None = None
    result: dict | None = None
    error: str | None = None

# API endpoint
async def start_export(request: ExportRequest) -> JobResponse:
    """Start export job and return job ID."""
    job_id = str(uuid4())

    # Persist job record
    await jobs_repo.create(Job(
        id=job_id,
        status=JobStatus.PENDING,
        created_at=datetime.utcnow(),
    ))

    # Enqueue task for background processing
    await task_queue.enqueue(
        "export_data",
        job_id=job_id,
        params=request.model_dump(),
    )

    # Return immediately with job ID
    return JobResponse(
        job_id=job_id,
        status="pending",
        poll_url=f"/jobs/{job_id}",
    )
```

### Pattern 2: Celery Task Configuration

Configure Celery tasks with proper retry and timeout settings.

```python
from celery import Celery

app = Celery("tasks", broker="redis://localhost:6379")

# Global configuration
app.conf.update(
    task_time_limit=3600,          # Hard limit: 1 hour
    task_soft_time_limit=3000,      # Soft limit: 50 minutes
    task_acks_late=True,            # Acknowledge after completion
    task_reject_on_worker_lost=True,
    worker_prefetch_multiplier=1,   # Don't prefetch too many tasks
)

@app.task(
    bind=True,
    max_retries=3,
    default_retry_delay=60,
    autoretry_for=(ConnectionError, TimeoutError),
)
def process_payment(self, payment_id: str) -> dict:
    """Process payment with automatic retry on transient errors."""
    try:
        result = payment_gateway.charge(payment_id)
        return {"status": "success", "transaction_id": result.id}
    except PaymentDeclinedError as e:
        # Don't retry permanent failures
        return {"status": "declined", "reason": str(e)}
    except TransientError as e:
        # Retry with exponential backoff
        raise self.retry(exc=e, countdown=2 ** self.request.retries * 60)
```

### Pattern 3: Make Tasks Idempotent

Workers may retry on crash or timeout. Design for safe re-execution.

```python
@app.task(bind=True)
def process_order(self, order_id: str) -> None:
    """Process order idempotently."""
    order = orders_repo.get(order_id)

    # Already processed? Return early
    if order.status == OrderStatus.COMPLETED:
        logger.info("Order already processed", order_id=order_id)
        return

    # Already in progress? Check if we should continue
    if order.status == OrderStatus.PROCESSING:
        # Use idempotency key to avoid double-charging
        pass

    # Process with idempotency key
    result = payment_provider.charge(
        amount=order.total,
        idempotency_key=f"order-{order_id}",  # Critical!
    )

    orders_repo.update(order_id, status=OrderStatus.COMPLETED)
```

**Idempotency Strategies:**

1. **Check-before-write**: Verify state before action
2. **Idempotency keys**: Use unique tokens with external services
3. **Upsert patterns**: `INSERT ... ON CONFLICT UPDATE`
4. **Deduplication window**: Track processed IDs for N hours

### Pattern 4: Job State Management

Persist job state transitions for visibility and debugging.

```python
class JobRepository:
    """Repository for managing job state."""

    async def create(self, job: Job) -> Job:
        """Create new job record."""
        await self._db.execute(
            """INSERT INTO jobs (id, status, created_at)
               VALUES ($1, $2, $3)""",
            job.id, job.status.value, job.created_at,
        )
        return job

    async def update_status(
        self,
        job_id: str,
        status: JobStatus,
        **fields,
    ) -> None:
        """Update job status with timestamp."""
        updates = {"status": status.value, **fields}

        if status == JobStatus.RUNNING:
            updates["started_at"] = datetime.utcnow()
        elif status in (JobStatus.SUCCEEDED, JobStatus.FAILED):
            updates["completed_at"] = datetime.utcnow()

        await self._db.execute(
            "UPDATE jobs SET status = $1, ... WHERE id = $2",
            updates, job_id,
        )

        logger.info(
            "Job status updated",
            job_id=job_id,
            status=status.value,
        )
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Return immediately** - Don't block requests for long operations
2. **Persist job state** - Enable status polling and debugging
3. **Make tasks idempotent** - Safe to retry on any failure
4. **Use idempotency keys** - For external service calls
5. **Set timeouts** - Both soft and hard limits
6. **Implement DLQ** - Capture permanently failed tasks
7. **Log transitions** - Track job state changes
8. **Retry appropriately** - Exponential backoff for transient errors
9. **Don't retry permanent failures** - Validation errors, invalid credentials
10. **Monitor queue depth** - Alert on backlog growth

<!-- chapter:end slug=python-background-jobs -->

---

<!-- chapter:begin slug=python-code-style position=130 -->

## 130. python-code-style

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-code-style/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-code-style/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-code-style.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-code-style
description: Python code style, linting, formatting, naming conventions, and documentation standards. Use when writing new code, reviewing style, configuring linters, writing docstrings, or establishing project standards.
---

# Python Code Style & Documentation

Consistent code style and clear documentation make codebases maintainable and collaborative. This skill covers modern Python tooling, naming conventions, and documentation standards.

## When to Use This Skill

- Setting up linting and formatting for a new project
- Writing or reviewing docstrings
- Establishing team coding standards
- Configuring ruff, mypy, or pyright
- Reviewing code for style consistency
- Creating project documentation

## Core Concepts

### 1. Automated Formatting

Let tools handle formatting debates. Configure once, enforce automatically.

### 2. Consistent Naming

Follow PEP 8 conventions with meaningful, descriptive names.

### 3. Documentation as Code

Docstrings should be maintained alongside the code they describe.

### 4. Type Annotations

Modern Python code should include type hints for all public APIs.

## Quick Start

```bash
# Install modern tooling
pip install ruff mypy

# Configure in pyproject.toml
[tool.ruff]
line-length = 120
target-version = "py312"  # Adjust based on your project's minimum Python version

[tool.mypy]
strict = true
```

## Fundamental Patterns

### Pattern 1: Modern Python Tooling

Use `ruff` as an all-in-one linter and formatter. It replaces flake8, isort, and black with a single fast tool.

```toml
# pyproject.toml
[tool.ruff]
line-length = 120
target-version = "py312"  # Adjust based on your project's minimum Python version

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort
    "B",    # flake8-bugbear
    "C4",   # flake8-comprehensions
    "UP",   # pyupgrade
    "SIM",  # flake8-simplify
]
ignore = ["E501"]  # Line length handled by formatter

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
```

Run with:

```bash
ruff check --fix .  # Lint and auto-fix
ruff format .       # Format code
```

### Pattern 2: Type Checking Configuration

Configure strict type checking for production code.

```toml
# pyproject.toml
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true
disallow_incomplete_defs = true

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
```

Alternative: Use `pyright` for faster checking.

```toml
[tool.pyright]
pythonVersion = "3.12"
typeCheckingMode = "strict"
```

### Pattern 3: Naming Conventions

Follow PEP 8 with emphasis on clarity over brevity.

**Files and Modules:**

```python
# Good: Descriptive snake_case
user_repository.py
order_processing.py
http_client.py

# Avoid: Abbreviations
usr_repo.py
ord_proc.py
http_cli.py
```

**Classes and Functions:**

```python
# Classes: PascalCase
class UserRepository:
    pass

class HTTPClientFactory:  # Acronyms stay uppercase
    pass

# Functions and variables: snake_case
def get_user_by_email(email: str) -> User | None:
    retry_count = 3
    max_connections = 100
```

**Constants:**

```python
# Module-level constants: SCREAMING_SNAKE_CASE
MAX_RETRY_ATTEMPTS = 3
DEFAULT_TIMEOUT_SECONDS = 30
API_BASE_URL = "https://api.example.com"
```

### Pattern 4: Import Organization

Group imports in a consistent order: standard library, third-party, local.

```python
# Standard library
import os
from collections.abc import Callable
from typing import Any

# Third-party packages
import httpx
from pydantic import BaseModel
from sqlalchemy import Column

# Local imports
from myproject.models import User
from myproject.services import UserService
```

Use absolute imports exclusively:

```python
# Preferred
from myproject.utils import retry_decorator

# Avoid relative imports
from ..utils import retry_decorator
```

## Advanced Patterns

### Pattern 5: Google-Style Docstrings

Write docstrings for all public classes, methods, and functions.

**Simple Function:**

```python
def get_user(user_id: str) -> User:
    """Retrieve a user by their unique identifier."""
    ...
```

**Complex Function:**

```python
def process_batch(
    items: list[Item],
    max_workers: int = 4,
    on_progress: Callable[[int, int], None] | None = None,
) -> BatchResult:
    """Process items concurrently using a worker pool.

    Processes each item in the batch using the configured number of
    workers. Progress can be monitored via the optional callback.

    Args:
        items: The items to process. Must not be empty.
        max_workers: Maximum concurrent workers. Defaults to 4.
        on_progress: Optional callback receiving (completed, total) counts.

    Returns:
        BatchResult containing succeeded items and any failures with
        their associated exceptions.

    Raises:
        ValueError: If items is empty.
        ProcessingError: If the batch cannot be processed.

    Example:
        >>> result = process_batch(items, max_workers=8)
        >>> print(f"Processed {len(result.succeeded)} items")
    """
    ...
```

**Class Docstring:**

```python
class UserService:
    """Service for managing user operations.

    Provides methods for creating, retrieving, updating, and
    deleting users with proper validation and error handling.

    Attributes:
        repository: The data access layer for user persistence.
        logger: Logger instance for operation tracking.

    Example:
        >>> service = UserService(repository, logger)
        >>> user = service.create_user(CreateUserInput(...))
    """

    def __init__(self, repository: UserRepository, logger: Logger) -> None:
        """Initialize the user service.

        Args:
            repository: Data access layer for users.
            logger: Logger for tracking operations.
        """
        self.repository = repository
        self.logger = logger
```

### Pattern 6: Line Length and Formatting

Set line length to 120 characters for modern displays while maintaining readability.

```python
# Good: Readable line breaks
def create_user(
    email: str,
    name: str,
    role: UserRole = UserRole.MEMBER,
    notify: bool = True,
) -> User:
    ...

# Good: Chain method calls clearly
result = (
    db.query(User)
    .filter(User.active == True)
    .order_by(User.created_at.desc())
    .limit(10)
    .all()
)

# Good: Format long strings
error_message = (
    f"Failed to process user {user_id}: "
    f"received status {response.status_code} "
    f"with body {response.text[:100]}"
)
```

### Pattern 7: Project Documentation

**README Structure:**

```markdown
# Project Name

Brief description of what the project does.

## Installation

\`\`\`bash
pip install myproject
\`\`\`

## Quick Start

\`\`\`python
from myproject import Client

client = Client(api_key="...")
result = client.process(data)
\`\`\`

## Configuration

Document environment variables and configuration options.

## Development

\`\`\`bash
pip install -e ".[dev]"
pytest
\`\`\`
```

**CHANGELOG Format (Keep a Changelog):**

```markdown
# Changelog

## [Unreleased]

### Added
- New feature X

### Changed
- Modified behavior of Y

### Fixed
- Bug in Z
```

## Best Practices Summary

1. **Use ruff** - Single tool for linting and formatting
2. **Enable strict mypy** - Catch type errors before runtime
3. **120 character lines** - Modern standard for readability
4. **Descriptive names** - Clarity over brevity
5. **Absolute imports** - More maintainable than relative
6. **Google-style docstrings** - Consistent, readable documentation
7. **Document public APIs** - Every public function needs a docstring
8. **Keep docs updated** - Treat documentation as code
9. **Automate in CI** - Run linters on every commit
10. **Target Python 3.10+** - For new projects, Python 3.12+ is recommended for modern language features

<!-- chapter:end slug=python-code-style -->

---

<!-- chapter:begin slug=python-configuration position=131 -->

## 131. python-configuration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-configuration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-configuration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-configuration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-configuration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-configuration
description: Python configuration management via environment variables and typed settings. Use when externalizing config, setting up pydantic-settings, managing secrets, or implementing environment-specific behavior.
---

# Python Configuration Management

Externalize configuration from code using environment variables and typed settings. Well-managed configuration enables the same code to run in any environment without modification.

## When to Use This Skill

- Setting up a new project's configuration system
- Migrating from hardcoded values to environment variables
- Implementing pydantic-settings for typed configuration
- Managing secrets and sensitive values
- Creating environment-specific settings (dev/staging/prod)
- Validating configuration at application startup

## Core Concepts

### 1. Externalized Configuration

All environment-specific values (URLs, secrets, feature flags) come from environment variables, not code.

### 2. Typed Settings

Parse and validate configuration into typed objects at startup, not scattered throughout code.

### 3. Fail Fast

Validate all required configuration at application boot. Missing config should crash immediately with a clear message.

### 4. Sensible Defaults

Provide reasonable defaults for local development while requiring explicit values for sensitive settings.

## Quick Start

```python
from pydantic_settings import BaseSettings
from pydantic import Field

class Settings(BaseSettings):
    database_url: str = Field(alias="DATABASE_URL")
    api_key: str = Field(alias="API_KEY")
    debug: bool = Field(default=False, alias="DEBUG")

settings = Settings()  # Loads from environment
```

## Fundamental Patterns

### Pattern 1: Typed Settings with Pydantic

Create a central settings class that loads and validates all configuration.

```python
from pydantic_settings import BaseSettings
from pydantic import Field, PostgresDsn, ValidationError
import sys

class Settings(BaseSettings):
    """Application configuration loaded from environment variables."""

    # Database
    db_host: str = Field(alias="DB_HOST")
    db_port: int = Field(default=5432, alias="DB_PORT")
    db_name: str = Field(alias="DB_NAME")
    db_user: str = Field(alias="DB_USER")
    db_password: str = Field(alias="DB_PASSWORD")

    # Redis
    redis_url: str = Field(default="redis://localhost:6379", alias="REDIS_URL")

    # API Keys
    api_secret_key: str = Field(alias="API_SECRET_KEY")

    # Feature flags
    enable_new_feature: bool = Field(default=False, alias="ENABLE_NEW_FEATURE")

    model_config = {
        "env_file": ".env",
        "env_file_encoding": "utf-8",
    }

# Create singleton instance at module load
try:
    settings = Settings()
except ValidationError as e:
    print(f"Configuration error:\n{e}")
    sys.exit(1)
```

Import `settings` throughout your application:

```python
from myapp.config import settings

def get_database_connection():
    return connect(
        host=settings.db_host,
        port=settings.db_port,
        database=settings.db_name,
    )
```

### Pattern 2: Fail Fast on Missing Configuration

Required settings should crash the application immediately with a clear error.

```python
from pydantic_settings import BaseSettings
from pydantic import Field, ValidationError
import sys

class Settings(BaseSettings):
    # Required - no default means it must be set
    api_key: str = Field(alias="API_KEY")
    database_url: str = Field(alias="DATABASE_URL")

    # Optional with defaults
    log_level: str = Field(default="INFO", alias="LOG_LEVEL")

try:
    settings = Settings()
except ValidationError as e:
    print("=" * 60)
    print("CONFIGURATION ERROR")
    print("=" * 60)
    for error in e.errors():
        field = error["loc"][0]
        print(f"  - {field}: {error['msg']}")
    print("\nPlease set the required environment variables.")
    sys.exit(1)
```

A clear error at startup is better than a cryptic `None` failure mid-request.

### Pattern 3: Local Development Defaults

Provide sensible defaults for local development while requiring explicit values for secrets.

```python
class Settings(BaseSettings):
    # Has local default, but prod will override
    db_host: str = Field(default="localhost", alias="DB_HOST")
    db_port: int = Field(default=5432, alias="DB_PORT")

    # Always required - no default for secrets
    db_password: str = Field(alias="DB_PASSWORD")
    api_secret_key: str = Field(alias="API_SECRET_KEY")

    # Development convenience
    debug: bool = Field(default=False, alias="DEBUG")

    model_config = {"env_file": ".env"}
```

Create a `.env` file for local development (never commit this):

```bash
# .env (add to .gitignore)
DB_PASSWORD=local_dev_password
API_SECRET_KEY=dev-secret-key
DEBUG=true
```

### Pattern 4: Namespaced Environment Variables

Prefix related variables for clarity and easy debugging.

```bash
# Database configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=admin
DB_PASSWORD=secret

# Redis configuration
REDIS_URL=redis://localhost:6379
REDIS_MAX_CONNECTIONS=10

# Authentication
AUTH_SECRET_KEY=your-secret-key
AUTH_TOKEN_EXPIRY_SECONDS=3600
AUTH_ALGORITHM=HS256

# Feature flags
FEATURE_NEW_CHECKOUT=true
FEATURE_BETA_UI=false
```

Makes `env | grep DB_` useful for debugging.

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Never hardcode config** - All environment-specific values from env vars
2. **Use typed settings** - Pydantic-settings with validation
3. **Fail fast** - Crash on missing required config at startup
4. **Provide dev defaults** - Make local development easy
5. **Never commit secrets** - Use `.env` files (gitignored) or secret managers
6. **Namespace variables** - `DB_HOST`, `REDIS_URL` for clarity
7. **Import settings singleton** - Don't call `os.getenv()` throughout code
8. **Document all variables** - README should list required env vars
9. **Validate early** - Check config correctness at boot time
10. **Use secrets_dir** - Support mounted secrets in containers

<!-- chapter:end slug=python-configuration -->

---

<!-- chapter:begin slug=python-design-patterns position=132 -->

## 132. python-design-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-design-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-design-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-design-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-design-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-design-patterns
description: Python design patterns including KISS, Separation of Concerns, Single Responsibility, and composition over inheritance. Use this skill when designing a new service or component from scratch and choosing how to layer responsibilities, when refactoring a God class or monolithic function that has grown too large, when deciding whether to add a new abstraction or live with duplication, when evaluating a pull request for structural issues like tight coupling or leaking internal types, when choosing between inheritance and composition for a new class hierarchy, or when a codebase is becoming hard to test because of entangled I/O and business logic.
---

# Python Design Patterns

Write maintainable Python code using fundamental design principles. These patterns help you build systems that are easy to understand, test, and modify.

## When to Use This Skill

- Designing new components or services
- Refactoring complex or tangled code
- Deciding whether to create an abstraction
- Choosing between inheritance and composition
- Evaluating code complexity and coupling
- Planning modular architectures

## Core Concepts

### 1. KISS (Keep It Simple)

Choose the simplest solution that works. Complexity must be justified by concrete requirements.

### 2. Single Responsibility (SRP)

Each unit should have one reason to change. Separate concerns into focused components.

### 3. Composition Over Inheritance

Build behavior by combining objects, not extending classes.

### 4. Rule of Three

Wait until you have three instances before abstracting. Duplication is often better than premature abstraction.

## Quick Start

```python
# Simple beats clever
# Instead of a factory/registry pattern:
FORMATTERS = {"json": JsonFormatter, "csv": CsvFormatter}

def get_formatter(name: str) -> Formatter:
    return FORMATTERS[name]()
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices Summary

1. **Keep it simple** - Choose the simplest solution that works
2. **Single responsibility** - Each unit has one reason to change
3. **Separate concerns** - Distinct layers with clear purposes
4. **Compose, don't inherit** - Combine objects for flexibility
5. **Rule of three** - Wait before abstracting
6. **Keep functions small** - 20-50 lines (varies by complexity), one purpose
7. **Inject dependencies** - Constructor injection for testability
8. **Delete before abstracting** - Remove dead code, then consider patterns
9. **Test each layer** - Isolated tests for each concern
10. **Explicit over clever** - Readable code beats elegant code

## Troubleshooting

**A class is growing and seems to have multiple responsibilities, but splitting it feels wrong.**
Apply the "reason to change" test: list every change that could require editing this class. If the list has items from different domains (e.g., HTTP parsing AND business rules AND formatting), split it. If all changes stem from the same domain concern, the class may be appropriately sized.

**Injecting all dependencies through the constructor is producing constructors with 7+ parameters.**
This is a sign of too many responsibilities in one class, not a problem with dependency injection. Split the class into smaller units first, then each constructor naturally becomes smaller.

**Composition is producing deeply nested wrapper objects that are hard to trace.**
Keep the composition shallow (2-3 levels). If wrapping is the only mechanism, consider whether a Protocol-based approach or simple function composition would be cleaner than a chain of decorator objects.

**The rule of three says not to abstract yet, but the duplication is causing bugs when one copy is updated but not the other.**
Duplication that diverges in dangerous ways should be abstracted sooner. The rule of three is a heuristic, not a law. If the copies are already diverging incorrectly, extract immediately and add a test that exercises the shared behavior.

**A service layer is importing from the API layer, breaking the dependency direction.**
This is a layering violation. The service layer must not import from handlers. Introduce a shared types/models layer that both can import from, keeping the dependency arrow pointing downward (API → Service → Repository).

## Related Skills

- [python-testing-patterns](../python-testing-patterns/SKILL.md) — Test each layer in isolation using the dependency injection structure established here
- [python-project-setup](../python-project-setup/SKILL.md) — Set up project structure and tooling that enforces layer boundaries from the start

<!-- chapter:end slug=python-design-patterns -->

---

<!-- chapter:begin slug=python-error-handling position=133 -->

## 133. python-error-handling

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-error-handling/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-error-handling/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-error-handling.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-error-handling/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-error-handling
description: Python error handling patterns including input validation, exception hierarchies, and partial failure handling. Use when implementing validation logic, designing exception strategies, handling batch processing failures, or building robust APIs.
---

# Python Error Handling

Build robust Python applications with proper input validation, meaningful exceptions, and graceful failure handling. Good error handling makes debugging easier and systems more reliable.

## When to Use This Skill

- Validating user input and API parameters
- Designing exception hierarchies for applications
- Handling partial failures in batch operations
- Converting external data to domain types
- Building user-friendly error messages
- Implementing fail-fast validation patterns

## Core Concepts

### 1. Fail Fast

Validate inputs early, before expensive operations. Report all validation errors at once when possible.

### 2. Meaningful Exceptions

Use appropriate exception types with context. Messages should explain what failed, why, and how to fix it.

### 3. Partial Failures

In batch operations, don't let one failure abort everything. Track successes and failures separately.

### 4. Preserve Context

Chain exceptions to maintain the full error trail for debugging.

## Quick Start

```python
def fetch_page(url: str, page_size: int) -> Page:
    if not url:
        raise ValueError("'url' is required")
    if not 1 <= page_size <= 100:
        raise ValueError(f"'page_size' must be 1-100, got {page_size}")
    # Now safe to proceed...
```

## Fundamental Patterns

### Pattern 1: Early Input Validation

Validate all inputs at API boundaries before any processing begins.

```python
def process_order(
    order_id: str,
    quantity: int,
    discount_percent: float,
) -> OrderResult:
    """Process an order with validation."""
    # Validate required fields
    if not order_id:
        raise ValueError("'order_id' is required")

    # Validate ranges
    if quantity <= 0:
        raise ValueError(f"'quantity' must be positive, got {quantity}")

    if not 0 <= discount_percent <= 100:
        raise ValueError(
            f"'discount_percent' must be 0-100, got {discount_percent}"
        )

    # Validation passed, proceed with processing
    return _process_validated_order(order_id, quantity, discount_percent)
```

### Pattern 2: Convert to Domain Types Early

Parse strings and external data into typed domain objects at system boundaries.

```python
from enum import Enum

class OutputFormat(Enum):
    JSON = "json"
    CSV = "csv"
    PARQUET = "parquet"

def parse_output_format(value: str) -> OutputFormat:
    """Parse string to OutputFormat enum.

    Args:
        value: Format string from user input.

    Returns:
        Validated OutputFormat enum member.

    Raises:
        ValueError: If format is not recognized.
    """
    try:
        return OutputFormat(value.lower())
    except ValueError:
        valid_formats = [f.value for f in OutputFormat]
        raise ValueError(
            f"Invalid format '{value}'. "
            f"Valid options: {', '.join(valid_formats)}"
        )

# Usage at API boundary
def export_data(data: list[dict], format_str: str) -> bytes:
    output_format = parse_output_format(format_str)  # Fail fast
    # Rest of function uses typed OutputFormat
    ...
```

### Pattern 3: Pydantic for Complex Validation

Use Pydantic models for structured input validation with automatic error messages.

```python
from pydantic import BaseModel, Field, field_validator

class CreateUserInput(BaseModel):
    """Input model for user creation."""

    email: str = Field(..., min_length=5, max_length=255)
    name: str = Field(..., min_length=1, max_length=100)
    age: int = Field(ge=0, le=150)

    @field_validator("email")
    @classmethod
    def validate_email_format(cls, v: str) -> str:
        if "@" not in v or "." not in v.split("@")[-1]:
            raise ValueError("Invalid email format")
        return v.lower()

    @field_validator("name")
    @classmethod
    def normalize_name(cls, v: str) -> str:
        return v.strip().title()

# Usage
try:
    user_input = CreateUserInput(
        email="user@example.com",
        name="john doe",
        age=25,
    )
except ValidationError as e:
    # Pydantic provides detailed error information
    print(e.errors())
```

### Pattern 4: Map Errors to Standard Exceptions

Use Python's built-in exception types appropriately, adding context as needed.

| Failure Type | Exception | Example |
|--------------|-----------|---------|
| Invalid input | `ValueError` | Bad parameter values |
| Wrong type | `TypeError` | Expected string, got int |
| Missing item | `KeyError` | Dict key not found |
| Operational failure | `RuntimeError` | Service unavailable |
| Timeout | `TimeoutError` | Operation took too long |
| File not found | `FileNotFoundError` | Path doesn't exist |
| Permission denied | `PermissionError` | Access forbidden |

```python
# Good: Specific exception with context
raise ValueError(f"'page_size' must be 1-100, got {page_size}")

# Avoid: Generic exception, no context
raise Exception("Invalid parameter")
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Validate early** - Check inputs before expensive operations
2. **Use specific exceptions** - `ValueError`, `TypeError`, not generic `Exception`
3. **Include context** - Messages should explain what, why, and how to fix
4. **Convert types at boundaries** - Parse strings to enums/domain types early
5. **Chain exceptions** - Use `raise ... from e` to preserve debug info
6. **Handle partial failures** - Don't abort batches on single item errors
7. **Use Pydantic** - For complex input validation with structured errors
8. **Document failure modes** - Docstrings should list possible exceptions
9. **Log with context** - Include IDs, counts, and other debugging info
10. **Test error paths** - Verify exceptions are raised correctly

<!-- chapter:end slug=python-error-handling -->

---

<!-- chapter:begin slug=python-observability position=134 -->

## 134. python-observability

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-observability/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-observability/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-observability.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-observability/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-observability
description: Python observability patterns including structured logging, metrics, and distributed tracing. Use when adding logging, implementing metrics collection, setting up tracing, or debugging production systems.
---

# Python Observability

Instrument Python applications with structured logs, metrics, and traces. When something breaks in production, you need to answer "what, where, and why" without deploying new code.

## When to Use This Skill

- Adding structured logging to applications
- Implementing metrics collection with Prometheus
- Setting up distributed tracing across services
- Propagating correlation IDs through request chains
- Debugging production issues
- Building observability dashboards

## Core Concepts

### 1. Structured Logging

Emit logs as JSON with consistent fields for production environments. Machine-readable logs enable powerful queries and alerts. For local development, consider human-readable formats.

### 2. The Four Golden Signals

Track latency, traffic, errors, and saturation for every service boundary.

### 3. Correlation IDs

Thread a unique ID through all logs and spans for a single request, enabling end-to-end tracing.

### 4. Bounded Cardinality

Keep metric label values bounded. Unbounded labels (like user IDs) explode storage costs.

## Quick Start

```python
import structlog

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.JSONRenderer(),
    ],
)

logger = structlog.get_logger()
logger.info("Request processed", user_id="123", duration_ms=45)
```

## Fundamental Patterns

### Pattern 1: Structured Logging with Structlog

Configure structlog for JSON output with consistent fields.

```python
import logging
import structlog

def configure_logging(log_level: str = "INFO") -> None:
    """Configure structured logging for the application."""
    structlog.configure(
        processors=[
            structlog.contextvars.merge_contextvars,
            structlog.processors.add_log_level,
            structlog.processors.TimeStamper(fmt="iso"),
            structlog.processors.StackInfoRenderer(),
            structlog.processors.format_exc_info,
            structlog.processors.JSONRenderer(),
        ],
        wrapper_class=structlog.make_filtering_bound_logger(
            getattr(logging, log_level.upper())
        ),
        context_class=dict,
        logger_factory=structlog.PrintLoggerFactory(),
        cache_logger_on_first_use=True,
    )

# Initialize at application startup
configure_logging("INFO")
logger = structlog.get_logger()
```

### Pattern 2: Consistent Log Fields

Every log entry should include standard fields for filtering and correlation.

```python
import structlog
from contextvars import ContextVar

# Store correlation ID in context
correlation_id: ContextVar[str] = ContextVar("correlation_id", default="")

logger = structlog.get_logger()

def process_request(request: Request) -> Response:
    """Process request with structured logging."""
    logger.info(
        "Request received",
        correlation_id=correlation_id.get(),
        method=request.method,
        path=request.path,
        user_id=request.user_id,
    )

    try:
        result = handle_request(request)
        logger.info(
            "Request completed",
            correlation_id=correlation_id.get(),
            status_code=200,
            duration_ms=elapsed,
        )
        return result
    except Exception as e:
        logger.error(
            "Request failed",
            correlation_id=correlation_id.get(),
            error_type=type(e).__name__,
            error_message=str(e),
        )
        raise
```

### Pattern 3: Semantic Log Levels

Use log levels consistently across the application.

| Level | Purpose | Examples |
|-------|---------|----------|
| `DEBUG` | Development diagnostics | Variable values, internal state |
| `INFO` | Request lifecycle, operations | Request start/end, job completion |
| `WARNING` | Recoverable anomalies | Retry attempts, fallback used |
| `ERROR` | Failures needing attention | Exceptions, service unavailable |

```python
# DEBUG: Detailed internal information
logger.debug("Cache lookup", key=cache_key, hit=cache_hit)

# INFO: Normal operational events
logger.info("Order created", order_id=order.id, total=order.total)

# WARNING: Abnormal but handled situations
logger.warning(
    "Rate limit approaching",
    current_rate=950,
    limit=1000,
    reset_seconds=30,
)

# ERROR: Failures requiring investigation
logger.error(
    "Payment processing failed",
    order_id=order.id,
    error=str(e),
    payment_provider="stripe",
)
```

Never log expected behavior at `ERROR`. A user entering a wrong password is `INFO`, not `ERROR`.

### Pattern 4: Correlation ID Propagation

Generate a unique ID at ingress and thread it through all operations.

```python
from contextvars import ContextVar
import uuid
import structlog

correlation_id: ContextVar[str] = ContextVar("correlation_id", default="")

def set_correlation_id(cid: str | None = None) -> str:
    """Set correlation ID for current context."""
    cid = cid or str(uuid.uuid4())
    correlation_id.set(cid)
    structlog.contextvars.bind_contextvars(correlation_id=cid)
    return cid

# FastAPI middleware example
from fastapi import Request

async def correlation_middleware(request: Request, call_next):
    """Middleware to set and propagate correlation ID."""
    # Use incoming header or generate new
    cid = request.headers.get("X-Correlation-ID") or str(uuid.uuid4())
    set_correlation_id(cid)

    response = await call_next(request)
    response.headers["X-Correlation-ID"] = cid
    return response
```

Propagate to outbound requests:

```python
import httpx

async def call_downstream_service(endpoint: str, data: dict) -> dict:
    """Call downstream service with correlation ID."""
    async with httpx.AsyncClient() as client:
        response = await client.post(
            endpoint,
            json=data,
            headers={"X-Correlation-ID": correlation_id.get()},
        )
        return response.json()
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Use structured logging** - JSON logs with consistent fields
2. **Propagate correlation IDs** - Thread through all requests and logs
3. **Track the four golden signals** - Latency, traffic, errors, saturation
4. **Bound label cardinality** - Never use unbounded values as metric labels
5. **Log at appropriate levels** - Don't cry wolf with ERROR
6. **Include context** - User ID, request ID, operation name in logs
7. **Use context managers** - Consistent timing and error handling
8. **Separate concerns** - Observability code shouldn't pollute business logic
9. **Test your observability** - Verify logs and metrics in integration tests
10. **Set up alerts** - Metrics are useless without alerting

<!-- chapter:end slug=python-observability -->

---

<!-- chapter:begin slug=python-packaging position=135 -->

## 135. python-packaging

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-packaging/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-packaging/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-packaging.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-packaging/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-packaging/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-packaging
description: Create distributable Python packages with proper project structure, setup.py/pyproject.toml, and publishing to PyPI. Use when packaging Python libraries, creating CLI tools, or distributing Python code.
---

# Python Packaging

Comprehensive guide to creating, structuring, and distributing Python packages using modern packaging tools, pyproject.toml, and publishing to PyPI.

## When to Use This Skill

- Creating Python libraries for distribution
- Building command-line tools with entry points
- Publishing packages to PyPI or private repositories
- Setting up Python project structure
- Creating installable packages with dependencies
- Building wheels and source distributions
- Versioning and releasing Python packages
- Creating namespace packages
- Implementing package metadata and classifiers

## Core Concepts

### 1. Package Structure

- **Source layout**: `src/package_name/` (recommended)
- **Flat layout**: `package_name/` (simpler but less flexible)
- **Package metadata**: pyproject.toml, setup.py, or setup.cfg
- **Distribution formats**: wheel (.whl) and source distribution (.tar.gz)

### 2. Modern Packaging Standards

- **PEP 517/518**: Build system requirements
- **PEP 621**: Metadata in pyproject.toml
- **PEP 660**: Editable installs
- **pyproject.toml**: Single source of configuration

### 3. Build Backends

- **setuptools**: Traditional, widely used
- **hatchling**: Modern, opinionated
- **flit**: Lightweight, for pure Python
- **poetry**: Dependency management + packaging

### 4. Distribution

- **PyPI**: Python Package Index (public)
- **TestPyPI**: Testing before production
- **Private repositories**: JFrog, AWS CodeArtifact, etc.

## Quick Start

### Minimal Package Structure

```
my-package/
├── pyproject.toml
├── README.md
├── LICENSE
├── src/
│   └── my_package/
│       ├── __init__.py
│       └── module.py
└── tests/
    └── test_module.py
```

### Minimal pyproject.toml

```toml
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "my-package"
version = "0.1.0"
description = "A short description"
authors = [{name = "Your Name", email = "you@example.com"}]
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
    "requests>=2.28.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "black>=22.0",
]
```

## Package Structure Patterns

### Pattern 1: Source Layout (Recommended)

```
my-package/
├── pyproject.toml
├── README.md
├── LICENSE
├── .gitignore
├── src/
│   └── my_package/
│       ├── __init__.py
│       ├── core.py
│       ├── utils.py
│       └── py.typed          # For type hints
├── tests/
│   ├── __init__.py
│   ├── test_core.py
│   └── test_utils.py
└── docs/
    └── index.md
```

**Advantages:**

- Prevents accidentally importing from source
- Cleaner test imports
- Better isolation

**pyproject.toml for source layout:**

```toml
[tool.setuptools.packages.find]
where = ["src"]
```

### Pattern 2: Flat Layout

```
my-package/
├── pyproject.toml
├── README.md
├── my_package/
│   ├── __init__.py
│   └── module.py
└── tests/
    └── test_module.py
```

**Simpler but:**

- Can import package without installing
- Less professional for libraries

### Pattern 3: Multi-Package Project

```
project/
├── pyproject.toml
├── packages/
│   ├── package-a/
│   │   └── src/
│   │       └── package_a/
│   └── package-b/
│       └── src/
│           └── package_b/
└── tests/
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=python-packaging -->

---

<!-- chapter:begin slug=python-performance-optimization position=136 -->

## 136. python-performance-optimization

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-performance-optimization/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-performance-optimization/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-performance-optimization.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-performance-optimization/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-performance-optimization/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-performance-optimization
description: Profile and optimize Python code using cProfile, memory profilers, and performance best practices. Use when debugging slow Python code, optimizing bottlenecks, or improving application performance.
---

# Python Performance Optimization

Comprehensive guide to profiling, analyzing, and optimizing Python code for better performance, including CPU profiling, memory optimization, and implementation best practices.

## When to Use This Skill

- Identifying performance bottlenecks in Python applications
- Reducing application latency and response times
- Optimizing CPU-intensive operations
- Reducing memory consumption and memory leaks
- Improving database query performance
- Optimizing I/O operations
- Speeding up data processing pipelines
- Implementing high-performance algorithms
- Profiling production applications

## Core Concepts

### 1. Profiling Types

- **CPU Profiling**: Identify time-consuming functions
- **Memory Profiling**: Track memory allocation and leaks
- **Line Profiling**: Profile at line-by-line granularity
- **Call Graph**: Visualize function call relationships

### 2. Performance Metrics

- **Execution Time**: How long operations take
- **Memory Usage**: Peak and average memory consumption
- **CPU Utilization**: Processor usage patterns
- **I/O Wait**: Time spent on I/O operations

### 3. Optimization Strategies

- **Algorithmic**: Better algorithms and data structures
- **Implementation**: More efficient code patterns
- **Parallelization**: Multi-threading/processing
- **Caching**: Avoid redundant computation
- **Native Extensions**: C/Rust for critical paths

## Quick Start

### Basic Timing

```python
import time

def measure_time():
    """Simple timing measurement."""
    start = time.time()

    # Your code here
    result = sum(range(1000000))

    elapsed = time.time() - start
    print(f"Execution time: {elapsed:.4f} seconds")
    return result

# Better: use timeit for accurate measurements
import timeit

execution_time = timeit.timeit(
    "sum(range(1000000))",
    number=100
)
print(f"Average time: {execution_time/100:.6f} seconds")
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Profile before optimizing** - Measure to find real bottlenecks
2. **Focus on hot paths** - Optimize code that runs most frequently
3. **Use appropriate data structures** - Dict for lookups, set for membership
4. **Avoid premature optimization** - Clarity first, then optimize
5. **Use built-in functions** - They're implemented in C
6. **Cache expensive computations** - Use lru_cache
7. **Batch I/O operations** - Reduce system calls
8. **Use generators** for large datasets
9. **Consider NumPy** for numerical operations
10. **Profile production code** - Use py-spy for live systems

## Common Pitfalls

- Optimizing without profiling
- Using global variables unnecessarily
- Not using appropriate data structures
- Creating unnecessary copies of data
- Not using connection pooling for databases
- Ignoring algorithmic complexity
- Over-optimizing rare code paths
- Not considering memory usage

<!-- chapter:end slug=python-performance-optimization -->

---

<!-- chapter:begin slug=python-project-structure position=137 -->

## 137. python-project-structure

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-project-structure/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-project-structure/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-project-structure.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-project-structure
description: Python project organization, module architecture, and public API design. Use when setting up new projects, organizing modules, defining public interfaces with __all__, or planning directory layouts.
---

# Python Project Structure & Module Architecture

Design well-organized Python projects with clear module boundaries, explicit public interfaces, and maintainable directory structures. Good organization makes code discoverable and changes predictable.

## When to Use This Skill

- Starting a new Python project from scratch
- Reorganizing an existing codebase for clarity
- Defining module public APIs with `__all__`
- Deciding between flat and nested directory structures
- Determining test file placement strategies
- Creating reusable library packages

## Core Concepts

### 1. Module Cohesion

Group related code that changes together. A module should have a single, clear purpose.

### 2. Explicit Interfaces

Define what's public with `__all__`. Everything not listed is an internal implementation detail.

### 3. Flat Hierarchies

Prefer shallow directory structures. Add depth only for genuine sub-domains.

### 4. Consistent Conventions

Apply naming and organization patterns uniformly across the project.

## Quick Start

```
myproject/
├── src/
│   └── myproject/
│       ├── __init__.py
│       ├── services/
│       ├── models/
│       └── api/
├── tests/
├── pyproject.toml
└── README.md
```

## Fundamental Patterns

### Pattern 1: One Concept Per File

Each file should focus on a single concept or closely related set of functions. Consider splitting when a file:

- Handles multiple unrelated responsibilities
- Grows beyond 300-500 lines (varies by complexity)
- Contains classes that change for different reasons

```python
# Good: Focused files
# user_service.py - User business logic
# user_repository.py - User data access
# user_models.py - User data structures

# Avoid: Kitchen sink files
# user.py - Contains service, repository, models, utilities...
```

### Pattern 2: Explicit Public APIs with `__all__`

Define the public interface for every module. Unlisted members are internal implementation details.

```python
# mypackage/services/__init__.py
from .user_service import UserService
from .order_service import OrderService
from .exceptions import ServiceError, ValidationError

__all__ = [
    "UserService",
    "OrderService",
    "ServiceError",
    "ValidationError",
]

# Internal helpers remain private by omission
# from .internal_helpers import _validate_input  # Not exported
```

### Pattern 3: Flat Directory Structure

Prefer minimal nesting. Deep hierarchies make imports verbose and navigation difficult.

```
# Preferred: Flat structure
project/
├── api/
│   ├── routes.py
│   └── middleware.py
├── services/
│   ├── user_service.py
│   └── order_service.py
├── models/
│   ├── user.py
│   └── order.py
└── utils/
    └── validation.py

# Avoid: Deep nesting
project/core/internal/services/impl/user/
```

Add sub-packages only when there's a genuine sub-domain requiring isolation.

### Pattern 4: Test File Organization

Choose one approach and apply it consistently throughout the project.

**Option A: Colocated Tests**

```
src/
├── user_service.py
├── test_user_service.py
├── order_service.py
└── test_order_service.py
```

Benefits: Tests live next to the code they verify. Easy to see coverage gaps.

**Option B: Parallel Test Directory**

```
src/
├── services/
│   ├── user_service.py
│   └── order_service.py
tests/
├── services/
│   ├── test_user_service.py
│   └── test_order_service.py
```

Benefits: Clean separation between production and test code. Standard for larger projects.

## Advanced Patterns

### Pattern 5: Package Initialization

Use `__init__.py` to provide a clean public interface for package consumers.

```python
# mypackage/__init__.py
"""MyPackage - A library for doing useful things."""

from .core import MainClass, HelperClass
from .exceptions import PackageError, ConfigError
from .config import Settings

__all__ = [
    "MainClass",
    "HelperClass",
    "PackageError",
    "ConfigError",
    "Settings",
]

__version__ = "1.0.0"
```

Consumers can then import directly from the package:

```python
from mypackage import MainClass, Settings
```

### Pattern 6: Layered Architecture

Organize code by architectural layer for clear separation of concerns.

```
myapp/
├── api/           # HTTP handlers, request/response
│   ├── routes/
│   └── middleware/
├── services/      # Business logic
├── repositories/  # Data access
├── models/        # Domain entities
├── schemas/       # API schemas (Pydantic)
└── config/        # Configuration
```

Each layer should only depend on layers below it, never above.

### Pattern 7: Domain-Driven Structure

For complex applications, organize by business domain rather than technical layer.

```
ecommerce/
├── users/
│   ├── models.py
│   ├── services.py
│   ├── repository.py
│   └── api.py
├── orders/
│   ├── models.py
│   ├── services.py
│   ├── repository.py
│   └── api.py
└── shared/
    ├── database.py
    └── exceptions.py
```

## File and Module Naming

### Conventions

- Use `snake_case` for all file and module names: `user_repository.py`
- Avoid abbreviations that obscure meaning: `user_repository.py` not `usr_repo.py`
- Match class names to file names: `UserService` in `user_service.py`

### Import Style

Use absolute imports for clarity and reliability:

```python
# Preferred: Absolute imports
from myproject.services import UserService
from myproject.models import User

# Avoid: Relative imports
from ..services import UserService
from . import models
```

Relative imports can break when modules are moved or reorganized.

## Best Practices Summary

1. **Keep files focused** - One concept per file, consider splitting at 300-500 lines (varies by complexity)
2. **Define `__all__` explicitly** - Make public interfaces clear
3. **Prefer flat structures** - Add depth only for genuine sub-domains
4. **Use absolute imports** - More reliable and clearer
5. **Be consistent** - Apply patterns uniformly across the project
6. **Match names to content** - File names should describe their purpose
7. **Separate concerns** - Keep layers distinct and dependencies flowing one direction
8. **Document your structure** - Include a README explaining the organization

<!-- chapter:end slug=python-project-structure -->

---

<!-- chapter:begin slug=python-resilience position=138 -->

## 138. python-resilience

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-resilience/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-resilience/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-resilience.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-resilience/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-resilience
description: Python resilience patterns including automatic retries, exponential backoff, timeouts, and fault-tolerant decorators. Use when adding retry logic, implementing timeouts, building fault-tolerant services, or handling transient failures.
---

# Python Resilience Patterns

Build fault-tolerant Python applications that gracefully handle transient failures, network issues, and service outages. Resilience patterns keep systems running when dependencies are unreliable.

## When to Use This Skill

- Adding retry logic to external service calls
- Implementing timeouts for network operations
- Building fault-tolerant microservices
- Handling rate limiting and backpressure
- Creating infrastructure decorators
- Designing circuit breakers

## Core Concepts

### 1. Transient vs Permanent Failures

Retry transient errors (network timeouts, temporary service issues). Don't retry permanent errors (invalid credentials, bad requests).

### 2. Exponential Backoff

Increase wait time between retries to avoid overwhelming recovering services.

### 3. Jitter

Add randomness to backoff to prevent thundering herd when many clients retry simultaneously.

### 4. Bounded Retries

Cap both attempt count and total duration to prevent infinite retry loops.

## Quick Start

```python
from tenacity import retry, stop_after_attempt, wait_exponential_jitter

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential_jitter(initial=1, max=10),
)
def call_external_service(request: dict) -> dict:
    return httpx.post("https://api.example.com", json=request).json()
```

## Fundamental Patterns

### Pattern 1: Basic Retry with Tenacity

Use the `tenacity` library for production-grade retry logic. For simpler cases, consider built-in retry functionality or a lightweight custom implementation.

```python
from tenacity import (
    retry,
    stop_after_attempt,
    stop_after_delay,
    wait_exponential_jitter,
    retry_if_exception_type,
)

TRANSIENT_ERRORS = (ConnectionError, TimeoutError, OSError)

@retry(
    retry=retry_if_exception_type(TRANSIENT_ERRORS),
    stop=stop_after_attempt(5) | stop_after_delay(60),
    wait=wait_exponential_jitter(initial=1, max=30),
)
def fetch_data(url: str) -> dict:
    """Fetch data with automatic retry on transient failures."""
    response = httpx.get(url, timeout=30)
    response.raise_for_status()
    return response.json()
```

### Pattern 2: Retry Only Appropriate Errors

Whitelist specific transient exceptions. Never retry:

- `ValueError`, `TypeError` - These are bugs, not transient issues
- `AuthenticationError` - Invalid credentials won't become valid
- HTTP 4xx errors (except 429) - Client errors are permanent

```python
from tenacity import retry, retry_if_exception_type
import httpx

# Define what's retryable
RETRYABLE_EXCEPTIONS = (
    ConnectionError,
    TimeoutError,
    httpx.ConnectTimeout,
    httpx.ReadTimeout,
)

@retry(
    retry=retry_if_exception_type(RETRYABLE_EXCEPTIONS),
    stop=stop_after_attempt(3),
    wait=wait_exponential_jitter(initial=1, max=10),
)
def resilient_api_call(endpoint: str) -> dict:
    """Make API call with retry on network issues."""
    return httpx.get(endpoint, timeout=10).json()
```

### Pattern 3: HTTP Status Code Retries

Retry specific HTTP status codes that indicate transient issues.

```python
from tenacity import retry, retry_if_result, stop_after_attempt
import httpx

RETRY_STATUS_CODES = {429, 502, 503, 504}

def should_retry_response(response: httpx.Response) -> bool:
    """Check if response indicates a retryable error."""
    return response.status_code in RETRY_STATUS_CODES

@retry(
    retry=retry_if_result(should_retry_response),
    stop=stop_after_attempt(3),
    wait=wait_exponential_jitter(initial=1, max=10),
)
def http_request(method: str, url: str, **kwargs) -> httpx.Response:
    """Make HTTP request with retry on transient status codes."""
    return httpx.request(method, url, timeout=30, **kwargs)
```

### Pattern 4: Combined Exception and Status Retry

Handle both network exceptions and HTTP status codes.

```python
from tenacity import (
    retry,
    retry_if_exception_type,
    retry_if_result,
    stop_after_attempt,
    wait_exponential_jitter,
    before_sleep_log,
)
import logging
import httpx

logger = logging.getLogger(__name__)

TRANSIENT_EXCEPTIONS = (
    ConnectionError,
    TimeoutError,
    httpx.ConnectError,
    httpx.ReadTimeout,
)
RETRY_STATUS_CODES = {429, 500, 502, 503, 504}

def is_retryable_response(response: httpx.Response) -> bool:
    return response.status_code in RETRY_STATUS_CODES

@retry(
    retry=(
        retry_if_exception_type(TRANSIENT_EXCEPTIONS) |
        retry_if_result(is_retryable_response)
    ),
    stop=stop_after_attempt(5),
    wait=wait_exponential_jitter(initial=1, max=30),
    before_sleep=before_sleep_log(logger, logging.WARNING),
)
def robust_http_call(
    method: str,
    url: str,
    **kwargs,
) -> httpx.Response:
    """HTTP call with comprehensive retry handling."""
    return httpx.request(method, url, timeout=30, **kwargs)
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Retry only transient errors** - Don't retry bugs or authentication failures
2. **Use exponential backoff** - Give services time to recover
3. **Add jitter** - Prevent thundering herd from synchronized retries
4. **Cap total duration** - `stop_after_attempt(5) | stop_after_delay(60)`
5. **Log every retry** - Silent retries hide systemic problems
6. **Use decorators** - Keep retry logic separate from business logic
7. **Inject dependencies** - Make infrastructure testable
8. **Set timeouts everywhere** - Every network call needs a timeout
9. **Fail gracefully** - Return cached/default values for non-critical paths
10. **Monitor retry rates** - High retry rates indicate underlying issues

<!-- chapter:end slug=python-resilience -->

---

<!-- chapter:begin slug=python-resource-management position=139 -->

## 139. python-resource-management

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-resource-management/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-resource-management/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-resource-management.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-resource-management/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-resource-management
description: Python resource management with context managers, cleanup patterns, and streaming. Use when managing connections, file handles, implementing cleanup logic, or building streaming responses with accumulated state.
---

# Python Resource Management

Manage resources deterministically using context managers. Resources like database connections, file handles, and network sockets should be released reliably, even when exceptions occur.

## When to Use This Skill

- Managing database connections and connection pools
- Working with file handles and I/O
- Implementing custom context managers
- Building streaming responses with state
- Handling nested resource cleanup
- Creating async context managers

## Core Concepts

### 1. Context Managers

The `with` statement ensures resources are released automatically, even on exceptions.

### 2. Protocol Methods

`__enter__`/`__exit__` for sync, `__aenter__`/`__aexit__` for async resource management.

### 3. Unconditional Cleanup

`__exit__` always runs, regardless of whether an exception occurred.

### 4. Exception Handling

Return `True` from `__exit__` to suppress exceptions, `False` to propagate them.

## Quick Start

```python
from contextlib import contextmanager

@contextmanager
def managed_resource():
    resource = acquire_resource()
    try:
        yield resource
    finally:
        resource.cleanup()

with managed_resource() as r:
    r.do_work()
```

## Fundamental Patterns

### Pattern 1: Class-Based Context Manager

Implement the context manager protocol for complex resources.

```python
class DatabaseConnection:
    """Database connection with automatic cleanup."""

    def __init__(self, dsn: str) -> None:
        self._dsn = dsn
        self._conn: Connection | None = None

    def connect(self) -> None:
        """Establish database connection."""
        self._conn = psycopg.connect(self._dsn)

    def close(self) -> None:
        """Close connection if open."""
        if self._conn is not None:
            self._conn.close()
            self._conn = None

    def __enter__(self) -> "DatabaseConnection":
        """Enter context: connect and return self."""
        self.connect()
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        """Exit context: always close connection."""
        self.close()

# Usage with context manager (preferred)
with DatabaseConnection(dsn) as db:
    result = db.execute(query)

# Manual management when needed
db = DatabaseConnection(dsn)
db.connect()
try:
    result = db.execute(query)
finally:
    db.close()
```

### Pattern 2: Async Context Manager

For async resources, implement the async protocol.

```python
class AsyncDatabasePool:
    """Async database connection pool."""

    def __init__(self, dsn: str, min_size: int = 1, max_size: int = 10) -> None:
        self._dsn = dsn
        self._min_size = min_size
        self._max_size = max_size
        self._pool: asyncpg.Pool | None = None

    async def __aenter__(self) -> "AsyncDatabasePool":
        """Create connection pool."""
        self._pool = await asyncpg.create_pool(
            self._dsn,
            min_size=self._min_size,
            max_size=self._max_size,
        )
        return self

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        """Close all connections in pool."""
        if self._pool is not None:
            await self._pool.close()

    async def execute(self, query: str, *args) -> list[dict]:
        """Execute query using pooled connection."""
        async with self._pool.acquire() as conn:
            return await conn.fetch(query, *args)

# Usage
async with AsyncDatabasePool(dsn) as pool:
    users = await pool.execute("SELECT * FROM users WHERE active = $1", True)
```

### Pattern 3: Using @contextmanager Decorator

Simplify context managers with the decorator for straightforward cases.

```python
from contextlib import contextmanager, asynccontextmanager
import time
import structlog

logger = structlog.get_logger()

@contextmanager
def timed_block(name: str):
    """Time a block of code."""
    start = time.perf_counter()
    try:
        yield
    finally:
        elapsed = time.perf_counter() - start
        logger.info(f"{name} completed", duration_seconds=round(elapsed, 3))

# Usage
with timed_block("data_processing"):
    process_large_dataset()

@asynccontextmanager
async def database_transaction(conn: AsyncConnection):
    """Manage database transaction."""
    await conn.execute("BEGIN")
    try:
        yield conn
        await conn.execute("COMMIT")
    except Exception:
        await conn.execute("ROLLBACK")
        raise

# Usage
async with database_transaction(conn) as tx:
    await tx.execute("INSERT INTO users ...")
    await tx.execute("INSERT INTO audit_log ...")
```

### Pattern 4: Unconditional Resource Release

Always clean up resources in `__exit__`, regardless of exceptions.

```python
class FileProcessor:
    """Process file with guaranteed cleanup."""

    def __init__(self, path: str) -> None:
        self._path = path
        self._file: IO | None = None
        self._temp_files: list[Path] = []

    def __enter__(self) -> "FileProcessor":
        self._file = open(self._path, "r")
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        """Clean up all resources unconditionally."""
        # Close main file
        if self._file is not None:
            self._file.close()

        # Clean up any temporary files
        for temp_file in self._temp_files:
            try:
                temp_file.unlink()
            except OSError:
                pass  # Best effort cleanup

        # Return None/False to propagate any exception
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Always use context managers** - For any resource that needs cleanup
2. **Clean up unconditionally** - `__exit__` runs even on exception
3. **Don't suppress unexpectedly** - Return `False` unless suppression is intentional
4. **Use @contextmanager** - For simple resource patterns
5. **Implement both protocols** - Support `with` and manual management
6. **Use ExitStack** - For dynamic numbers of resources
7. **Accumulate efficiently** - List + join, not string concatenation
8. **Track metrics** - Time-to-first-byte matters for streaming
9. **Document behavior** - Especially exception suppression
10. **Test cleanup paths** - Verify resources are released on errors

<!-- chapter:end slug=python-resource-management -->

---

<!-- chapter:begin slug=python-testing-patterns position=140 -->

## 140. python-testing-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-testing-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-testing-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-testing-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-testing-patterns/references/advanced-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-testing-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-testing-patterns
description: Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.
---

# Python Testing Patterns

Comprehensive guide to implementing robust testing strategies in Python using pytest, fixtures, mocking, parameterization, and test-driven development practices.

## When to Use This Skill

- Writing unit tests for Python code
- Setting up test suites and test infrastructure
- Implementing test-driven development (TDD)
- Creating integration tests for APIs and services
- Mocking external dependencies and services
- Testing async code and concurrent operations
- Setting up continuous testing in CI/CD
- Implementing property-based testing
- Testing database operations
- Debugging failing tests

## Core Concepts

### 1. Test Types

- **Unit Tests**: Test individual functions/classes in isolation
- **Integration Tests**: Test interaction between components
- **Functional Tests**: Test complete features end-to-end
- **Performance Tests**: Measure speed and resource usage

### 2. Test Structure (AAA Pattern)

- **Arrange**: Set up test data and preconditions
- **Act**: Execute the code under test
- **Assert**: Verify the results

### 3. Test Coverage

- Measure what code is exercised by tests
- Identify untested code paths
- Aim for meaningful coverage, not just high percentages

### 4. Test Isolation

- Tests should be independent
- No shared state between tests
- Each test should clean up after itself

## Quick Start

```python
# test_example.py
def add(a, b):
    return a + b

def test_add():
    """Basic test example."""
    result = add(2, 3)
    assert result == 5

def test_add_negative():
    """Test with negative numbers."""
    assert add(-1, 1) == 0

# Run with: pytest test_example.py
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing Best Practices

### Test Organization

```python
# tests/
#   __init__.py
#   conftest.py           # Shared fixtures
#   test_unit/            # Unit tests
#     test_models.py
#     test_utils.py
#   test_integration/     # Integration tests
#     test_api.py
#     test_database.py
#   test_e2e/            # End-to-end tests
#     test_workflows.py
```

### Test Naming Convention

A common pattern: `test_<unit>_<scenario>_<expected_outcome>`. Adapt to your team's preferences.

```python
# Pattern: test_<unit>_<scenario>_<expected>
def test_create_user_with_valid_data_returns_user():
    ...

def test_create_user_with_duplicate_email_raises_conflict():
    ...

def test_get_user_with_unknown_id_returns_none():
    ...

# Good test names - clear and descriptive
def test_user_creation_with_valid_data():
    """Clear name describes what is being tested."""
    pass

def test_login_fails_with_invalid_password():
    """Name describes expected behavior."""
    pass

def test_api_returns_404_for_missing_resource():
    """Specific about inputs and expected outcomes."""
    pass

# Bad test names - avoid these
def test_1():  # Not descriptive
    pass

def test_user():  # Too vague
    pass

def test_function():  # Doesn't explain what's tested
    pass
```

### Testing Retry Behavior

Verify that retry logic works correctly using mock side effects.

```python
from unittest.mock import Mock

def test_retries_on_transient_error():
    """Test that service retries on transient failures."""
    client = Mock()
    # Fail twice, then succeed
    client.request.side_effect = [
        ConnectionError("Failed"),
        ConnectionError("Failed"),
        {"status": "ok"},
    ]

    service = ServiceWithRetry(client, max_retries=3)
    result = service.fetch()

    assert result == {"status": "ok"}
    assert client.request.call_count == 3

def test_gives_up_after_max_retries():
    """Test that service stops retrying after max attempts."""
    client = Mock()
    client.request.side_effect = ConnectionError("Failed")

    service = ServiceWithRetry(client, max_retries=3)

    with pytest.raises(ConnectionError):
        service.fetch()

    assert client.request.call_count == 3

def test_does_not_retry_on_permanent_error():
    """Test that permanent errors are not retried."""
    client = Mock()
    client.request.side_effect = ValueError("Invalid input")

    service = ServiceWithRetry(client, max_retries=3)

    with pytest.raises(ValueError):
        service.fetch()

    # Only called once - no retry for ValueError
    assert client.request.call_count == 1
```

### Mocking Time with Freezegun

Use freezegun to control time in tests for predictable time-dependent behavior.

```python
from freezegun import freeze_time
from datetime import datetime, timedelta

@freeze_time("2026-01-15 10:00:00")
def test_token_expiry():
    """Test token expires at correct time."""
    token = create_token(expires_in_seconds=3600)
    assert token.expires_at == datetime(2026, 1, 15, 11, 0, 0)

@freeze_time("2026-01-15 10:00:00")
def test_is_expired_returns_false_before_expiry():
    """Test token is not expired when within validity period."""
    token = create_token(expires_in_seconds=3600)
    assert not token.is_expired()

@freeze_time("2026-01-15 12:00:00")
def test_is_expired_returns_true_after_expiry():
    """Test token is expired after validity period."""
    token = Token(expires_at=datetime(2026, 1, 15, 11, 30, 0))
    assert token.is_expired()

def test_with_time_travel():
    """Test behavior across time using freeze_time context."""
    with freeze_time("2026-01-01") as frozen_time:
        item = create_item()
        assert item.created_at == datetime(2026, 1, 1)

        # Move forward in time
        frozen_time.move_to("2026-01-15")
        assert item.age_days == 14
```

### Test Markers

```python
# test_markers.py
import pytest

@pytest.mark.slow
def test_slow_operation():
    """Mark slow tests."""
    import time
    time.sleep(2)


@pytest.mark.integration
def test_database_integration():
    """Mark integration tests."""
    pass


@pytest.mark.skip(reason="Feature not implemented yet")
def test_future_feature():
    """Skip tests temporarily."""
    pass


@pytest.mark.skipif(os.name == "nt", reason="Unix only test")
def test_unix_specific():
    """Conditional skip."""
    pass


@pytest.mark.xfail(reason="Known bug #123")
def test_known_bug():
    """Mark expected failures."""
    assert False


# Run with:
# pytest -m slow          # Run only slow tests
# pytest -m "not slow"    # Skip slow tests
# pytest -m integration   # Run integration tests
```

### Coverage Reporting

```bash
# Install coverage
pip install pytest-cov

# Run tests with coverage
pytest --cov=myapp tests/

# Generate HTML report
pytest --cov=myapp --cov-report=html tests/

# Fail if coverage below threshold
pytest --cov=myapp --cov-fail-under=80 tests/

# Show missing lines
pytest --cov=myapp --cov-report=term-missing tests/
```

For advanced patterns (async testing, monkeypatching, property-based testing, database testing, CI/CD integration, and configuration), see [references/advanced-patterns.md](references/advanced-patterns.md)

<!-- chapter:end slug=python-testing-patterns -->

---

<!-- chapter:begin slug=python-type-safety position=141 -->

## 141. python-type-safety

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/python-type-safety/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-type-safety/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/python-type-safety.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/python-type-safety/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: python-type-safety
description: Python type safety with type hints, generics, protocols, and strict type checking. Use when adding type annotations, implementing generic classes, defining structural interfaces, or configuring mypy/pyright.
---

# Python Type Safety

Leverage Python's type system to catch errors at static analysis time. Type annotations serve as enforced documentation that tooling validates automatically.

## When to Use This Skill

- Adding type hints to existing code
- Creating generic, reusable classes
- Defining structural interfaces with protocols
- Configuring mypy or pyright for strict checking
- Understanding type narrowing and guards
- Building type-safe APIs and libraries

## Core Concepts

### 1. Type Annotations

Declare expected types for function parameters, return values, and variables.

### 2. Generics

Write reusable code that preserves type information across different types.

### 3. Protocols

Define structural interfaces without inheritance (duck typing with type safety).

### 4. Type Narrowing

Use guards and conditionals to narrow types within code blocks.

## Quick Start

```python
def get_user(user_id: str) -> User | None:
    """Return type makes 'might not exist' explicit."""
    ...

# Type checker enforces handling None case
user = get_user("123")
if user is None:
    raise UserNotFoundError("123")
print(user.name)  # Type checker knows user is User here
```

## Fundamental Patterns

### Pattern 1: Annotate All Public Signatures

Every public function, method, and class should have type annotations.

```python
def get_user(user_id: str) -> User:
    """Retrieve user by ID."""
    ...

def process_batch(
    items: list[Item],
    max_workers: int = 4,
) -> BatchResult[ProcessedItem]:
    """Process items concurrently."""
    ...

class UserRepository:
    def __init__(self, db: Database) -> None:
        self._db = db

    async def find_by_id(self, user_id: str) -> User | None:
        """Return User if found, None otherwise."""
        ...

    async def find_by_email(self, email: str) -> User | None:
        ...

    async def save(self, user: User) -> User:
        """Save and return user with generated ID."""
        ...
```

Use `mypy --strict` or `pyright` in CI to catch type errors early. For existing projects, enable strict mode incrementally using per-module overrides.

### Pattern 2: Use Modern Union Syntax

Python 3.10+ provides cleaner union syntax.

```python
# Preferred (3.10+)
def find_user(user_id: str) -> User | None:
    ...

def parse_value(v: str) -> int | float | str:
    ...

# Older style (still valid, needed for 3.9)
from typing import Optional, Union

def find_user(user_id: str) -> Optional[User]:
    ...
```

### Pattern 3: Type Narrowing with Guards

Use conditionals to narrow types for the type checker.

```python
def process_user(user_id: str) -> UserData:
    user = find_user(user_id)

    if user is None:
        raise UserNotFoundError(f"User {user_id} not found")

    # Type checker knows user is User here, not User | None
    return UserData(
        name=user.name,
        email=user.email,
    )

def process_items(items: list[Item | None]) -> list[ProcessedItem]:
    # Filter and narrow types
    valid_items = [item for item in items if item is not None]
    # valid_items is now list[Item]
    return [process(item) for item in valid_items]
```

### Pattern 4: Generic Classes

Create type-safe reusable containers.

```python
from typing import TypeVar, Generic

T = TypeVar("T")
E = TypeVar("E", bound=Exception)

class Result(Generic[T, E]):
    """Represents either a success value or an error."""

    def __init__(
        self,
        value: T | None = None,
        error: E | None = None,
    ) -> None:
        if (value is None) == (error is None):
            raise ValueError("Exactly one of value or error must be set")
        self._value = value
        self._error = error

    @property
    def is_success(self) -> bool:
        return self._error is None

    @property
    def is_failure(self) -> bool:
        return self._error is not None

    def unwrap(self) -> T:
        """Get value or raise the error."""
        if self._error is not None:
            raise self._error
        return self._value  # type: ignore[return-value]

    def unwrap_or(self, default: T) -> T:
        """Get value or return default."""
        if self._error is not None:
            return default
        return self._value  # type: ignore[return-value]

# Usage preserves types
def parse_config(path: str) -> Result[Config, ConfigError]:
    try:
        return Result(value=Config.from_file(path))
    except ConfigError as e:
        return Result(error=e)

result = parse_config("config.yaml")
if result.is_success:
    config = result.unwrap()  # Type: Config
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices Summary

1. **Annotate all public APIs** - Functions, methods, class attributes
2. **Use `T | None`** - Modern union syntax over `Optional[T]`
3. **Run strict type checking** - `mypy --strict` in CI
4. **Use generics** - Preserve type info in reusable code
5. **Define protocols** - Structural typing for interfaces
6. **Narrow types** - Use guards to help the type checker
7. **Bound type vars** - Restrict generics to meaningful types
8. **Create type aliases** - Meaningful names for complex types
9. **Minimize `Any`** - Use specific types or generics. `Any` is acceptable for truly dynamic data or when interfacing with untyped third-party code
10. **Document with types** - Types are enforceable documentation

<!-- chapter:end slug=python-type-safety -->

---

<!-- chapter:begin slug=uv-package-manager position=142 -->

## 142. uv-package-manager

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/python-development/skills/uv-package-manager/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/uv-package-manager/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/uv-package-manager.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/advanced-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/python-development/skills/uv-package-manager/references/advanced-patterns.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: uv-package-manager
description: Master the uv package manager for fast Python dependency management, virtual environments, and modern Python project workflows. Use when setting up Python projects, managing dependencies, or optimizing Python development workflows with uv.
---

# UV Package Manager

Comprehensive guide to using uv, an extremely fast Python package installer and resolver written in Rust, for modern Python project management and dependency workflows.

## When to Use This Skill

- Setting up new Python projects quickly
- Managing Python dependencies faster than pip
- Creating and managing virtual environments
- Installing Python interpreters
- Resolving dependency conflicts efficiently
- Migrating from pip/pip-tools/poetry
- Speeding up CI/CD pipelines
- Managing monorepo Python projects
- Working with lockfiles for reproducible builds
- Optimizing Docker builds with Python dependencies

## Core Concepts

### 1. What is uv?

- **Ultra-fast package installer**: 10-100x faster than pip
- **Written in Rust**: Leverages Rust's performance
- **Drop-in pip replacement**: Compatible with pip workflows
- **Virtual environment manager**: Create and manage venvs
- **Python installer**: Download and manage Python versions
- **Resolver**: Advanced dependency resolution
- **Lockfile support**: Reproducible installations

### 2. Key Features

- Blazing fast installation speeds
- Disk space efficient with global cache
- Compatible with pip, pip-tools, poetry
- Comprehensive dependency resolution
- Cross-platform support (Linux, macOS, Windows)
- No Python required for installation
- Built-in virtual environment support

### 3. UV vs Traditional Tools

- **vs pip**: 10-100x faster, better resolver
- **vs pip-tools**: Faster, simpler, better UX
- **vs poetry**: Faster, less opinionated, lighter
- **vs conda**: Faster, Python-focused

## Installation

### Quick Install

```bash
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# Using pip (if you already have Python)
pip install uv

# Using Homebrew (macOS)
brew install uv

# Using cargo (if you have Rust)
cargo install --git https://github.com/astral-sh/uv uv
```

### Verify Installation

```bash
uv --version
# uv 0.x.x
```

## Quick Start

### Create a New Project

```bash
# Create new project with virtual environment
uv init my-project
cd my-project

# Or create in current directory
uv init .

# Initialize creates:
# - .python-version (Python version)
# - pyproject.toml (project config)
# - README.md
# - .gitignore
```

### Install Dependencies

```bash
# Install packages (creates venv if needed)
uv add requests pandas

# Install dev dependencies
uv add --dev pytest black ruff

# Install from requirements.txt
uv pip install -r requirements.txt

# Install from pyproject.toml
uv sync
```

## Virtual Environment Management

### Pattern 1: Creating Virtual Environments

```bash
# Create virtual environment with uv
uv venv

# Create with specific Python version
uv venv --python 3.12

# Create with custom name
uv venv my-env

# Create with system site packages
uv venv --system-site-packages

# Specify location
uv venv /path/to/venv
```

### Pattern 2: Activating Virtual Environments

```bash
# Linux/macOS
source .venv/bin/activate

# Windows (Command Prompt)
.venv\Scripts\activate.bat

# Windows (PowerShell)
.venv\Scripts\Activate.ps1

# Or use uv run (no activation needed)
uv run python script.py
uv run pytest
```

### Pattern 3: Using uv run

```bash
# Run Python script (auto-activates venv)
uv run python app.py

# Run installed CLI tool
uv run black .
uv run pytest

# Run with specific Python version
uv run --python 3.11 python script.py

# Pass arguments
uv run python script.py --arg value
```

## Package Management

### Pattern 4: Adding Dependencies

```bash
# Add package (adds to pyproject.toml)
uv add requests

# Add with version constraint
uv add "django>=4.0,<5.0"

# Add multiple packages
uv add numpy pandas matplotlib

# Add dev dependency
uv add --dev pytest pytest-cov

# Add optional dependency group
uv add --optional docs sphinx

# Add from git
uv add git+https://github.com/user/repo.git

# Add from git with specific ref
uv add git+https://github.com/user/repo.git@v1.0.0

# Add from local path
uv add ./local-package

# Add editable local package
uv add -e ./local-package
```

### Pattern 5: Removing Dependencies

```bash
# Remove package
uv remove requests

# Remove dev dependency
uv remove --dev pytest

# Remove multiple packages
uv remove numpy pandas matplotlib
```

### Pattern 6: Upgrading Dependencies

```bash
# Upgrade specific package
uv add --upgrade requests

# Upgrade all packages
uv sync --upgrade

# Upgrade package to latest
uv add --upgrade requests

# Show what would be upgraded
uv tree --outdated
```

### Pattern 7: Locking Dependencies

```bash
# Generate uv.lock file
uv lock

# Update lock file
uv lock --upgrade

# Lock without installing
uv lock --no-install

# Lock specific package
uv lock --upgrade-package requests
```

## Python Version Management

### Pattern 8: Installing Python Versions

```bash
# Install Python version
uv python install 3.12

# Install multiple versions
uv python install 3.11 3.12 3.13

# Install latest version
uv python install

# List installed versions
uv python list

# Find available versions
uv python list --all-versions
```

### Pattern 9: Setting Python Version

```bash
# Set Python version for project
uv python pin 3.12

# This creates/updates .python-version file

# Use specific Python version for command
uv --python 3.11 run python script.py

# Create venv with specific version
uv venv --python 3.12
```

## Project Configuration

### Pattern 10: pyproject.toml with uv

```toml
[project]
name = "my-project"
version = "0.1.0"
description = "My awesome project"
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
    "requests>=2.31.0",
    "pydantic>=2.0.0",
    "click>=8.1.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.4.0",
    "pytest-cov>=4.1.0",
    "black>=23.0.0",
    "ruff>=0.1.0",
    "mypy>=1.5.0",
]
docs = [
    "sphinx>=7.0.0",
    "sphinx-rtd-theme>=1.3.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.uv]
dev-dependencies = [
    # Additional dev dependencies managed by uv
]

[tool.uv.sources]
# Custom package sources
my-package = { git = "https://github.com/user/repo.git" }
```

### Pattern 11: Using uv with Existing Projects

```bash
# Migrate from requirements.txt
uv add -r requirements.txt

# Migrate from poetry
# Already have pyproject.toml, just use:
uv sync

# Export to requirements.txt
uv pip freeze > requirements.txt

# Export with hashes
uv pip freeze --require-hashes > requirements.txt
```

For advanced workflows including Docker integration, lockfile management, performance optimization, tool comparison, common workflows, tool integration, troubleshooting, best practices, migration guides, and command reference, see [references/advanced-patterns.md](references/advanced-patterns.md)

<!-- chapter:end slug=uv-package-manager -->

---

## Part: Quantitative Trading

---

<!-- chapter:begin slug=backtesting-frameworks position=143 -->

## 143. backtesting-frameworks

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/quantitative-trading/skills/backtesting-frameworks/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/quantitative-trading/skills/backtesting-frameworks/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/backtesting-frameworks.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/quantitative-trading/skills/backtesting-frameworks/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: backtesting-frameworks
description: Build robust backtesting systems for trading strategies with proper handling of look-ahead bias, survivorship bias, and transaction costs. Use when developing trading algorithms, validating strategies, or building backtesting infrastructure.
---

# Backtesting Frameworks

Build robust, production-grade backtesting systems that avoid common pitfalls and produce reliable strategy performance estimates.

## When to Use This Skill

- Developing trading strategy backtests
- Building backtesting infrastructure
- Validating strategy performance
- Avoiding common backtesting biases
- Implementing walk-forward analysis
- Comparing strategy alternatives

## Core Concepts

### 1. Backtesting Biases

| Bias             | Description               | Mitigation              |
| ---------------- | ------------------------- | ----------------------- |
| **Look-ahead**   | Using future information  | Point-in-time data      |
| **Survivorship** | Only testing on survivors | Use delisted securities |
| **Overfitting**  | Curve-fitting to history  | Out-of-sample testing   |
| **Selection**    | Cherry-picking strategies | Pre-registration        |
| **Transaction**  | Ignoring trading costs    | Realistic cost models   |

### 2. Proper Backtest Structure

```
Historical Data
      │
      ▼
┌─────────────────────────────────────────┐
│              Training Set               │
│  (Strategy Development & Optimization)  │
└─────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────┐
│             Validation Set              │
│  (Parameter Selection, No Peeking)      │
└─────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────┐
│               Test Set                  │
│  (Final Performance Evaluation)         │
└─────────────────────────────────────────┘
```

### 3. Walk-Forward Analysis

```
Window 1: [Train──────][Test]
Window 2:     [Train──────][Test]
Window 3:         [Train──────][Test]
Window 4:             [Train──────][Test]
                                     ─────▶ Time
```

## Detailed worked examples and patterns

Detailed sections (starting with `## Implementation Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices

### Do's

- **Use point-in-time data** - Avoid look-ahead bias
- **Include transaction costs** - Realistic estimates
- **Test out-of-sample** - Always reserve data
- **Use walk-forward** - Not just train/test
- **Monte Carlo analysis** - Understand uncertainty

### Don'ts

- **Don't overfit** - Limit parameters
- **Don't ignore survivorship** - Include delisted
- **Don't use adjusted data carelessly** - Understand adjustments
- **Don't optimize on full history** - Reserve test set
- **Don't ignore capacity** - Market impact matters

<!-- chapter:end slug=backtesting-frameworks -->

---

<!-- chapter:begin slug=risk-metrics-calculation position=144 -->

## 144. risk-metrics-calculation

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/quantitative-trading/skills/risk-metrics-calculation/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/quantitative-trading/skills/risk-metrics-calculation/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/risk-metrics-calculation.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/quantitative-trading/skills/risk-metrics-calculation/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: risk-metrics-calculation
description: Calculate portfolio risk metrics including VaR, CVaR, Sharpe, Sortino, and drawdown analysis. Use when measuring portfolio risk, implementing risk limits, or building risk monitoring systems.
---

# Risk Metrics Calculation

Comprehensive risk measurement toolkit for portfolio management, including Value at Risk, Expected Shortfall, and drawdown analysis.

## When to Use This Skill

- Measuring portfolio risk
- Implementing risk limits
- Building risk dashboards
- Calculating risk-adjusted returns
- Setting position sizes
- Regulatory reporting

## Core Concepts

### 1. Risk Metric Categories

| Category          | Metrics         | Use Case             |
| ----------------- | --------------- | -------------------- |
| **Volatility**    | Std Dev, Beta   | General risk         |
| **Tail Risk**     | VaR, CVaR       | Extreme losses       |
| **Drawdown**      | Max DD, Calmar  | Capital preservation |
| **Risk-Adjusted** | Sharpe, Sortino | Performance          |

### 2. Time Horizons

```
Intraday:   Minute/hourly VaR for day traders
Daily:      Standard risk reporting
Weekly:     Rebalancing decisions
Monthly:    Performance attribution
Annual:     Strategic allocation
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use multiple metrics** - No single metric captures all risk
- **Consider tail risk** - VaR isn't enough, use CVaR
- **Rolling analysis** - Risk changes over time
- **Stress test** - Historical and hypothetical
- **Document assumptions** - Distribution, lookback, etc.

### Don'ts

- **Don't rely on VaR alone** - Underestimates tail risk
- **Don't assume normality** - Returns are fat-tailed
- **Don't ignore correlation** - Increases in stress
- **Don't use short lookbacks** - Miss regime changes
- **Don't forget transaction costs** - Affects realized risk

<!-- chapter:end slug=risk-metrics-calculation -->

---

## Part: Reverse Engineering

---

<!-- chapter:begin slug=anti-reversing-techniques position=145 -->

## 145. anti-reversing-techniques

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/reverse-engineering/skills/anti-reversing-techniques/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/anti-reversing-techniques/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/anti-reversing-techniques.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (2), referenced from this skill's directory:
  - `references/advanced-techniques.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/anti-reversing-techniques/references/advanced-techniques.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/anti-reversing-techniques/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: anti-reversing-techniques
description: Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging protections for CTF challenges, when reverse engineering packed binaries, or when building security research tools that need to detect virtualized environments.
---

> **AUTHORIZED USE ONLY**: This skill contains dual-use security techniques. Before proceeding with any bypass or analysis:
>
> 1. **Verify authorization**: Confirm you have explicit written permission from the software owner, or are operating within a legitimate security context (CTF, authorized pentest, malware analysis, security research)
> 2. **Document scope**: Ensure your activities fall within the defined scope of your authorization
> 3. **Legal compliance**: Understand that unauthorized bypassing of software protection may violate laws (CFAA, DMCA anti-circumvention, etc.)
>
> **Legitimate use cases**: Malware analysis, authorized penetration testing, CTF competitions, academic security research, analyzing software you own/have rights to

# Anti-Reversing Techniques

Understanding protection mechanisms encountered during authorized software analysis, security research, and malware analysis. This knowledge helps analysts bypass protections to complete legitimate analysis tasks.

For advanced techniques, see [references/advanced-techniques.md](references/advanced-techniques.md)

---

## Input / Output

**What you provide:**

- **Binary path or sample**: the executable, DLL, or firmware image under analysis
- **Platform**: Windows x86/x64, Linux, macOS, ARM — affects which checks apply
- **Goal**: bypass for dynamic analysis, identify protection type, build detection code, implement for CTF

**What this skill produces:**

- **Protection identification**: named technique (e.g., RDTSC timing check, PEB BeingDebugged) with location in binary
- **Bypass strategy**: specific patch addresses, hook points, or tool commands to neutralize each check
- **Analysis report**: structured findings listing each protection layer, severity, and recommended bypass
- **Code artifacts**: Python/IDAPython scripts, GDB command sequences, or C stubs for bypassing or implementing checks

---

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Troubleshooting

**Detection technique works on x86 but not ARM**

RDTSC and CPUID are x86-only. On ARM, use `MRS x0, PMCCNTR_EL0` (requires kernel PMU access) or `clock_gettime(CLOCK_MONOTONIC)`. PEB/TEB do not exist on ARM — replace with `/proc/self/status` (Linux) or `task_info` (macOS). Rebuild detection logic with platform-specific APIs.

**False positive on legitimate debugger or analysis tool**

Timing checks fire when Process Monitor or AV hooks inflate syscall latency. Calibrate the threshold at startup: measure the guarded path 3 times and use `mean + 3*stddev`. For ptrace checks, verify the TracerPid comm name via `/proc/<pid>/comm` before exiting — it may be an unrelated monitoring tool, not a debugger.

**Bypass patch causes crash instead of continuing execution**

Before NOPing a conditional jump, trace the "detected" branch fully. If it initializes or frees heap state needed later, patching the jump skips that setup and corrupts state. Instead, patch the comparison operand to the expected "clean" value, or use x64dbg's "Set condition to always false" on the breakpoint rather than modifying bytes.

---

## Related Skills

- `binary-analysis-patterns` — static and dynamic analysis workflows for ELF/PE/Mach-O
- `memory-forensics` — process memory acquisition, artifact extraction, and live analysis
- `protocol-reverse-engineering` — decoding custom binary protocols and encrypted network traffic

<!-- chapter:end slug=anti-reversing-techniques -->

---

<!-- chapter:begin slug=binary-analysis-patterns position=146 -->

## 146. binary-analysis-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/reverse-engineering/skills/binary-analysis-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/binary-analysis-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/binary-analysis-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/binary-analysis-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: binary-analysis-patterns
description: Master binary analysis patterns including disassembly, decompilation, control flow analysis, and code pattern recognition. Use when analyzing executables, understanding compiled code, or performing static analysis on binaries.
---

# Binary Analysis Patterns

Comprehensive patterns and techniques for analyzing compiled binaries, understanding assembly code, and reconstructing program logic.

## When to Use This Skill

- Reverse-engineering an unknown executable to understand its behavior
- Analyzing malware or obfuscated binaries with Ghidra / IDA Pro / Binary Ninja
- Recognizing common assembly idioms (function prologues, switch tables, vtable dispatch)
- Reconstructing high-level control flow from compiled code
- Identifying compiler-introduced patterns (stack canaries, PIC trampolines)

## Detailed section: Disassembly Fundamentals

Originally a 2047-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap.

## Control Flow Patterns

### Conditional Branches

```asm
; if (a == b)
cmp eax, ebx
jne skip_block
; ... if body ...
skip_block:

; if (a < b) - signed
cmp eax, ebx
jge skip_block    ; Jump if greater or equal
; ... if body ...
skip_block:

; if (a < b) - unsigned
cmp eax, ebx
jae skip_block    ; Jump if above or equal
; ... if body ...
skip_block:
```

### Loop Patterns

```asm
; for (int i = 0; i < n; i++)
xor ecx, ecx           ; i = 0
loop_start:
cmp ecx, [n]           ; i < n
jge loop_end
; ... loop body ...
inc ecx                ; i++
jmp loop_start
loop_end:

; while (condition)
jmp loop_check
loop_body:
; ... body ...
loop_check:
cmp eax, ebx
jl loop_body

; do-while
loop_body:
; ... body ...
cmp eax, ebx
jl loop_body
```

### Switch Statement Patterns

```asm
; Jump table pattern
mov eax, [switch_var]
cmp eax, max_case
ja default_case
jmp [jump_table + eax*8]

; Sequential comparison (small switch)
cmp eax, 1
je case_1
cmp eax, 2
je case_2
cmp eax, 3
je case_3
jmp default_case
```

## Data Structure Patterns

### Array Access

```asm
; array[i] - 4-byte elements
mov eax, [rbx + rcx*4]        ; rbx=base, rcx=index

; array[i] - 8-byte elements
mov rax, [rbx + rcx*8]

; Multi-dimensional array[i][j]
; arr[i][j] = base + (i * cols + j) * element_size
imul eax, [cols]
add eax, [j]
mov edx, [rbx + rax*4]
```

### Structure Access

```c
struct Example {
    int a;      // offset 0
    char b;     // offset 4
    // padding  // offset 5-7
    long c;     // offset 8
    short d;    // offset 16
};
```

```asm
; Accessing struct fields
mov rdi, [struct_ptr]
mov eax, [rdi]         ; s->a (offset 0)
movzx eax, byte [rdi+4] ; s->b (offset 4)
mov rax, [rdi+8]       ; s->c (offset 8)
movzx eax, word [rdi+16] ; s->d (offset 16)
```

### Linked List Traversal

```asm
; while (node != NULL)
list_loop:
test rdi, rdi          ; node == NULL?
jz list_done
; ... process node ...
mov rdi, [rdi+8]       ; node = node->next (assuming next at offset 8)
jmp list_loop
list_done:
```

## Common Code Patterns

### String Operations

```asm
; strlen pattern
xor ecx, ecx
strlen_loop:
cmp byte [rdi + rcx], 0
je strlen_done
inc ecx
jmp strlen_loop
strlen_done:
; ecx contains length

; strcpy pattern
strcpy_loop:
mov al, [rsi]
mov [rdi], al
test al, al
jz strcpy_done
inc rsi
inc rdi
jmp strcpy_loop
strcpy_done:

; memcpy using rep movsb
mov rdi, dest
mov rsi, src
mov rcx, count
rep movsb
```

### Arithmetic Patterns

```asm
; Multiplication by constant
; x * 3
lea eax, [rax + rax*2]

; x * 5
lea eax, [rax + rax*4]

; x * 10
lea eax, [rax + rax*4]  ; x * 5
add eax, eax            ; * 2

; Division by power of 2 (signed)
mov eax, [x]
cdq                     ; Sign extend to EDX:EAX
and edx, 7              ; For divide by 8
add eax, edx            ; Adjust for negative
sar eax, 3              ; Arithmetic shift right

; Modulo power of 2
and eax, 7              ; x % 8
```

### Bit Manipulation

```asm
; Test specific bit
test eax, 0x80          ; Test bit 7
jnz bit_set

; Set bit
or eax, 0x10            ; Set bit 4

; Clear bit
and eax, ~0x10          ; Clear bit 4

; Toggle bit
xor eax, 0x10           ; Toggle bit 4

; Count leading zeros
bsr eax, ecx            ; Bit scan reverse
xor eax, 31             ; Convert to leading zeros

; Population count (popcnt)
popcnt eax, ecx         ; Count set bits
```

## Decompilation Patterns

### Variable Recovery

```asm
; Local variable at rbp-8
mov qword [rbp-8], rax  ; Store to local
mov rax, [rbp-8]        ; Load from local

; Stack-allocated array
lea rax, [rbp-0x40]     ; Array starts at rbp-0x40
mov [rax], edx          ; array[0] = value
mov [rax+4], ecx        ; array[1] = value
```

### Function Signature Recovery

```asm
; Identify parameters by register usage
func:
    ; rdi used as first param (System V)
    mov [rbp-8], rdi    ; Save param to local
    ; rsi used as second param
    mov [rbp-16], rsi
    ; Identify return by RAX at end
    mov rax, [result]
    ret
```

### Type Recovery

```asm
; 1-byte operations suggest char/bool
movzx eax, byte [rdi]   ; Zero-extend byte
movsx eax, byte [rdi]   ; Sign-extend byte

; 2-byte operations suggest short
movzx eax, word [rdi]
movsx eax, word [rdi]

; 4-byte operations suggest int/float
mov eax, [rdi]
movss xmm0, [rdi]       ; Float

; 8-byte operations suggest long/double/pointer
mov rax, [rdi]
movsd xmm0, [rdi]       ; Double
```

## Ghidra Analysis Tips

### Improving Decompilation

```java
// In Ghidra scripting
// Fix function signature
Function func = getFunctionAt(toAddr(0x401000));
func.setReturnType(IntegerDataType.dataType, SourceType.USER_DEFINED);

// Create structure type
StructureDataType struct = new StructureDataType("MyStruct", 0);
struct.add(IntegerDataType.dataType, "field_a", null);
struct.add(PointerDataType.dataType, "next", null);

// Apply to memory
createData(toAddr(0x601000), struct);
```

### Pattern Matching Scripts

```python
# Find all calls to dangerous functions
for func in currentProgram.getFunctionManager().getFunctions(True):
    for ref in getReferencesTo(func.getEntryPoint()):
        if func.getName() in ["strcpy", "sprintf", "gets"]:
            print(f"Dangerous call at {ref.getFromAddress()}")
```

## IDA Pro Patterns

### IDAPython Analysis

```python
import idaapi
import idautils
import idc

# Find all function calls
def find_calls(func_name):
    for func_ea in idautils.Functions():
        for head in idautils.Heads(func_ea, idc.find_func_end(func_ea)):
            if idc.print_insn_mnem(head) == "call":
                target = idc.get_operand_value(head, 0)
                if idc.get_func_name(target) == func_name:
                    print(f"Call to {func_name} at {hex(head)}")

# Rename functions based on strings
def auto_rename():
    for s in idautils.Strings():
        for xref in idautils.XrefsTo(s.ea):
            func = idaapi.get_func(xref.frm)
            if func and "sub_" in idc.get_func_name(func.start_ea):
                # Use string as hint for naming
                pass
```

## Best Practices

### Analysis Workflow

1. **Initial triage**: File type, architecture, imports/exports
2. **String analysis**: Identify interesting strings, error messages
3. **Function identification**: Entry points, exports, cross-references
4. **Control flow mapping**: Understand program structure
5. **Data structure recovery**: Identify structs, arrays, globals
6. **Algorithm identification**: Crypto, hashing, compression
7. **Documentation**: Comments, renamed symbols, type definitions

### Common Pitfalls

- **Optimizer artifacts**: Code may not match source structure
- **Inline functions**: Functions may be expanded inline
- **Tail call optimization**: `jmp` instead of `call` + `ret`
- **Dead code**: Unreachable code from optimization
- **Position-independent code**: RIP-relative addressing

<!-- chapter:end slug=binary-analysis-patterns -->

---

<!-- chapter:begin slug=memory-forensics position=147 -->

## 147. memory-forensics

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/reverse-engineering/skills/memory-forensics/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/memory-forensics/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/memory-forensics.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/memory-forensics/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: memory-forensics
description: Master memory forensics techniques including memory acquisition, process analysis, and artifact extraction using Volatility and related tools. Use when analyzing memory dumps, investigating incidents, or performing malware analysis from RAM captures.
---

# Memory Forensics

Comprehensive techniques for acquiring, analyzing, and extracting artifacts from memory dumps for incident response and malware analysis.

## When to Use This Skill

- Performing memory analysis during incident response or breach investigation
- Extracting malware artifacts (processes, injected code, network connections) from a RAM capture
- Acquiring volatile memory from a live Windows/Linux/macOS system before shutdown
- Using Volatility 3 / Rekall to triage memory dumps
- Recovering credentials, browser sessions, or open files from process memory

## Memory Acquisition

### Live Acquisition Tools

#### Windows

```powershell
# WinPmem (Recommended)
winpmem_mini_x64.exe memory.raw

# DumpIt
DumpIt.exe

# Belkasoft RAM Capturer
# GUI-based, outputs raw format

# Magnet RAM Capture
# GUI-based, outputs raw format
```

#### Linux

```bash
# LiME (Linux Memory Extractor)
sudo insmod lime.ko "path=/tmp/memory.lime format=lime"

# /dev/mem (limited, requires permissions)
sudo dd if=/dev/mem of=memory.raw bs=1M

# /proc/kcore (ELF format)
sudo cp /proc/kcore memory.elf
```

#### macOS

```bash
# osxpmem
sudo ./osxpmem -o memory.raw

# MacQuisition (commercial)
```

### Virtual Machine Memory

```bash
# VMware: .vmem file is raw memory
cp vm.vmem memory.raw

# VirtualBox: Use debug console
vboxmanage debugvm "VMName" dumpvmcore --filename memory.elf

# QEMU
virsh dump <domain> memory.raw --memory-only

# Hyper-V
# Checkpoint contains memory state
```

## Detailed section: Volatility 3 Framework

Originally a 2680-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap.

## Analysis Workflows

### Malware Analysis Workflow

```bash
# 1. Initial process survey
vol -f memory.raw windows.pstree > processes.txt
vol -f memory.raw windows.pslist > pslist.txt

# 2. Network connections
vol -f memory.raw windows.netscan > network.txt

# 3. Detect injection
vol -f memory.raw windows.malfind > malfind.txt

# 4. Analyze suspicious processes
vol -f memory.raw windows.dlllist --pid <PID>
vol -f memory.raw windows.handles --pid <PID>

# 5. Dump suspicious executables
vol -f memory.raw windows.pslist --pid <PID> --dump

# 6. Extract strings from dumps
strings -a pid.<PID>.exe > strings.txt

# 7. YARA scanning
vol -f memory.raw windows.yarascan --yara-rules malware.yar
```

### Incident Response Workflow

```bash
# 1. Timeline of events
vol -f memory.raw windows.timeliner > timeline.csv

# 2. User activity
vol -f memory.raw windows.cmdline
vol -f memory.raw windows.consoles

# 3. Persistence mechanisms
vol -f memory.raw windows.registry.printkey \
    --key "Software\Microsoft\Windows\CurrentVersion\Run"

# 4. Services
vol -f memory.raw windows.svcscan

# 5. Scheduled tasks
vol -f memory.raw windows.scheduled_tasks

# 6. Recent files
vol -f memory.raw windows.filescan | grep -i "recent"
```

## Data Structures

### Windows Process Structures

```c
// EPROCESS (Executive Process)
typedef struct _EPROCESS {
    KPROCESS Pcb;                    // Kernel process block
    EX_PUSH_LOCK ProcessLock;
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER ExitTime;
    // ...
    LIST_ENTRY ActiveProcessLinks;   // Doubly-linked list
    ULONG_PTR UniqueProcessId;       // PID
    // ...
    PEB* Peb;                        // Process Environment Block
    // ...
} EPROCESS;

// PEB (Process Environment Block)
typedef struct _PEB {
    BOOLEAN InheritedAddressSpace;
    BOOLEAN ReadImageFileExecOptions;
    BOOLEAN BeingDebugged;           // Anti-debug check
    // ...
    PVOID ImageBaseAddress;          // Base address of executable
    PPEB_LDR_DATA Ldr;              // Loader data (DLL list)
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
    // ...
} PEB;
```

### VAD (Virtual Address Descriptor)

```c
typedef struct _MMVAD {
    MMVAD_SHORT Core;
    union {
        ULONG LongFlags;
        MMVAD_FLAGS VadFlags;
    } u;
    // ...
    PVOID FirstPrototypePte;
    PVOID LastContiguousPte;
    // ...
    PFILE_OBJECT FileObject;
} MMVAD;

// Memory protection flags
#define PAGE_EXECUTE           0x10
#define PAGE_EXECUTE_READ      0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
```

## Detection Patterns

### Process Injection Indicators

```python
# Malfind indicators
# - PAGE_EXECUTE_READWRITE protection (suspicious)
# - MZ header in non-image VAD region
# - Shellcode patterns at allocation start

# Common injection techniques
# 1. Classic DLL Injection
#    - VirtualAllocEx + WriteProcessMemory + CreateRemoteThread

# 2. Process Hollowing
#    - CreateProcess (SUSPENDED) + NtUnmapViewOfSection + WriteProcessMemory

# 3. APC Injection
#    - QueueUserAPC targeting alertable threads

# 4. Thread Execution Hijacking
#    - SuspendThread + SetThreadContext + ResumeThread
```

### Rootkit Detection

```bash
# Compare process lists
vol -f memory.raw windows.pslist > pslist.txt
vol -f memory.raw windows.psscan > psscan.txt
diff pslist.txt psscan.txt  # Hidden processes

# Check for DKOM (Direct Kernel Object Manipulation)
vol -f memory.raw windows.callbacks

# Detect hooked functions
vol -f memory.raw windows.ssdt  # System Service Descriptor Table

# Driver analysis
vol -f memory.raw windows.driverscan
vol -f memory.raw windows.driverirp
```

### Credential Extraction

```bash
# Dump hashes (requires hivelist first)
vol -f memory.raw windows.hashdump

# LSA secrets
vol -f memory.raw windows.lsadump

# Cached domain credentials
vol -f memory.raw windows.cachedump

# Mimikatz-style extraction
# Requires specific plugins/tools
```

## YARA Integration

### Writing Memory YARA Rules

```yara
rule Suspicious_Injection
{
    meta:
        description = "Detects common injection shellcode"

    strings:
        // Common shellcode patterns
        $mz = { 4D 5A }
        $shellcode1 = { 55 8B EC 83 EC }  // Function prologue
        $api_hash = { 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? E8 }  // Push hash, call

    condition:
        $mz at 0 or any of ($shellcode*)
}

rule Cobalt_Strike_Beacon
{
    meta:
        description = "Detects Cobalt Strike beacon in memory"

    strings:
        $config = { 00 01 00 01 00 02 }
        $sleep = "sleeptime"
        $beacon = "%s (admin)" wide

    condition:
        2 of them
}
```

### Scanning Memory

```bash
# Scan all process memory
vol -f memory.raw windows.yarascan --yara-rules rules.yar

# Scan specific process
vol -f memory.raw windows.yarascan --yara-rules rules.yar --pid 1234

# Scan kernel memory
vol -f memory.raw windows.yarascan --yara-rules rules.yar --kernel
```

## String Analysis

### Extracting Strings

```bash
# Basic string extraction
strings -a memory.raw > all_strings.txt

# Unicode strings
strings -el memory.raw >> all_strings.txt

# Targeted extraction from process dump
vol -f memory.raw windows.memmap --pid 1234 --dump
strings -a pid.1234.dmp > process_strings.txt

# Pattern matching
grep -E "(https?://|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})" all_strings.txt
```

### FLOSS for Obfuscated Strings

```bash
# FLOSS extracts obfuscated strings
floss malware.exe > floss_output.txt

# From memory dump
floss pid.1234.dmp
```

## Best Practices

### Acquisition Best Practices

1. **Minimize footprint**: Use lightweight acquisition tools
2. **Document everything**: Record time, tool, and hash of capture
3. **Verify integrity**: Hash memory dump immediately after capture
4. **Chain of custody**: Maintain proper forensic handling

### Analysis Best Practices

1. **Start broad**: Get overview before deep diving
2. **Cross-reference**: Use multiple plugins for same data
3. **Timeline correlation**: Correlate memory findings with disk/network
4. **Document findings**: Keep detailed notes and screenshots
5. **Validate results**: Verify findings through multiple methods

### Common Pitfalls

- **Stale data**: Memory is volatile, analyze promptly
- **Incomplete dumps**: Verify dump size matches expected RAM
- **Symbol issues**: Ensure correct symbol files for OS version
- **Smear**: Memory may change during acquisition
- **Encryption**: Some data may be encrypted in memory

<!-- chapter:end slug=memory-forensics -->

---

<!-- chapter:begin slug=protocol-reverse-engineering position=148 -->

## 148. protocol-reverse-engineering

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/reverse-engineering/skills/protocol-reverse-engineering/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/reverse-engineering/skills/protocol-reverse-engineering/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/protocol-reverse-engineering.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: protocol-reverse-engineering
description: Master network protocol reverse engineering including packet analysis, protocol dissection, and custom protocol documentation. Use when analyzing network traffic, understanding proprietary protocols, or debugging network communication.
---

# Protocol Reverse Engineering

Comprehensive techniques for capturing, analyzing, and documenting network protocols for security research, interoperability, and debugging.

## Traffic Capture

### Wireshark Capture

```bash
# Capture on specific interface
wireshark -i eth0 -k

# Capture with filter
wireshark -i eth0 -k -f "port 443"

# Capture to file
tshark -i eth0 -w capture.pcap

# Ring buffer capture (rotate files)
tshark -i eth0 -b filesize:100000 -b files:10 -w capture.pcap
```

### tcpdump Capture

```bash
# Basic capture
tcpdump -i eth0 -w capture.pcap

# With filter
tcpdump -i eth0 port 8080 -w capture.pcap

# Capture specific bytes
tcpdump -i eth0 -s 0 -w capture.pcap  # Full packet

# Real-time display
tcpdump -i eth0 -X port 80
```

### Man-in-the-Middle Capture

```bash
# mitmproxy for HTTP/HTTPS
mitmproxy --mode transparent -p 8080

# SSL/TLS interception
mitmproxy --mode transparent --ssl-insecure

# Dump to file
mitmdump -w traffic.mitm

# Burp Suite
# Configure browser proxy to 127.0.0.1:8080
```

## Protocol Analysis

### Wireshark Analysis

```
# Display filters
tcp.port == 8080
http.request.method == "POST"
ip.addr == 192.168.1.1
tcp.flags.syn == 1 && tcp.flags.ack == 0
frame contains "password"

# Following streams
Right-click > Follow > TCP Stream
Right-click > Follow > HTTP Stream

# Export objects
File > Export Objects > HTTP

# Decryption
Edit > Preferences > Protocols > TLS
  - (Pre)-Master-Secret log filename
  - RSA keys list
```

### tshark Analysis

```bash
# Extract specific fields
tshark -r capture.pcap -T fields -e ip.src -e ip.dst -e tcp.port

# Statistics
tshark -r capture.pcap -q -z conv,tcp
tshark -r capture.pcap -q -z endpoints,ip

# Filter and extract
tshark -r capture.pcap -Y "http" -T json > http_traffic.json

# Protocol hierarchy
tshark -r capture.pcap -q -z io,phs
```

### Scapy for Custom Analysis

```python
from scapy.all import *

# Read pcap
packets = rdpcap("capture.pcap")

# Analyze packets
for pkt in packets:
    if pkt.haslayer(TCP):
        print(f"Src: {pkt[IP].src}:{pkt[TCP].sport}")
        print(f"Dst: {pkt[IP].dst}:{pkt[TCP].dport}")
        if pkt.haslayer(Raw):
            print(f"Data: {pkt[Raw].load[:50]}")

# Filter packets
http_packets = [p for p in packets if p.haslayer(TCP)
                and (p[TCP].sport == 80 or p[TCP].dport == 80)]

# Create custom packets
pkt = IP(dst="target")/TCP(dport=80)/Raw(load="GET / HTTP/1.1\r\n")
send(pkt)
```

## Protocol Identification

### Common Protocol Signatures

```
HTTP        - "HTTP/1." or "GET " or "POST " at start
TLS/SSL     - 0x16 0x03 (record layer)
DNS         - UDP port 53, specific header format
SMB         - 0xFF 0x53 0x4D 0x42 ("SMB" signature)
SSH         - "SSH-2.0" banner
FTP         - "220 " response, "USER " command
SMTP        - "220 " banner, "EHLO" command
MySQL       - 0x00 length prefix, protocol version
PostgreSQL  - 0x00 0x00 0x00 startup length
Redis       - "*" RESP array prefix
MongoDB     - BSON documents with specific header
```

### Protocol Header Patterns

```
+--------+--------+--------+--------+
|  Magic number / Signature         |
+--------+--------+--------+--------+
|  Version       |  Flags          |
+--------+--------+--------+--------+
|  Length        |  Message Type   |
+--------+--------+--------+--------+
|  Sequence Number / Session ID     |
+--------+--------+--------+--------+
|  Payload...                       |
+--------+--------+--------+--------+
```

## Binary Protocol Analysis

### Structure Identification

```python
# Common patterns in binary protocols

# Length-prefixed message
struct Message {
    uint32_t length;      # Total message length
    uint16_t msg_type;    # Message type identifier
    uint8_t  flags;       # Flags/options
    uint8_t  reserved;    # Padding/alignment
    uint8_t  payload[];   # Variable-length payload
};

# Type-Length-Value (TLV)
struct TLV {
    uint8_t  type;        # Field type
    uint16_t length;      # Field length
    uint8_t  value[];     # Field data
};

# Fixed header + variable payload
struct Packet {
    uint8_t  magic[4];    # "ABCD" signature
    uint32_t version;
    uint32_t payload_len;
    uint32_t checksum;    # CRC32 or similar
    uint8_t  payload[];
};
```

### Python Protocol Parser

```python
import struct
from dataclasses import dataclass

@dataclass
class MessageHeader:
    magic: bytes
    version: int
    msg_type: int
    length: int

    @classmethod
    def from_bytes(cls, data: bytes):
        magic, version, msg_type, length = struct.unpack(
            ">4sHHI", data[:12]
        )
        return cls(magic, version, msg_type, length)

def parse_messages(data: bytes):
    offset = 0
    messages = []

    while offset < len(data):
        header = MessageHeader.from_bytes(data[offset:])
        payload = data[offset+12:offset+12+header.length]
        messages.append((header, payload))
        offset += 12 + header.length

    return messages

# Parse TLV structure
def parse_tlv(data: bytes):
    fields = []
    offset = 0

    while offset < len(data):
        field_type = data[offset]
        length = struct.unpack(">H", data[offset+1:offset+3])[0]
        value = data[offset+3:offset+3+length]
        fields.append((field_type, value))
        offset += 3 + length

    return fields
```

### Hex Dump Analysis

```python
def hexdump(data: bytes, width: int = 16):
    """Format binary data as hex dump."""
    lines = []
    for i in range(0, len(data), width):
        chunk = data[i:i+width]
        hex_part = ' '.join(f'{b:02x}' for b in chunk)
        ascii_part = ''.join(
            chr(b) if 32 <= b < 127 else '.'
            for b in chunk
        )
        lines.append(f'{i:08x}  {hex_part:<{width*3}}  {ascii_part}')
    return '\n'.join(lines)

# Example output:
# 00000000  48 54 54 50 2f 31 2e 31  20 32 30 30 20 4f 4b 0d  HTTP/1.1 200 OK.
# 00000010  0a 43 6f 6e 74 65 6e 74  2d 54 79 70 65 3a 20 74  .Content-Type: t
```

## Encryption Analysis

### Identifying Encryption

```python
# Entropy analysis - high entropy suggests encryption/compression
import math
from collections import Counter

def entropy(data: bytes) -> float:
    if not data:
        return 0.0
    counter = Counter(data)
    probs = [count / len(data) for count in counter.values()]
    return -sum(p * math.log2(p) for p in probs)

# Entropy thresholds:
# < 6.0: Likely plaintext or structured data
# 6.0-7.5: Possibly compressed
# > 7.5: Likely encrypted or random

# Common encryption indicators
# - High, uniform entropy
# - No obvious structure or patterns
# - Length often multiple of block size (16 for AES)
# - Possible IV at start (16 bytes for AES-CBC)
```

### TLS Analysis

```bash
# Extract TLS metadata
tshark -r capture.pcap -Y "ssl.handshake" \
    -T fields -e ip.src -e ssl.handshake.ciphersuite

# JA3 fingerprinting (client)
tshark -r capture.pcap -Y "ssl.handshake.type == 1" \
    -T fields -e ssl.handshake.ja3

# JA3S fingerprinting (server)
tshark -r capture.pcap -Y "ssl.handshake.type == 2" \
    -T fields -e ssl.handshake.ja3s

# Certificate extraction
tshark -r capture.pcap -Y "ssl.handshake.certificate" \
    -T fields -e x509sat.printableString
```

### Decryption Approaches

```bash
# Pre-master secret log (browser)
export SSLKEYLOGFILE=/tmp/keys.log

# Configure Wireshark
# Edit > Preferences > Protocols > TLS
# (Pre)-Master-Secret log filename: /tmp/keys.log

# Decrypt with private key (if available)
# Only works for RSA key exchange
# Edit > Preferences > Protocols > TLS > RSA keys list
```

## Custom Protocol Documentation

### Protocol Specification Template

```markdown
# Protocol Name Specification

## Overview

Brief description of protocol purpose and design.

## Transport

- Layer: TCP/UDP
- Port: XXXX
- Encryption: TLS 1.2+

## Message Format

### Header (12 bytes)

| Offset | Size | Field   | Description             |
| ------ | ---- | ------- | ----------------------- |
| 0      | 4    | Magic   | 0x50524F54 ("PROT")     |
| 4      | 2    | Version | Protocol version (1)    |
| 6      | 2    | Type    | Message type identifier |
| 8      | 4    | Length  | Payload length in bytes |

### Message Types

| Type | Name      | Description            |
| ---- | --------- | ---------------------- |
| 0x01 | HELLO     | Connection initiation  |
| 0x02 | HELLO_ACK | Connection accepted    |
| 0x03 | DATA      | Application data       |
| 0x04 | CLOSE     | Connection termination |

### Type 0x01: HELLO

| Offset | Size | Field      | Description              |
| ------ | ---- | ---------- | ------------------------ |
| 0      | 4    | ClientID   | Unique client identifier |
| 4      | 2    | Flags      | Connection flags         |
| 6      | var  | Extensions | TLV-encoded extensions   |

## State Machine
```

[INIT] --HELLO--> [WAIT_ACK] --HELLO_ACK--> [CONNECTED]
|
DATA/DATA
|
[CLOSED] <--CLOSE--+

```

## Examples
### Connection Establishment
```

Client -> Server: HELLO (ClientID=0x12345678)
Server -> Client: HELLO_ACK (Status=OK)
Client -> Server: DATA (payload)

```

```

### Wireshark Dissector (Lua)

```lua
-- custom_protocol.lua
local proto = Proto("custom", "Custom Protocol")

-- Define fields
local f_magic = ProtoField.string("custom.magic", "Magic")
local f_version = ProtoField.uint16("custom.version", "Version")
local f_type = ProtoField.uint16("custom.type", "Type")
local f_length = ProtoField.uint32("custom.length", "Length")
local f_payload = ProtoField.bytes("custom.payload", "Payload")

proto.fields = { f_magic, f_version, f_type, f_length, f_payload }

-- Message type names
local msg_types = {
    [0x01] = "HELLO",
    [0x02] = "HELLO_ACK",
    [0x03] = "DATA",
    [0x04] = "CLOSE"
}

function proto.dissector(buffer, pinfo, tree)
    pinfo.cols.protocol = "CUSTOM"

    local subtree = tree:add(proto, buffer())

    -- Parse header
    subtree:add(f_magic, buffer(0, 4))
    subtree:add(f_version, buffer(4, 2))

    local msg_type = buffer(6, 2):uint()
    subtree:add(f_type, buffer(6, 2)):append_text(
        " (" .. (msg_types[msg_type] or "Unknown") .. ")"
    )

    local length = buffer(8, 4):uint()
    subtree:add(f_length, buffer(8, 4))

    if length > 0 then
        subtree:add(f_payload, buffer(12, length))
    end
end

-- Register for TCP port
local tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(8888, proto)
```

## Active Testing

### Fuzzing with Boofuzz

```python
from boofuzz import *

def main():
    session = Session(
        target=Target(
            connection=TCPSocketConnection("target", 8888)
        )
    )

    # Define protocol structure
    s_initialize("HELLO")
    s_static(b"\x50\x52\x4f\x54")  # Magic
    s_word(1, name="version")       # Version
    s_word(0x01, name="type")       # Type (HELLO)
    s_size("payload", length=4)     # Length field
    s_block_start("payload")
    s_dword(0x12345678, name="client_id")
    s_word(0, name="flags")
    s_block_end()

    session.connect(s_get("HELLO"))
    session.fuzz()

if __name__ == "__main__":
    main()
```

### Replay and Modification

```python
from scapy.all import *

# Replay captured traffic
packets = rdpcap("capture.pcap")
for pkt in packets:
    if pkt.haslayer(TCP) and pkt[TCP].dport == 8888:
        send(pkt)

# Modify and replay
for pkt in packets:
    if pkt.haslayer(Raw):
        # Modify payload
        original = pkt[Raw].load
        modified = original.replace(b"client", b"CLIENT")
        pkt[Raw].load = modified
        # Recalculate checksums
        del pkt[IP].chksum
        del pkt[TCP].chksum
        send(pkt)
```

## Best Practices

### Analysis Workflow

1. **Capture traffic**: Multiple sessions, different scenarios
2. **Identify boundaries**: Message start/end markers
3. **Map structure**: Fixed header, variable payload
4. **Identify fields**: Compare multiple samples
5. **Document format**: Create specification
6. **Validate understanding**: Implement parser/generator
7. **Test edge cases**: Fuzzing, boundary conditions

### Common Patterns to Look For

- Magic numbers/signatures at message start
- Version fields for compatibility
- Length fields (often before variable data)
- Type/opcode fields for message identification
- Sequence numbers for ordering
- Checksums/CRCs for integrity
- Timestamps for timing
- Session/connection identifiers

<!-- chapter:end slug=protocol-reverse-engineering -->

---

## Part: Review Agent Governance

---

<!-- chapter:begin slug=review-agent-setup position=149 -->

## 149. review-agent-setup

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/review-agent-governance/skills/review-agent-setup/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/review-agent-governance/skills/review-agent-setup/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/review-agent-setup.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: review-agent-setup
description: Configure human-in-the-loop gating for AI agent review actions in Claude Code. Use when setting up a project where an agent may post PR reviews, comments, merges, or edit CI configuration, and you want a cryptographically auditable approval trail with Cedar-enforced gates.
---

# review-agent-governance — Setup

Gate AI agent review actions (PR reviews, comments, merges, CI edits) behind
explicit human approval. Every attempt, approved or denied, produces an
Ed25519-signed receipt.

## When to use this plugin

Install it in projects where a Claude Code agent:

- Reviews, comments on, or merges pull requests (`gh pr review`, `gh pr merge`)
- Triages issues (`gh issue comment`, `gh issue close`)
- Publishes releases (`gh release create`)
- Modifies CI configuration (`.github/workflows/`, `.gitlab-ci.yml`)
- Pushes to protected branches (`main`, `master`, `release`, `production`)
- Posts to external notification surfaces (Slack webhooks, Discord)

If the agent is only doing local file edits and running tests, this plugin is
overkill. Use `protect-mcp` for general tool-call policy enforcement and skip
this one.

## One-time setup

### 1. Install the plugin

```bash
claude plugin install wshobson/agents/review-agent-governance
```

### 2. Copy the default policy to your project

```bash
cp .claude/plugins/review-agent-governance/policies/review-agent-governance.cedar \
   ./review-governance.cedar
```

You can edit this file to match your project's specific rules. See
`../agents/review-policy-author.md` for guidance on authoring review
policies.

### 3. Create a receipts directory and sign key

```bash
mkdir -p ./review-receipts
echo "./review-receipts/" >> .gitignore
echo "./review-governance.key" >> .gitignore
echo "./.review-approved" >> .gitignore
```

The first invocation of `protect-mcp sign` will create the key. Commit the
public key from the first receipt so auditors can verify later.

## Per-session workflow

The Cedar policy denies review-surface actions unconditionally. To approve
a specific action, open an approval window before it and close it after.

### Flag file (simplest)

```bash
# Before the action you want to approve
touch ./.review-approved

# Let Claude Code run the review / comment / merge

# Immediately after
rm ./.review-approved
```

### Slash command (from within Claude Code)

```
/approve-review "Reviewing PR #123 authored by contributor X"
```

This creates `./.review-approved` with the given reason embedded as a note,
and writes a human-approved receipt to the chain. A follow-up `rm` is still
needed to close the window.

### Dry-run everything (force full policy evaluation)

If you want every tool call to go through Cedar with no approval bypass:

```bash
export REVIEW_APPROVAL_FLAG=./.never-approve
```

Any tool call matching a forbid rule will be denied; approved windows have
no effect. Useful for CI or for a locked-down audit run.

## Verifying the chain

List all receipts:

```bash
ls -la ./review-receipts/
```

Verify the entire chain offline:

```bash
npx @veritasacta/verify ./review-receipts/*.json
```

Exit 0 means every receipt is authentic and the chain is intact. Exit 1
means one receipt has been tampered with. Exit 2 means a receipt is
malformed.

Look at recent denials:

```
/list-pending
```

Within Claude Code this slash command walks the receipt chain and prints
any recent `decision: deny` entries with the tool name, command pattern,
and timestamp.

## Example: approving a PR review

```bash
# 1. Human reviews the agent's proposed comment
$ /list-pending
  Recent denials:
  - 2026-04-17T14:23:01Z  Bash "gh pr review 42 --approve --body 'LGTM'"
  - 2026-04-17T14:23:02Z  Bash "gh pr comment 42 --body 'Looking good'"

# 2. Human decides the first one is appropriate, approves it
$ /approve-review "Approving LGTM on PR 42 after visual inspection"
  ./.review-approved created

# 3. Agent retries the action; this time it succeeds
$ agent: gh pr review 42 --approve --body "LGTM"
  [receipt: rec_XXX, decision=allow, reason=human_approved]

# 4. Human closes the window
$ rm ./.review-approved
```

Every step is in the receipt chain. The chain is offline-verifiable for
regulators, counterparties, or downstream auditors who want to confirm
that no review action bypassed the human gate.

## Composing with protect-mcp

If both plugins are installed, run them side by side:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "npx protect-mcp@0.7.4 evaluate --policy ./protect.cedar --tool \"$TOOL_NAME\" --input \"$TOOL_INPUT\" --fail-on-missing-policy false"
          }
        ]
      },
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "if [ -f ./.review-approved ]; then exit 0; fi; npx protect-mcp@0.7.4 evaluate --policy ./review-governance.cedar --tool \"$TOOL_NAME\" --input \"$TOOL_INPUT\" --fail-on-missing-policy false"
          }
        ]
      }
    ]
  }
}
```

Both hooks must pass for the tool call to proceed. Cedar deny in either
policy blocks it.

## Standards

- **Ed25519** — RFC 8032 (digital signatures)
- **JCS** — RFC 8785 (deterministic JSON canonicalization)
- **Cedar** — AWS's open authorization policy language
- **IETF draft** — [draft-farley-acta-signed-receipts](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/)

<!-- chapter:end slug=review-agent-setup -->

---

## Part: Security Scanning

---

<!-- chapter:begin slug=attack-tree-construction position=150 -->

## 150. attack-tree-construction

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/security-scanning/skills/attack-tree-construction/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/attack-tree-construction/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/attack-tree-construction.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/attack-tree-construction/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: attack-tree-construction
description: Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to stakeholders.
---

# Attack Tree Construction

Systematic attack path visualization and analysis.

## When to Use This Skill

- Visualizing complex attack scenarios
- Identifying defense gaps and priorities
- Communicating risks to stakeholders
- Planning defensive investments
- Penetration test planning
- Security architecture review

## Core Concepts

### 1. Attack Tree Structure

```
                    [Root Goal]
                         |
            ┌────────────┴────────────┐
            │                         │
       [Sub-goal 1]              [Sub-goal 2]
       (OR node)                 (AND node)
            │                         │
      ┌─────┴─────┐             ┌─────┴─────┐
      │           │             │           │
   [Attack]   [Attack]      [Attack]   [Attack]
    (leaf)     (leaf)        (leaf)     (leaf)
```

### 2. Node Types

| Type     | Symbol    | Description             |
| -------- | --------- | ----------------------- |
| **OR**   | Oval      | Any child achieves goal |
| **AND**  | Rectangle | All children required   |
| **Leaf** | Box       | Atomic attack step      |

### 3. Attack Attributes

| Attribute     | Description             | Values             |
| ------------- | ----------------------- | ------------------ |
| **Cost**      | Resources needed        | $, $$, $$$         |
| **Time**      | Duration to execute     | Hours, Days, Weeks |
| **Skill**     | Expertise required      | Low, Medium, High  |
| **Detection** | Likelihood of detection | Low, Medium, High  |

## Templates and detailed worked examples

Full template library lives in `references/details.md`. Read that file when you need concrete templates for this skill.

## Best Practices

### Do's

- **Start with clear goals** - Define what attacker wants
- **Be exhaustive** - Consider all attack vectors
- **Attribute attacks** - Cost, skill, and detection
- **Update regularly** - New threats emerge
- **Validate with experts** - Red team review

### Don'ts

- **Don't oversimplify** - Real attacks are complex
- **Don't ignore dependencies** - AND nodes matter
- **Don't forget insider threats** - Not all attackers are external
- **Don't skip mitigations** - Trees are for defense planning
- **Don't make it static** - Threat landscape evolves

<!-- chapter:end slug=attack-tree-construction -->

---

<!-- chapter:begin slug=sast-configuration position=151 -->

## 151. sast-configuration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/security-scanning/skills/sast-configuration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/sast-configuration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/sast-configuration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: sast-configuration
description: Configure Static Application Security Testing (SAST) tools for automated vulnerability detection in application code. Use when setting up security scanning, implementing DevSecOps practices, or automating code vulnerability detection.
---

# SAST Configuration

Static Application Security Testing (SAST) tool setup, configuration, and custom rule creation for comprehensive security scanning across multiple programming languages.

## Overview

This skill provides comprehensive guidance for setting up and configuring SAST tools including Semgrep, SonarQube, and CodeQL. Use this skill when you need to:

- Set up SAST scanning in CI/CD pipelines
- Create custom security rules for your codebase
- Configure quality gates and compliance policies
- Optimize scan performance and reduce false positives
- Integrate multiple SAST tools for defense-in-depth

## Core Capabilities

### 1. Semgrep Configuration

- Custom rule creation with pattern matching
- Language-specific security rules (Python, JavaScript, Go, Java, etc.)
- CI/CD integration (GitHub Actions, GitLab CI, Jenkins)
- False positive tuning and rule optimization
- Organizational policy enforcement

### 2. SonarQube Setup

- Quality gate configuration
- Security hotspot analysis
- Code coverage and technical debt tracking
- Custom quality profiles for languages
- Enterprise integration with LDAP/SAML

### 3. CodeQL Analysis

- GitHub Advanced Security integration
- Custom query development
- Vulnerability variant analysis
- Security research workflows
- SARIF result processing

## Quick Start

### Initial Assessment

1. Identify primary programming languages in your codebase
2. Determine compliance requirements (PCI-DSS, SOC 2, etc.)
3. Choose SAST tool based on language support and integration needs
4. Review baseline scan to understand current security posture

### Basic Setup

```bash
# Semgrep quick start
pip install semgrep
semgrep --config=auto --error

# SonarQube with Docker
docker run -d --name sonarqube -p 9000:9000 sonarqube:10.8-community

# CodeQL CLI setup
gh extension install github/gh-codeql
codeql database create mydb --language=python
```

## Integration Patterns

### CI/CD Pipeline Integration

```yaml
# GitHub Actions example
- name: Run Semgrep
  uses: returntocorp/semgrep-action@v1
  with:
    config: >-
      p/security-audit
      p/owasp-top-ten
```

### Pre-commit Hook

```bash
# .pre-commit-config.yaml
- repo: https://github.com/returntocorp/semgrep
  rev: v1.45.0
  hooks:
    - id: semgrep
      args: ['--config=auto', '--error']
```

## Best Practices

1. **Start with Baseline**
   - Run initial scan to establish security baseline
   - Prioritize critical and high severity findings
   - Create remediation roadmap

2. **Incremental Adoption**
   - Begin with security-focused rules
   - Gradually add code quality rules
   - Implement blocking only for critical issues

3. **False Positive Management**
   - Document legitimate suppressions
   - Create allow lists for known safe patterns
   - Regularly review suppressed findings

4. **Performance Optimization**
   - Exclude test files and generated code
   - Use incremental scanning for large codebases
   - Cache scan results in CI/CD

5. **Team Enablement**
   - Provide security training for developers
   - Create internal documentation for common patterns
   - Establish security champions program

## Common Use Cases

### New Project Setup

```bash
./scripts/run-sast.sh --setup --language python --tools semgrep,sonarqube
```

### Custom Rule Development

```yaml
# See references/semgrep-rules.md for detailed examples
rules:
  - id: hardcoded-jwt-secret
    pattern: jwt.encode($DATA, "...", ...)
    message: JWT secret should not be hardcoded
    severity: ERROR
```

### Compliance Scanning

```bash
# PCI-DSS focused scan
semgrep --config p/pci-dss --json -o pci-scan-results.json
```

## Troubleshooting

### High False Positive Rate

- Review and tune rule sensitivity
- Add path filters to exclude test files
- Use nostmt metadata for noisy patterns
- Create organization-specific rule exceptions

### Performance Issues

- Enable incremental scanning
- Parallelize scans across modules
- Optimize rule patterns for efficiency
- Cache dependencies and scan results

### Integration Failures

- Verify API tokens and credentials
- Check network connectivity and proxy settings
- Review SARIF output format compatibility
- Validate CI/CD runner permissions

## Related Skills

- [OWASP Top 10 Checklist](../owasp-top10-checklist/SKILL.md)
- [Container Security](../container-security/SKILL.md)
- [Dependency Scanning](../dependency-scanning/SKILL.md)

## Tool Comparison

| Tool      | Best For                 | Language Support | Cost            | Integration   |
| --------- | ------------------------ | ---------------- | --------------- | ------------- |
| Semgrep   | Custom rules, fast scans | 30+ languages    | Free/Enterprise | Excellent     |
| SonarQube | Code quality + security  | 25+ languages    | Free/Commercial | Good          |
| CodeQL    | Deep analysis, research  | 10+ languages    | Free (OSS)      | GitHub native |

## Next Steps

1. Complete initial SAST tool setup
2. Run baseline security scan
3. Create custom rules for organization-specific patterns
4. Integrate into CI/CD pipeline
5. Establish security gate policies
6. Train development team on findings and remediation

<!-- chapter:end slug=sast-configuration -->

---

<!-- chapter:begin slug=security-requirement-extraction position=152 -->

## 152. security-requirement-extraction

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/security-scanning/skills/security-requirement-extraction/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/security-requirement-extraction/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/security-requirement-extraction.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/security-requirement-extraction/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: security-requirement-extraction
description: Derive security requirements from threat models and business context. Use when translating threats into actionable requirements, creating security user stories, or building security test cases.
---

# Security Requirement Extraction

Transform threat analysis into actionable security requirements.

## When to Use This Skill

- Converting threat models to requirements
- Writing security user stories
- Creating security test cases
- Building security acceptance criteria
- Compliance requirement mapping
- Security architecture documentation

## Core Concepts

### 1. Requirement Categories

```
Business Requirements → Security Requirements → Technical Controls
         ↓                       ↓                      ↓
  "Protect customer    "Encrypt PII at rest"   "AES-256 encryption
   data"                                        with KMS key rotation"
```

### 2. Security Requirement Types

| Type               | Focus                   | Example                               |
| ------------------ | ----------------------- | ------------------------------------- |
| **Functional**     | What system must do     | "System must authenticate users"      |
| **Non-functional** | How system must perform | "Authentication must complete in <2s" |
| **Constraint**     | Limitations imposed     | "Must use approved crypto libraries"  |

### 3. Requirement Attributes

| Attribute        | Description                 |
| ---------------- | --------------------------- |
| **Traceability** | Links to threats/compliance |
| **Testability**  | Can be verified             |
| **Priority**     | Business importance         |
| **Risk Level**   | Impact if not met           |

## Templates and detailed worked examples

Full template library lives in `references/details.md`. Read that file when you need concrete templates for this skill.

## Best Practices

### Do's

- **Trace to threats** - Every requirement should map to threats
- **Be specific** - Vague requirements can't be tested
- **Include acceptance criteria** - Define "done"
- **Consider compliance** - Map to frameworks early
- **Review regularly** - Requirements evolve with threats

### Don'ts

- **Don't be generic** - "Be secure" is not a requirement
- **Don't skip rationale** - Explain why it matters
- **Don't ignore priorities** - Not all requirements are equal
- **Don't forget testability** - If you can't test it, you can't verify it
- **Don't work in isolation** - Involve stakeholders

<!-- chapter:end slug=security-requirement-extraction -->

---

<!-- chapter:begin slug=stride-analysis-patterns position=153 -->

## 153. stride-analysis-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/security-scanning/skills/stride-analysis-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/stride-analysis-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/stride-analysis-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/stride-analysis-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: stride-analysis-patterns
description: Apply STRIDE methodology to systematically identify threats. Use when analyzing system security, conducting threat modeling sessions, or creating security documentation.
---

# STRIDE Analysis Patterns

Systematic threat identification using the STRIDE methodology.

## When to Use This Skill

- Starting new threat modeling sessions
- Analyzing existing system architecture
- Reviewing security design decisions
- Creating threat documentation
- Training teams on threat identification
- Compliance and audit preparation

## Core Concepts

### 1. STRIDE Categories

```
S - Spoofing       → Authentication threats
T - Tampering      → Integrity threats
R - Repudiation    → Non-repudiation threats
I - Information    → Confidentiality threats
    Disclosure
D - Denial of      → Availability threats
    Service
E - Elevation of   → Authorization threats
    Privilege
```

### 2. Threat Analysis Matrix

| Category            | Question                                  | Control Family |
| ------------------- | ----------------------------------------- | -------------- |
| **Spoofing**        | Can attacker pretend to be someone else?  | Authentication |
| **Tampering**       | Can attacker modify data in transit/rest? | Integrity      |
| **Repudiation**     | Can attacker deny actions?                | Logging/Audit  |
| **Info Disclosure** | Can attacker access unauthorized data?    | Encryption     |
| **DoS**             | Can attacker disrupt availability?        | Rate limiting  |
| **Elevation**       | Can attacker gain higher privileges?      | Authorization  |

## Templates and detailed worked examples

Full template library lives in `references/details.md`. Read that file when you need concrete templates for this skill.

## Best Practices

### Do's

- **Involve stakeholders** - Security, dev, and ops perspectives
- **Be systematic** - Cover all STRIDE categories
- **Prioritize realistically** - Focus on high-impact threats
- **Update regularly** - Threat models are living documents
- **Use visual aids** - DFDs help communication

### Don'ts

- **Don't skip categories** - Each reveals different threats
- **Don't assume security** - Question every component
- **Don't work in isolation** - Collaborative modeling is better
- **Don't ignore low-probability** - High-impact threats matter
- **Don't stop at identification** - Follow through with mitigations

<!-- chapter:end slug=stride-analysis-patterns -->

---

<!-- chapter:begin slug=threat-mitigation-mapping position=154 -->

## 154. threat-mitigation-mapping

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/security-scanning/skills/threat-mitigation-mapping/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/threat-mitigation-mapping/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/threat-mitigation-mapping.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/security-scanning/skills/threat-mitigation-mapping/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: threat-mitigation-mapping
description: Map identified threats to appropriate security controls and mitigations. Use when prioritizing security investments, creating remediation plans, or validating control effectiveness.
---

# Threat Mitigation Mapping

Connect threats to controls for effective security planning.

## When to Use This Skill

- Prioritizing security investments
- Creating remediation roadmaps
- Validating control coverage
- Designing defense-in-depth
- Security architecture review
- Risk treatment planning

## Core Concepts

### 1. Control Categories

```
Preventive ────► Stop attacks before they occur
   │              (Firewall, Input validation)
   │
Detective ─────► Identify attacks in progress
   │              (IDS, Log monitoring)
   │
Corrective ────► Respond and recover from attacks
                  (Incident response, Backup restore)
```

### 2. Control Layers

| Layer           | Examples                             |
| --------------- | ------------------------------------ |
| **Network**     | Firewall, WAF, DDoS protection       |
| **Application** | Input validation, authentication     |
| **Data**        | Encryption, access controls          |
| **Endpoint**    | EDR, patch management                |
| **Process**     | Security training, incident response |

### 3. Defense in Depth

```
                    ┌──────────────────────┐
                    │      Perimeter       │ ← Firewall, WAF
                    │   ┌──────────────┐   │
                    │   │   Network    │   │ ← Segmentation, IDS
                    │   │  ┌────────┐  │   │
                    │   │  │  Host  │  │   │ ← EDR, Hardening
                    │   │  │ ┌────┐ │  │   │
                    │   │  │ │App │ │  │   │ ← Auth, Validation
                    │   │  │ │Data│ │  │   │ ← Encryption
                    │   │  │ └────┘ │  │   │
                    │   │  └────────┘  │   │
                    │   └──────────────┘   │
                    └──────────────────────┘
```

## Templates and detailed worked examples

Full template library and detailed mitigation/control mappings live in `references/details.md`. Read that file when you need the concrete templates for: Mitigation Model, Defense in Depth scoring, Executive Summary scaffolding, Critical Gaps reporting, Recommendations, Implementation Roadmap, Results by Control.

## Best Practices

### Do's

- **Map all threats** - No threat should be unmapped
- **Layer controls** - Defense in depth is essential
- **Mix control types** - Preventive, detective, corrective
- **Track effectiveness** - Measure and improve
- **Review regularly** - Controls degrade over time

### Don'ts

- **Don't rely on single controls** - Single points of failure
- **Don't ignore cost** - ROI matters
- **Don't skip testing** - Untested controls may fail
- **Don't set and forget** - Continuous improvement
- **Don't ignore people/process** - Technology alone isn't enough

<!-- chapter:end slug=threat-mitigation-mapping -->

---

## Part: Shell Scripting

---

<!-- chapter:begin slug=bash-defensive-patterns position=155 -->

## 155. bash-defensive-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/shell-scripting/skills/bash-defensive-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/shell-scripting/skills/bash-defensive-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/bash-defensive-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/shell-scripting/skills/bash-defensive-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: bash-defensive-patterns
description: Master defensive Bash programming techniques for production-grade scripts. Use when writing robust shell scripts, CI/CD pipelines, or system utilities requiring fault tolerance and safety.
---

# Bash Defensive Patterns

Comprehensive guidance for writing production-ready Bash scripts using defensive programming techniques, error handling, and safety best practices to prevent common pitfalls and ensure reliability.

## When to Use This Skill

- Writing production automation scripts
- Building CI/CD pipeline scripts
- Creating system administration utilities
- Developing error-resilient deployment automation
- Writing scripts that must handle edge cases safely
- Building maintainable shell script libraries
- Implementing comprehensive logging and monitoring
- Creating scripts that must work across different platforms

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices Summary

1. **Always use strict mode** - `set -Eeuo pipefail`
2. **Quote all variables** - `"$variable"` prevents word splitting
3. **Use [[]] conditionals** - More robust than [ ]
4. **Implement error trapping** - Catch and handle errors gracefully
5. **Validate all inputs** - Check file existence, permissions, formats
6. **Use functions for reusability** - Prefix with meaningful names
7. **Implement structured logging** - Include timestamps and levels
8. **Support dry-run mode** - Allow users to preview changes
9. **Handle temporary files safely** - Use mktemp, cleanup with trap
10. **Design for idempotency** - Scripts should be safe to rerun
11. **Document requirements** - List dependencies and minimum versions
12. **Test error paths** - Ensure error handling works correctly
13. **Use `command -v`** - Safer than `which` for checking executables
14. **Prefer printf over echo** - More predictable across systems

<!-- chapter:end slug=bash-defensive-patterns -->

---

<!-- chapter:begin slug=bats-testing-patterns position=156 -->

## 156. bats-testing-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/shell-scripting/skills/bats-testing-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/shell-scripting/skills/bats-testing-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/bats-testing-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/shell-scripting/skills/bats-testing-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: bats-testing-patterns
description: Master Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring test-driven development of shell utilities.
---

# Bats Testing Patterns

Comprehensive guidance for writing comprehensive unit tests for shell scripts using Bats (Bash Automated Testing System), including test patterns, fixtures, and best practices for production-grade shell testing.

## When to Use This Skill

- Writing unit tests for shell scripts
- Implementing test-driven development (TDD) for scripts
- Setting up automated testing in CI/CD pipelines
- Testing edge cases and error conditions
- Validating behavior across different shell environments
- Building maintainable test suites for scripts
- Creating fixtures for complex test scenarios
- Testing multiple shell dialects (bash, sh, dash)

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Testing Error Conditions

```bash
#!/usr/bin/env bats

@test "Function fails with missing file" {
    run my_function "/nonexistent/file.txt"
    [ "$status" -ne 0 ]
    [[ "$output" == *"not found"* ]]
}

@test "Function fails with invalid input" {
    run my_function ""
    [ "$status" -ne 0 ]
}

@test "Function fails with permission denied" {
    touch "$TMPDIR/readonly.txt"
    chmod 000 "$TMPDIR/readonly.txt"
    run my_function "$TMPDIR/readonly.txt"
    [ "$status" -ne 0 ]
    chmod 644 "$TMPDIR/readonly.txt"  # Cleanup
}

@test "Function provides helpful error message" {
    run my_function --invalid-option
    [ "$status" -ne 0 ]
    [[ "$output" == *"Usage:"* ]]
}
```

### Testing with Dependencies

```bash
#!/usr/bin/env bats

setup() {
    # Check for required tools
    if ! command -v jq &>/dev/null; then
        skip "jq is not installed"
    fi

    export SCRIPT="${BATS_TEST_DIRNAME}/../bin/script.sh"
}

@test "JSON parsing works" {
    skip_if ! command -v jq &>/dev/null
    run my_json_parser '{"key": "value"}'
    [ "$status" -eq 0 ]
}
```

### Testing Shell Compatibility

```bash
#!/usr/bin/env bats

@test "Script works in bash" {
    bash "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
}

@test "Script works in sh (POSIX)" {
    sh "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
}

@test "Script works in dash" {
    if command -v dash &>/dev/null; then
        dash "${BATS_TEST_DIRNAME}/../bin/script.sh" arg1
    else
        skip "dash not installed"
    fi
}
```

### Parallel Execution

```bash
#!/usr/bin/env bats

@test "Multiple independent operations" {
    run bash -c 'for i in {1..10}; do
        my_operation "$i" &
    done
    wait'
    [ "$status" -eq 0 ]
}

@test "Concurrent file operations" {
    for i in {1..5}; do
        my_function "$TMPDIR/file$i" &
    done
    wait
    [ -f "$TMPDIR/file1" ]
    [ -f "$TMPDIR/file5" ]
}
```

## Test Helper Pattern

### test_helper.sh

```bash
#!/usr/bin/env bash

# Source script under test
export SCRIPT_DIR="${BATS_TEST_DIRNAME%/*}/bin"

# Common test utilities
assert_file_exists() {
    if [ ! -f "$1" ]; then
        echo "Expected file to exist: $1"
        return 1
    fi
}

assert_file_equals() {
    local file="$1"
    local expected="$2"

    if [ ! -f "$file" ]; then
        echo "File does not exist: $file"
        return 1
    fi

    local actual=$(cat "$file")
    if [ "$actual" != "$expected" ]; then
        echo "File contents do not match"
        echo "Expected: $expected"
        echo "Actual: $actual"
        return 1
    fi
}

# Create temporary test directory
setup_test_dir() {
    export TEST_DIR=$(mktemp -d)
}

cleanup_test_dir() {
    rm -rf "$TEST_DIR"
}
```

## Integration with CI/CD

### GitHub Actions Workflow

```yaml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Install Bats
        run: |
          npm install --global bats

      - name: Run Tests
        run: |
          bats tests/*.bats

      - name: Run Tests with Tap Reporter
        run: |
          bats tests/*.bats --tap | tee test_output.tap
```

### Makefile Integration

```makefile
.PHONY: test test-verbose test-tap

test:
	bats tests/*.bats

test-verbose:
	bats tests/*.bats --verbose

test-tap:
	bats tests/*.bats --tap

test-parallel:
	bats tests/*.bats --parallel 4

coverage: test
	# Optional: Generate coverage reports
```

## Best Practices

1. **Test one thing per test** - Single responsibility principle
2. **Use descriptive test names** - Clearly states what is being tested
3. **Clean up after tests** - Always remove temporary files in teardown
4. **Test both success and failure paths** - Don't just test happy path
5. **Mock external dependencies** - Isolate unit under test
6. **Use fixtures for complex data** - Makes tests more readable
7. **Run tests in CI/CD** - Catch regressions early
8. **Test across shell dialects** - Ensure portability
9. **Keep tests fast** - Run in parallel when possible
10. **Document complex test setup** - Explain unusual patterns

<!-- chapter:end slug=bats-testing-patterns -->

---

<!-- chapter:begin slug=shellcheck-configuration position=157 -->

## 157. shellcheck-configuration

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/shell-scripting/skills/shellcheck-configuration/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/shell-scripting/skills/shellcheck-configuration/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/shellcheck-configuration.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/shell-scripting/skills/shellcheck-configuration/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: shellcheck-configuration
description: Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring script portability.
---

# ShellCheck Configuration and Static Analysis

Comprehensive guidance for configuring and using ShellCheck to improve shell script quality, catch common pitfalls, and enforce best practices through static code analysis.

## When to Use This Skill

- Setting up linting for shell scripts in CI/CD pipelines
- Analyzing existing shell scripts for issues
- Understanding ShellCheck error codes and warnings
- Configuring ShellCheck for specific project requirements
- Integrating ShellCheck into development workflows
- Suppressing false positives and configuring rule sets
- Enforcing consistent code quality standards
- Migrating scripts to meet quality gates

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Run ShellCheck in CI/CD** - Catch issues before merging
2. **Configure for your target shell** - Don't analyze bash as sh
3. **Document exclusions** - Explain why violations are suppressed
4. **Address violations** - Don't just disable warnings
5. **Enable strict mode** - Use `--enable=all` with careful exclusions
6. **Update regularly** - Keep ShellCheck current for new checks
7. **Use pre-commit hooks** - Catch issues locally before pushing
8. **Integrate with editors** - Get real-time feedback during development

<!-- chapter:end slug=shellcheck-configuration -->

---

## Part: Ship Mate

---

<!-- chapter:begin slug=scan position=158 -->

## 158. scan

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ship-mate/skills/scan/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ship-mate/skills/scan/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/scan.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: scan
description: Scans the codebase to generate project-doc.md and AGENTS.md. Use when bootstrapping a new agent-driven repo, refreshing project documentation after architectural changes, or running a delta scan to detect drift. Runs a full scan on first use and a smart delta scan on subsequent runs. Uses understand-anything + context-mode when available, falls back to native tools otherwise. Only updates AGENTS.md on detected architectural changes with human confirmation.
---

# Codebase Scanner

You are a technical analyst. Your job is to scan the project codebase and produce accurate, project-specific documentation used by all downstream agents.

## Step 1: Check Optional Plugin Dependencies

Check whether the two optional enhancement plugins are available:

```
understand-anything  →  /plugin list | grep understand-anything
context-mode         →  /plugin list | grep context-mode
```

These plugins are **optional**. They improve scan quality but are not required:

- **understand-anything** (Lum1104/Understand-Anything) — provides deeper semantic code analysis
- **context-mode** (mksglu/context-mode) — routes large outputs through a sandbox to protect the context window

If both are present, use them in Steps 3–4 as described below. If either or both are missing, proceed with the **native fallback** approach: use `find`, `grep`, `cat`, and `git` commands directly, routing large outputs through `ctx_execute` / `ctx_execute_file` if context-mode is available, otherwise summarise inline.

> **Note:** To install the optional plugins manually:
> ```
> /plugin marketplace add Lum1104/Understand-Anything && /plugin install understand-anything
> /plugin marketplace add mksglu/context-mode && /plugin install context-mode@context-mode
> ```

## Step 2: Determine Scan Mode

Check if `.claude/pipeline/project-doc.md` exists.

- **Does not exist** → FULL SCAN (first run)
- **Exists** → DELTA SCAN

## Step 3A: Full Scan

Use `understand-anything` to analyse the entire codebase. If **context-mode** is available (verified in Step 1), route ALL output through its tools (`ctx_batch_execute` / `ctx_execute_file`) — never dump raw file contents into the main context window. If context-mode is not available, summarise each file's findings inline and avoid printing raw file contents.

Produce `.claude/pipeline/project-doc.md` using the following structure (based on the architecture-blueprint-generator pattern):

```md
# Project Documentation
> Generated: [timestamp] | Mode: FULL

## Tech Stack
- Runtime: [e.g. Node.js 20, Python 3.11]
- Language: [e.g. TypeScript, Python]
- Framework: [e.g. Next.js 14 App Router, FastAPI]
- Database: [e.g. PostgreSQL via Prisma]
- Styling: [e.g. Tailwind CSS]
- State Management: [e.g. Zustand, Redux]

## Dependencies
[Key libraries with versions, grouped by: core / dev / testing]

## Architecture Pattern
[e.g. Feature-based, Layered MVC, Clean Architecture]
[Describe how the project is structured and why]

## Folder Structure
[Top-level directory map with purpose of each folder]

## Code Style Conventions
[Naming patterns, file naming, import ordering, export patterns]
[Inferred from actual code — not guessed]

## Modularity Practices
[How concerns are separated, shared module locations, service patterns]

## Data Architecture
[Entity relationships, data access patterns, ORM usage]

## Cross-Cutting Concerns
[Auth/authz approach, error handling patterns, logging, validation]

## Service Communication
[REST / GraphQL / event-driven — document what actually exists]

## Test Coverage
- Overall coverage: [X%]
- Testing framework: [e.g. Jest, Vitest, Pytest]
- Key untested areas: [list]
- Test patterns used: [unit / integration / e2e]

## Entry Points
[Main files, key config files, environment setup]

## Changed Files
[Only present in delta scans — list of files re-scanned]

## Last Scanned
[ISO timestamp]
```

After writing `project-doc.md`, proceed to **Step 4** to generate `AGENTS.md`.

## Step 3B: Delta Scan

1. Run `git diff HEAD~1 --name-only` to get changed files
2. If no changed files, report "No changes detected — project-doc.md is current" and exit
3. Use `understand-anything` to re-analyse only the changed files; route output through `ctx_execute_file` if context-mode is available, otherwise summarise inline
4. Patch only the affected sections of `.claude/pipeline/project-doc.md`
5. Update the `Last Scanned` and `Changed Files` fields
6. Proceed to **Step 4B** (architectural change detection)

## Step 4A: Generate AGENTS.md (First Run Only)

Write `AGENTS.md` to the repo root. This is NOT a copy of `project-doc.md` — it is rewritten as agent instructions, tailored to this specific project. Every agent reads this file first.

Structure:

```md
# AGENTS.md — [Project Name]
> Auto-generated by the dev pipeline scanner. Do not edit manually.
> Last updated: [timestamp]
> ⚠️  To update this file, architectural changes must be detected by the scanner and confirmed by a human.

## How to Read This File
Every agent in this pipeline reads this file before doing any work.
It defines the rules, patterns, and guardrails specific to this project.

## Stack Context
[One-line summary: e.g. "Next.js 14 App Router + Prisma + PostgreSQL + Tailwind + Vitest"]

## Code Style Rules
[Written as DO/DON'T instructions inferred from actual codebase patterns]
Example:
- DO use named exports. Default exports are not used in this project.
- DON'T add business logic to API route handlers — delegate to /lib/services/
- DO use [naming convention] for [file type]

## Architecture Guardrails
[Rules derived from the actual architecture — not generic advice]
Example:
- This project uses the Repository pattern. Never query the DB directly from components.
- All API responses must go through the [ResponseWrapper] utility.

## Testing Requirements
[Coverage stat + specific rules for this project]
Example:
- Current coverage: 67%. All new code must include unit tests.
- QA agent: flag any feature with <80% coverage on new code.
- Integration tests use [real DB / mock DB] — do not change this.

## Modularity Conventions
[Specific rules about where code goes]
Example:
- Shared UI components → /components/ui
- Business logic → /lib/services/[domain]/
- Types → /types/[domain].ts

## Security Rules (All Agents)
- Never hardcode secrets, tokens, or credentials
- Use environment variables for all sensitive config
- Flag any auth-adjacent code changes immediately

## Agent-Specific Instructions

### Orchestrator
[Project-specific questions to always ask — e.g. "Does this touch the payment flow?"]

### Architect
[Known complexity areas, performance constraints, patterns to prefer]
[e.g. "This project has a known N+1 issue in /lib/services/orders — avoid adding more eager loading"]

### Developer
[Specific libraries to use, anti-patterns banned in this codebase]
[e.g. "Use dayjs — moment is banned", "Use React Query for all data fetching — no raw fetch()"]

### PR Reviewer
[What counts as 🔴 Critical vs 🟡 Should Fix in this project]
[e.g. "Any change to /lib/auth/ is automatically 🔴 Critical — requires human approval"]

### QA Agent
[Known edge cases for this domain, critical user paths to always test]
[e.g. "Always test empty state, loading state, and error state for every UI feature"]
```

If the project is MERN stack (MongoDB + Express + React + Node.js — detected from package.json / requirements), append a `### MERN Stack Notes` section to AGENTS.md covering: use Mongoose middleware over raw queries, handle async errors in Express with a central error handler, avoid storing JWT tokens in localStorage (use httpOnly cookies), and never expose Mongoose error objects directly in API responses.

## Step 4B: Architectural Change Detection (Delta Runs Only)

After patching `project-doc.md`, compare the new version against the previous. Check for:
- New framework or major library added
- New architectural directory pattern created (e.g. new `/lib/hooks/`, `/services/`)
- Major dependency swap (e.g. axios → fetch, moment → dayjs)
- New auth or session handling pattern

If any detected, show:

```
⚠️  Architectural change detected in delta scan:
    [List specific changes found]

AGENTS.md may need updating. Review and confirm:
  [y] Update AGENTS.md — patch affected sections only
  [n] Skip — this is not an architectural change
```

Only on `[y]` confirmation: patch the relevant sections of `AGENTS.md`. Never rewrite the full file.

## Step 5: Report

Print a summary:

```
✅ Scan complete ([FULL/DELTA])
   project-doc.md → updated
   AGENTS.md      → [generated / patched / unchanged]
   Changed files  → [N files re-scanned / N/A for full scan]
   Coverage       → [X%]
```

Update `state.json` field `checkpoints.scan = "completed"`.

<!-- chapter:end slug=scan -->

---

## Part: Signed Audit Trails

---

<!-- chapter:begin slug=signed-audit-trails-recipe position=159 -->

## 159. signed-audit-trails-recipe

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/signed-audit-trails/skills/signed-audit-trails-recipe/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/signed-audit-trails/skills/signed-audit-trails-recipe/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/signed-audit-trails-recipe.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: signed-audit-trails-recipe
description: Step-by-step cookbook for setting up cryptographically signed audit trails on Claude Code tool calls. Use when explaining, evaluating, or demonstrating the pattern before committing to the protect-mcp runtime hooks. Covers Cedar policy, Ed25519 receipts, offline verification, tamper detection, CI/CD integration, and SLSA composition.
---

# Signed Audit Trails for Claude Code Tool Calls

Cookbook-style walkthrough for cryptographically signed receipts on every
Claude Code tool call. This is the teaching skill. For the runtime
implementation, install the [`protect-mcp`](../../protect-mcp/) plugin.

## What this gives you

Every tool call (`Bash`, `Edit`, `Write`, `WebFetch`) is:

1. **Evaluated against a Cedar policy** before execution. If the policy denies
   the call, the tool does not run.
2. **Signed as an Ed25519 receipt** after execution. Receipts are
   JCS-canonical, hash-chained, and verifiable offline by anyone with the
   public key.

An auditor, regulator, or counterparty can verify the full chain later with a
single CLI command (`npx @veritasacta/verify receipts/*.json`). No network
call, no vendor lookup, no trust in the operator.

## When to use the pattern

- **Regulated environments** (finance, healthcare, critical infrastructure)
  where you need tamper-evident evidence of agent behavior
- **CI/CD pipelines** where you want to prove that a policy gate held for
  every automated build step
- **Multi-party collaboration** where a counterparty wants to verify your
  agent's behavior without trusting your operator
- **Compliance contexts** (EU AI Act Article 12, SLSA provenance for
  agent-built software) where standard logging is not sufficient

## Step 1: Install the hook configuration

Create `.claude/settings.json` in your project root:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hook": {
          "type": "command",
          "command": "npx protect-mcp@latest evaluate --policy ./protect.cedar --tool \"$TOOL_NAME\" --input \"$TOOL_INPUT\" --fail-on-missing-policy false"
        }
      }
    ],
    "PostToolUse": [
      {
        "matcher": ".*",
        "hook": {
          "type": "command",
          "command": "npx protect-mcp@latest sign --tool \"$TOOL_NAME\" --input \"$TOOL_INPUT\" --output \"$TOOL_OUTPUT\" --receipts ./receipts/ --key ./protect-mcp.key"
        }
      }
    ]
  }
}
```

The first run of `protect-mcp sign` generates `./protect-mcp.key` (Ed25519
private key) if one does not exist. Commit the **public** key fingerprint
(visible in any receipt's `public_key` field); do not commit the private
key.

Add the private key and receipt directory to `.gitignore`:

```bash
echo "./protect-mcp.key" >> .gitignore
echo "./receipts/" >> .gitignore
```

## Step 2: Write a Cedar policy

Create `./protect.cedar`:

```cedar
// Allow all read-oriented tools by default.
permit (
    principal,
    action in [Action::"Read", Action::"Glob", Action::"Grep", Action::"WebSearch"],
    resource
);

// Allow Bash commands from a safe list only.
permit (
    principal,
    action == Action::"Bash",
    resource
) when {
    context.command_pattern in [
        "git", "npm", "pnpm", "yarn", "ls", "cat", "pwd",
        "echo", "test", "node", "python", "make"
    ]
};

// Explicit deny on destructive commands. Cedar deny is authoritative.
forbid (
    principal,
    action == Action::"Bash",
    resource
) when {
    context.command_pattern in ["rm -rf", "dd", "mkfs", "shred"]
};

// Restrict writes to the project directory.
permit (
    principal,
    action in [Action::"Write", Action::"Edit"],
    resource
) when {
    context.path_starts_with == "./"
};
```

Four rules:

- Read-oriented tools always allowed
- `Bash` allowed for safe command patterns (`git`, `npm`, etc.)
- `Bash rm -rf` and similar destructive commands explicitly denied
- Writes allowed only within the project (`./` prefix)

Cedar `forbid` rules take precedence over `permit` rules, so destructive
commands cannot be bypassed by a later permissive rule.

## Step 3: Use Claude Code normally

Start Claude Code. Every tool call goes through both hooks:

```
You: Please read the README and summarize it.

Claude: I will read README.md.
  [PreToolUse: Read ./README.md -> allow]
  [Tool: Read executes]
  [PostToolUse: receipt rcpt-a8f3c9d2 signed to ./receipts/]

... summary of README ...
```

A session of 20 tool calls produces 20 receipts, each hash-chained to its
predecessor.

## Step 4: Inspect a receipt

```bash
cat ./receipts/$(ls -t ./receipts/ | head -1)
```

```json
{
  "receipt_id": "rcpt-a8f3c9d2",
  "receipt_version": "1.0",
  "issuer_id": "claude-code-protect-mcp",
  "event_time": "2026-04-17T12:34:56.123Z",
  "tool_name": "Read",
  "input_hash": "sha256:a3f8c9d2e1b7465f...",
  "decision": "allow",
  "policy_id": "protect.cedar",
  "policy_digest": "sha256:b7e2f4a6c8d0e1f3...",
  "parent_receipt_id": "rcpt-3d1ab7c2",
  "public_key": "4437ca56815c0516...",
  "signature": "4cde814b7889e987..."
}
```

Every field except `signature` and `public_key` is covered by the Ed25519
signature. Modifying any field after signing invalidates the signature.

## Step 5: Verify the receipt chain

```bash
npx @veritasacta/verify ./receipts/*.json
```

Exit codes:

| Code | Meaning |
|------|---------|
| `0`  | All receipts verified; chain intact |
| `1`  | A receipt failed signature verification (tampered, or wrong key) |
| `2`  | A receipt was malformed |

## Step 6: Demonstrate tamper detection

Modify any receipt's `decision` field from `allow` to `deny`:

```bash
python3 -c "
import json, os
path = './receipts/' + sorted(os.listdir('./receipts'))[-1]
r = json.loads(open(path).read())
r['decision'] = 'deny'
open(path, 'w').write(json.dumps(r))
"

npx @veritasacta/verify ./receipts/*.json
```

The verifier exits with code `1` and reports which receipt failed. The
Ed25519 signature no longer matches the JCS-canonical bytes of the
tampered payload.

Restore the field and verification passes again.

## How the cryptography works

Three invariants make receipts verifiable offline across any conformant
implementation:

1. **JCS canonicalization (RFC 8785)** before signing. Keys sorted,
   whitespace minimized, strings NFC-normalized. Two independent
   implementations produce byte-identical signing payloads for the same
   receipt content.
2. **Ed25519 signatures (RFC 8032)** over the canonical bytes.
   Deterministic, fixed-size, no nonce dependency.
3. **Hash chain linkage.** Each receipt's `parent_receipt_hash` is the
   SHA-256 of the predecessor's canonical form. Insertions, deletions, and
   reorderings break later receipts.

For the formal wire format see
[draft-farley-acta-signed-receipts](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/).

## Cross-implementation interop

The receipt format has four independent implementations today:

| Implementation | Language | Use case |
|----------------|----------|----------|
| [protect-mcp](https://www.npmjs.com/package/protect-mcp) | TypeScript | Claude Code, Cursor, MCP hosts |
| [protect-mcp-adk](https://pypi.org/project/protect-mcp-adk/) | Python | Google Agent Development Kit |
| [sb-runtime](https://github.com/ScopeBlind/sb-runtime) | Rust | OS-level sandbox (Landlock + seccomp) |
| APS governance hook | Python | CrewAI, LangChain |

A receipt produced by any of them verifies against
[`@veritasacta/verify`](https://www.npmjs.com/package/@veritasacta/verify).
The auditor does not need to trust the operator's tooling choice: the format
is the contract.

## CI/CD integration

Gate merges on receipt chain verification so no build lands with a broken
evidence chain:

```yaml
# .github/workflows/verify-receipts.yml
name: Verify Decision Receipts
on: [push, pull_request]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - name: Run governed agent
        run: python scripts/run_agent.py > receipts.jsonl
      - name: Verify receipt chain
        run: npx @veritasacta/verify receipts.jsonl
```

Archive the receipts as an artifact so the chain survives beyond the job run:

```yaml
      - name: Upload receipts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: decision-receipts
          path: receipts/
```

## Composition with SLSA provenance for agent-built software

When Claude Code builds and releases software (running `npm install`,
`npm build`, `npm publish` as tool calls), the receipt chain is the
per-step build log. SLSA Provenance v1 has an extension point for this: the
`byproducts` field can reference the receipt chain alongside the build
attestation.

The [agent-commit build type](https://refs.arewm.com/agent-commit/v0.2)
documents the pattern using the ResourceDescriptor shape:

```json
{
  "name": "decision-receipts",
  "digest": { "sha256": "..." },
  "uri": "oci://registry/org/build-xyz/receipts:sha256-...",
  "annotations": {
    "predicateType": "https://veritasacta.com/attestation/decision-receipt/v0.1",
    "signerRole": "supervisor-hook"
  }
}
```

The SLSA provenance is signed by the builder identity; the receipt
attestation is signed by the supervisor-hook identity. Two trust domains,
cross-referenced at the byproduct layer. See
[slsa-framework/slsa#1594](https://github.com/slsa-framework/slsa/issues/1594)
for the composition discussion.

## Common pitfalls

**Private key in version control.** The generated `./protect-mcp.key` must
not be committed. The examples above add it to `.gitignore`. If a key is
accidentally committed, rotate immediately (delete the key file and let the
hook regenerate on next run).

**Hook command quoting.** The hooks receive `$TOOL_NAME` and `$TOOL_INPUT`
as environment variables. Keep the quoting `"$TOOL_INPUT"` so inputs with
spaces or special characters pass through intact.

**Receipts directory in CI.** If Claude Code runs in CI, upload receipts as
an artifact at the end of the job or the chain is lost at job end.

**Policy is missing.** The example `PreToolUse` hook uses
`--fail-on-missing-policy false` so an absent `./protect.cedar` does not
break Claude Code out of the box. Remove this flag in production so a
missing policy is treated as a hard failure.

## Related in this marketplace

- [`protect-mcp`](../../protect-mcp/) — the runtime hook implementation
  (use this plugin in production)
- [`review-agent-governance`](../../review-agent-governance/) — require
  human approval before review-surface actions; composes with protect-mcp

## References

- [`draft-farley-acta-signed-receipts`](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/) — IETF draft, receipt wire format
- [RFC 8032](https://datatracker.ietf.org/doc/html/rfc8032) — Ed25519
- [RFC 8785](https://datatracker.ietf.org/doc/html/rfc8785) — JCS
- [Cedar policy language](https://docs.cedarpolicy.com/)
- [protect-mcp on npm](https://www.npmjs.com/package/protect-mcp)
- [@veritasacta/verify on npm](https://www.npmjs.com/package/@veritasacta/verify)
- [in-toto/attestation#549](https://github.com/in-toto/attestation/pull/549) — Decision Receipt predicate proposal
- [agent-commit build type](https://refs.arewm.com/agent-commit/v0.2) — SLSA provenance for agent-produced commits
- [Microsoft Agent Governance Toolkit](https://github.com/microsoft/agent-governance-toolkit) (`examples/protect-mcp-governed/`)
- [AWS Cedar for Agents](https://github.com/cedar-policy/cedar-for-agents)

<!-- chapter:end slug=signed-audit-trails-recipe -->

---

## Part: Skill Forge Essentials

---

<!-- chapter:begin slug=ai-debt-detector position=160 -->

## 160. ai-debt-detector

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/skill-forge-essentials/skills/ai-debt-detector/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/skill-forge-essentials/skills/ai-debt-detector/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/ai-debt-detector.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: ai-debt-detector
description: >-
  Use after generating code, after accepting AI suggestions, or when reviewing
  AI-written modules. Also use when code works but feels brittle, when error
  handling seems thin, when orphaned resources or missing cleanup are suspected,
  or when the agent claims done but hidden debt may exist. Catches the specific
  failure patterns AI agents produce that humans would not.
---

# AI Debt Detector

## Overview

AI agents generate code that passes the happy path but hides debt: missing error handling, orphaned resources, ignored failure modes, hallucinated packages, silent architectural drift. This skill forces a targeted audit for the exact patterns AI agents get wrong.

## When to Use

- After any AI code generation session (20+ lines produced)
- Before merging AI-generated PRs
- When code works but something feels off
- After vibe-coding sprints where debt accumulates fastest
- When the agent claims done without showing verification

## Process

After code generation, scan for these AI-specific debt patterns:

1. **FAILURE MODES** - What happens when this fails?
   - Network timeout? Disk full? Permission denied? Null input?
   - Is there a try/catch? Does it catch SPECIFIC errors or swallow everything?
   - Are resources cleaned up on failure? (streams closed, connections returned, temp files deleted)

2. **ORPHANS** - What gets created but never cleaned up?
   - Temp files, event listeners, intervals, subscriptions, connections
   - Are there corresponding cleanup/dispose/close calls for every open/create?
   - In React: does every addEventListener have a removeEventListener in cleanup?

3. **EDGE CASES** - What inputs break this?
   - Empty array/string? null/undefined? Multi-MB input? Unicode? Concurrent calls?
   - Does the code assume the happy path? (AI almost always does)

4. **HALLUCINATED DEPS** - Do all imports actually exist?
   - Is every package in package.json/requirements.txt?
   - Are API methods real? (AI invents plausible-sounding methods that don't exist)
   - Does this library's latest version still export this function?

5. **ARCHITECTURAL DRIFT** - Does this match the project's patterns?
   - Same error handling style as existing code?
   - Uses the project's established utilities (not reinventing)?
   - Follows the file structure convention?

## Red Flags (stop and fix immediately)

- `catch (e) {}` or `catch (e) { console.log(e) }` - swallowed error
- No `finally` block when resources were opened
- `// TODO: handle error` - AI's way of punting
- Import from a path that doesn't exist in the project
- Timeout set but no abort/cleanup on timeout
- Database connection opened but never released back to pool

## Common Mistakes

- Trusting that compilation means correctness (compilation checks syntax, not logic)
- Reviewing only the diff without checking what the AI did NOT generate (missing error paths)
- Assuming the AI used the right library version (it often uses deprecated APIs)
- Skipping the orphan check because garbage collection handles it (it doesn't for connections, listeners, timers)

## Why This Exists

AI agents systematically optimize for "looks correct" and "passes the happy path." They miss failure modes, orphan resources, and hallucinate dependencies at rates significantly higher than manual code. This skill forces an audit for those specific blind spots.

<!-- chapter:end slug=ai-debt-detector -->

---

<!-- chapter:begin slug=session-guard position=161 -->

## 161. session-guard

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/skill-forge-essentials/skills/session-guard/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/skill-forge-essentials/skills/session-guard/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/session-guard.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: session-guard
description: >-
  Use when working on complex multi-step tasks, when a session is getting long
  (40+ tool calls), when the agent starts ignoring rules it followed earlier,
  when conventions drift, when output quality seems to degrade, or after any
  context compaction event. Prevents long-session corruption AND context
  compaction amnesia through behavioral self-enforcement.
---

# Session Guard

## Overview

Long sessions corrupt silently. Context compaction drops instructions unannounced. Hooks don't fix it (confirmed by multiple developers on GitHub issues #19471, #9796, #64171). This skill prevents both through behavioral self-enforcement: monitor health, anchor critical rules through compaction, split before damage occurs. No packages, no databases - pure behavioral enforcement that works in every harness.

## When to Use

- Session exceeds 40 tool calls
- Agent contradicts earlier decisions
- Style/naming conventions start drifting
- After any context compaction event
- Task scope growing unbounded

## Health Signals

| Signal | Threshold | Action |
|--------|-----------|--------|
| Tool call count | >40 | YELLOW: checkpoint + recite critical rules |
| Tool call count | >60 | RED: split or compact with anchor |
| Agent contradicts earlier decision | Any | VERIFY: re-read source of truth |
| Style/naming drift | Any | RECITE: state the active rules aloud |
| File read returns unexpected content | Any | RE-READ: don't trust cached state |
| Task scope growing unbounded | Continuous | SPLIT: one task per session |

## Protocol

### Green Zone (0-40 tool calls)
Normal operation. No intervention needed.

### Yellow Zone (40-60 tool calls)
1. CHECKPOINT - summarize progress in one paragraph
2. RECITE - state the 3-5 most critical active rules aloud: "Active rules: [naming convention], [file structure], [error handling pattern], [testing requirement]"
3. ASSESS - almost done? Push through. Not done? Prepare split.
4. REDUCE - no exploratory reads. Only targeted operations.

### Red Zone (60+ tool calls OR drift signal)
1. STOP - do not make more tool calls
2. VERIFY - re-read project rules (don't trust memory)
3. CHECKPOINT - write state to handoff document
4. SPLIT - create handoff, suggest fresh session

## Context Anchoring (anti-compaction)

When compaction has occurred (sudden loss of earlier context, or after /compact):

1. RE-READ the project's rules file immediately
2. RECITE the 3-5 critical rules aloud in your response
3. VERIFY your planned next action matches those rules before executing
4. If uncertain about ANY prior decision, RE-READ the source file - don't guess

### What survives compaction:
- Most recent user messages (high priority)
- Currently-invoked skill body (capped at 5K tokens, oldest dropped first)
- Git status and project structure
- File contents read AFTER compaction

### What gets LOST in compaction:
- Decisions made early in conversation
- Architectural rules stated only verbally (not in files)
- Context from tool outputs (file reads, command outputs)

### Compaction-Safe Pattern
Keep critical instructions in FILES (CLAUDE.md, CONTEXT.md), NOT in conversation. If a rule matters, it must live in a file the agent can re-read - not in something agreed on earlier.

## Common Mistakes

- Trusting that you remember the rules after 50+ tool calls (you don't - re-read)
- Re-reading EVERYTHING to be safe (wastes tool calls - be targeted)
- Feeling fine therefore assuming context is fine (compaction is SILENT)
- Splitting AFTER noticing problems (split BEFORE - prevention, not recovery)

## Why This Matters

Context compaction is the #1 unsolved platform problem in 2026. Hooks don't fix it (confirmed: the agent ignores post-compaction injections because the compaction summary creates narrative momentum). This skill is the lightweight behavioral countermeasure: no infrastructure, no packages - disciplined self-monitoring that works in every harness.

<!-- chapter:end slug=session-guard -->

---

<!-- chapter:begin slug=visual-edit-precision position=162 -->

## 162. visual-edit-precision

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/skill-forge-essentials/skills/visual-edit-precision/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/skill-forge-essentials/skills/visual-edit-precision/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/visual-edit-precision.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: visual-edit-precision
description: >-
  Use when making UI/frontend changes guided by visual context, when the user
  selects elements visually, draws annotations, or provides screenshots alongside
  change requests. Also use when editing components where spatial context
  (element identity, DOM references, layout data) supplements text instructions.
---

# Visual Edit Precision

## Overview

When visual context accompanies a change request (element selections, annotations, screenshots), make targeted, minimal edits. Precision over ambition: change exactly what was indicated, preserve everything else.

## Process

When visual context is provided:

1. **IDENTIFY** - What exact element(s) were indicated? Which component file owns them?
2. **SCOPE** - Change ONLY what was pointed at. Don't refactor surrounding code.
3. **PRESERVE** - Keep existing styles, classes, and behavior. Only modify what was asked.
4. **TARGETED** - Make the minimal CSS/markup change that achieves the visual result.
5. **VERIFY** - Confirm the change renders correctly without side effects.

## Key Principles

### Precision Over Ambition

Visual context gives a SPECIFIC element. Don't:
- Refactor the entire component when only one style was requested
- Change the component's API when only its appearance was pointed at
- Touch logic when only visuals were selected

Do:
- Find the exact file and line for the selected element
- Make the minimal edit that achieves the described visual change
- Preserve all existing behavior, event handlers, accessibility

### Multiple Edits

When multiple visual edits arrive:
- Each targets its own element independently
- Don't wait for one to finish before processing another
- If two edits conflict (same element, different requests), handle the most recent

## Common Mistakes

- Rewriting an entire component when the user pointed at one button
- Changing global config when only one element's color needs adjusting
- Breaking responsive behavior by adding fixed widths to match a selection
- Ignoring specificity (user indicated ONE card, agent changed ALL cards)
- Removing accessibility attributes (aria-*, role, tabindex) during visual edits

<!-- chapter:end slug=visual-edit-precision -->

---

## Part: Social Publishing

---

<!-- chapter:begin slug=social-publishing position=163 -->

## 163. social-publishing

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/social-publishing/skills/social-publishing/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/social-publishing/skills/social-publishing/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/social-publishing.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: social-publishing
description: >
  Schedule and publish social media posts across 13 platforms (X, LinkedIn, Instagram,
  Facebook Pages, TikTok, Discord, Telegram, YouTube, Reddit, WordPress, Pinterest) via
  the SocialClaw API. Use when the user wants to publish, schedule, or manage social
  media content programmatically. Requires SOCIALCLAW_API_KEY.
license: MIT
metadata:
  version: "1.0.0"
  source: https://github.com/ndesv21/socialclaw
  homepage: https://getsocialclaw.com
---

# Social Publishing

Agent-first social media publishing via [SocialClaw](https://getsocialclaw.com). One workspace API key, 13 platforms, zero per-platform OAuth setup.

## When to Use This Skill

Use this skill when the user wants to:
- Publish or schedule posts across multiple social media platforms
- Orchestrate a multi-platform content campaign
- Upload and attach media to social posts
- Retrieve post-level engagement analytics
- Manage a content calendar programmatically

## Supported Platforms

| Platform | Notes |
|----------|-------|
| X (Twitter) | Profile posts, threads |
| LinkedIn | Profile posts + Company pages |
| Instagram | Business + standalone accounts |
| Facebook Pages | Page posts with link previews |
| TikTok | Video descriptions |
| Discord | Channel targeting, embeds |
| Telegram | Channel/group messaging |
| YouTube | Video descriptions and metadata |
| Reddit | Subreddit posts with flair |
| WordPress | Blog posts with SEO metadata |
| Pinterest | Pins with board targeting |

## Setup

```bash
# Install via npx
npx skills add ndesv21/socialclaw

# Or install as package
npm install socialclaw@0.1.12

# Set your workspace API key
export SOCIALCLAW_API_KEY=your_key_here
```

Get a workspace API key at [getsocialclaw.com](https://getsocialclaw.com).

## Workflow

### Step 1: Define Campaign
Specify platforms, message content, schedule, and any media attachments.

### Step 2: Draft Platform Variants
Claude generates platform-optimized copy for each channel (character limits, hashtag norms, tone).

### Step 3: Upload Media (Optional)
Upload images or videos once — SocialClaw stores them for reuse across platforms.

### Step 4: Validate Schedule
Claude checks platform-specific timing rules and rate limits before submitting.

### Step 5: Publish or Schedule
Posts queue via the SocialClaw API. Receive post IDs and scheduled times for confirmation.

### Step 6: Analytics
Pull engagement metrics (impressions, clicks, reactions) 24–48 hours after publishing.

## Usage Examples

### Single Platform Post
```
Post to our company LinkedIn page:
"Excited to announce our Q2 product roadmap — here's what's coming next.
[roadmap image]"
```

### Multi-Platform Campaign
```
Announce our beta launch on X, LinkedIn, Instagram, and Discord.
Message: "Our beta is live! 100 spots available — sign up at example.com #launch"
Schedule for tomorrow 9am PST
```

### Content Series
```
Create a 5-day drip campaign for our feature launch week.
Platforms: X and LinkedIn.
I'll provide copy for each day.
```

## Guidelines

1. **One key, all platforms** — SOCIALCLAW_API_KEY authenticates across all connected accounts
2. **Platform-native copy** — Adapt tone and format for each platform rather than copy-pasting
3. **Validate timing** — Always confirm schedule before submission to avoid rate limit errors
4. **Media reuse** — Upload assets once and reference by ID across multiple posts

## Limitations

- Requires active SocialClaw account with connected social accounts
- Platform availability depends on workspace tier
- Some platforms require video content for optimal reach (TikTok, YouTube, Instagram Reels)

<!-- chapter:end slug=social-publishing -->

---

## Part: Startup Business Analyst

---

<!-- chapter:begin slug=competitive-landscape position=164 -->

## 164. competitive-landscape

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/startup-business-analyst/skills/competitive-landscape/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/competitive-landscape/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/competitive-landscape.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: competitive-landscape
description: Analyze competition, identify differentiation opportunities, and develop winning market positioning strategies using Porter's Five Forces, Blue Ocean Strategy, and positioning maps. Use this skill when evaluating competitors, assessing market positioning, identifying sustainable competitive advantages, or preparing competitive strategy analysis for a startup or investor pitch.
version: 1.0.0
---

# Competitive Landscape Analysis

Comprehensive frameworks for analyzing competition, identifying differentiation opportunities, and developing winning market positioning strategies.

## Overview

Understand competitive dynamics using proven frameworks (Porter's Five Forces, Blue Ocean Strategy, positioning maps) to identify opportunities and craft defensible competitive advantages.

## Porter's Five Forces

Analyze industry attractiveness and competitive intensity.

### Force 1: Threat of New Entrants

**Barriers to Entry:**

- Capital requirements
- Economies of scale
- Switching costs
- Brand loyalty
- Regulatory barriers
- Access to distribution
- Network effects

**High Threat:** Low barriers, easy to enter (e.g., simple SaaS tools)
**Low Threat:** High barriers (e.g., regulated industries, hardware)

**Analysis Questions:**

- How easy is it for new competitors to enter?
- What would it cost to launch a competing product?
- Are there network effects or switching costs protecting incumbents?

### Force 2: Bargaining Power of Suppliers

**Supplier Power Factors:**

- Supplier concentration
- Availability of substitutes
- Importance to supplier
- Switching costs
- Forward integration threat

**High Power:** Few suppliers, critical inputs (e.g., cloud infrastructure providers)
**Low Power:** Many alternatives, commoditized (e.g., generic services)

**Analysis Questions:**

- Who are our critical suppliers?
- Could they raise prices or reduce quality?
- Can we switch suppliers easily?

### Force 3: Bargaining Power of Buyers

**Buyer Power Factors:**

- Buyer concentration
- Volume purchased
- Product differentiation
- Price sensitivity
- Backward integration threat

**High Power:** Few large customers, standardized products (e.g., enterprise deals)
**Low Power:** Many small customers, differentiated product (e.g., consumer subscriptions)

**Analysis Questions:**

- Can customers easily switch to competitors?
- Do few customers generate most revenue?
- How price-sensitive are buyers?

### Force 4: Threat of Substitutes

**Substitute Considerations:**

- Alternative solutions
- Price-performance tradeoff
- Switching costs
- Buyer propensity to substitute

**High Threat:** Many alternatives, low switching cost (e.g., productivity software)
**Low Threat:** Unique solution, high switching cost (e.g., ERP systems)

**Analysis Questions:**

- What alternative ways can customers solve this problem?
- How do substitutes compare on price and performance?
- What's the cost to switch to a substitute?

### Force 5: Competitive Rivalry

**Rivalry Intensity Factors:**

- Number of competitors
- Industry growth rate
- Product differentiation
- Exit barriers
- Strategic stakes

**High Rivalry:** Many competitors, slow growth, commoditized (e.g., email marketing)
**Low Rivalry:** Few competitors, fast growth, differentiated (e.g., emerging AI tools)

**Analysis Questions:**

- How many direct competitors exist?
- Is the market growing or stagnant?
- How differentiated are offerings?
- Are competitors competing on price or value?

### Forces Analysis Summary

Create a scorecard:

| Force          | Intensity (1-5) | Impact | Key Factors                       |
| -------------- | --------------- | ------ | --------------------------------- |
| New Entrants   | 3               | Medium | Low barriers but network effects  |
| Supplier Power | 2               | Low    | Many cloud providers              |
| Buyer Power    | 4               | High   | Enterprise customers concentrated |
| Substitutes    | 3               | Medium | Manual processes alternative      |
| Rivalry        | 4               | High   | 10+ direct competitors            |

**Overall Assessment:** Moderate industry attractiveness with high rivalry and buyer power

## Blue Ocean Strategy

Identify uncontested market space through value innovation.

### Four Actions Framework

**Eliminate:**
What factors can be eliminated that the industry takes for granted?

**Reduce:**
What factors can be reduced well below industry standard?

**Raise:**
What factors can be raised well above industry standard?

**Create:**
What factors can be created that the industry never offered?

### Strategy Canvas

Map your offering vs. competitors on key factors.

**Example: Budget Hotels**

```
High |                    ★ Traditional Hotels
     |          ★ Budget Hotels (new)
     |
Low  |___________________________________
     Price  Luxury  Convenience  Cleanliness

Budget Hotel Strategy:
- Eliminate: Luxury amenities, room service
- Reduce: Lobby size, staff
- Raise: Cleanliness, online booking
- Create: Self-service kiosks, mobile app
```

### Value Innovation

Find the sweet spot: Lower cost + higher value

**Steps:**

1. Map industry competing factors
2. Identify factors to eliminate/reduce (cost savings)
3. Identify factors to raise/create (differentiation)
4. Validate that combination creates new market space

## Competitive Positioning

### Positioning Map

Plot competitors on 2-3 key dimensions.

**Example Dimensions:**

- Price vs. Features
- Complexity vs. Ease of Use
- Enterprise vs. SMB Focus
- Self-Service vs. High-Touch
- Generalist vs. Specialist

**How to Create:**

1. Choose 2 dimensions most important to customers
2. Plot all competitors
3. Identify gaps (white space)
4. Validate gap represents real customer need

**Example:**

```
High Price
    |
    |  ★ Enterprise A      ★ Enterprise B
    |
    |          ● Our Position (gap)
    |
    |  ★ Competitor C      ★ Competitor D
    |
Low Price |____________________________________________
        Simple                           Complex
```

### Differentiation Strategy

**How to Differentiate:**

1. **Product Differentiation**
   - Unique features
   - Superior performance
   - Better design/UX
   - Integration ecosystem

2. **Service Differentiation**
   - Customer support quality
   - Onboarding experience
   - Response time
   - Success programs

3. **Brand Differentiation**
   - Trust and reputation
   - Thought leadership
   - Community
   - Values alignment

4. **Price Differentiation**
   - Premium positioning
   - Value positioning
   - Transparent pricing
   - Flexible packaging

### Positioning Statement Framework

```
For [target customer]
Who [statement of need or opportunity]
Our product is [product category]
That [statement of key benefit]
Unlike [primary competitive alternative]
Our product [statement of primary differentiation]
```

**Example:**

```
For e-commerce companies
Who struggle with email marketing automation
Our product is an AI-powered email platform
That increases conversion rates by 40%
Unlike Klaviyo and Mailchimp
Our product uses AI to personalize at scale
```

## Competitive Intelligence

### Information Gathering

**Public Sources:**

- Company websites and blogs
- Press releases and news
- Job postings (hint at strategy)
- Customer reviews (G2, Capterra)
- Social media and forums
- Glassdoor (employee insights)
- SEC filings (public companies)
- Patent filings

**Direct Research:**

- Customer interviews
- Win/loss analysis
- Sales team feedback
- Product demos and trials
- Conference attendance

### Competitor Profile Template

For each key competitor, document:

**Company Overview:**

- Founded, HQ, funding, size
- Leadership team
- Company stage and trajectory

**Product:**

- Core features
- Target customers
- Pricing and packaging
- Technology stack
- Recent launches

**Go-to-Market:**

- Sales model (self-serve, sales-led)
- Marketing strategy
- Distribution channels
- Partnerships

**Strengths:**

- What they do better than anyone
- Key competitive advantages
- Market position

**Weaknesses:**

- Gaps in product
- Customer complaints
- Operational challenges

**Strategy:**

- Stated direction
- Inferred priorities
- Likely next moves

## Competitive Pricing Analysis

### Price Positioning

**Premium (Top 25%):**

- Superior product/service
- Strong brand
- High-touch sales
- Enterprise focus

**Mid-Market (Middle 50%):**

- Balanced value
- Standard features
- Mixed sales model
- Broad market

**Value (Bottom 25%):**

- Basic functionality
- Self-service
- Cost leadership
- High volume, low margin

### Pricing Comparison Matrix

| Competitor   | Entry Price | Mid Tier | Enterprise | Model        |
| ------------ | ----------- | -------- | ---------- | ------------ |
| Competitor A | $29/mo      | $99/mo   | Custom     | Subscription |
| Competitor B | $49/mo      | $199/mo  | $499/mo    | Subscription |
| Us           | $39/mo      | $129/mo  | Custom     | Subscription |

**Analysis:**

- Are we priced competitively?
- What does our pricing signal?
- Are there gaps in our packaging?

## Go-to-Market Strategy

### Market Entry Strategies

**Direct Competition:**

- Head-to-head against established players
- Requires differentiation and resources
- Example: Better features at lower price

**Niche Focus:**

- Target underserved segment
- Become specialist vs. generalist
- Example: "Salesforce for real estate"

**Disruptive Innovation:**

- Target non-consumers or low end
- Improve over time to move upmarket
- Example: Freemium model disrupting enterprise

**Platform Play:**

- Build ecosystem and network effects
- Aggregate complementary services
- Example: Marketplace or API platform

### Beachhead Market

**Characteristics of Good Beachhead:**

- Specific, reachable segment
- Acute pain you solve well
- Limited competition
- Willing to pay
- Can lead to expansion

**Example:**
Instead of "project management software", target "project management for construction teams"

## Competitive Advantage

### Sustainable Advantages

**Network Effects:**

- Value increases with users
- Example: Slack, marketplaces

**Switching Costs:**

- High cost to change
- Example: CRM systems with data

**Economies of Scale:**

- Unit costs decrease with volume
- Example: Cloud infrastructure

**Brand:**

- Trust and reputation
- Example: Security software

**Proprietary Technology:**

- Patents or trade secrets
- Example: Algorithms, data

**Regulatory:**

- Licenses or approvals
- Example: Fintech, healthcare

### Testing Your Advantage

Ask:

- Can competitors copy this in < 2 years?
- Does this matter to customers?
- Do we execute this better than anyone?
- Is this advantage durable?

If "no" to any, it's not a sustainable advantage.

## Competitive Monitoring

### What to Track

**Product Changes:**

- New features
- Pricing changes
- Packaging adjustments

**Market Signals:**

- Funding announcements
- Key hires (especially leadership)
- Customer wins/losses
- Partnerships

**Performance Metrics:**

- Revenue (if public or disclosed)
- Customer count
- Growth rate
- Market share estimates

### Monitoring Cadence

**Weekly:**

- Product release notes
- News mentions

**Monthly:**

- Win/loss analysis review
- Positioning map updates

**Quarterly:**

- Deep competitive review
- Strategy adjustment

**Annually:**

- Major strategy reassessment
- Market trends analysis


## Quick Start

To analyze competitive landscape:

1. **Identify competitors** - Direct, indirect, and future threats
2. **Apply Porter's Five Forces** - Assess industry attractiveness
3. **Create positioning map** - Visualize competitive space
4. **Profile top 3-5 competitors** - Deep dive on key rivals
5. **Identify differentiation** - What makes you unique
6. **Analyze pricing** - Where do you fit?
7. **Assess advantages** - What's defensible?
8. **Develop strategy** - How to win

<!-- chapter:end slug=competitive-landscape -->

---

<!-- chapter:begin slug=market-sizing-analysis position=165 -->

## 165. market-sizing-analysis

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/startup-business-analyst/skills/market-sizing-analysis/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/market-sizing-analysis/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/market-sizing-analysis.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (3), referenced from this skill's directory:
  - `examples/saas-market-sizing.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/market-sizing-analysis/examples/saas-market-sizing.md
  - `references/data-sources.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/market-sizing-analysis/references/data-sources.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/market-sizing-analysis/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: market-sizing-analysis
description: Calculate TAM/SAM/SOM for market opportunities using top-down, bottom-up, and value theory methodologies. Use this skill when sizing markets, estimating addressable revenue, validating market opportunity for a new venture, or building investor-ready market analysis for a startup pitch or business plan.
version: 1.0.0
---

# Market Sizing Analysis

Comprehensive market sizing methodologies for calculating Total Addressable Market (TAM), Serviceable Available Market (SAM), and Serviceable Obtainable Market (SOM) for startup opportunities.

## Overview

Market sizing provides the foundation for startup strategy, fundraising, and business planning. Calculate market opportunity using three complementary methodologies: top-down (industry reports), bottom-up (customer segment calculations), and value theory (willingness to pay).

## Core Concepts

### The Three-Tier Market Framework

**TAM (Total Addressable Market)**

- Total revenue opportunity if achieving 100% market share
- Defines the universe of potential customers
- Used for long-term vision and market validation
- Example: All email marketing software revenue globally

**SAM (Serviceable Available Market)**

- Portion of TAM targetable with current product/service
- Accounts for geographic, segment, or capability constraints
- Represents realistic addressable opportunity
- Example: AI-powered email marketing for e-commerce in North America

**SOM (Serviceable Obtainable Market)**

- Realistic market share achievable in 3-5 years
- Accounts for competition, resources, and market dynamics
- Used for financial projections and fundraising
- Example: 2-5% of SAM based on competitive landscape

### When to Use Each Methodology

**Top-Down Analysis**

- Use when established market research exists
- Best for mature, well-defined markets
- Validates market existence and growth
- Starts with industry reports and narrows down

**Bottom-Up Analysis**

- Use when targeting specific customer segments
- Best for new or niche markets
- Most credible for investors
- Builds from customer data and pricing

**Value Theory**

- Use when creating new market categories
- Best for disruptive innovations
- Estimates based on value creation
- Calculates willingness to pay for problem solution

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

<!-- chapter:end slug=market-sizing-analysis -->

---

<!-- chapter:begin slug=startup-financial-modeling position=166 -->

## 166. startup-financial-modeling

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/startup-business-analyst/skills/startup-financial-modeling/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/startup-financial-modeling/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/startup-financial-modeling.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/startup-financial-modeling/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: startup-financial-modeling
description: Build comprehensive 3-5 year financial models with revenue projections, cost structures, cash flow analysis, and scenario planning for early-stage startups. Use this skill when creating financial projections, calculating burn rate or runway, modeling fundraising scenarios, or preparing investor-ready financials for a seed or Series A raise.
version: 1.0.0
---

# Startup Financial Modeling

Build comprehensive 3-5 year financial models with revenue projections, cost structures, cash flow analysis, and scenario planning for early-stage startups.

## Overview

Financial modeling provides the quantitative foundation for startup strategy, fundraising, and operational planning. Create realistic projections using cohort-based revenue modeling, detailed cost structures, and scenario analysis to support decision-making and investor presentations.

## Core Components

### Revenue Model

**Cohort-Based Projections:**
Build revenue from customer acquisition and retention by cohort.

**Formula:**

```
MRR = Σ (Cohort Size × Retention Rate × ARPU)
ARR = MRR × 12
```

**Key Inputs:**

- Monthly new customer acquisitions
- Customer retention rates by month
- Average revenue per user (ARPU)
- Pricing and packaging assumptions
- Expansion revenue (upsells, cross-sells)

### Cost Structure

**Operating Expenses Categories:**

1. **Cost of Goods Sold (COGS)**
   - Hosting and infrastructure
   - Payment processing fees
   - Customer support (variable portion)
   - Third-party services per customer

2. **Sales & Marketing (S&M)**
   - Customer acquisition cost (CAC)
   - Marketing programs and advertising
   - Sales team compensation
   - Marketing tools and software

3. **Research & Development (R&D)**
   - Engineering team compensation
   - Product management
   - Design and UX
   - Development tools and infrastructure

4. **General & Administrative (G&A)**
   - Executive team
   - Finance, legal, HR
   - Office and facilities
   - Insurance and compliance

### Cash Flow Analysis

**Components:**

- Beginning cash balance
- Cash inflows (revenue, fundraising)
- Cash outflows (operating expenses, CapEx)
- Ending cash balance
- Monthly burn rate
- Runway (months of cash remaining)

**Formula:**

```
Runway = Current Cash Balance / Monthly Burn Rate
Monthly Burn = Monthly Revenue - Monthly Expenses
```

### Headcount Planning

**Role-Based Hiring Plan:**
Track headcount by department and role.

**Key Metrics:**

- Fully-loaded cost per employee
- Revenue per employee
- Headcount by department (% of total)

**Typical Ratios (Early-Stage SaaS):**

- Engineering: 40-50%
- Sales & Marketing: 25-35%
- G&A: 10-15%
- Customer Success: 5-10%

## Financial Model Structure

### Three-Scenario Framework

**Conservative Scenario (P10):**

- Slower customer acquisition
- Lower pricing or conversion
- Higher churn rates
- Extended sales cycles
- Used for cash management

**Base Scenario (P50):**

- Most likely outcomes
- Realistic assumptions
- Primary planning scenario
- Used for board reporting

**Optimistic Scenario (P90):**

- Faster growth
- Better unit economics
- Lower churn
- Used for upside planning

### Time Horizon

**Detailed Projections: 3 Years**

- Monthly detail for Year 1
- Monthly detail for Year 2
- Quarterly detail for Year 3

**High-Level Projections: Years 4-5**

- Annual projections
- Key metrics only
- Support long-term planning

## Detailed section: Step-by-Step Process

Originally a 2763-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap.

## Business Model Templates

### SaaS Financial Model

**Revenue Drivers:**

- New MRR (customers × ARPU)
- Expansion MRR (upsells)
- Contraction MRR (downgrades)
- Churned MRR (lost customers)

**Key Ratios:**

- Gross margin: 75-85%
- S&M as % revenue: 40-60% (early stage)
- CAC payback: < 12 months
- Net retention: 100-120%

**Example Projection:**

```
Year 1: $500K ARR, 50 customers, $100K MRR by Dec
Year 2: $2.5M ARR, 200 customers, $208K MRR by Dec
Year 3: $8M ARR, 600 customers, $667K MRR by Dec
```

### Marketplace Financial Model

**Revenue Drivers:**

- GMV (Gross Merchandise Value)
- Take rate (% of GMV)
- Net revenue = GMV × Take rate

**Key Ratios:**

- Take rate: 10-30% depending on category
- CAC for buyers vs. sellers
- Contribution margin: 60-70%

**Example Projection:**

```
Year 1: $5M GMV, 15% take rate = $750K revenue
Year 2: $20M GMV, 15% take rate = $3M revenue
Year 3: $60M GMV, 15% take rate = $9M revenue
```

### E-Commerce Financial Model

**Revenue Drivers:**

- Traffic (visitors)
- Conversion rate
- Average order value (AOV)
- Purchase frequency

**Key Ratios:**

- Gross margin: 40-60%
- Contribution margin: 20-35%
- CAC payback: 3-6 months

### Services / Agency Financial Model

**Revenue Drivers:**

- Billable hours or projects
- Hourly rate or project fee
- Utilization rate
- Team capacity

**Key Ratios:**

- Gross margin: 50-70%
- Utilization: 70-85%
- Revenue per employee

## Fundraising Integration

### Funding Scenario Modeling

**Pre-Money Valuation:**
Based on metrics and comparables.

**Dilution:**

```
Post-Money = Pre-Money + Investment
Dilution % = Investment / Post-Money
```

**Use of Funds:**
Allocate funding to extend runway and achieve milestones.

**Example:**

```
Raise: $5M at $20M pre-money
Post-Money: $25M
Dilution: 20%

Use of Funds:
- Product Development: $2M (40%)
- Sales & Marketing: $2M (40%)
- G&A and Operations: $0.5M (10%)
- Working Capital: $0.5M (10%)
```

### Milestone-Based Planning

**Identify Key Milestones:**

- Product launch
- First $1M ARR
- Break-even on CAC
- Series A fundraise

**Funding Amount:**
Ensure runway to achieve next milestone + 6 months buffer.

## Common Pitfalls

**Pitfall 1: Overly Optimistic Revenue**

- New startups rarely hit aggressive projections
- Use conservative customer acquisition assumptions
- Model realistic churn rates

**Pitfall 2: Underestimating Costs**

- Add 20% buffer to expense estimates
- Include fully-loaded compensation
- Account for software and tools

**Pitfall 3: Ignoring Cash Flow Timing**

- Revenue ≠ cash (payment terms)
- Expenses paid before revenue collected
- Model cash conversion carefully

**Pitfall 4: Static Headcount**

- Hiring takes time (3-6 months to fill roles)
- Ramp time for productivity (3-6 months)
- Account for attrition (10-15% annually)

**Pitfall 5: Not Scenario Planning**

- Single scenario is never accurate
- Always model conservative case
- Plan for what you'll do if base case fails

## Model Validation

**Sanity Checks:**

- [ ] Revenue growth rate is achievable (3x in Year 2, 2x in Year 3)
- [ ] Unit economics are realistic (LTV/CAC > 3, payback < 18 months)
- [ ] Burn multiple is reasonable (< 2.0 in Year 2-3)
- [ ] Headcount scales with revenue (revenue per employee growing)
- [ ] Gross margin is appropriate for business model
- [ ] S&M spending aligns with CAC and growth targets

**Benchmark Against Peers:**
Compare key metrics to similar companies at similar stage.

**Investor Feedback:**
Share model with advisors or investors for feedback on assumptions.


## Quick Start

To create a startup financial model:

1. **Define business model** - Revenue drivers and pricing
2. **Project revenue** - Cohort-based with retention
3. **Model costs** - COGS, S&M, R&D, G&A by month
4. **Plan headcount** - Hiring by role and department
5. **Calculate cash flow** - Revenue - expenses = burn/runway
6. **Compute metrics** - CAC, LTV, burn multiple, runway
7. **Create scenarios** - Conservative, base, optimistic
8. **Validate assumptions** - Sanity check and benchmark
9. **Integrate fundraising** - Model funding rounds and milestones

<!-- chapter:end slug=startup-financial-modeling -->

---

<!-- chapter:begin slug=startup-metrics-framework position=167 -->

## 167. startup-metrics-framework

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/startup-business-analyst/skills/startup-metrics-framework/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/startup-metrics-framework/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/startup-metrics-framework.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: startup-metrics-framework
description: Track, calculate, and optimize key performance metrics for SaaS, marketplace, consumer, and B2B startups from seed through Series A, including unit economics, growth efficiency, and cash management. Use this skill when defining a metrics framework, calculating CAC/LTV/burn multiple, benchmarking business health, or preparing metrics dashboards for investors or board reporting.
version: 1.0.0
---

# Startup Metrics Framework

Comprehensive guide to tracking, calculating, and optimizing key performance metrics for different startup business models from seed through Series A.

## Overview

Track the right metrics at the right stage. Focus on unit economics, growth efficiency, and cash management metrics that matter for fundraising and operational excellence.

## Universal Startup Metrics

### Revenue Metrics

**MRR (Monthly Recurring Revenue)**

```
MRR = Σ (Active Subscriptions × Monthly Price)
```

**ARR (Annual Recurring Revenue)**

```
ARR = MRR × 12
```

**Growth Rate**

```
MoM Growth = (This Month MRR - Last Month MRR) / Last Month MRR
YoY Growth = (This Year ARR - Last Year ARR) / Last Year ARR
```

**Target Benchmarks:**

- Seed stage: 15-20% MoM growth
- Series A: 10-15% MoM growth, 3-5x YoY
- Series B+: 100%+ YoY (Rule of 40)

### Unit Economics

**CAC (Customer Acquisition Cost)**

```
CAC = Total S&M Spend / New Customers Acquired
```

Include: Sales salaries, marketing spend, tools, overhead

**LTV (Lifetime Value)**

```
LTV = ARPU × Gross Margin% × (1 / Churn Rate)
```

Simplified:

```
LTV = ARPU × Average Customer Lifetime × Gross Margin%
```

**LTV:CAC Ratio**

```
LTV:CAC = LTV / CAC
```

**Benchmarks:**

- LTV:CAC > 3.0 = Healthy
- LTV:CAC 1.0-3.0 = Needs improvement
- LTV:CAC < 1.0 = Unsustainable

**CAC Payback Period**

```
CAC Payback = CAC / (ARPU × Gross Margin%)
```

**Benchmarks:**

- < 12 months = Excellent
- 12-18 months = Good
- > 24 months = Concerning

### Cash Efficiency Metrics

**Burn Rate**

```
Monthly Burn = Monthly Revenue - Monthly Expenses
```

Negative burn = losing money (typical early-stage)

**Runway**

```
Runway (months) = Cash Balance / Monthly Burn Rate
```

**Target:** Always maintain 12-18 months runway

**Burn Multiple**

```
Burn Multiple = Net Burn / Net New ARR
```

**Benchmarks:**

- < 1.0 = Exceptional efficiency
- 1.0-1.5 = Good
- 1.5-2.0 = Acceptable
- > 2.0 = Inefficient

Lower is better (spending less to generate ARR)

## SaaS Metrics

### Revenue Composition

**New MRR**
New customers × ARPU

**Expansion MRR**
Upsells and cross-sells from existing customers

**Contraction MRR**
Downgrades from existing customers

**Churned MRR**
Lost customers

**Net New MRR Formula:**

```
Net New MRR = New MRR + Expansion MRR - Contraction MRR - Churned MRR
```

### Retention Metrics

**Logo Retention**

```
Logo Retention = (Customers End - New Customers) / Customers Start
```

**Dollar Retention (NDR - Net Dollar Retention)**

```
NDR = (ARR Start + Expansion - Contraction - Churn) / ARR Start
```

**Benchmarks:**

- NDR > 120% = Best-in-class
- NDR 100-120% = Good
- NDR < 100% = Needs work

**Gross Retention**

```
Gross Retention = (ARR Start - Churn - Contraction) / ARR Start
```

**Benchmarks:**

- > 90% = Excellent
- 85-90% = Good
- < 85% = Concerning

### SaaS-Specific Metrics

**Magic Number**

```
Magic Number = Net New ARR (quarter) / S&M Spend (prior quarter)
```

**Benchmarks:**

- > 0.75 = Efficient, ready to scale
- 0.5-0.75 = Moderate efficiency
- < 0.5 = Inefficient, don't scale yet

**Rule of 40**

```
Rule of 40 = Revenue Growth Rate% + Profit Margin%
```

**Benchmarks:**

- > 40% = Excellent
- 20-40% = Acceptable
- < 20% = Needs improvement

**Example:**
50% growth + (10%) margin = 40% ✓

**Quick Ratio**

```
Quick Ratio = (New MRR + Expansion MRR) / (Churned MRR + Contraction MRR)
```

**Benchmarks:**

- > 4.0 = Healthy growth
- 2.0-4.0 = Moderate
- < 2.0 = Churn problem

## Marketplace Metrics

### GMV (Gross Merchandise Value)

**Total Transaction Volume:**

```
GMV = Σ (Transaction Value)
```

**Growth Rate:**

```
GMV Growth Rate = (Current Period GMV - Prior Period GMV) / Prior Period GMV
```

**Target:** 20%+ MoM early-stage

### Take Rate

```
Take Rate = Net Revenue / GMV
```

**Typical Ranges:**

- Payment processors: 2-3%
- E-commerce marketplaces: 10-20%
- Service marketplaces: 15-25%
- High-value B2B: 5-15%

### Marketplace Liquidity

**Time to Transaction**
How long from listing to sale/match?

**Fill Rate**
% of requests that result in transaction

**Repeat Rate**
% of users who transact multiple times

**Benchmarks:**

- Fill rate > 80% = Strong liquidity
- Repeat rate > 60% = Strong retention

### Marketplace Balance

**Supply/Demand Ratio:**
Track relative growth of supply and demand sides.

**Warning Signs:**

- Too much supply: Low fill rates, frustrated suppliers
- Too much demand: Long wait times, frustrated customers

**Goal:** Balanced growth (1:1 ratio ideal, but varies by model)

## Consumer/Mobile Metrics

### Engagement Metrics

**DAU (Daily Active Users)**
Unique users active each day

**MAU (Monthly Active Users)**
Unique users active each month

**DAU/MAU Ratio**

```
DAU/MAU = DAU / MAU
```

**Benchmarks:**

- > 50% = Exceptional (daily habit)
- 20-50% = Good
- < 20% = Weak engagement

**Session Frequency**
Average sessions per user per day/week

**Session Duration**
Average time spent per session

### Retention Curves

**Day 1 Retention:** % users who return next day
**Day 7 Retention:** % users active 7 days after signup
**Day 30 Retention:** % users active 30 days after signup

**Benchmarks (Day 30):**

- > 40% = Excellent
- 25-40% = Good
- < 25% = Weak

**Retention Curve Shape:**

- Flattening curve = good (users becoming habitual)
- Steep decline = poor product-market fit

### Viral Coefficient (K-Factor)

```
K-Factor = Invites per User × Invite Conversion Rate
```

**Example:**
10 invites/user × 20% conversion = 2.0 K-factor

**Benchmarks:**

- K > 1.0 = Viral growth
- K = 0.5-1.0 = Strong referrals
- K < 0.5 = Weak virality

## B2B Metrics

### Sales Efficiency

**Win Rate**

```
Win Rate = Deals Won / Total Opportunities
```

**Target:** 20-30% for new sales team, 30-40% mature

**Sales Cycle Length**
Average days from opportunity to close

**Shorter is better:**

- SMB: 30-60 days
- Mid-market: 60-120 days
- Enterprise: 120-270 days

**Average Contract Value (ACV)**

```
ACV = Total Contract Value / Contract Length (years)
```

### Pipeline Metrics

**Pipeline Coverage**

```
Pipeline Coverage = Total Pipeline Value / Quota
```

**Target:** 3-5x coverage (3-5x pipeline needed to hit quota)

**Conversion Rates by Stage:**

- Lead → Opportunity: 10-20%
- Opportunity → Demo: 50-70%
- Demo → Proposal: 30-50%
- Proposal → Close: 20-40%

## Metrics by Stage

### Pre-Seed (Product-Market Fit)

**Focus Metrics:**

1. Active users growth
2. User retention (Day 7, Day 30)
3. Core engagement (sessions, features used)
4. Qualitative feedback (NPS, interviews)

**Don't worry about:**

- Revenue (may be zero)
- CAC (not optimizing yet)
- Unit economics

### Seed ($500K-$2M ARR)

**Focus Metrics:**

1. MRR growth rate (15-20% MoM)
2. CAC and LTV (establish baseline)
3. Gross retention (> 85%)
4. Core product engagement

**Start tracking:**

- Sales efficiency
- Burn rate and runway

### Series A ($2M-$10M ARR)

**Focus Metrics:**

1. ARR growth (3-5x YoY)
2. Unit economics (LTV:CAC > 3, payback < 18 months)
3. Net dollar retention (> 100%)
4. Burn multiple (< 2.0)
5. Magic number (> 0.5)

**Mature tracking:**

- Rule of 40
- Sales efficiency
- Pipeline coverage

## Metric Tracking Best Practices

### Data Infrastructure

**Requirements:**

- Single source of truth (analytics platform)
- Real-time or daily updates
- Automated calculations
- Historical tracking

**Tools:**

- Mixpanel, Amplitude (product analytics)
- ChartMogul, Baremetrics (SaaS metrics)
- Looker, Tableau (BI dashboards)

### Reporting Cadence

**Daily:**

- MRR, active users
- Sign-ups, conversions

**Weekly:**

- Growth rates
- Retention cohorts
- Sales pipeline

**Monthly:**

- Full metric suite
- Board reporting
- Investor updates

**Quarterly:**

- Trend analysis
- Benchmarking
- Strategy review

### Common Mistakes

**Mistake 1: Vanity Metrics**
Don't focus on:

- Total users (without retention)
- Page views (without engagement)
- Downloads (without activation)

Focus on actionable metrics tied to value.

**Mistake 2: Too Many Metrics**
Track 5-7 core metrics intensely, not 50 loosely.

**Mistake 3: Ignoring Unit Economics**
CAC and LTV are critical even at seed stage.

**Mistake 4: Not Segmenting**
Break down metrics by customer segment, channel, cohort.

**Mistake 5: Gaming Metrics**
Optimize for real business outcomes, not dashboard numbers.

## Investor Metrics

### What VCs Want to See

**Seed Round:**

- MRR growth rate
- User retention
- Early unit economics
- Product engagement

**Series A:**

- ARR and growth rate
- CAC payback < 18 months
- LTV:CAC > 3.0
- Net dollar retention > 100%
- Burn multiple < 2.0

**Series B+:**

- Rule of 40 > 40%
- Efficient growth (magic number)
- Path to profitability
- Market leadership metrics

### Metric Presentation

**Dashboard Format:**

```
Current MRR: $250K (↑ 18% MoM)
ARR: $3.0M (↑ 280% YoY)
CAC: $1,200 | LTV: $4,800 | LTV:CAC = 4.0x
NDR: 112% | Logo Retention: 92%
Burn: $180K/mo | Runway: 18 months
```

**Include:**

- Current value
- Growth rate or trend
- Context (target, benchmark)


## Quick Start

To implement startup metrics framework:

1. **Identify business model** - SaaS, marketplace, consumer, B2B
2. **Choose 5-7 core metrics** - Based on stage and model
3. **Establish tracking** - Set up analytics and dashboards
4. **Calculate unit economics** - CAC, LTV, payback
5. **Set targets** - Use benchmarks for goals
6. **Review regularly** - Weekly for core metrics
7. **Share with team** - Align on goals and progress
8. **Update investors** - Monthly/quarterly reporting

<!-- chapter:end slug=startup-metrics-framework -->

---

<!-- chapter:begin slug=team-composition-analysis position=168 -->

## 168. team-composition-analysis

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/startup-business-analyst/skills/team-composition-analysis/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/team-composition-analysis/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/team-composition-analysis.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/startup-business-analyst/skills/team-composition-analysis/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: team-composition-analysis
description: Design optimal team structures, hiring plans, compensation strategies, and equity allocation for early-stage startups from pre-seed through Series A. Use this skill when planning headcount, determining which roles to hire next, setting compensation or equity ranges, designing org structure, or building a hiring budget aligned to funding milestones.
version: 1.0.0
---

# Team Composition Analysis

Design optimal team structures, hiring plans, compensation strategies, and equity allocation for early-stage startups from pre-seed through Series A.

## Overview

Build the right team at the right time with appropriate compensation and equity. Plan role-by-role hiring aligned with revenue milestones, budget constraints, and market benchmarks.

## Team Structure by Stage

### Pre-Seed (0-$500K ARR)

**Team Size: 2-5 people**

**Core Roles:**

- Founders (2-3): Product, engineering, business
- First engineer (if needed)
- Contract roles: Design, marketing

**Focus:** Build and validate product-market fit

### Seed ($500K-$2M ARR)

**Team Size: 5-15 people**

**Key Hires:**

- Engineering lead + 2-3 engineers
- First sales/business development
- Product manager
- Marketing/growth lead

**Focus:** Scale product and prove repeatable sales

### Series A ($2M-$10M ARR)

**Team Size: 15-50 people**

**Department Build-Out:**

- Engineering (40%): 6-20 people
- Sales & Marketing (30%): 5-15 people
- Customer Success (10%): 2-5 people
- G&A (10%): 2-5 people
- Product (10%): 2-5 people

**Focus:** Scale revenue and build repeatable processes

## Detailed section: Role-by-Role Planning

Originally a 1720-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap.

## Compensation Strategy

### Base Salary Benchmarks (US, 2024)

**Engineering:**

- Junior: $90K-$120K
- Mid-Level: $120K-$150K
- Senior: $150K-$180K
- Staff/Principal: $180K-$220K
- Engineering Manager: $160K-$200K
- VP Engineering: $180K-$250K

**Sales:**

- SDR/BDR: $50K-$70K base + $50K-$70K commission
- Account Executive: $80K-$120K base + $80K-$120K commission
- Sales Manager: $120K-$160K base + $80K-$120K commission
- VP Sales: $150K-$200K base + $150K-$200K commission

**Product:**

- Product Manager: $120K-$150K
- Senior PM: $150K-$180K
- Head of Product: $150K-$180K
- VP Product: $180K-$220K

**Marketing:**

- Marketing Manager: $90K-$130K
- Content/Demand Gen: $70K-$100K
- Head of Marketing: $130K-$170K
- VP Marketing: $150K-$200K

**Customer Success:**

- CS Representative: $60K-$90K
- CS Manager: $100K-$130K
- VP Customer Success: $140K-$180K

### Total Compensation Formula

```
Total Comp = Base Salary × 1.30 (benefits & taxes) + Equity Value
```

**Fully-Loaded Cost:**

- Base salary
- Payroll taxes (7.65% FICA)
- Benefits (health insurance, 401k): $10K-$15K per employee
- Other (workspace, equipment, software): $5K-$10K per employee

**Rule of Thumb:** Multiply base salary by 1.3-1.4 for fully-loaded cost

### Geographic Adjustments

**San Francisco / New York:** +20-30% above benchmarks
**Seattle / Boston / Los Angeles:** +10-20%
**Austin / Denver / Chicago:** +0-10%
**Remote / Other US Cities:** -10-20%
**International:** Varies widely by country

## Equity Allocation

### Equity by Role and Stage

**Founders:**

- First founder: 40-60%
- Second founder: 20-40%
- Third founder: 10-20%
- Vesting: 4 years with 1-year cliff

**Early Employees (Pre-Seed):**

- First engineer: 0.5-2.0%
- First 5 employees: 0.25-1.0% each

**Seed Stage Hires:**

- VP/Head level: 0.5-1.5%
- Senior IC: 0.1-0.5%
- Mid-level: 0.05-0.25%
- Junior: 0.01-0.1%

**Series A Hires:**

- C-level (CTO, CFO): 1.0-3.0%
- VP level: 0.3-1.0%
- Director level: 0.1-0.5%
- Senior IC: 0.05-0.2%
- Mid-level: 0.01-0.1%
- Junior: 0.005-0.05%

### Equity Pool Sizing

**Option Pool by Round:**

- Pre-Seed: 10-15% reserved
- Seed: 10-15% top-up
- Series A: 10-15% top-up
- Series B+: 5-10% per round

**Pre-Funding Dilution:**
Investors often require option pool creation before investment, diluting founders.

**Example:**

```
Pre-money: $10M
Investors want 15% option pool post-money

Calculation:
Post-money: $15M ($10M + $5M investment)
Option pool: $2.25M (15% × $15M)
Founders diluted by pool creation before new money
```

## Organizational Design

### Reporting Structure

**Pre-Seed:**

```
Founders (flat structure)
├── Contractors
└── First hires (report to founders)
```

**Seed:**

```
CEO
├── Engineering Lead (2-4 engineers)
├── Sales/Growth Lead (1-2 reps)
├── Product Manager
└── Operations
```

**Series A:**

```
CEO
├── CTO / VP Engineering (6-20 people)
│   ├── Engineering Manager(s)
│   └── Individual Contributors
├── VP Sales (5-15 people)
│   ├── Sales Manager
│   ├── Account Executives
│   └── SDRs
├── Head of Product (2-5 people)
│   ├── Product Managers
│   └── Designers
├── Head of Customer Success (2-5 people)
└── CFO / Finance Lead (2-5 people)
    ├── Recruiter
    └── Operations
```

### Span of Control

**Manager Ratios:**

- First-line managers: 4-8 direct reports
- Directors: 3-5 direct reports (managers)
- VPs: 3-5 direct reports (directors)
- CEO: 5-8 direct reports (executive team)

## Full-Time vs. Contract

### Use Full-Time for:

- Core product development
- Sales (revenue-generating roles)
- Mission-critical operations
- Institutional knowledge roles

### Use Contractors for:

- Specialized short-term needs (legal, accounting)
- Variable workload (design, marketing campaigns)
- Skills outside core competency
- Testing role before FTE hire
- Geographic expansion before permanent presence

### Cost Comparison

**Full-Time:**

- Lower hourly cost
- Benefits and overhead
- Long-term commitment
- Cultural fit matters

**Contract:**

- Higher hourly rate ($75-$200/hour vs. $40-$100/hour FTE equivalent)
- No benefits or overhead
- Flexible engagement
- Easier to scale up/down

## Hiring Velocity

### Realistic Timeline

**Role Opening to Hire:**

- Junior: 6-8 weeks
- Mid-Level: 8-12 weeks
- Senior: 12-16 weeks
- Executive: 16-24 weeks

**Time to Productivity:**

- Junior: 4-6 months
- Mid-Level: 2-4 months
- Senior: 1-3 months
- Executive: 3-6 months

### Planning Buffer

Always add 2-3 months buffer to hiring plans.

**Example:**
If need engineer by July 1:

- Start recruiting: April 1 (12 weeks)
- Productivity: September 1 (2 months ramp)

## Budget Planning

### Compensation as % of Revenue

**Early Stage (Seed):**

- Total comp: 120-150% of revenue (burning cash to grow)
- Engineering: 50-60%
- Sales: 30-40%
- Other: 20-30%

**Growth Stage (Series A):**

- Total comp: 70-100% of revenue
- Engineering: 35-45%
- Sales: 25-35%
- Other: 20-30%

### Headcount Budget Formula

```
Total Comp Budget = Σ (Role Count × Fully-Loaded Cost × % of Year)

Example:
3 Engineers × $202K × 100% = $606K
2 AEs × $230K × 75% (mid-year start) = $345K
1 PM × $162K × 100% = $162K
Total: $1.1M
```


## Quick Start

To plan team composition:

1. **Identify stage** - Pre-seed, seed, or Series A
2. **Define roles** - What functions are needed now
3. **Prioritize hires** - Critical path for business goals
4. **Set compensation** - Base salary + equity by level
5. **Plan timeline** - Account for recruiting and ramp time
6. **Calculate budget** - Fully-loaded cost × headcount
7. **Design org chart** - Reporting structure and span of control
8. **Allocate equity** - Fair allocation that preserves pool

<!-- chapter:end slug=team-composition-analysis -->

---

## Part: Systems Programming

---

<!-- chapter:begin slug=go-concurrency-patterns position=169 -->

## 169. go-concurrency-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/systems-programming/skills/go-concurrency-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/systems-programming/skills/go-concurrency-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/go-concurrency-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/systems-programming/skills/go-concurrency-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: go-concurrency-patterns
description: Master Go concurrency with goroutines, channels, sync primitives, and context. Use when building concurrent Go applications, implementing worker pools, or debugging race conditions.
---

# Go Concurrency Patterns

Production patterns for Go concurrency including goroutines, channels, synchronization primitives, and context management.

## When to Use This Skill

- Building concurrent Go applications
- Implementing worker pools and pipelines
- Managing goroutine lifecycles
- Using channels for communication
- Debugging race conditions
- Implementing graceful shutdown

## Core Concepts

### 1. Go Concurrency Primitives

| Primitive         | Purpose                          |
| ----------------- | -------------------------------- |
| `goroutine`       | Lightweight concurrent execution |
| `channel`         | Communication between goroutines |
| `select`          | Multiplex channel operations     |
| `sync.Mutex`      | Mutual exclusion                 |
| `sync.WaitGroup`  | Wait for goroutines to complete  |
| `context.Context` | Cancellation and deadlines       |

### 2. Go Concurrency Mantra

```
Don't communicate by sharing memory;
share memory by communicating.
```

## Quick Start

```go
package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    results := make(chan string, 10)
    var wg sync.WaitGroup

    // Spawn workers
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go worker(ctx, i, results, &wg)
    }

    // Close results when done
    go func() {
        wg.Wait()
        close(results)
    }()

    // Collect results
    for result := range results {
        fmt.Println(result)
    }
}

func worker(ctx context.Context, id int, results chan<- string, wg *sync.WaitGroup) {
    defer wg.Done()

    select {
    case <-ctx.Done():
        return
    case results <- fmt.Sprintf("Worker %d done", id):
    }
}
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use context** - For cancellation and deadlines
- **Close channels** - From sender side only
- **Use errgroup** - For concurrent operations with errors
- **Buffer channels** - When you know the count
- **Prefer channels** - Over mutexes when possible

### Don'ts

- **Don't leak goroutines** - Always have exit path
- **Don't close from receiver** - Causes panic
- **Don't use shared memory** - Unless necessary
- **Don't ignore context cancellation** - Check ctx.Done()
- **Don't use time.Sleep for sync** - Use proper primitives

<!-- chapter:end slug=go-concurrency-patterns -->

---

<!-- chapter:begin slug=memory-safety-patterns position=170 -->

## 170. memory-safety-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/systems-programming/skills/memory-safety-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/systems-programming/skills/memory-safety-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/memory-safety-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/systems-programming/skills/memory-safety-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: memory-safety-patterns
description: Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.
---

# Memory Safety Patterns

Cross-language patterns for memory-safe programming including RAII, ownership, smart pointers, and resource management.

## When to Use This Skill

- Writing memory-safe systems code
- Managing resources (files, sockets, memory)
- Preventing use-after-free and leaks
- Implementing RAII patterns
- Choosing between languages for safety
- Debugging memory issues

## Core Concepts

### 1. Memory Bug Categories

| Bug Type             | Description                      | Prevention        |
| -------------------- | -------------------------------- | ----------------- |
| **Use-after-free**   | Access freed memory              | Ownership, RAII   |
| **Double-free**      | Free same memory twice           | Smart pointers    |
| **Memory leak**      | Never free memory                | RAII, GC          |
| **Buffer overflow**  | Write past buffer end            | Bounds checking   |
| **Dangling pointer** | Pointer to freed memory          | Lifetime tracking |
| **Data race**        | Concurrent unsynchronized access | Ownership, Sync   |

### 2. Safety Spectrum

```
Manual (C) → Smart Pointers (C++) → Ownership (Rust) → GC (Go, Java)
Less safe                                              More safe
More control                                           Less control
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Prefer RAII** - Tie resource lifetime to scope
- **Use smart pointers** - Avoid raw pointers in C++
- **Understand ownership** - Know who owns what
- **Check bounds** - Use safe access methods
- **Use tools** - AddressSanitizer, Valgrind, Miri

### Don'ts

- **Don't use raw pointers** - Unless interfacing with C
- **Don't return local references** - Dangling pointer
- **Don't ignore compiler warnings** - They catch bugs
- **Don't use `unsafe` carelessly** - In Rust, minimize it
- **Don't assume thread safety** - Be explicit

## Debugging Tools

```bash
# AddressSanitizer (Clang/GCC)
clang++ -fsanitize=address -g source.cpp

# Valgrind
valgrind --leak-check=full ./program

# Rust Miri (undefined behavior detector)
cargo +nightly miri run

# ThreadSanitizer
clang++ -fsanitize=thread -g source.cpp
```

<!-- chapter:end slug=memory-safety-patterns -->

---

<!-- chapter:begin slug=rust-async-patterns position=171 -->

## 171. rust-async-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/systems-programming/skills/rust-async-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/systems-programming/skills/rust-async-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/rust-async-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (1), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/systems-programming/skills/rust-async-patterns/references/details.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: rust-async-patterns
description: Master Rust async programming with Tokio, async traits, error handling, and concurrent patterns. Use when building async Rust applications, implementing concurrent systems, or debugging async code.
---

# Rust Async Patterns

Production patterns for async Rust programming with Tokio runtime, including tasks, channels, streams, and error handling.

## When to Use This Skill

- Building async Rust applications
- Implementing concurrent network services
- Using Tokio for async I/O
- Handling async errors properly
- Debugging async code issues
- Optimizing async performance

## Core Concepts

### 1. Async Execution Model

```
Future (lazy) → poll() → Ready(value) | Pending
                ↑           ↓
              Waker ← Runtime schedules
```

### 2. Key Abstractions

| Concept    | Purpose                                  |
| ---------- | ---------------------------------------- |
| `Future`   | Lazy computation that may complete later |
| `async fn` | Function returning impl Future           |
| `await`    | Suspend until future completes           |
| `Task`     | Spawned future running concurrently      |
| `Runtime`  | Executor that polls futures              |

## Quick Start

```toml
# Cargo.toml
[dependencies]
tokio = { version = "1", features = ["full"] }
futures = "0.3"
async-trait = "0.1"
anyhow = "1.0"
tracing = "0.1"
tracing-subscriber = "0.3"
```

```rust
use tokio::time::{sleep, Duration};
use anyhow::Result;

#[tokio::main]
async fn main() -> Result<()> {
    // Initialize tracing
    tracing_subscriber::fmt::init();

    // Async operations
    let result = fetch_data("https://api.example.com").await?;
    println!("Got: {}", result);

    Ok(())
}

async fn fetch_data(url: &str) -> Result<String> {
    // Simulated async operation
    sleep(Duration::from_millis(100)).await;
    Ok(format!("Data from {}", url))
}
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

### Do's

- **Use `tokio::select!`** - For racing futures
- **Prefer channels** - Over shared state when possible
- **Use `JoinSet`** - For managing multiple tasks
- **Instrument with tracing** - For debugging async code
- **Handle cancellation** - Check `CancellationToken`

### Don'ts

- **Don't block** - Never use `std::thread::sleep` in async
- **Don't hold locks across awaits** - Causes deadlocks
- **Don't spawn unboundedly** - Use semaphores for limits
- **Don't ignore errors** - Propagate with `?` or log
- **Don't forget Send bounds** - For spawned futures

<!-- chapter:end slug=rust-async-patterns -->

---

## Part: UI Design

---

<!-- chapter:begin slug=accessibility-compliance position=172 -->

## 172. accessibility-compliance

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/accessibility-compliance/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/accessibility-compliance/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/accessibility-compliance.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `references/aria-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/accessibility-compliance/references/aria-patterns.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/accessibility-compliance/references/details.md
  - `references/mobile-accessibility.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/accessibility-compliance/references/mobile-accessibility.md
  - `references/wcag-guidelines.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/accessibility-compliance/references/wcag-guidelines.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: accessibility-compliance
description: Implement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.
---

# Accessibility Compliance

Master accessibility implementation to create inclusive experiences that work for everyone, including users with disabilities.

## When to Use This Skill

- Implementing WCAG 2.2 Level AA or AAA compliance
- Building screen reader accessible interfaces
- Adding keyboard navigation to interactive components
- Implementing focus management and focus trapping
- Creating accessible forms with proper labeling
- Supporting reduced motion and high contrast preferences
- Building mobile accessibility features (iOS VoiceOver, Android TalkBack)
- Conducting accessibility audits and fixing violations

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Use Semantic HTML**: Prefer native elements over ARIA when possible
2. **Test with Real Users**: Include people with disabilities in user testing
3. **Keyboard First**: Design interactions to work without a mouse
4. **Don't Disable Focus Styles**: Style them, don't remove them
5. **Provide Text Alternatives**: All non-text content needs descriptions
6. **Support Zoom**: Content should work at 200% zoom
7. **Announce Changes**: Use live regions for dynamic content
8. **Respect Preferences**: Honor prefers-reduced-motion and prefers-contrast

## Common Issues

- **Missing alt text**: Images without descriptions
- **Poor color contrast**: Text hard to read against background
- **Keyboard traps**: Focus stuck in component
- **Missing labels**: Form inputs without associated labels
- **Auto-playing media**: Content that plays without user initiation
- **Inaccessible custom controls**: Recreating native functionality poorly
- **Missing skip links**: No way to bypass repetitive content
- **Focus order issues**: Tab order doesn't match visual order

## Testing Tools

- **Automated**: axe DevTools, WAVE, Lighthouse
- **Manual**: VoiceOver (macOS/iOS), NVDA/JAWS (Windows), TalkBack (Android)
- **Simulators**: NoCoffee (vision), Silktide (various disabilities)

<!-- chapter:end slug=accessibility-compliance -->

---

<!-- chapter:begin slug=design-system-patterns position=173 -->

## 173. design-system-patterns

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/design-system-patterns/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/design-system-patterns/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/design-system-patterns.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `references/component-architecture.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/design-system-patterns/references/component-architecture.md
  - `references/design-tokens.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/design-system-patterns/references/design-tokens.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/design-system-patterns/references/details.md
  - `references/theming-architecture.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/design-system-patterns/references/theming-architecture.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: design-system-patterns
description: Build scalable design systems with design tokens, theming infrastructure, and component architecture patterns. Use when creating design tokens, implementing theme switching, building component libraries, or establishing design system foundations.
---

# Design System Patterns

Master design system architecture to create consistent, maintainable, and scalable UI foundations across web and mobile applications.

## When to Use This Skill

- Creating design tokens for colors, typography, spacing, and shadows
- Implementing light/dark theme switching with CSS custom properties
- Building multi-brand theming systems
- Architecting component libraries with consistent APIs
- Establishing design-to-code workflows with Figma tokens
- Creating semantic token hierarchies (primitive, semantic, component)
- Setting up design system documentation and guidelines

## Core Capabilities

### 1. Design Tokens

- Primitive tokens (raw values: colors, sizes, fonts)
- Semantic tokens (contextual meaning: text-primary, surface-elevated)
- Component tokens (specific usage: button-bg, card-border)
- Token naming conventions and organization
- Multi-platform token generation (CSS, iOS, Android)

### 2. Theming Infrastructure

- CSS custom properties architecture
- Theme context providers in React
- Dynamic theme switching
- System preference detection (prefers-color-scheme)
- Persistent theme storage
- Reduced motion and high contrast modes

### 3. Component Architecture

- Compound component patterns
- Polymorphic components (as prop)
- Variant and size systems
- Slot-based composition
- Headless UI patterns
- Style props and responsive variants

### 4. Token Pipeline

- Figma to code synchronization
- Style Dictionary configuration
- Token transformation and formatting
- CI/CD integration for token updates

## Quick Start

```typescript
// Design tokens with CSS custom properties
const tokens = {
  colors: {
    // Primitive tokens
    gray: {
      50: "#fafafa",
      100: "#f5f5f5",
      900: "#171717",
    },
    blue: {
      500: "#3b82f6",
      600: "#2563eb",
    },
  },
  // Semantic tokens (reference primitives)
  semantic: {
    light: {
      "text-primary": "var(--color-gray-900)",
      "text-secondary": "var(--color-gray-600)",
      "surface-default": "var(--color-white)",
      "surface-elevated": "var(--color-gray-50)",
      "border-default": "var(--color-gray-200)",
      "interactive-primary": "var(--color-blue-500)",
    },
    dark: {
      "text-primary": "var(--color-gray-50)",
      "text-secondary": "var(--color-gray-400)",
      "surface-default": "var(--color-gray-900)",
      "surface-elevated": "var(--color-gray-800)",
      "border-default": "var(--color-gray-700)",
      "interactive-primary": "var(--color-blue-400)",
    },
  },
};
```

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Name Tokens by Purpose**: Use semantic names (text-primary) not visual descriptions (dark-gray)
2. **Maintain Token Hierarchy**: Primitives > Semantic > Component tokens
3. **Document Token Usage**: Include usage guidelines with token definitions
4. **Version Tokens**: Treat token changes as API changes with semver
5. **Test Theme Combinations**: Verify all themes work with all components
6. **Automate Token Pipeline**: CI/CD for Figma-to-code synchronization
7. **Provide Migration Paths**: Deprecate tokens gradually with clear alternatives

## Common Issues

- **Token Sprawl**: Too many tokens without clear hierarchy
- **Inconsistent Naming**: Mixed conventions (camelCase vs kebab-case)
- **Missing Dark Mode**: Tokens that don't adapt to theme changes
- **Hardcoded Values**: Using raw values instead of tokens
- **Circular References**: Tokens referencing each other in loops
- **Platform Gaps**: Tokens missing for some platforms (web but not mobile)

<!-- chapter:end slug=design-system-patterns -->

---

<!-- chapter:begin slug=interaction-design position=174 -->

## 174. interaction-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/interaction-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/interaction-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/interaction-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (3), referenced from this skill's directory:
  - `references/animation-libraries.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/interaction-design/references/animation-libraries.md
  - `references/microinteraction-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/interaction-design/references/microinteraction-patterns.md
  - `references/scroll-animations.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/interaction-design/references/scroll-animations.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: interaction-design
description: Design and implement microinteractions, motion design, transitions, and user feedback patterns. Use when adding polish to UI interactions, implementing loading states, or creating delightful user experiences.
---

# Interaction Design

Create engaging, intuitive interactions through motion, feedback, and thoughtful state transitions that enhance usability and delight users.

## When to Use This Skill

- Adding microinteractions to enhance user feedback
- Implementing smooth page and component transitions
- Designing loading states and skeleton screens
- Creating gesture-based interactions
- Building notification and toast systems
- Implementing drag-and-drop interfaces
- Adding scroll-triggered animations
- Designing hover and focus states

## Core Principles

### 1. Purposeful Motion

Motion should communicate, not decorate:

- **Feedback**: Confirm user actions occurred
- **Orientation**: Show where elements come from/go to
- **Focus**: Direct attention to important changes
- **Continuity**: Maintain context during transitions

### 2. Timing Guidelines

| Duration  | Use Case                                  |
| --------- | ----------------------------------------- |
| 100-150ms | Micro-feedback (hovers, clicks)           |
| 200-300ms | Small transitions (toggles, dropdowns)    |
| 300-500ms | Medium transitions (modals, page changes) |
| 500ms+    | Complex choreographed animations          |

### 3. Easing Functions

```css
/* Common easings */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* Decelerate - entering */
--ease-in: cubic-bezier(0.55, 0, 1, 0.45); /* Accelerate - exiting */
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* Both - moving between */
--spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* Overshoot - playful */
```

## Quick Start: Button Microinteraction

```tsx
import { motion } from "framer-motion";

export function InteractiveButton({ children, onClick }) {
  return (
    <motion.button
      onClick={onClick}
      whileHover={{ scale: 1.02 }}
      whileTap={{ scale: 0.98 }}
      transition={{ type: "spring", stiffness: 400, damping: 17 }}
      className="px-4 py-2 bg-blue-600 text-white rounded-lg"
    >
      {children}
    </motion.button>
  );
}
```

## Interaction Patterns

### 1. Loading States

**Skeleton Screens**: Preserve layout while loading

```tsx
function CardSkeleton() {
  return (
    <div className="animate-pulse">
      <div className="h-48 bg-gray-200 rounded-lg" />
      <div className="mt-4 h-4 bg-gray-200 rounded w-3/4" />
      <div className="mt-2 h-4 bg-gray-200 rounded w-1/2" />
    </div>
  );
}
```

**Progress Indicators**: Show determinate progress

```tsx
function ProgressBar({ progress }: { progress: number }) {
  return (
    <div className="h-2 bg-gray-200 rounded-full overflow-hidden">
      <motion.div
        className="h-full bg-blue-600"
        initial={{ width: 0 }}
        animate={{ width: `${progress}%` }}
        transition={{ ease: "easeOut" }}
      />
    </div>
  );
}
```

### 2. State Transitions

**Toggle with smooth transition**:

```tsx
function Toggle({ checked, onChange }) {
  return (
    <button
      role="switch"
      aria-checked={checked}
      onClick={() => onChange(!checked)}
      className={`
        relative w-12 h-6 rounded-full transition-colors duration-200
        ${checked ? "bg-blue-600" : "bg-gray-300"}
      `}
    >
      <motion.span
        className="absolute top-1 left-1 w-4 h-4 bg-white rounded-full shadow"
        animate={{ x: checked ? 24 : 0 }}
        transition={{ type: "spring", stiffness: 500, damping: 30 }}
      />
    </button>
  );
}
```

### 3. Page Transitions

**Framer Motion layout animations**:

```tsx
import { AnimatePresence, motion } from "framer-motion";

function PageTransition({ children, key }) {
  return (
    <AnimatePresence mode="wait">
      <motion.div
        key={key}
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        exit={{ opacity: 0, y: -20 }}
        transition={{ duration: 0.3 }}
      >
        {children}
      </motion.div>
    </AnimatePresence>
  );
}
```

### 4. Feedback Patterns

**Ripple effect on click**:

```tsx
function RippleButton({ children, onClick }) {
  const [ripples, setRipples] = useState([]);

  const handleClick = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const ripple = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top,
      id: Date.now(),
    };
    setRipples((prev) => [...prev, ripple]);
    setTimeout(() => {
      setRipples((prev) => prev.filter((r) => r.id !== ripple.id));
    }, 600);
    onClick?.(e);
  };

  return (
    <button onClick={handleClick} className="relative overflow-hidden">
      {children}
      {ripples.map((ripple) => (
        <span
          key={ripple.id}
          className="absolute bg-white/30 rounded-full animate-ripple"
          style={{ left: ripple.x, top: ripple.y }}
        />
      ))}
    </button>
  );
}
```

### 5. Gesture Interactions

**Swipe to dismiss**:

```tsx
function SwipeCard({ children, onDismiss }) {
  return (
    <motion.div
      drag="x"
      dragConstraints={{ left: 0, right: 0 }}
      onDragEnd={(_, info) => {
        if (Math.abs(info.offset.x) > 100) {
          onDismiss();
        }
      }}
      className="cursor-grab active:cursor-grabbing"
    >
      {children}
    </motion.div>
  );
}
```

## CSS Animation Patterns

### Keyframe Animations

```css
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.animate-fadeIn {
  animation: fadeIn 0.3s ease-out;
}
.animate-pulse {
  animation: pulse 2s ease-in-out infinite;
}
.animate-spin {
  animation: spin 1s linear infinite;
}
```

### CSS Transitions

```css
.card {
  transition:
    transform 0.2s ease-out,
    box-shadow 0.2s ease-out;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}
```

## Accessibility Considerations

```css
/* Respect user motion preferences */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
```

```tsx
function AnimatedComponent() {
  const prefersReducedMotion = window.matchMedia(
    "(prefers-reduced-motion: reduce)",
  ).matches;

  return (
    <motion.div
      animate={{ opacity: 1 }}
      transition={{ duration: prefersReducedMotion ? 0 : 0.3 }}
    />
  );
}
```

## Best Practices

1. **Performance First**: Use `transform` and `opacity` for smooth 60fps
2. **Reduce Motion Support**: Always respect `prefers-reduced-motion`
3. **Consistent Timing**: Use a timing scale across the app
4. **Natural Physics**: Prefer spring animations over linear
5. **Interruptible**: Allow users to cancel long animations
6. **Progressive Enhancement**: Work without JS animations
7. **Test on Devices**: Performance varies significantly

## Common Issues

- **Janky Animations**: Avoid animating `width`, `height`, `top`, `left`
- **Over-animation**: Too much motion causes fatigue
- **Blocking Interactions**: Never prevent user input during animations
- **Memory Leaks**: Clean up animation listeners on unmount
- **Flash of Content**: Use `will-change` sparingly for optimization

<!-- chapter:end slug=interaction-design -->

---

<!-- chapter:begin slug=mobile-android-design position=175 -->

## 175. mobile-android-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/mobile-android-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-android-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/mobile-android-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `references/android-navigation.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-android-design/references/android-navigation.md
  - `references/compose-components.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-android-design/references/compose-components.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-android-design/references/details.md
  - `references/material3-theming.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-android-design/references/material3-theming.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: mobile-android-design
description: Master Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.
---

# Android Mobile Design

Master Material Design 3 (Material You) and Jetpack Compose to build modern, adaptive Android applications that integrate seamlessly with the Android ecosystem.

## When to Use This Skill

- Designing Android app interfaces following Material Design 3
- Building Jetpack Compose UI and layouts
- Implementing Android navigation patterns (Navigation Compose)
- Creating adaptive layouts for phones, tablets, and foldables
- Using Material 3 theming with dynamic colors
- Building accessible Android interfaces
- Implementing Android-specific gestures and interactions
- Designing for different screen configurations

## Detailed section: Core Concepts

Originally a 9201-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap.

## Quick Start Component

```kotlin
@Composable
fun ItemListCard(
    item: Item,
    onItemClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    Card(
        onClick = onItemClick,
        modifier = modifier.fillMaxWidth(),
        shape = RoundedCornerShape(12.dp)
    ) {
        Row(
            modifier = Modifier
                .padding(16.dp)
                .fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Box(
                modifier = Modifier
                    .size(48.dp)
                    .clip(CircleShape)
                    .background(MaterialTheme.colorScheme.primaryContainer),
                contentAlignment = Alignment.Center
            ) {
                Icon(
                    imageVector = Icons.Default.Star,
                    contentDescription = null,
                    tint = MaterialTheme.colorScheme.onPrimaryContainer
                )
            }

            Spacer(modifier = Modifier.width(16.dp))

            Column(modifier = Modifier.weight(1f)) {
                Text(
                    text = item.title,
                    style = MaterialTheme.typography.titleMedium
                )
                Text(
                    text = item.subtitle,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }

            Icon(
                imageVector = Icons.Default.ChevronRight,
                contentDescription = null,
                tint = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }
    }
}
```

## Best Practices

1. **Use Material Theme**: Access colors via `MaterialTheme.colorScheme` for automatic dark mode support
2. **Support Dynamic Color**: Enable dynamic color on Android 12+ for personalization
3. **Adaptive Layouts**: Use `WindowSizeClass` for responsive designs
4. **Content Descriptions**: Add `contentDescription` to all interactive elements
5. **Touch Targets**: Minimum 48dp touch targets for accessibility
6. **State Hoisting**: Hoist state to make components reusable and testable
7. **Remember Properly**: Use `remember` and `rememberSaveable` appropriately
8. **Preview Annotations**: Add `@Preview` with different configurations

## Common Issues

- **Recomposition Issues**: Avoid passing unstable lambdas; use `remember`
- **State Loss**: Use `rememberSaveable` for configuration changes
- **Performance**: Use `LazyColumn` instead of `Column` for long lists
- **Theme Leaks**: Ensure `MaterialTheme` wraps all composables
- **Navigation Crashes**: Handle back press and deep links properly
- **Memory Leaks**: Cancel coroutines in `DisposableEffect`

<!-- chapter:end slug=mobile-android-design -->

---

<!-- chapter:begin slug=mobile-ios-design position=176 -->

## 176. mobile-ios-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/mobile-ios-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-ios-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/mobile-ios-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (3), referenced from this skill's directory:
  - `references/hig-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-ios-design/references/hig-patterns.md
  - `references/ios-navigation.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-ios-design/references/ios-navigation.md
  - `references/swiftui-components.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/mobile-ios-design/references/swiftui-components.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: mobile-ios-design
description: Master iOS Human Interface Guidelines and SwiftUI patterns for building native iOS apps. Use when designing iOS interfaces, implementing SwiftUI views, or ensuring apps follow Apple's design principles.
---

# iOS Mobile Design

Master iOS Human Interface Guidelines (HIG) and SwiftUI patterns to build polished, native iOS applications that feel at home on Apple platforms.

## When to Use This Skill

- Designing iOS app interfaces following Apple HIG
- Building SwiftUI views and layouts
- Implementing iOS navigation patterns (NavigationStack, TabView, sheets)
- Creating adaptive layouts for iPhone and iPad
- Using SF Symbols and system typography
- Building accessible iOS interfaces
- Implementing iOS-specific gestures and interactions
- Designing for Dynamic Type and Dark Mode

## Core Concepts

### 1. Human Interface Guidelines Principles

**Clarity**: Content is legible, icons are precise, adornments are subtle
**Deference**: UI helps users understand content without competing with it
**Depth**: Visual layers and motion convey hierarchy and enable navigation

**Platform Considerations:**

- **iOS**: Touch-first, compact displays, portrait orientation
- **iPadOS**: Larger canvas, multitasking, pointer support
- **visionOS**: Spatial computing, eye/hand input

### 2. SwiftUI Layout System

**Stack-Based Layouts:**

```swift
// Vertical stack with alignment
VStack(alignment: .leading, spacing: 12) {
    Text("Title")
        .font(.headline)
    Text("Subtitle")
        .font(.subheadline)
        .foregroundStyle(.secondary)
}

// Horizontal stack with flexible spacing
HStack {
    Image(systemName: "star.fill")
    Text("Featured")
    Spacer()
    Text("View All")
        .foregroundStyle(.blue)
}
```

**Grid Layouts:**

```swift
// Adaptive grid that fills available width
LazyVGrid(columns: [
    GridItem(.adaptive(minimum: 150, maximum: 200))
], spacing: 16) {
    ForEach(items) { item in
        ItemCard(item: item)
    }
}

// Fixed column grid
LazyVGrid(columns: [
    GridItem(.flexible()),
    GridItem(.flexible()),
    GridItem(.flexible())
], spacing: 12) {
    ForEach(items) { item in
        ItemThumbnail(item: item)
    }
}
```

### 3. Navigation Patterns

**NavigationStack (iOS 16+):**

```swift
struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            List(items) { item in
                NavigationLink(value: item) {
                    ItemRow(item: item)
                }
            }
            .navigationTitle("Items")
            .navigationDestination(for: Item.self) { item in
                ItemDetailView(item: item)
            }
        }
    }
}
```

**TabView (iOS 18+):**

```swift
struct MainTabView: View {
    @State private var selectedTab = 0

    var body: some View {
        TabView(selection: $selectedTab) {
            Tab("Home", systemImage: "house", value: 0) {
                HomeView()
            }

            Tab("Search", systemImage: "magnifyingglass", value: 1) {
                SearchView()
            }

            Tab("Profile", systemImage: "person", value: 2) {
                ProfileView()
            }
        }
    }
}
```

### 4. System Integration

**SF Symbols:**

```swift
// Basic symbol
Image(systemName: "heart.fill")
    .foregroundStyle(.red)

// Symbol with rendering mode
Image(systemName: "cloud.sun.fill")
    .symbolRenderingMode(.multicolor)

// Variable symbol (iOS 16+)
Image(systemName: "speaker.wave.3.fill", variableValue: volume)

// Symbol effect (iOS 17+)
Image(systemName: "bell.fill")
    .symbolEffect(.bounce, value: notificationCount)
```

**Dynamic Type:**

```swift
// Use semantic fonts
Text("Headline")
    .font(.headline)

Text("Body text that scales with user preferences")
    .font(.body)

// Custom font that respects Dynamic Type
Text("Custom")
    .font(.custom("Avenir", size: 17, relativeTo: .body))
```

### 5. Visual Design

**Colors and Materials:**

```swift
// Semantic colors that adapt to light/dark mode
Text("Primary")
    .foregroundStyle(.primary)
Text("Secondary")
    .foregroundStyle(.secondary)

// System materials for blur effects
Rectangle()
    .fill(.ultraThinMaterial)
    .frame(height: 100)

// Vibrant materials for overlays
Text("Overlay")
    .padding()
    .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))
```

**Shadows and Depth:**

```swift
// Standard card shadow
RoundedRectangle(cornerRadius: 16)
    .fill(.background)
    .shadow(color: .black.opacity(0.1), radius: 8, y: 4)

// Elevated appearance
.shadow(radius: 2, y: 1)
.shadow(radius: 8, y: 4)
```

## Quick Start Component

```swift
import SwiftUI

struct FeatureCard: View {
    let title: String
    let description: String
    let systemImage: String

    var body: some View {
        HStack(spacing: 16) {
            Image(systemName: systemImage)
                .font(.title)
                .foregroundStyle(.blue)
                .frame(width: 44, height: 44)
                .background(.blue.opacity(0.1), in: Circle())

            VStack(alignment: .leading, spacing: 4) {
                Text(title)
                    .font(.headline)
                Text(description)
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
                    .lineLimit(2)
            }

            Spacer()

            Image(systemName: "chevron.right")
                .foregroundStyle(.tertiary)
        }
        .padding()
        .background(.background, in: RoundedRectangle(cornerRadius: 12))
        .shadow(color: .black.opacity(0.05), radius: 4, y: 2)
    }
}
```

## Best Practices

1. **Use Semantic Colors**: Always use `.primary`, `.secondary`, `.background` for automatic light/dark mode support
2. **Embrace SF Symbols**: Use system symbols for consistency and automatic accessibility
3. **Support Dynamic Type**: Use semantic fonts (`.body`, `.headline`) instead of fixed sizes
4. **Add Accessibility**: Include `.accessibilityLabel()` and `.accessibilityHint()` modifiers
5. **Use Safe Areas**: Respect `safeAreaInset` and avoid hardcoded padding at screen edges
6. **Implement State Restoration**: Use `@SceneStorage` for preserving user state
7. **Support iPad Multitasking**: Design for split view and slide over
8. **Test on Device**: Simulator doesn't capture full haptic and performance experience

## Common Issues

- **Layout Breaking**: Use `.fixedSize()` sparingly; prefer flexible layouts
- **Performance Issues**: Use `LazyVStack`/`LazyHStack` for long scrolling lists
- **Navigation Bugs**: Ensure `NavigationLink` values are `Hashable`
- **Dark Mode Problems**: Avoid hardcoded colors; use semantic or asset catalog colors
- **Accessibility Failures**: Test with VoiceOver enabled
- **Memory Leaks**: Watch for strong reference cycles in closures

<!-- chapter:end slug=mobile-ios-design -->

---

<!-- chapter:begin slug=react-native-design position=177 -->

## 177. react-native-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/react-native-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/react-native-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/react-native-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/react-native-design/references/details.md
  - `references/navigation-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/react-native-design/references/navigation-patterns.md
  - `references/reanimated-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/react-native-design/references/reanimated-patterns.md
  - `references/styling-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/react-native-design/references/styling-patterns.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: react-native-design
description: Master React Native styling, navigation, and Reanimated animations for cross-platform mobile development. Use when building React Native apps, implementing navigation patterns, or creating performant animations.
---

# React Native Design

Master React Native styling patterns, React Navigation, and Reanimated 3 to build performant, cross-platform mobile applications with native-quality user experiences.

## When to Use This Skill

- Building cross-platform mobile apps with React Native
- Implementing navigation with React Navigation 6+
- Creating performant animations with Reanimated 3
- Styling components with StyleSheet and styled-components
- Building responsive layouts for different screen sizes
- Implementing platform-specific designs (iOS/Android)
- Creating gesture-driven interactions with Gesture Handler
- Optimizing React Native performance

## Detailed section: Core Concepts

Originally a 6471-byte section in this SKILL.md. Moved to `references/details.md` to fit Codex's 8 KB skill body cap.

## Quick Start Component

```typescript
import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  Pressable,
  Image,
} from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

interface ItemCardProps {
  title: string;
  subtitle: string;
  imageUrl: string;
  onPress: () => void;
}

const AnimatedPressable = Animated.createAnimatedComponent(Pressable);

export function ItemCard({ title, subtitle, imageUrl, onPress }: ItemCardProps) {
  const scale = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ scale: scale.value }],
  }));

  return (
    <AnimatedPressable
      style={[styles.card, animatedStyle]}
      onPress={onPress}
      onPressIn={() => { scale.value = withSpring(0.97); }}
      onPressOut={() => { scale.value = withSpring(1); }}
    >
      <Image source={{ uri: imageUrl }} style={styles.image} />
      <View style={styles.content}>
        <Text style={styles.title} numberOfLines={1}>
          {title}
        </Text>
        <Text style={styles.subtitle} numberOfLines={2}>
          {subtitle}
        </Text>
      </View>
    </AnimatedPressable>
  );
}

const styles = StyleSheet.create({
  card: {
    backgroundColor: '#ffffff',
    borderRadius: 16,
    overflow: 'hidden',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 8,
    elevation: 4,
  },
  image: {
    width: '100%',
    height: 160,
    backgroundColor: '#f3f4f6',
  },
  content: {
    padding: 16,
    gap: 4,
  },
  title: {
    fontSize: 18,
    fontWeight: '600',
    color: '#1f2937',
  },
  subtitle: {
    fontSize: 14,
    color: '#6b7280',
    lineHeight: 20,
  },
});
```

## Best Practices

1. **Use TypeScript**: Define navigation and prop types for type safety
2. **Memoize Components**: Use `React.memo` and `useCallback` to prevent unnecessary rerenders
3. **Run Animations on UI Thread**: Use Reanimated worklets for 60fps animations
4. **Avoid Inline Styles**: Use StyleSheet.create for performance
5. **Handle Safe Areas**: Use `SafeAreaView` or `useSafeAreaInsets`
6. **Test on Real Devices**: Simulator/emulator performance differs from real devices
7. **Use FlatList for Lists**: Never use ScrollView with map for long lists
8. **Platform-Specific Code**: Use Platform.select for iOS/Android differences

## Common Issues

- **Gesture Conflicts**: Wrap gestures with `GestureDetector` and use `simultaneousHandlers`
- **Navigation Type Errors**: Define `ParamList` types for all navigators
- **Animation Jank**: Move animations to UI thread with `runOnUI` worklets
- **Memory Leaks**: Cancel animations and cleanup in useEffect
- **Font Loading**: Use `expo-font` or `react-native-asset` for custom fonts
- **Safe Area Issues**: Test on notched devices (iPhone, Android with cutouts)

<!-- chapter:end slug=react-native-design -->

---

<!-- chapter:begin slug=responsive-design position=178 -->

## 178. responsive-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/responsive-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/responsive-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/responsive-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (4), referenced from this skill's directory:
  - `references/breakpoint-strategies.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/responsive-design/references/breakpoint-strategies.md
  - `references/container-queries.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/responsive-design/references/container-queries.md
  - `references/details.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/responsive-design/references/details.md
  - `references/fluid-layouts.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/responsive-design/references/fluid-layouts.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: responsive-design
description: Implement modern responsive layouts using container queries, fluid typography, CSS Grid, and mobile-first breakpoint strategies. Use when building adaptive interfaces, implementing fluid layouts, or creating component-level responsive behavior.
---

# Responsive Design

Master modern responsive design techniques to create interfaces that adapt seamlessly across all screen sizes and device contexts.

## When to Use This Skill

- Implementing mobile-first responsive layouts
- Using container queries for component-based responsiveness
- Creating fluid typography and spacing scales
- Building complex layouts with CSS Grid and Flexbox
- Designing breakpoint strategies for design systems
- Implementing responsive images and media
- Creating adaptive navigation patterns
- Building responsive tables and data displays

## Detailed patterns and worked examples

Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

## Best Practices

1. **Mobile-First**: Start with mobile styles, enhance for larger screens
2. **Content Breakpoints**: Set breakpoints based on content, not devices
3. **Fluid Over Fixed**: Use fluid values for typography and spacing
4. **Container Queries**: Use for component-level responsiveness
5. **Test Real Devices**: Simulators don't catch all issues
6. **Performance**: Optimize images, lazy load off-screen content
7. **Touch Targets**: Maintain 44x44px minimum on mobile
8. **Logical Properties**: Use inline/block for internationalization

## Common Issues

- **Horizontal Overflow**: Content breaking out of viewport
- **Fixed Widths**: Using px instead of relative units
- **Viewport Height**: 100vh issues on mobile browsers
- **Font Size**: Text too small on mobile
- **Touch Targets**: Buttons too small to tap accurately
- **Aspect Ratio**: Images squishing or stretching
- **Z-Index Stacking**: Overlays breaking on different screens

<!-- chapter:end slug=responsive-design -->

---

<!-- chapter:begin slug=visual-design-foundations position=179 -->

## 179. visual-design-foundations

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/visual-design-foundations/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/visual-design-foundations/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/visual-design-foundations.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (3), referenced from this skill's directory:
  - `references/color-systems.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/visual-design-foundations/references/color-systems.md
  - `references/spacing-iconography.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/visual-design-foundations/references/spacing-iconography.md
  - `references/typography-systems.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/visual-design-foundations/references/typography-systems.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: visual-design-foundations
description: Apply typography, color theory, spacing systems, and iconography principles to create cohesive visual designs. Use when establishing design tokens, building style guides, or improving visual hierarchy and consistency.
---

# Visual Design Foundations

Build cohesive, accessible visual systems using typography, color, spacing, and iconography fundamentals.

## When to Use This Skill

- Establishing design tokens for a new project
- Creating or refining a spacing and sizing system
- Selecting and pairing typefaces
- Building accessible color palettes
- Designing icon systems and visual assets
- Improving visual hierarchy and readability
- Auditing designs for visual consistency
- Implementing dark mode or theming

## Core Systems

### 1. Typography Scale

**Modular Scale** (ratio-based sizing):

```css
:root {
  --font-size-xs: 0.75rem; /* 12px */
  --font-size-sm: 0.875rem; /* 14px */
  --font-size-base: 1rem; /* 16px */
  --font-size-lg: 1.125rem; /* 18px */
  --font-size-xl: 1.25rem; /* 20px */
  --font-size-2xl: 1.5rem; /* 24px */
  --font-size-3xl: 1.875rem; /* 30px */
  --font-size-4xl: 2.25rem; /* 36px */
  --font-size-5xl: 3rem; /* 48px */
}
```

**Line Height Guidelines**:
| Text Type | Line Height |
|-----------|-------------|
| Headings | 1.1 - 1.3 |
| Body text | 1.5 - 1.7 |
| UI labels | 1.2 - 1.4 |

### 2. Spacing System

**8-point grid** (industry standard):

```css
:root {
  --space-1: 0.25rem; /* 4px */
  --space-2: 0.5rem; /* 8px */
  --space-3: 0.75rem; /* 12px */
  --space-4: 1rem; /* 16px */
  --space-5: 1.25rem; /* 20px */
  --space-6: 1.5rem; /* 24px */
  --space-8: 2rem; /* 32px */
  --space-10: 2.5rem; /* 40px */
  --space-12: 3rem; /* 48px */
  --space-16: 4rem; /* 64px */
}
```

### 3. Color System

**Semantic color tokens**:

```css
:root {
  /* Brand */
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-primary-active: #1e40af;

  /* Semantic */
  --color-success: #16a34a;
  --color-warning: #ca8a04;
  --color-error: #dc2626;
  --color-info: #0891b2;

  /* Neutral */
  --color-gray-50: #f9fafb;
  --color-gray-100: #f3f4f6;
  --color-gray-200: #e5e7eb;
  --color-gray-300: #d1d5db;
  --color-gray-400: #9ca3af;
  --color-gray-500: #6b7280;
  --color-gray-600: #4b5563;
  --color-gray-700: #374151;
  --color-gray-800: #1f2937;
  --color-gray-900: #111827;
}
```

## Quick Start: Design Tokens in Tailwind

```js
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ["Inter", "system-ui", "sans-serif"],
        mono: ["JetBrains Mono", "monospace"],
      },
      fontSize: {
        xs: ["0.75rem", { lineHeight: "1rem" }],
        sm: ["0.875rem", { lineHeight: "1.25rem" }],
        base: ["1rem", { lineHeight: "1.5rem" }],
        lg: ["1.125rem", { lineHeight: "1.75rem" }],
        xl: ["1.25rem", { lineHeight: "1.75rem" }],
        "2xl": ["1.5rem", { lineHeight: "2rem" }],
      },
      colors: {
        brand: {
          50: "#eff6ff",
          500: "#3b82f6",
          600: "#2563eb",
          700: "#1d4ed8",
        },
      },
      spacing: {
        // Extends default with custom values
        18: "4.5rem",
        88: "22rem",
      },
    },
  },
};
```

## Typography Best Practices

### Font Pairing

**Safe combinations**:

- Heading: **Inter** / Body: **Inter** (single family)
- Heading: **Playfair Display** / Body: **Source Sans Pro** (contrast)
- Heading: **Space Grotesk** / Body: **IBM Plex Sans** (geometric)

### Responsive Typography

```css
/* Fluid typography using clamp() */
h1 {
  font-size: clamp(2rem, 5vw + 1rem, 3.5rem);
  line-height: 1.1;
}

p {
  font-size: clamp(1rem, 2vw + 0.5rem, 1.125rem);
  line-height: 1.6;
  max-width: 65ch; /* Optimal reading width */
}
```

### Font Loading

```css
/* Prevent layout shift */
@font-face {
  font-family: "Inter";
  src: url("/fonts/Inter.woff2") format("woff2");
  font-display: swap;
  font-weight: 400 700;
}
```

## Color Theory

### Contrast Requirements (WCAG)

| Element            | Minimum Ratio |
| ------------------ | ------------- |
| Body text          | 4.5:1 (AA)    |
| Large text (18px+) | 3:1 (AA)      |
| UI components      | 3:1 (AA)      |
| Enhanced           | 7:1 (AAA)     |

### Dark Mode Strategy

```css
:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f9fafb;
  --text-primary: #111827;
  --text-secondary: #6b7280;
  --border: #e5e7eb;
}

[data-theme="dark"] {
  --bg-primary: #111827;
  --bg-secondary: #1f2937;
  --text-primary: #f9fafb;
  --text-secondary: #9ca3af;
  --border: #374151;
}
```

### Color Accessibility

```tsx
// Check contrast programmatically
function getContrastRatio(foreground: string, background: string): number {
  const getLuminance = (hex: string) => {
    const rgb = hexToRgb(hex);
    const [r, g, b] = rgb.map((c) => {
      c = c / 255;
      return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
    });
    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
  };

  const l1 = getLuminance(foreground);
  const l2 = getLuminance(background);
  const lighter = Math.max(l1, l2);
  const darker = Math.min(l1, l2);

  return (lighter + 0.05) / (darker + 0.05);
}
```

## Spacing Guidelines

### Component Spacing

```
Card padding:      16-24px (--space-4 to --space-6)
Section gap:       32-64px (--space-8 to --space-16)
Form field gap:    16-24px (--space-4 to --space-6)
Button padding:    8-16px vertical, 16-24px horizontal
Icon-text gap:     8px (--space-2)
```

### Visual Rhythm

```css
/* Consistent vertical rhythm */
.prose > * + * {
  margin-top: var(--space-4);
}

.prose > h2 + * {
  margin-top: var(--space-2);
}

.prose > * + h2 {
  margin-top: var(--space-8);
}
```

## Iconography

### Icon Sizing System

```css
:root {
  --icon-xs: 12px;
  --icon-sm: 16px;
  --icon-md: 20px;
  --icon-lg: 24px;
  --icon-xl: 32px;
}
```

### Icon Component

```tsx
interface IconProps {
  name: string;
  size?: "xs" | "sm" | "md" | "lg" | "xl";
  className?: string;
}

const sizeMap = {
  xs: 12,
  sm: 16,
  md: 20,
  lg: 24,
  xl: 32,
};

export function Icon({ name, size = "md", className }: IconProps) {
  return (
    <svg
      width={sizeMap[size]}
      height={sizeMap[size]}
      className={cn("inline-block flex-shrink-0", className)}
      aria-hidden="true"
    >
      <use href={`/icons.svg#${name}`} />
    </svg>
  );
}
```

## Best Practices

1. **Establish Constraints**: Limit choices to maintain consistency
2. **Document Decisions**: Create a living style guide
3. **Test Accessibility**: Verify contrast, sizing, touch targets
4. **Use Semantic Tokens**: Name by purpose, not appearance
5. **Design Mobile-First**: Start with constraints, add complexity
6. **Maintain Vertical Rhythm**: Consistent spacing creates harmony
7. **Limit Font Weights**: 2-3 weights per family is sufficient

## Common Issues

- **Inconsistent Spacing**: Not using a defined scale
- **Poor Contrast**: Failing WCAG requirements
- **Font Overload**: Too many families or weights
- **Magic Numbers**: Arbitrary values instead of tokens
- **Missing States**: Forgetting hover, focus, disabled
- **No Dark Mode Plan**: Retrofitting is harder than planning

<!-- chapter:end slug=visual-design-foundations -->

---

<!-- chapter:begin slug=web-component-design position=180 -->

## 180. web-component-design

- **Source:** https://github.com/wshobson/agents/blob/main/plugins/ui-design/skills/web-component-design/SKILL.md
- **Raw:** https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/web-component-design/SKILL.md
- **Markdown:** https://skillsdocs.com/wshobson/agents/web-component-design.md
- **Licence:** MIT — https://spdx.org/licenses/MIT.html

Bundled files (3), referenced from this skill's directory:
  - `references/accessibility-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/web-component-design/references/accessibility-patterns.md
  - `references/component-patterns.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/web-component-design/references/component-patterns.md
  - `references/css-styling-approaches.md` — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/web-component-design/references/css-styling-approaches.md

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: web-component-design
description: Master React, Vue, and Svelte component patterns including CSS-in-JS, composition strategies, and reusable component architecture. Use when building UI component libraries, designing component APIs, or implementing frontend design systems.
---

# Web Component Design

Build reusable, maintainable UI components using modern frameworks with clean composition patterns and styling approaches.

## When to Use This Skill

- Designing reusable component libraries or design systems
- Implementing complex component composition patterns
- Choosing and applying CSS-in-JS solutions
- Building accessible, responsive UI components
- Creating consistent component APIs across a codebase
- Refactoring legacy components into modern patterns
- Implementing compound components or render props

## Core Concepts

### 1. Component Composition Patterns

**Compound Components**: Related components that work together

```tsx
// Usage
<Select value={value} onChange={setValue}>
  <Select.Trigger>Choose option</Select.Trigger>
  <Select.Options>
    <Select.Option value="a">Option A</Select.Option>
    <Select.Option value="b">Option B</Select.Option>
  </Select.Options>
</Select>
```

**Render Props**: Delegate rendering to parent

```tsx
<DataFetcher url="/api/users">
  {({ data, loading, error }) =>
    loading ? <Spinner /> : <UserList users={data} />
  }
</DataFetcher>
```

**Slots (Vue/Svelte)**: Named content injection points

```vue
<template>
  <Card>
    <template #header>Title</template>
    <template #content>Body text</template>
    <template #footer><Button>Action</Button></template>
  </Card>
</template>
```

### 2. CSS-in-JS Approaches

| Solution              | Approach               | Best For                          |
| --------------------- | ---------------------- | --------------------------------- |
| **Tailwind CSS**      | Utility classes        | Rapid prototyping, design systems |
| **CSS Modules**       | Scoped CSS files       | Existing CSS, gradual adoption    |
| **styled-components** | Template literals      | React, dynamic styling            |
| **Emotion**           | Object/template styles | Flexible, SSR-friendly            |
| **Vanilla Extract**   | Zero-runtime           | Performance-critical apps         |

### 3. Component API Design

```tsx
interface ButtonProps {
  variant?: "primary" | "secondary" | "ghost";
  size?: "sm" | "md" | "lg";
  isLoading?: boolean;
  isDisabled?: boolean;
  leftIcon?: React.ReactNode;
  rightIcon?: React.ReactNode;
  children: React.ReactNode;
  onClick?: () => void;
}
```

**Principles**:

- Use semantic prop names (`isLoading` vs `loading`)
- Provide sensible defaults
- Support composition via `children`
- Allow style overrides via `className` or `style`

## Quick Start: React Component with Tailwind

```tsx
import { forwardRef, type ComponentPropsWithoutRef } from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50",
  {
    variants: {
      variant: {
        primary: "bg-blue-600 text-white hover:bg-blue-700",
        secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
        ghost: "hover:bg-gray-100 hover:text-gray-900",
      },
      size: {
        sm: "h-8 px-3 text-sm",
        md: "h-10 px-4 text-sm",
        lg: "h-12 px-6 text-base",
      },
    },
    defaultVariants: {
      variant: "primary",
      size: "md",
    },
  },
);

interface ButtonProps
  extends
    ComponentPropsWithoutRef<"button">,
    VariantProps<typeof buttonVariants> {
  isLoading?: boolean;
}

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, isLoading, children, ...props }, ref) => (
    <button
      ref={ref}
      className={cn(buttonVariants({ variant, size }), className)}
      disabled={isLoading || props.disabled}
      {...props}
    >
      {isLoading && <Spinner className="mr-2 h-4 w-4" />}
      {children}
    </button>
  ),
);
Button.displayName = "Button";
```

## Framework Patterns

### React: Compound Components

```tsx
import { createContext, useContext, useState, type ReactNode } from "react";

interface AccordionContextValue {
  openItems: Set<string>;
  toggle: (id: string) => void;
}

const AccordionContext = createContext<AccordionContextValue | null>(null);

function useAccordion() {
  const context = useContext(AccordionContext);
  if (!context) throw new Error("Must be used within Accordion");
  return context;
}

export function Accordion({ children }: { children: ReactNode }) {
  const [openItems, setOpenItems] = useState<Set<string>>(new Set());

  const toggle = (id: string) => {
    setOpenItems((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };

  return (
    <AccordionContext.Provider value={{ openItems, toggle }}>
      <div className="divide-y">{children}</div>
    </AccordionContext.Provider>
  );
}

Accordion.Item = function AccordionItem({
  id,
  title,
  children,
}: {
  id: string;
  title: string;
  children: ReactNode;
}) {
  const { openItems, toggle } = useAccordion();
  const isOpen = openItems.has(id);

  return (
    <div>
      <button onClick={() => toggle(id)} className="w-full text-left py-3">
        {title}
      </button>
      {isOpen && <div className="pb-3">{children}</div>}
    </div>
  );
};
```

### Vue 3: Composables

```vue
<script setup lang="ts">
import { ref, computed, provide, inject, type InjectionKey } from "vue";

interface TabsContext {
  activeTab: Ref<string>;
  setActive: (id: string) => void;
}

const TabsKey: InjectionKey<TabsContext> = Symbol("tabs");

// Parent component
const activeTab = ref("tab-1");
provide(TabsKey, {
  activeTab,
  setActive: (id: string) => {
    activeTab.value = id;
  },
});

// Child component usage
const tabs = inject(TabsKey);
const isActive = computed(() => tabs?.activeTab.value === props.id);
</script>
```

### Svelte 5: Runes

```svelte
<script lang="ts">
  interface Props {
    variant?: 'primary' | 'secondary';
    size?: 'sm' | 'md' | 'lg';
    onclick?: () => void;
    children: import('svelte').Snippet;
  }

  let { variant = 'primary', size = 'md', onclick, children }: Props = $props();

  const classes = $derived(
    `btn btn-${variant} btn-${size}`
  );
</script>

<button class={classes} {onclick}>
  {@render children()}
</button>
```

## Best Practices

1. **Single Responsibility**: Each component does one thing well
2. **Prop Drilling Prevention**: Use context for deeply nested data
3. **Accessible by Default**: Include ARIA attributes, keyboard support
4. **Controlled vs Uncontrolled**: Support both patterns when appropriate
5. **Forward Refs**: Allow parent access to DOM nodes
6. **Memoization**: Use `React.memo`, `useMemo` for expensive renders
7. **Error Boundaries**: Wrap components that may fail

## Common Issues

- **Prop Explosion**: Too many props - consider composition instead
- **Style Conflicts**: Use scoped styles or CSS Modules
- **Re-render Cascades**: Profile with React DevTools, memo appropriately
- **Accessibility Gaps**: Test with screen readers and keyboard navigation
- **Bundle Size**: Tree-shake unused component variants

<!-- chapter:end slug=web-component-design -->
