diff --git a/README.md b/README.md index c595b2d..5b0c021 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,137 @@ # LibreFang Registry -Community-maintained content registry for [LibreFang](https://github.com/librefang/librefang) -- the open-source Agent Operating System. +Community-maintained content registry for [LibreFang](https://github.com/librefang/librefang) — the open-source Agent Operating System. -This repository is the single source of truth for all installable content definitions. Anyone can submit a PR to add new agents, hands, integrations, skills, or provider models -- no changes to the LibreFang binary required. +This repository is the **single source of truth** for all installable content definitions. Anyone can submit a PR to add new agents, hands, integrations, skills, or provider models — no changes to the LibreFang binary required. -## Structure +## Overview + +| Type | Count | Description | +|------|------:|-------------| +| [Hands](#hands) | 14 | User-facing "apps" — agent + tools + settings + dashboard | +| [Agents](#agents) | 32 | Autonomous agent definitions with model config and tools | +| [Integrations](#integrations) | 25 | MCP server connections (GitHub, Slack, DBs, etc.) | +| [Providers](#providers) | 48 | LLM provider & model metadata with pricing | +| [Models](#providers) | 223 | Individual model definitions across all providers | +| [Aliases](#aliases) | 70 | Short names mapped to canonical model IDs | +| [Plugins](#plugins) | 10 | Memory, guardrails, and conversation plugins | +| [Skills](#skills) | 2 | Reusable prompt templates and Python scripts | + +## Repository Structure ``` librefang-registry/ -├── agents/ # Agent definitions (TOML manifests) -│ ├── hello-world/agent.toml -│ ├── researcher/agent.toml -│ └── ... (33 agents) -├── hands/ # Hand definitions (TOML + docs) -│ ├── browser/HAND.toml -│ ├── trader/HAND.toml -│ └── ... (14 hands) -├── integrations/ # MCP server integration templates +├── agents/ # Agent definitions (TOML manifests) +│ ├── hello-world/ +│ │ └── agent.toml +│ ├── researcher/ +│ │ └── agent.toml +│ └── ... (32 agents) +├── hands/ # Hand definitions (app bundles) +│ ├── browser/ +│ │ ├── HAND.toml # Metadata, tools, settings, i18n (6 languages) +│ │ └── SKILL.md # Domain expert knowledge injected at runtime +│ ├── trader/ +│ │ ├── HAND.toml +│ │ └── SKILL.md +│ └── ... (14 hands) +├── integrations/ # MCP server integration templates │ ├── github.toml │ ├── slack.toml -│ └── ... (25 integrations) -├── skills/ # Reusable skill definitions -│ ├── custom-skill-prompt/skill.toml -│ └── custom-skill-python/ -├── providers/ # LLM provider & model metadata +│ └── ... (25 integrations) +├── providers/ # LLM provider & model metadata │ ├── anthropic.toml │ ├── openai.toml -│ └── ... (46 providers, 190+ models) -├── plugins/ # Plugin packages (10 plugins) -├── aliases.toml # Global model alias mappings -├── schema.toml # Provider/model schema reference +│ └── ... (48 providers, 223 models) +├── plugins/ # Memory, guardrails, and utility plugins +│ ├── episodic-memory/ +│ ├── guardrails/ +│ └── ... (10 plugins) +├── skills/ # Reusable skill definitions +│ ├── custom-skill-prompt/skill.toml +│ └── custom-skill-python/ +├── aliases.toml # Global model alias mappings (70 aliases) +├── schema.toml # Provider/model schema reference ├── scripts/ -│ └── validate.py # Validation script +│ └── validate.py # Content validation script ├── CONTRIBUTING.md -└── LICENSE # MIT +└── LICENSE # MIT ``` ## Content Types +### Hands + +Hands are the **user-facing "apps"** in LibreFang. Each hand bundles an agent, tools, user-configurable settings, dashboard metrics, dependency checks, and i18n translations into a single deployable unit. + +Every hand includes a `SKILL.md` — domain-specific expert knowledge that is injected into the agent's context at runtime, giving it deep expertise in its domain. + +| Icon | Hand | Category | Description | +|:----:|------|----------|-------------| +| 📈 | analytics | data | Data collection, analysis, visualization, dashboards, and automated reporting | +| 🔌 | apitester | development | Endpoint discovery, request validation, load testing, and regression detection | +| 🌐 | browser | productivity | Web navigation, form filling, and multi-step web tasks with user approval | +| 🎬 | clip | content | Turns long-form video into viral short clips with captions and thumbnails | +| 🔍 | collector | data | Intelligence collection, change detection, and knowledge graphs | +| 👷 | devops | development | CI/CD management, infrastructure monitoring, deployment, and incident response | +| 📊 | lead | data | Lead generation, enrichment, scoring, and scheduled delivery | +| 💼 | linkedin | communication | Profile optimization, content creation, networking, and engagement | +| 🔮 | predictor | data | Signal collection, calibrated predictions, and accuracy tracking | +| 📢 | reddit | communication | Subreddit monitoring, content posting, and engagement tracking | +| 🧪 | researcher | productivity | Deep research, cross-referencing, fact-checking, and structured reports | +| 🎯 | strategist | productivity | Market research, competitive analysis, and strategic planning | +| 📈 | trader | data | Multi-signal analysis, adversarial reasoning, and risk management | +| 𝕏 | twitter | communication | Content creation, scheduled posting, engagement, and analytics | + +**HAND.toml format:** + +```toml +id = "browser" +name = "Browser Hand" +description = "Autonomous web browser" +category = "productivity" +icon = "🌐" +tools = ["browser_navigate", "browser_click", "browser_type"] + +[routing] +aliases = ["browse", "open website"] +weak_aliases = ["web", "url"] + +[[requires]] +key = "chromium" +requirement_type = "binary" +check_value = "chromium" + +[[settings]] +key = "headless" +setting_type = "toggle" +default = "true" + +[agent] +name = "browser-hand" +module = "builtin:chat" +system_prompt = """You are an autonomous web browser agent...""" + +[dashboard] +[[dashboard.metrics]] +label = "Pages Visited" +memory_key = "pages_visited" +format = "number" + +# i18n — 6 languages supported: zh, ja, ko, es, fr, de +[i18n.zh] +name = "浏览器 Hand" +description = "自主网页浏览器" +category = "生产力" + +[i18n.zh.settings.headless] +label = "无头模式" +description = "在后台运行浏览器" +``` + ### Agents -Agent definitions in `agents//agent.toml` describe autonomous agents with their model config, tools, capabilities, and routing aliases. +Agent definitions describe autonomous agents with model configuration, tools, capabilities, and routing aliases. ```toml name = "hello-world" @@ -56,30 +147,11 @@ system_prompt = "You are a helpful assistant." tools = ["web_search", "file_read"] ``` -### Hands - -Hands in `hands//HAND.toml` are higher-level application bundles -- the user-facing "apps" in LibreFang. Each hand bundles an agent config, tools, settings, dashboard metrics, and dependency requirements. - -```toml -id = "browser" -name = "Browser Hand" -category = "productivity" -tools = ["browser_navigate", "browser_click", "browser_type"] - -[agent] -name = "browser-hand" -module = "builtin:chat" -system_prompt = "You are an autonomous web browser agent..." - -[[settings]] -key = "headless" -setting_type = "toggle" -default = "true" -``` +**32 built-in agents:** academic-researcher, analyst, architect, assistant, code-reviewer, coder, customer-support, data-scientist, debugger, devops-lead, doc-writer, email-assistant, health-tracker, hello-world, home-automation, legal-assistant, meeting-assistant, ops, orchestrator, personal-finance, planner, recipe-assistant, recruiter, researcher, sales-assistant, security-auditor, social-media, test-engineer, translator, travel-planner, tutor, writer ### Integrations -Integration templates in `integrations/.toml` define MCP server connections (GitHub, Slack, databases, etc.) with transport config, required env vars, and setup instructions. +Integration templates define [MCP](https://modelcontextprotocol.io/) server connections with transport configuration, required environment variables, and setup instructions. ```toml id = "github" @@ -96,9 +168,47 @@ name = "GITHUB_PERSONAL_ACCESS_TOKEN" is_secret = true ``` +**25 integrations across 6 categories:** + +| Category | Integrations | +|----------|-------------| +| DevTools | bitbucket, github, gitlab, jira, linear, sentry | +| Data | elasticsearch, mongodb, postgresql, redis, sqlite | +| Productivity | dropbox, gmail, google-calendar, google-drive, notion, todoist | +| Communication | discord, slack, teams | +| Cloud | aws, azure, gcp | +| AI Search | brave-search, exa-search | + +### Providers + +Provider files define LLM providers and their models with pricing, context windows, and capability flags. See [schema.toml](schema.toml) for the full field reference. + +**48 providers** including: Anthropic, OpenAI, Google Gemini, DeepSeek, Groq, Mistral, Cohere, xAI, Together, Fireworks, Ollama (local), LM Studio (local), vLLM (self-hosted), and many more. + +**223 models** with metadata for each: pricing (input/output per token), context window size, capability flags (vision, function calling, streaming), and tier classification. + +### Aliases + +Global model alias mappings in [aliases.toml](aliases.toml) let users reference models by short names: + +```toml +"sonnet" = "claude-sonnet-4-6" +"gpt4" = "gpt-4o" +"flash" = "gemini-2.5-flash" +"deepseek" = "deepseek-chat" +``` + +Models can also define aliases directly in their provider TOML files, which are auto-registered at load time. + +### Plugins + +Plugins extend agent capabilities with memory systems, safety guardrails, and conversation utilities. + +**10 plugins:** auto-summarizer, context-decay, conversation-logger, episodic-memory, guardrails, keyword-memory, sentiment-tracker, todo-tracker, topic-memory, user-profile + ### Skills -Skills in `skills//skill.toml` are reusable prompt templates or Python scripts that agents can invoke. +Reusable prompt templates or Python scripts that agents can invoke. ```toml [skill] @@ -112,13 +222,9 @@ type = "promptonly" template = "Create a meeting agenda for: {{topic}}" ``` -### Providers +## Usage -Provider files in `providers/.toml` define LLM providers and their models with pricing, context windows, and capability flags. See [schema.toml](schema.toml) for the full field reference. - -## How LibreFang Uses This Registry - -LibreFang ships with built-in content compiled into the binary. This repository serves as the upstream source for updates and community contributions. +### Install from Registry ```bash # Update all registry content @@ -133,15 +239,15 @@ librefang integration install github ### Custom Local Content -You can also create custom content locally without submitting a PR: +Create custom content locally without submitting to this registry: ```bash -# Create a custom agent +# Custom agent mkdir -p ~/.librefang/agents/my-agent # Edit ~/.librefang/agents/my-agent/agent.toml -# Add custom models to your config -# ~/.librefang/model_catalog.toml +# Custom model aliases +# Add to ~/.librefang/model_catalog.toml ``` ## Validation @@ -150,9 +256,9 @@ mkdir -p ~/.librefang/agents/my-agent python scripts/validate.py ``` -This validates all provider TOML files for correctness: required fields, valid tiers, non-negative costs, no duplicate IDs. +Validates all content files for correctness: required fields, valid types, non-negative costs, no duplicate IDs. -## How to Contribute +## Contributing 1. Fork this repository 2. Add or edit content in the appropriate directory @@ -161,19 +267,6 @@ This validates all provider TOML files for correctness: required fields, valid t See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed instructions for each content type. -## Current Stats - -| Type | Count | -|------|-------| -| Agents | 33 | -| Hands | 14 | -| Integrations | 25 | -| Skills | 2 | -| Plugins | 10 | -| Providers | 46 | -| Models | 220+ | -| Aliases | 80+ | - ## License MIT License. See [LICENSE](LICENSE). diff --git a/hands/README.md b/hands/README.md index 8802579..6ca99e0 100644 --- a/hands/README.md +++ b/hands/README.md @@ -10,7 +10,7 @@ Hand definitions for LibreFang. Hands are the user-facing "apps" -- higher-level hands/ ├── browser/ │ ├── HAND.toml # Hand definition -│ └── SKILL.md # Documentation +│ └── SKILL.md # Expert knowledge for the agent ├── trader/ │ ├── HAND.toml │ └── SKILL.md @@ -47,6 +47,17 @@ name = "hand-agent" module = "builtin:chat" system_prompt = """...""" +# Optional: i18n for name, description, category, and settings +# Supported languages: zh, ja, ko, es, fr, de +[i18n.zh] +name = "浏览器 Hand" +description = "自主网页浏览器" +category = "生产力" + +[i18n.zh.settings.headless] # Per-setting label/description translation +label = "无头模式" +description = "在后台运行浏览器" + [dashboard] # Dashboard metrics [[dashboard.metrics]] label = "Tasks Completed" @@ -58,15 +69,24 @@ format = "number" | Hand | Category | Description | |------|----------|-------------| -| browser | productivity | Autonomous web browser | -| trader | data | Crypto/stock trading assistant | -| researcher | productivity | Deep research automation | -| analytics | data | Data analysis and dashboards | -| ... | | See each directory for details | +| analytics | data | Data analytics, visualization, dashboards, and automated reporting | +| apitester | development | API testing, endpoint discovery, load testing, and regression detection | +| browser | productivity | Web navigation, form filling, and multi-step web tasks | +| clip | content | Turns long-form video into short clips with captions and thumbnails | +| collector | data | Intelligence collection, change detection, and knowledge graphs | +| devops | development | CI/CD management, infrastructure monitoring, and incident response | +| lead | data | Lead generation, enrichment, scoring, and scheduled delivery | +| linkedin | communication | LinkedIn content creation, networking, and engagement | +| predictor | data | Signal collection, calibrated predictions, and accuracy tracking | +| reddit | communication | Subreddit monitoring, content posting, and engagement tracking | +| researcher | productivity | Deep research, cross-referencing, fact-checking, and reports | +| strategist | productivity | Market research, competitive analysis, and strategic planning | +| trader | data | Market intelligence, multi-signal analysis, and risk management | +| twitter | communication | Twitter/X content creation, scheduling, and performance tracking | ## Adding a New Hand -1. Create `hands//HAND.toml` (and optionally `SKILL.md`) +1. Create `hands//HAND.toml` and `SKILL.md` (expert knowledge for the agent) 2. Ensure `id` matches the directory name 3. Run `python scripts/validate.py` 4. Submit a PR diff --git a/hands/analytics/HAND.toml b/hands/analytics/HAND.toml index 1d35f06..169c41e 100644 --- a/hands/analytics/HAND.toml +++ b/hands/analytics/HAND.toml @@ -484,6 +484,217 @@ token_consumption = "high" default_active = true # Note: High consumption when actively analyzing data, lower when idle +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "数据分析 Hand" description = "自主数据分析智能体——数据采集、分析、可视化、仪表盘和自动化报告" +category = "数据" + +[i18n.zh.settings.data_source] +label = "数据源" +description = "主要数据源类型" + +[i18n.zh.settings.analysis_type] +label = "分析类型" +description = "默认分析方法" + +[i18n.zh.settings.output_format] +label = "输出格式" +description = "分析结果的呈现方式" + +[i18n.zh.settings.visualization] +label = "可视化" +description = "生成图表和可视化内容" + +[i18n.zh.settings.auto_schedule] +label = "定时报告" +description = "按计划自动生成报告" + +[i18n.zh.settings.report_frequency] +label = "报告频率" +description = "定时报告的生成频率" + +[i18n.zh.settings.confidence_threshold] +label = "置信度阈值" +description = "报告中纳入分析结论的最低置信度要求" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "データ分析 Hand" +description = "自律型データ分析エージェント——データ収集、分析、可視化、ダッシュボード、自動レポート生成" +category = "データ" + +[i18n.ja.settings.data_source] +label = "データソース" +description = "主要なデータソースの種類" + +[i18n.ja.settings.analysis_type] +label = "分析タイプ" +description = "デフォルトの分析アプローチ" + +[i18n.ja.settings.output_format] +label = "出力形式" +description = "分析結果の表示方法" + +[i18n.ja.settings.visualization] +label = "可視化" +description = "チャートやビジュアライゼーションを生成する" + +[i18n.ja.settings.auto_schedule] +label = "定期レポート" +description = "スケジュールに基づいてレポートを自動生成する" + +[i18n.ja.settings.report_frequency] +label = "レポート頻度" +description = "定期レポートの生成頻度" + +[i18n.ja.settings.confidence_threshold] +label = "信頼度しきい値" +description = "レポートに分析結果を含めるための最低信頼度" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Analítica" +description = "Agente autónomo de analítica de datos — recopilación, análisis, visualización, paneles de control e informes automatizados" +category = "Datos" + +[i18n.es.settings.data_source] +label = "Fuente de datos" +description = "Tipo de fuente de datos principal" + +[i18n.es.settings.analysis_type] +label = "Tipo de análisis" +description = "Enfoque de análisis predeterminado" + +[i18n.es.settings.output_format] +label = "Formato de salida" +description = "Cómo presentar los resultados del análisis" + +[i18n.es.settings.visualization] +label = "Visualización" +description = "Generar gráficos y visualizaciones" + +[i18n.es.settings.auto_schedule] +label = "Informes programados" +description = "Generar informes automáticamente según un calendario" + +[i18n.es.settings.report_frequency] +label = "Frecuencia de informes" +description = "Con qué frecuencia generar los informes programados" + +[i18n.es.settings.confidence_threshold] +label = "Umbral de confianza" +description = "Nivel mínimo de confianza para incluir hallazgos en los informes" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Analytique" +description = "Agent autonome d'analyse de données — collecte, analyse, visualisation, tableaux de bord et rapports automatisés" +category = "Données" + +[i18n.fr.settings.data_source] +label = "Source de données" +description = "Type de source de données principal" + +[i18n.fr.settings.analysis_type] +label = "Type d'analyse" +description = "Approche d'analyse par défaut" + +[i18n.fr.settings.output_format] +label = "Format de sortie" +description = "Mode de présentation des résultats d'analyse" + +[i18n.fr.settings.visualization] +label = "Visualisation" +description = "Générer des graphiques et des visualisations" + +[i18n.fr.settings.auto_schedule] +label = "Rapports programmés" +description = "Générer automatiquement des rapports selon un calendrier" + +[i18n.fr.settings.report_frequency] +label = "Fréquence des rapports" +description = "Fréquence de génération des rapports programmés" + +[i18n.fr.settings.confidence_threshold] +label = "Seuil de confiance" +description = "Niveau de confiance minimum pour inclure les résultats dans les rapports" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Analytik-Hand" +description = "Autonomer Datenanalyse-Agent — Datenerfassung, Analyse, Visualisierung, Dashboards und automatisierte Berichte" +category = "Daten" + +[i18n.de.settings.data_source] +label = "Datenquelle" +description = "Primärer Datenquellentyp" + +[i18n.de.settings.analysis_type] +label = "Analysetyp" +description = "Standard-Analyseansatz" + +[i18n.de.settings.output_format] +label = "Ausgabeformat" +description = "Darstellung der Analyseergebnisse" + +[i18n.de.settings.visualization] +label = "Visualisierung" +description = "Diagramme und Visualisierungen generieren" + +[i18n.de.settings.auto_schedule] +label = "Geplante Berichte" +description = "Berichte automatisch nach Zeitplan generieren" + +[i18n.de.settings.report_frequency] +label = "Berichtshäufigkeit" +description = "Häufigkeit der geplanten Berichtserstellung" + +[i18n.de.settings.confidence_threshold] +label = "Konfidenzschwelle" +description = "Mindest-Konfidenzniveau für die Aufnahme von Ergebnissen in Berichte" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "데이터 분석 Hand" +description = "자율 데이터 분석 에이전트 — 데이터 수집, 분석, 시각화, 대시보드 및 자동화 보고서" +category = "데이터" + +[i18n.ko.settings.data_source] +label = "데이터 소스" +description = "주요 데이터 소스 유형" + +[i18n.ko.settings.analysis_type] +label = "분석 유형" +description = "기본 분석 방법" + +[i18n.ko.settings.output_format] +label = "출력 형식" +description = "분석 결과 표시 방식" + +[i18n.ko.settings.visualization] +label = "시각화" +description = "차트 및 시각화 콘텐츠 생성" + +[i18n.ko.settings.auto_schedule] +label = "정기 보고서" +description = "일정에 따라 자동으로 보고서 생성" + +[i18n.ko.settings.report_frequency] +label = "보고서 빈도" +description = "정기 보고서 생성 주기" + +[i18n.ko.settings.confidence_threshold] +label = "신뢰도 임계값" +description = "보고서에 분석 결과를 포함하기 위한 최소 신뢰도 수준" diff --git a/hands/analytics/SKILL.md b/hands/analytics/SKILL.md index 16a404d..264b35f 100644 --- a/hands/analytics/SKILL.md +++ b/hands/analytics/SKILL.md @@ -337,3 +337,702 @@ Level 4: What to do (prescriptive) | Timeliness | Current | Data refreshed daily | | Uniqueness | 99% | 1% duplicate records found | ``` + +--- + +## Worked Examples + +### Example 1: E-commerce Sales Analysis + +**Goal**: Analyze 12 months of order data to identify revenue drivers, customer segments, and growth trends. + +#### Step 1 — Load and clean +```python +import pandas as pd +import numpy as np + +df = pd.read_csv('orders.csv', parse_dates=['order_date']) + +# Quick audit +print(f"Rows: {len(df):,} Columns: {df.shape[1]}") +print(df.isnull().sum()[df.isnull().sum() > 0]) + +# Clean +df = df.dropna(subset=['customer_id', 'order_total']) +df['order_total'] = df['order_total'].clip(lower=0) # Remove negative values +df['order_month'] = df['order_date'].dt.to_period('M') +``` + +#### Step 2 — Revenue trend analysis +```python +monthly = ( + df.groupby('order_month') + .agg(revenue=('order_total', 'sum'), + orders=('order_id', 'nunique'), + customers=('customer_id', 'nunique')) + .reset_index() +) +monthly['aov'] = monthly['revenue'] / monthly['orders'] # Average order value +monthly['revenue_mom'] = monthly['revenue'].pct_change() # Month-over-month growth + +fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True) +axes[0].bar(monthly['order_month'].astype(str), monthly['revenue'], color='steelblue') +axes[0].set_title('Monthly Revenue', fontsize=14, fontweight='bold') +axes[0].set_ylabel('Revenue ($)') + +axes[1].plot(monthly['order_month'].astype(str), monthly['aov'], marker='o', color='coral') +axes[1].set_title('Average Order Value', fontsize=14, fontweight='bold') +axes[1].set_ylabel('AOV ($)') +plt.xticks(rotation=45, ha='right') +plt.tight_layout() +plt.savefig('revenue_trend.png', dpi=150, bbox_inches='tight') +plt.close() +``` + +#### Step 3 — Customer segmentation (RFM) +```python +snapshot_date = df['order_date'].max() + pd.Timedelta(days=1) + +rfm = df.groupby('customer_id').agg( + recency=('order_date', lambda x: (snapshot_date - x.max()).days), + frequency=('order_id', 'nunique'), + monetary=('order_total', 'sum') +) + +# Score each dimension 1-4 using quartiles +for col in ['recency', 'frequency', 'monetary']: + labels = [4, 3, 2, 1] if col == 'recency' else [1, 2, 3, 4] + rfm[f'{col}_score'] = pd.qcut(rfm[col], q=4, labels=labels, duplicates='drop') + +rfm['rfm_score'] = (rfm['recency_score'].astype(int) + + rfm['frequency_score'].astype(int) + + rfm['monetary_score'].astype(int)) + +# Segment mapping +def segment(row): + r, f, m = int(row['recency_score']), int(row['frequency_score']), int(row['monetary_score']) + if r >= 3 and f >= 3: + return 'Champions' + elif r >= 3 and f < 3: + return 'New / Promising' + elif r < 3 and f >= 3: + return 'At Risk' + else: + return 'Needs Attention' + +rfm['segment'] = rfm.apply(segment, axis=1) +print(rfm.groupby('segment').agg( + count=('monetary', 'size'), + avg_revenue=('monetary', 'mean'), + avg_frequency=('frequency', 'mean') +).sort_values('avg_revenue', ascending=False)) +``` + +#### Step 4 — Cohort retention analysis +```python +df['cohort'] = df.groupby('customer_id')['order_date'].transform('min').dt.to_period('M') +df['order_period'] = df['order_date'].dt.to_period('M') +df['cohort_index'] = (df['order_period'] - df['cohort']).apply(lambda x: x.n) + +cohort_table = ( + df.groupby(['cohort', 'cohort_index'])['customer_id'] + .nunique() + .reset_index() + .pivot(index='cohort', columns='cohort_index', values='customer_id') +) + +# Convert to retention percentages +retention = cohort_table.div(cohort_table[0], axis=0) * 100 + +fig, ax = plt.subplots(figsize=(14, 8)) +sns.heatmap(retention, annot=True, fmt='.0f', cmap='YlOrRd_r', ax=ax) +ax.set_title('Cohort Retention (% of original customers)', fontsize=14, fontweight='bold') +ax.set_xlabel('Months Since First Purchase') +ax.set_ylabel('Cohort') +plt.tight_layout() +plt.savefig('cohort_retention.png', dpi=150, bbox_inches='tight') +plt.close() +``` + +--- + +### Example 2: A/B Test Analysis + +**Goal**: Evaluate whether a new checkout flow (variant B) improves conversion rate over the existing flow (variant A). + +#### Step 1 — Sample size calculation (pre-test) +```python +from scipy import stats +import numpy as np + +baseline_rate = 0.12 # Current conversion rate: 12% +mde = 0.02 # Minimum detectable effect: 2 percentage points +alpha = 0.05 # Significance level +power = 0.80 # Statistical power + +# Using the normal approximation formula +p1 = baseline_rate +p2 = baseline_rate + mde +p_avg = (p1 + p2) / 2 + +z_alpha = stats.norm.ppf(1 - alpha / 2) # Two-tailed +z_beta = stats.norm.ppf(power) + +n_per_group = ((z_alpha * np.sqrt(2 * p_avg * (1 - p_avg)) + + z_beta * np.sqrt(p1 * (1 - p1) + p2 * (1 - p2))) ** 2 + / (p2 - p1) ** 2) + +print(f"Required sample size per group: {int(np.ceil(n_per_group)):,}") +print(f"Total required: {int(np.ceil(n_per_group)) * 2:,}") +``` + +#### Step 2 — Run the test and collect results +```python +ab = pd.read_csv('ab_test_results.csv') + +summary = ab.groupby('variant').agg( + visitors=('user_id', 'nunique'), + conversions=('converted', 'sum') +) +summary['conversion_rate'] = summary['conversions'] / summary['visitors'] +print(summary) +``` + +#### Step 3 — Statistical significance +```python +a = ab[ab['variant'] == 'A'] +b = ab[ab['variant'] == 'B'] + +# Chi-squared test for proportions +contingency = pd.crosstab(ab['variant'], ab['converted']) +chi2, p_value, dof, expected = stats.chi2_contingency(contingency) + +# Proportions z-test (more direct) +from statsmodels.stats.proportion import proportions_ztest +successes = [summary.loc['B', 'conversions'], summary.loc['A', 'conversions']] +trials = [summary.loc['B', 'visitors'], summary.loc['A', 'visitors']] +z_stat, p_val = proportions_ztest(successes, trials, alternative='larger') + +print(f"Z-statistic: {z_stat:.4f}") +print(f"P-value: {p_val:.4f}") +print(f"Significant: {'Yes' if p_val < 0.05 else 'No'} (at alpha=0.05)") +``` + +#### Step 4 — Effect size and confidence interval +```python +p_a = summary.loc['A', 'conversion_rate'] +p_b = summary.loc['B', 'conversion_rate'] +n_a = summary.loc['A', 'visitors'] +n_b = summary.loc['B', 'visitors'] + +lift = (p_b - p_a) / p_a +se_diff = np.sqrt(p_a * (1 - p_a) / n_a + p_b * (1 - p_b) / n_b) +ci_lower = (p_b - p_a) - 1.96 * se_diff +ci_upper = (p_b - p_a) + 1.96 * se_diff + +print(f"Control rate: {p_a:.4f}") +print(f"Variant rate: {p_b:.4f}") +print(f"Absolute lift: {p_b - p_a:+.4f}") +print(f"Relative lift: {lift:+.2%}") +print(f"95% CI for diff: [{ci_lower:+.4f}, {ci_upper:+.4f}]") +``` + +#### Step 5 — Recommendation template +``` +## A/B Test Report: New Checkout Flow + +| Metric | Control (A) | Variant (B) | +|---------------------|-------------|-------------| +| Visitors | 15,204 | 15,198 | +| Conversions | 1,824 | 2,127 | +| Conversion Rate | 12.00% | 13.99% | + +**Result**: Statistically significant (p = 0.0003, alpha = 0.05) +**Lift**: +1.99pp absolute / +16.6% relative +**95% CI**: [+0.90pp, +3.08pp] +**Recommendation**: Deploy variant B. The effect is both statistically +and practically significant with a lower bound above the +1pp threshold. +``` + +--- + +### Example 3: Customer Churn Analysis + +**Goal**: Identify which factors most strongly predict customer churn and quantify their relative importance. + +#### Step 1 — Feature engineering +```python +df = pd.read_csv('customers.csv') + +# Create behavioral features from raw data +features = df.copy() +features['tenure_months'] = (pd.Timestamp.now() - pd.to_datetime(df['signup_date'])).dt.days / 30 +features['support_tickets_per_month'] = df['total_tickets'] / features['tenure_months'].clip(lower=1) +features['avg_session_minutes'] = df['total_session_minutes'] / df['total_sessions'].clip(lower=1) +features['days_since_last_login'] = (pd.Timestamp.now() - pd.to_datetime(df['last_login'])).dt.days +features['has_premium'] = (df['plan'] == 'premium').astype(int) + +# Drop raw columns, keep engineered features +feature_cols = [ + 'tenure_months', 'support_tickets_per_month', 'avg_session_minutes', + 'days_since_last_login', 'has_premium', 'monthly_spend', 'num_features_used' +] +``` + +#### Step 2 — Correlation analysis +```python +churn_corr = features[feature_cols + ['churned']].corr()['churned'].drop('churned').sort_values() + +fig, ax = plt.subplots(figsize=(8, 5)) +churn_corr.plot(kind='barh', ax=ax, color=['coral' if x > 0 else 'steelblue' for x in churn_corr]) +ax.set_title('Feature Correlation with Churn', fontsize=14, fontweight='bold') +ax.set_xlabel('Pearson Correlation') +ax.axvline(x=0, color='black', linewidth=0.5) +plt.tight_layout() +plt.savefig('churn_correlations.png', dpi=150, bbox_inches='tight') +plt.close() +``` + +#### Step 3 — Key driver identification via group comparison +```python +churned = features[features['churned'] == 1] +retained = features[features['churned'] == 0] + +comparison = [] +for col in feature_cols: + t_stat, p_val = stats.ttest_ind(churned[col].dropna(), retained[col].dropna()) + d = cohens_d(churned[col].dropna(), retained[col].dropna()) # From earlier definition + comparison.append({ + 'feature': col, + 'churned_mean': churned[col].mean(), + 'retained_mean': retained[col].mean(), + 'diff_pct': (churned[col].mean() - retained[col].mean()) / retained[col].mean() * 100, + 'cohens_d': abs(d), + 'p_value': p_val, + 'significant': p_val < 0.05 + }) + +result = pd.DataFrame(comparison).sort_values('cohens_d', ascending=False) +print(result.to_string(index=False)) +``` + +#### Step 4 — Interpret and report +``` +## Churn Driver Analysis + +**Top 3 factors distinguishing churned vs. retained customers:** + +| Factor | Churned (avg) | Retained (avg) | Diff | Effect Size | +|----------------------------|---------------|----------------|----------|-------------| +| Days since last login | 34.2 | 8.7 | +293% | Large | +| Support tickets per month | 2.8 | 0.9 | +211% | Large | +| Number of features used | 3.1 | 7.4 | -58% | Medium | + +**Actionable insights:** +1. Customers inactive >14 days are 4x more likely to churn -- trigger re-engagement email at day 10 +2. High support ticket rate signals frustration -- escalate accounts with >2 tickets/month to success team +3. Low feature adoption correlates with churn -- implement onboarding flow targeting unused features +``` + +--- + +## Advanced pandas Patterns + +### Window Functions + +```python +# Expanding window (cumulative statistics) +df['cumulative_avg'] = df['value'].expanding().mean() +df['cumulative_max'] = df['value'].expanding().max() + +# Exponentially weighted moving average (EWMA) -- emphasizes recent values +df['ewma_7'] = df['value'].ewm(span=7).mean() # Span-based decay +df['ewma_a'] = df['value'].ewm(alpha=0.3).mean() # Explicit decay factor + +# Comparison: rolling vs. EWMA +# - rolling(7).mean() weights all 7 values equally +# - ewm(span=7).mean() weights recent values exponentially more +# Use EWMA when recent data matters more (stock prices, real-time metrics) + +# Rolling with min_periods (handles early rows with insufficient data) +df['rolling_avg'] = df['value'].rolling(window=30, min_periods=5).mean() + +# Rolling rank (percentile within window) +df['rolling_pctile'] = df['value'].rolling(90).rank(pct=True) +``` + +### Multi-Index Operations + +```python +# Create multi-index from groupby +multi = df.groupby(['region', 'product']).agg( + revenue=('amount', 'sum'), + units=('quantity', 'sum') +) + +# Access levels +multi.loc['North'] # All products in North region +multi.loc[('North', 'Widget')] # Specific region + product +multi.xs('Widget', level='product') # All regions for Widget + +# Swap and sort levels +multi = multi.swaplevel().sort_index() + +# Reset to flat columns +flat = multi.reset_index() + +# Stack / unstack (reshape between long and wide) +wide = multi['revenue'].unstack(level='product') # Products become columns +long = wide.stack() # Back to multi-index +``` + +### Merge and Join Patterns + +```python +# Inner join (only matching rows) +merged = orders.merge(customers, on='customer_id', how='inner') + +# Left join with indicator (see which rows matched) +merged = orders.merge(customers, on='customer_id', how='left', indicator=True) +unmatched = merged[merged['_merge'] == 'left_only'] + +# Join on multiple keys +merged = df1.merge(df2, on=['date', 'region'], how='left') + +# Join with different column names +merged = orders.merge(products, left_on='prod_id', right_on='product_id') + +# Anti-join (rows in A that have no match in B) +anti = df_a.merge(df_b, on='key', how='left', indicator=True) +anti = anti[anti['_merge'] == 'left_only'].drop(columns='_merge') + +# Self-join (compare rows within same table) +df_prev = df[['customer_id', 'order_date', 'amount']].rename( + columns={'order_date': 'prev_date', 'amount': 'prev_amount'} +) +df_with_prev = df.merge(df_prev, on='customer_id', how='left') +df_with_prev = df_with_prev[df_with_prev['prev_date'] < df_with_prev['order_date']] +``` + +### Apply and Transform + +```python +# transform() returns same-shaped output -- useful for group-level stats on each row +df['group_mean'] = df.groupby('category')['value'].transform('mean') +df['pct_of_group'] = df['value'] / df.groupby('category')['value'].transform('sum') +df['z_within_group'] = df.groupby('category')['value'].transform( + lambda x: (x - x.mean()) / x.std() +) + +# apply() for multi-column group operations +def top_n(group, n=3): + return group.nlargest(n, 'value') + +top3_per_category = df.groupby('category', group_keys=False).apply(top_n, n=3) + +# Vectorized operations (prefer these over apply when possible) +# Slow: +df['result'] = df.apply(lambda row: row['a'] * row['b'] + row['c'], axis=1) +# Fast: +df['result'] = df['a'] * df['b'] + df['c'] + +# np.where for conditional columns (vectorized if/else) +df['tier'] = np.where(df['revenue'] > 10000, 'high', 'low') + +# np.select for multiple conditions +conditions = [ + df['revenue'] > 10000, + df['revenue'] > 5000, + df['revenue'] > 0, +] +choices = ['high', 'medium', 'low'] +df['tier'] = np.select(conditions, choices, default='none') +``` + +### Memory Optimization for Large Datasets + +```python +# Check current memory usage +print(df.memory_usage(deep=True).sum() / 1024**2, "MB") + +# Downcast numeric types +df['int_col'] = pd.to_numeric(df['int_col'], downcast='integer') # int64 -> int8/16/32 +df['float_col'] = pd.to_numeric(df['float_col'], downcast='float') # float64 -> float32 + +# Use category type for low-cardinality strings +for col in df.select_dtypes(include='object'): + if df[col].nunique() / len(df) < 0.5: # Less than 50% unique values + df[col] = df[col].astype('category') + +# Read in chunks for files that exceed memory +chunks = pd.read_csv('huge_file.csv', chunksize=100_000) +results = [] +for chunk in chunks: + processed = chunk.groupby('category')['value'].sum() + results.append(processed) +final = pd.concat(results).groupby(level=0).sum() + +# Specify dtypes at load time (avoids loading as float64/object first) +dtypes = { + 'id': 'int32', + 'category': 'category', + 'value': 'float32', + 'flag': 'bool' +} +df = pd.read_csv('data.csv', dtype=dtypes) + +# Use pyarrow backend for better memory efficiency (pandas 2.0+) +df = pd.read_csv('data.csv', engine='pyarrow', dtype_backend='pyarrow') +``` + +--- + +## Dashboard and Reporting Patterns + +### Executive Dashboard Template + +```python +import matplotlib.pyplot as plt +import matplotlib.gridspec as gridspec +from matplotlib.patches import FancyBboxPatch + +def executive_dashboard(kpis, trend_df, comparison_df, output='dashboard.png'): + """ + kpis: dict with keys like {'Revenue': '$1.2M', 'Growth': '+15%', ...} + trend_df: DataFrame with 'date' and 'value' columns + comparison_df: DataFrame with 'category' and 'current'/'previous' columns + """ + fig = plt.figure(figsize=(16, 10)) + gs = gridspec.GridSpec(3, len(kpis), hspace=0.4, wspace=0.3) + + # Row 1: KPI cards + for i, (label, value) in enumerate(kpis.items()): + ax = fig.add_subplot(gs[0, i]) + ax.text(0.5, 0.6, value, ha='center', va='center', + fontsize=28, fontweight='bold', color='#2c3e50') + ax.text(0.5, 0.2, label, ha='center', va='center', + fontsize=12, color='#7f8c8d') + ax.set_xlim(0, 1) + ax.set_ylim(0, 1) + ax.axis('off') + # Card background + rect = FancyBboxPatch((0.05, 0.05), 0.9, 0.9, boxstyle="round,pad=0.05", + facecolor='#f8f9fa', edgecolor='#dee2e6') + ax.add_patch(rect) + + # Row 2: Trend line + ax_trend = fig.add_subplot(gs[1, :]) + ax_trend.plot(trend_df['date'], trend_df['value'], linewidth=2, color='steelblue') + ax_trend.fill_between(trend_df['date'], trend_df['value'], alpha=0.1, color='steelblue') + ax_trend.set_title('Trend Over Time', fontsize=13, fontweight='bold') + ax_trend.set_ylabel('Value') + + # Row 3: Period comparison (grouped bar) + ax_comp = fig.add_subplot(gs[2, :]) + x = range(len(comparison_df)) + width = 0.35 + ax_comp.bar([i - width/2 for i in x], comparison_df['previous'], width, + label='Previous', color='#bdc3c7') + ax_comp.bar([i + width/2 for i in x], comparison_df['current'], width, + label='Current', color='steelblue') + ax_comp.set_xticks(list(x)) + ax_comp.set_xticklabels(comparison_df['category'], rotation=45, ha='right') + ax_comp.set_title('Current vs. Previous Period', fontsize=13, fontweight='bold') + ax_comp.legend() + + plt.savefig(output, dpi=150, bbox_inches='tight', facecolor='white') + plt.close() +``` + +### Weekly Metrics Report Template + +```python +def weekly_report(df, date_col='date', metric_col='value', group_col=None): + """Generate a standard weekly metrics summary.""" + df[date_col] = pd.to_datetime(df[date_col]) + df['week'] = df[date_col].dt.isocalendar().week.astype(int) + df['year'] = df[date_col].dt.year + + current_week = df['week'].max() + prev_week = current_week - 1 + + curr = df[df['week'] == current_week] + prev = df[df['week'] == prev_week] + + report = { + 'period': f"Week {current_week}", + 'total': curr[metric_col].sum(), + 'mean': curr[metric_col].mean(), + 'median': curr[metric_col].median(), + 'wow_change': (curr[metric_col].sum() - prev[metric_col].sum()) + / prev[metric_col].sum() * 100 + if prev[metric_col].sum() != 0 else None, + } + + if group_col: + report['by_group'] = curr.groupby(group_col)[metric_col].agg(['sum', 'mean', 'count']) + + # Sparkline trend (last 8 weeks) + weekly_totals = ( + df.groupby('week')[metric_col].sum() + .tail(8) + .reset_index() + ) + + fig, ax = plt.subplots(figsize=(6, 2)) + ax.plot(weekly_totals['week'], weekly_totals[metric_col], marker='o', + linewidth=2, color='steelblue', markersize=4) + ax.fill_between(weekly_totals['week'], weekly_totals[metric_col], + alpha=0.1, color='steelblue') + ax.set_title(f'{metric_col.title()} — Last 8 Weeks', fontsize=10) + ax.tick_params(labelsize=8) + plt.tight_layout() + plt.savefig('weekly_sparkline.png', dpi=150, bbox_inches='tight') + plt.close() + + return report +``` + +### Anomaly Detection Patterns + +```python +def detect_anomalies(series, method='zscore', threshold=3.0, window=30): + """ + Detect anomalies in a numeric series. + + Methods: + - 'zscore': Flag values beyond `threshold` standard deviations from mean + - 'iqr': Flag values beyond 1.5x IQR from quartiles + - 'rolling': Flag values beyond `threshold` std devs from rolling mean + """ + anomalies = pd.Series(False, index=series.index) + + if method == 'zscore': + z = (series - series.mean()) / series.std() + anomalies = z.abs() > threshold + + elif method == 'iqr': + q1 = series.quantile(0.25) + q3 = series.quantile(0.75) + iqr = q3 - q1 + anomalies = (series < q1 - 1.5 * iqr) | (series > q3 + 1.5 * iqr) + + elif method == 'rolling': + rolling_mean = series.rolling(window, min_periods=5).mean() + rolling_std = series.rolling(window, min_periods=5).std() + anomalies = (series - rolling_mean).abs() > threshold * rolling_std + + return anomalies + + +# Usage: detect and visualize +anomalies = detect_anomalies(df['metric'], method='rolling', threshold=2.5, window=30) + +fig, ax = plt.subplots(figsize=(14, 5)) +ax.plot(df.index, df['metric'], linewidth=1, color='steelblue', label='Metric') +ax.scatter(df.index[anomalies], df['metric'][anomalies], + color='red', s=40, zorder=5, label='Anomaly') +ax.legend() +ax.set_title('Anomaly Detection (Rolling Z-Score)', fontsize=14, fontweight='bold') +plt.tight_layout() +plt.savefig('anomalies.png', dpi=150, bbox_inches='tight') +plt.close() + +print(f"Detected {anomalies.sum()} anomalies out of {len(series):,} data points") +``` + +**Method selection guide:** + +| Method | Best For | Assumptions | Sensitivity | +|--------|----------|-------------|-------------| +| Z-score | Stationary data with normal distribution | Constant mean and variance | Low (misses local anomalies) | +| IQR | Skewed distributions, outlier screening | None (non-parametric) | Medium | +| Rolling z-score | Time series with trends or seasonality | Local stationarity within window | High (adapts to drift) | + +--- + +## Common Analytics Pitfalls + +### Simpson's Paradox + +A trend that appears in grouped data reverses when the groups are combined. + +``` +Department A: Drug works better (80% vs 70%) +Department B: Drug works better (50% vs 40%) +Combined: Drug appears WORSE (55% vs 60%) <-- paradox +``` + +**Why it happens**: Unequal group sizes create a confounding effect. Department B (with lower overall rates) sent most patients to the drug group. + +**Prevention**: Always segment data by relevant confounders before drawing conclusions. If aggregate and segmented results disagree, trust the segmented analysis and report the confounding variable. + +### Survivorship Bias + +Analyzing only entities that "survived" a selection process, ignoring those that dropped out. + +**Classic examples:** +- Studying only successful companies to find success patterns (ignoring failed companies with the same patterns) +- Analyzing only current customers to understand satisfaction (ignoring those who already left) +- Looking at fund performance by examining only funds that still exist (dead funds were closed) + +**Prevention**: Always ask "what is missing from this dataset?" before drawing conclusions. If possible, include data from non-survivors. Explicitly note the selection criteria and what it excludes. + +### Correlation vs. Causation + +A statistically significant correlation between X and Y does not mean X causes Y. Possible explanations: + +| Explanation | Example | +|-------------|---------| +| X causes Y | Exercise reduces blood pressure | +| Y causes X | Depression reduces exercise (not exercise causes depression) | +| Z causes both | Income drives both education spending AND health outcomes | +| Coincidence | Ice cream sales correlate with drowning deaths (both driven by summer) | + +**Prevention**: Establish causation only with randomized controlled experiments (A/B tests). For observational data, state findings as "associated with" not "causes." Look for confounders and test whether the relationship holds when controlling for them. + +### Cherry-Picking Time Windows + +Selecting a start/end date that makes a metric look better or worse than the true trend. + +```python +# Example: same data, different conclusions +# "Revenue up 40%!" -- comparing Jan (seasonal low) to Dec (seasonal high) +# "Revenue flat." -- comparing Dec 2024 to Dec 2025 (year-over-year) + +# Prevention: always use year-over-year comparison for seasonal data +df['yoy_change'] = df.groupby(df['date'].dt.month)['revenue'].pct_change(periods=12) +``` + +**Prevention checklist:** +- Compare like-for-like periods (YoY for seasonal businesses) +- Show the full time range, not a selected subset +- Use multiple time windows (WoW, MoM, QoQ, YoY) and note if they disagree +- Include a moving average to show the underlying trend separate from noise + +### Small Sample Size Issues + +Small samples produce unstable statistics that can flip with just a few more observations. + +```python +# Illustrate instability: conversion rates with small vs. large samples +from scipy.stats import beta + +# Scenario: 3 conversions out of 10 visitors (30%) +a_small, b_small = 3 + 1, 10 - 3 + 1 # Beta posterior +ci_small = beta.interval(0.95, a_small, b_small) +print(f"n=10: 30% conversion, 95% CI: [{ci_small[0]:.1%}, {ci_small[1]:.1%}]") +# Output: 95% CI: [9.9%, 56.8%] -- extremely wide, almost useless + +# Scenario: 300 conversions out of 1000 visitors (30%) +a_large, b_large = 300 + 1, 1000 - 300 + 1 +ci_large = beta.interval(0.95, a_large, b_large) +print(f"n=1000: 30% conversion, 95% CI: [{ci_large[0]:.1%}, {ci_large[1]:.1%}]") +# Output: 95% CI: [27.2%, 32.9%] -- narrow and actionable +``` + +**Rules of thumb:** +- n < 30: Do not draw firm conclusions. Report as directional only. +- Conversion rates need hundreds (not dozens) of conversions to stabilize. +- Always report confidence intervals alongside point estimates. +- If sample size is fixed and small, use exact tests (Fisher's exact) rather than approximations (chi-squared). diff --git a/hands/apitester/HAND.toml b/hands/apitester/HAND.toml index f295e5d..f5b99b1 100644 --- a/hands/apitester/HAND.toml +++ b/hands/apitester/HAND.toml @@ -460,6 +460,265 @@ token_consumption = "medium" default_active = false activation_warning = "API Tester hand runs continuously, consuming tokens. Use on-demand for specific tests." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "API 测试 Hand" description = "自主 API 测试智能体——端点发现、请求验证、负载测试和回归检测" +category = "开发" + +[i18n.zh.settings.base_url] +label = "基础 URL" +description = "待测试 API 的基础 URL(例如 https://api.example.com/v1)" + +[i18n.zh.settings.auth_type] +label = "认证方式" +description = "API 请求的认证方式" + +[i18n.zh.settings.auth_token] +label = "认证令牌 / API 密钥" +description = "Bearer 令牌、API 密钥或 Base64 编码的凭据,取决于认证方式" + +[i18n.zh.settings.test_mode] +label = "测试模式" +description = "执行的 API 测试类型" + +[i18n.zh.settings.openapi_spec_url] +label = "OpenAPI 规范 URL" +description = "OpenAPI/Swagger 规范的 URL(例如 /openapi.json)。留空则自动发现。" + +[i18n.zh.settings.auto_schedule] +label = "自动定时" +description = "按计划自动运行测试" + +[i18n.zh.settings.test_frequency] +label = "测试频率" +description = "定时测试的执行频率" + +[i18n.zh.settings.fail_on_error] +label = "严格模式" +description = "将任何非 2xx 响应视为失败(而非允许预期的错误码)" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将测试计划和破坏性请求写入队列文件供审核,而非直接执行" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "APIテスト Hand" +description = "自律型APIテストエージェント——エンドポイント検出、リクエスト検証、負荷テスト、リグレッション検出" +category = "開発" + +[i18n.ja.settings.base_url] +label = "ベースURL" +description = "テスト対象APIのベースURL(例: https://api.example.com/v1)" + +[i18n.ja.settings.auth_type] +label = "認証方式" +description = "APIリクエストの認証方法" + +[i18n.ja.settings.auth_token] +label = "認証トークン / APIキー" +description = "認証方式に応じたBearerトークン、APIキー、またはBase64エンコードされた資格情報" + +[i18n.ja.settings.test_mode] +label = "テストモード" +description = "実行するAPIテストの種類" + +[i18n.ja.settings.openapi_spec_url] +label = "OpenAPI仕様URL" +description = "OpenAPI/Swagger仕様のURL(例: /openapi.json)。空欄にすると自動検出します。" + +[i18n.ja.settings.auto_schedule] +label = "自動スケジュール" +description = "スケジュールに基づいてテストを自動実行する" + +[i18n.ja.settings.test_frequency] +label = "テスト頻度" +description = "定期テストの実行頻度" + +[i18n.ja.settings.fail_on_error] +label = "厳格モード" +description = "2xx以外のレスポンスをすべて失敗として扱う(期待されるエラーコードを許容しない)" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "テスト計画や破壊的リクエストを直接実行せず、レビュー用のキューファイルに書き出す" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Pruebas API" +description = "Agente autónomo de pruebas de API — descubrimiento de endpoints, validación de peticiones, pruebas de carga y detección de regresiones" +category = "Desarrollo" + +[i18n.es.settings.base_url] +label = "URL base" +description = "URL base de la API a probar (ej. https://api.example.com/v1)" + +[i18n.es.settings.auth_type] +label = "Tipo de autenticación" +description = "Cómo autenticar las peticiones a la API" + +[i18n.es.settings.auth_token] +label = "Token de autenticación / Clave API" +description = "Token Bearer, clave API o credenciales codificadas en Base64 según el tipo de autenticación" + +[i18n.es.settings.test_mode] +label = "Modo de prueba" +description = "Qué tipo de pruebas de API realizar" + +[i18n.es.settings.openapi_spec_url] +label = "URL de especificación OpenAPI" +description = "URL de la especificación OpenAPI/Swagger (ej. /openapi.json). Dejar vacío para descubrimiento automático." + +[i18n.es.settings.auto_schedule] +label = "Programación automática" +description = "Ejecutar pruebas automáticamente según un calendario" + +[i18n.es.settings.test_frequency] +label = "Frecuencia de pruebas" +description = "Con qué frecuencia ejecutar las pruebas programadas" + +[i18n.es.settings.fail_on_error] +label = "Modo estricto" +description = "Tratar cualquier respuesta no 2xx como un fallo (en lugar de permitir códigos de error esperados)" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Escribir planes de prueba y peticiones destructivas en un archivo de cola para revisión en lugar de ejecutarlos directamente" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand de Test API" +description = "Agent autonome de test d'API — découverte de points de terminaison, validation de requêtes, tests de charge et détection de régression" +category = "Développement" + +[i18n.fr.settings.base_url] +label = "URL de base" +description = "URL de base de l'API à tester (ex. https://api.example.com/v1)" + +[i18n.fr.settings.auth_type] +label = "Type d'authentification" +description = "Méthode d'authentification des requêtes API" + +[i18n.fr.settings.auth_token] +label = "Jeton d'authentification / Clé API" +description = "Jeton Bearer, clé API ou identifiants encodés en Base64 selon le type d'authentification" + +[i18n.fr.settings.test_mode] +label = "Mode de test" +description = "Type de tests API à exécuter" + +[i18n.fr.settings.openapi_spec_url] +label = "URL de spécification OpenAPI" +description = "URL de la spécification OpenAPI/Swagger (ex. /openapi.json). Laisser vide pour la découverte automatique." + +[i18n.fr.settings.auto_schedule] +label = "Planification automatique" +description = "Exécuter automatiquement les tests selon un calendrier" + +[i18n.fr.settings.test_frequency] +label = "Fréquence des tests" +description = "Fréquence d'exécution des tests planifiés" + +[i18n.fr.settings.fail_on_error] +label = "Mode strict" +description = "Traiter toute réponse non 2xx comme un échec (au lieu d'autoriser les codes d'erreur attendus)" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Écrire les plans de test et requêtes destructives dans un fichier d'attente pour révision au lieu de les exécuter directement" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "API-Test-Hand" +description = "Autonomer API-Test-Agent — Endpunkt-Erkennung, Anfrage-Validierung, Lasttests und Regressionserkennung" +category = "Entwicklung" + +[i18n.de.settings.base_url] +label = "Basis-URL" +description = "Basis-URL der zu testenden API (z.B. https://api.example.com/v1)" + +[i18n.de.settings.auth_type] +label = "Authentifizierungstyp" +description = "Authentifizierungsmethode für API-Anfragen" + +[i18n.de.settings.auth_token] +label = "Authentifizierungstoken / API-Schlüssel" +description = "Bearer-Token, API-Schlüssel oder Base64-kodierte Anmeldedaten je nach Authentifizierungstyp" + +[i18n.de.settings.test_mode] +label = "Testmodus" +description = "Art der durchzuführenden API-Tests" + +[i18n.de.settings.openapi_spec_url] +label = "OpenAPI-Spezifikations-URL" +description = "URL der OpenAPI/Swagger-Spezifikation (z.B. /openapi.json). Leer lassen für automatische Erkennung." + +[i18n.de.settings.auto_schedule] +label = "Automatische Planung" +description = "Tests automatisch nach Zeitplan ausführen" + +[i18n.de.settings.test_frequency] +label = "Testhäufigkeit" +description = "Ausführungshäufigkeit der geplanten Tests" + +[i18n.de.settings.fail_on_error] +label = "Strikter Modus" +description = "Jede Nicht-2xx-Antwort als Fehler behandeln (anstatt erwartete Fehlercodes zuzulassen)" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Testpläne und destruktive Anfragen in eine Warteschlange zur Überprüfung schreiben, anstatt sie direkt auszuführen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "API 테스트 Hand" +description = "자율 API 테스트 에이전트 — 엔드포인트 탐색, 요청 검증, 부하 테스트 및 회귀 감지" +category = "개발" + +[i18n.ko.settings.base_url] +label = "기본 URL" +description = "테스트할 API의 기본 URL (예: https://api.example.com/v1)" + +[i18n.ko.settings.auth_type] +label = "인증 방식" +description = "API 요청의 인증 방식" + +[i18n.ko.settings.auth_token] +label = "인증 토큰 / API 키" +description = "인증 방식에 따른 Bearer 토큰, API 키 또는 Base64 인코딩 자격 증명" + +[i18n.ko.settings.test_mode] +label = "테스트 모드" +description = "수행할 API 테스트 유형" + +[i18n.ko.settings.openapi_spec_url] +label = "OpenAPI 스펙 URL" +description = "OpenAPI/Swagger 스펙의 URL (예: /openapi.json). 비워두면 자동 탐색합니다." + +[i18n.ko.settings.auto_schedule] +label = "자동 일정" +description = "일정에 따라 자동으로 테스트 실행" + +[i18n.ko.settings.test_frequency] +label = "테스트 빈도" +description = "정기 테스트 실행 주기" + +[i18n.ko.settings.fail_on_error] +label = "엄격 모드" +description = "모든 비-2xx 응답을 실패로 처리 (예상된 오류 코드 허용 안 함)" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "테스트 계획 및 파괴적 요청을 직접 실행하지 않고 큐 파일에 기록하여 검토" diff --git a/hands/apitester/SKILL.md b/hands/apitester/SKILL.md index 58fc634..ca1c16f 100644 --- a/hands/apitester/SKILL.md +++ b/hands/apitester/SKILL.md @@ -237,3 +237,656 @@ First Seen: 2025-01-15 run Previous Value: string (email format) Current Value: field absent ``` + +--- + +## Worked Examples + +### Example 1: Testing a REST API CRUD Endpoint + +Full test suite for a `/api/users` resource covering create, read, update, delete, and edge cases. + +**Setup — Create a test user**: +```bash +# POST /api/users — create +RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"name": "Ada Lovelace", "email": "ada@example.com", "role": "engineer"}' \ + "https://api.example.com/api/users") + +BODY=$(echo "$RESPONSE" | sed '$d') +STATUS=$(echo "$RESPONSE" | tail -1) + +# Expect 201 Created +[ "$STATUS" = "201" ] && echo "PASS: Create user" || echo "FAIL: Expected 201, got $STATUS" + +# Extract ID for subsequent tests +USER_ID=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") +``` + +**Read operations**: +```bash +# GET /api/users — list all +curl -s -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users" | python3 -m json.tool + +# GET /api/users/:id — single user +curl -s -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users/$USER_ID" | python3 -m json.tool + +# GET /api/users/nonexistent-id — expect 404 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users/00000000-0000-0000-0000-000000000000") +[ "$STATUS" = "404" ] && echo "PASS: 404 for missing user" || echo "FAIL: Expected 404, got $STATUS" +``` + +**Update operations**: +```bash +# PUT /api/users/:id — full update +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X PUT \ + -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \ + -d '{"name": "Ada Lovelace", "email": "ada.updated@example.com", "role": "lead"}' \ + "https://api.example.com/api/users/$USER_ID") +[ "$STATUS" = "200" ] && echo "PASS: Full update" || echo "FAIL: Expected 200, got $STATUS" + +# PATCH — partial update (expect 200); also test invalid data (expect 400/422) +``` + +**Delete and verify**: +```bash +# DELETE /api/users/:id +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ + -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users/$USER_ID") +[ "$STATUS" = "204" ] || [ "$STATUS" = "200" ] && echo "PASS: Delete user" || echo "FAIL: Expected 2xx, got $STATUS" + +# GET deleted user — expect 404 or 410 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users/$USER_ID") +[ "$STATUS" = "404" ] || [ "$STATUS" = "410" ] && echo "PASS: Deleted user gone" || echo "FAIL: Expected 404/410, got $STATUS" + +# DELETE again — idempotency check +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ + -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users/$USER_ID") +[ "$STATUS" = "404" ] || [ "$STATUS" = "204" ] && echo "PASS: Idempotent delete" || echo "FAIL: Got $STATUS" +``` + +**Edge cases to test**: duplicate create (expect 409), empty body (expect 400/422), extra unknown fields (verify ignored or rejected, not persisted). + +### Example 2: Testing an Authenticated API with Rate Limiting + +Scenario: API uses Bearer tokens, tokens expire after 1 hour, rate limit is 100 requests/minute. + +**Token lifecycle testing**: +```bash +# Step 1: Obtain token +AUTH_RESPONSE=$(curl -s -X POST \ + -H "Content-Type: application/json" \ + -d '{"client_id": "myapp", "client_secret": "secret", "grant_type": "client_credentials"}' \ + "https://api.example.com/oauth/token") + +ACCESS_TOKEN=$(echo "$AUTH_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])") +EXPIRES_IN=$(echo "$AUTH_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['expires_in'])") +echo "Token obtained, expires in ${EXPIRES_IN}s" + +# Step 2: Use token — expect 200 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + "https://api.example.com/api/protected") +[ "$STATUS" = "200" ] && echo "PASS: Valid token accepted" || echo "FAIL: Got $STATUS" + +# Step 3: Use expired/invalid token — expect 401 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: Bearer expired.token.here" \ + "https://api.example.com/api/protected") +[ "$STATUS" = "401" ] && echo "PASS: Expired token rejected" || echo "FAIL: Got $STATUS" + +# Step 4: Missing Authorization header — expect 401 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + "https://api.example.com/api/protected") +[ "$STATUS" = "401" ] && echo "PASS: No auth rejected" || echo "FAIL: Got $STATUS" + +# Step 5: Malformed header — expect 401 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: NotBearer $ACCESS_TOKEN" \ + "https://api.example.com/api/protected") +[ "$STATUS" = "401" ] && echo "PASS: Bad scheme rejected" || echo "FAIL: Got $STATUS" +``` + +**Rate limit testing**: +```bash +# Hit the endpoint rapidly and watch for 429 +RESULTS_FILE=$(mktemp) +for i in $(seq 1 120); do + curl -s -o /dev/null -w "%{http_code}\n" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + "https://api.example.com/api/data" >> "$RESULTS_FILE" & +done +wait + +# Count status codes +echo "=== Rate Limit Results ===" +sort "$RESULTS_FILE" | uniq -c | sort -rn +# Expected: ~100 x 200, ~20 x 429 + +# Check rate limit headers on a single request +curl -s -D- -o /dev/null \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + "https://api.example.com/api/data" | grep -i "x-ratelimit" +# Expected headers: +# X-RateLimit-Limit: 100 +# X-RateLimit-Remaining: 99 +# X-RateLimit-Reset: 1700000060 + +rm "$RESULTS_FILE" +``` + +**Backoff strategy**: On 429, respect `Retry-After` header. Use exponential backoff (1s, 2s, 4s...) as fallback. Verify the API returns `X-RateLimit-Reset` for client scheduling. + +### Example 3: Testing a Webhook Endpoint + +Scenario: Your API accepts webhook callbacks at `POST /webhooks/payment` with HMAC-SHA256 signature verification. + +**Payload and signature generation**: +```bash +WEBHOOK_SECRET="whsec_test_secret_key_12345" +PAYLOAD='{"event":"payment.completed","data":{"id":"pay_123","amount":4999,"currency":"usd"}}' +TIMESTAMP=$(date +%s) +SIGNATURE=$(printf "%s.%s" "$TIMESTAMP" "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}') + +# Valid webhook delivery +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -H "X-Webhook-Signature: t=$TIMESTAMP,v1=$SIGNATURE" \ + -H "X-Webhook-Id: wh_evt_001" \ + -d "$PAYLOAD" \ + "https://api.example.com/webhooks/payment") +[ "$STATUS" = "200" ] || [ "$STATUS" = "204" ] && echo "PASS: Valid webhook accepted" || echo "FAIL: Got $STATUS" +``` + +**Signature verification tests**: +```bash +# Wrong signature — expect 401 or 403 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -H "X-Webhook-Signature: t=$TIMESTAMP,v1=badsignaturevalue" \ + -d "$PAYLOAD" \ + "https://api.example.com/webhooks/payment") +[ "$STATUS" = "401" ] || [ "$STATUS" = "403" ] && echo "PASS: Bad signature rejected" || echo "FAIL: Got $STATUS" + +# Missing signature header — expect 401 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD" \ + "https://api.example.com/webhooks/payment") +[ "$STATUS" = "401" ] && echo "PASS: Missing signature rejected" || echo "FAIL: Got $STATUS" + +# Stale timestamp (replay attack) — expect 403 +OLD_TIMESTAMP=$((TIMESTAMP - 600)) +OLD_SIGNATURE=$(printf "%s.%s" "$OLD_TIMESTAMP" "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}') +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -H "X-Webhook-Signature: t=$OLD_TIMESTAMP,v1=$OLD_SIGNATURE" \ + -d "$PAYLOAD" \ + "https://api.example.com/webhooks/payment") +[ "$STATUS" = "403" ] && echo "PASS: Stale timestamp rejected" || echo "FAIL: Got $STATUS" +``` + +**Also test**: idempotency (same `X-Webhook-Id` sent twice — should be processed once), invalid/empty payloads (expect 400). + +--- + +## Authentication Testing Patterns + +### OAuth 2.0 Flow Testing + +**Authorization Code flow**: +```bash +# Step 1: Initiate authorization — verify redirect +AUTHORIZE_URL="https://api.example.com/oauth/authorize?response_type=code&client_id=myapp&redirect_uri=https://myapp.example.com/callback&scope=read+write&state=random_state_123" +STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$AUTHORIZE_URL") +[ "$STATUS" = "302" ] || [ "$STATUS" = "200" ] && echo "PASS: Auth endpoint reachable" || echo "FAIL: Got $STATUS" + +# Step 2: Exchange authorization code for token +TOKEN_RESPONSE=$(curl -s -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=authorization_code&code=AUTH_CODE_HERE&redirect_uri=https://myapp.example.com/callback&client_id=myapp&client_secret=secret" \ + "https://api.example.com/oauth/token") +echo "$TOKEN_RESPONSE" | python3 -m json.tool +# Verify: access_token, refresh_token, expires_in, token_type present + +# Step 3: Use invalid authorization code — expect 400 +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=authorization_code&code=INVALID_CODE&redirect_uri=https://myapp.example.com/callback&client_id=myapp&client_secret=secret" \ + "https://api.example.com/oauth/token") +[ "$STATUS" = "400" ] && echo "PASS: Invalid code rejected" || echo "FAIL: Got $STATUS" + +# Step 4: Reuse authorization code — must fail (codes are single-use) +# Use the same AUTH_CODE_HERE again +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=authorization_code&code=AUTH_CODE_HERE&redirect_uri=https://myapp.example.com/callback&client_id=myapp&client_secret=secret" \ + "https://api.example.com/oauth/token") +[ "$STATUS" = "400" ] && echo "PASS: Code reuse rejected" || echo "FAIL: Got $STATUS" +``` + +**Client Credentials flow**: Same pattern as above with `grant_type=client_credentials`. Test: valid credentials (expect `access_token`), invalid secret (expect 401), invalid `grant_type` (expect 400). + +**Refresh Token flow**: Exchange `grant_type=refresh_token` with `refresh_token=$REFRESH_TOKEN`. Verify: new `access_token` returned, old refresh token invalidated if rotation is enabled (reuse should return 400/401). + +### JWT Validation Testing + +Test each type of JWT failure independently: + +| Test Case | Token Modification | Expected Status | Expected Error | +|-----------|-------------------|-----------------|----------------| +| Expired token | Set `exp` to past timestamp | 401 | `token_expired` | +| Not-yet-valid | Set `nbf` to future timestamp | 401 | `token_not_yet_valid` | +| Wrong signature | Sign with different key | 401 | `invalid_signature` | +| Malformed token | Remove a segment | 401 | `malformed_token` | +| Missing `sub` claim | Remove `sub` from payload | 401 | `missing_claims` | +| Wrong audience | Set `aud` to different app | 401 | `invalid_audience` | +| Wrong issuer | Set `iss` to unknown issuer | 401 | `invalid_issuer` | +| Algorithm none attack | Set `alg: none`, remove signature | 401 | `invalid_algorithm` | + +```bash +# Generate a test JWT with wrong signature (using python3 as a helper) +HEADER=$(echo -n '{"alg":"HS256","typ":"JWT"}' | base64 | tr -d '=' | tr '+/' '-_') +PAYLOAD=$(echo -n '{"sub":"user123","exp":9999999999}' | base64 | tr -d '=' | tr '+/' '-_') +BAD_SIG=$(echo -n "fakesignature" | base64 | tr -d '=' | tr '+/' '-_') +BAD_JWT="${HEADER}.${PAYLOAD}.${BAD_SIG}" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: Bearer $BAD_JWT" \ + "https://api.example.com/api/protected") +[ "$STATUS" = "401" ] && echo "PASS: Bad JWT signature rejected" || echo "FAIL: Got $STATUS" + +# Algorithm "none" attack +NONE_HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr -d '=' | tr '+/' '-_') +NONE_JWT="${NONE_HEADER}.${PAYLOAD}." +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: Bearer $NONE_JWT" \ + "https://api.example.com/api/protected") +[ "$STATUS" = "401" ] && echo "PASS: alg:none attack blocked" || echo "FAIL: Got $STATUS — SECURITY RISK" +``` + +### API Key Testing Patterns + +```bash +# Valid API key in header +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "X-API-Key: valid_key_abc123" \ + "https://api.example.com/api/data") +[ "$STATUS" = "200" ] && echo "PASS: Valid API key" || echo "FAIL: Got $STATUS" +``` + +**Also test**: key in query param (if supported), revoked key (expect 401/403), empty key (expect 401), read-only key attempting write (expect 403). + +### Session-Based Auth Testing + +Test pattern: login (capture `Set-Cookie`), use cookie for authenticated request (expect 200), logout, reuse cookie (expect 401). Also verify session fixation prevention — session ID should rotate on login. + +--- + +## Contract Testing + +### Schema Validation Techniques + +Validate API responses against a JSON Schema using `python3 -c "from jsonschema import validate; ..."`: + +```bash +# Fetch response and validate against schema file +curl -s -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/users/user_001" | python3 -c " +import sys, json +from jsonschema import validate, ValidationError +schema = json.load(open('/tmp/user_schema.json')) +try: + validate(instance=json.load(sys.stdin), schema=schema) + print('PASS: Schema valid') +except ValidationError as e: + print(f'FAIL: {e.message}') +" +``` + +Schema should define `required` fields, property `type`/`format`/`enum` constraints, and `additionalProperties: false` for strict mode. + +### Breaking Change Detection + +Compare current response structure against a recorded baseline: + +```bash +# Helper: extract JSON shape as "path: type" lines +extract_shape() { + curl -s -H "Authorization: Bearer $TOKEN" "$1" | python3 -c " +import sys, json +def shape(obj, prefix=''): + s = {} + if isinstance(obj, dict): + for k, v in obj.items(): + p = f'{prefix}.{k}' if prefix else k + s[p] = type(v).__name__; s.update(shape(v, p)) + elif isinstance(obj, list) and obj: + s[f'{prefix}[]'] = type(obj[0]).__name__; s.update(shape(obj[0], f'{prefix}[]')) + return s +for p, t in sorted(shape(json.load(sys.stdin)).items()): print(f'{p}: {t}') +" +} + +# Record baseline once, then diff against current +extract_shape "https://api.example.com/api/users/user_001" > /tmp/api_baseline.txt +# ... later ... +extract_shape "https://api.example.com/api/users/user_001" > /tmp/api_current.txt +diff /tmp/api_baseline.txt /tmp/api_current.txt && echo "PASS: No schema changes" || echo "WARN: Schema changed" +``` + +### Backward Compatibility Checklist + +When a new API version is deployed, verify that existing consumers are not broken: + +| Check | How to Test | Severity | +|-------|------------|----------| +| Removed fields | Diff response shape against baseline | **HIGH** — breaks consumers | +| Renamed fields | Diff response keys | **HIGH** — breaks consumers | +| Changed field type | Compare type of each field | **HIGH** — breaks deserialization | +| New required request field | Send old-format request | **HIGH** — breaks callers | +| Changed enum values | Check if old values still accepted | **MEDIUM** — breaks validation | +| Changed error format | Compare error response structure | **MEDIUM** — breaks error handlers | +| Changed status codes | Compare response codes for same input | **MEDIUM** — breaks status checks | +| New optional fields | Verify response still parses | **LOW** — usually safe | +| Pagination format change | Test with existing page params | **MEDIUM** — breaks pagination loops | + +### Consumer-Driven Contract Testing + +Concept: Each API consumer defines the minimum contract they need (required fields, forbidden fields, expected status codes). The provider runs all consumer contracts in CI. + +```json +{ + "consumer": "mobile-app-v2", + "provider": "user-service", + "interactions": [ + { + "description": "get user profile", + "request": {"method": "GET", "path": "/api/users/me", "headers": {"Authorization": "Bearer valid_token"}}, + "response": {"status": 200, "body_contains": ["id", "name", "email"], "body_must_not_contain": ["password", "internal_id"]} + } + ] +} +``` + +Runner approach: iterate interactions, execute each request with curl, verify status code matches and required/forbidden fields are present/absent in the response body. + +--- + +## Performance Testing Deep Dive + +### Load Test Types + +| Type | Purpose | Pattern | +|------|---------|---------| +| **Soak** | Detect memory leaks, connection pool exhaustion | Steady traffic (e.g., 5 req/s) for hours; compare first-quarter vs last-quarter response times | +| **Spike** | Verify graceful handling of sudden bursts | Baseline → 10x-20x burst → recovery; check error rate and recovery time | +| **Stress** | Find the breaking point | Incrementally increase concurrency until errors begin | + +### Stress Testing (Representative Example) + +Incrementally increase load until errors begin — adapt the same pattern for soak (fixed concurrency, long duration) or spike (sudden burst) testing: + +```bash +echo "concurrency,success_rate,avg_time,p95_time" > /tmp/stress_results.csv +for CONCURRENCY in 10 25 50 100 200 500; do + RESULTS=$(mktemp) + for i in $(seq 1 $CONCURRENCY); do + curl -s -o /dev/null -w "%{http_code} %{time_total}\n" \ + -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/data" >> "$RESULTS" & + done + wait + + TOTAL=$(wc -l < "$RESULTS") + SUCCESS=$(grep -c "^200" "$RESULTS") + AVG_TIME=$(awk '{sum+=$2; n++} END {printf "%.3f", sum/n}' "$RESULTS") + P95_TIME=$(awk '{print $2}' "$RESULTS" | sort -n | awk -v p=0.95 'NR==1{n=0} {a[n++]=$1} END {print a[int(n*p)]}') + + echo "$CONCURRENCY,$((SUCCESS*100/TOTAL))%,$AVG_TIME,$P95_TIME" >> /tmp/stress_results.csv + echo "Concurrency $CONCURRENCY: ${SUCCESS}/${TOTAL} success, avg=${AVG_TIME}s, p95=${P95_TIME}s" + + rm "$RESULTS" + sleep 3 # Let the server recover between steps +done + +echo "=== Stress Test Summary ===" +column -t -s',' /tmp/stress_results.csv +``` + +### Latency Percentile Analysis + +Collect many response times (e.g., 1000 with concurrency capped at 20), then compute p50/p75/p90/p95/p99 percentiles. Compare first-quarter vs last-quarter averages to detect degradation over time. + +```bash +# Collect response times +TIMES_FILE=$(mktemp) +for i in $(seq 1 1000); do + curl -s -o /dev/null -w "%{time_total}\n" \ + -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/data" >> "$TIMES_FILE" & + [ $((i % 20)) -eq 0 ] && wait +done +wait +# Sort and compute percentiles with: sort -n "$TIMES_FILE" | python3 ... +rm "$TIMES_FILE" +``` + +### Connection Pool Testing + +- **Keep-alive reuse**: Send multiple URLs in one curl call with `Connection: keep-alive`; second/third requests should show near-zero `time_connect`. +- **Connection exhaustion**: Open 500 concurrent keep-alive connections; watch for 503 or connection refused errors. + +--- + +## Common API Bugs & How to Find Them + +### N+1 Query Detection + +Response time should not scale linearly with data size. If fetching 10 items takes 100ms but 100 items takes 1000ms, the API likely has an N+1 query problem. + +```bash +# Compare response times for different page sizes +for SIZE in 1 10 50 100; do + TIME=$(curl -s -o /dev/null -w "%{time_total}" \ + -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/orders?per_page=$SIZE") + echo "page_size=$SIZE time=${TIME}s" +done +# Expected (healthy): Times should NOT scale linearly +# page_size=1 time=0.045s +# page_size=10 time=0.052s +# page_size=50 time=0.078s +# page_size=100 time=0.110s +# Red flag (N+1): Times scale roughly linearly +# page_size=1 time=0.045s +# page_size=10 time=0.350s +# page_size=50 time=1.600s +# page_size=100 time=3.200s +``` + +### Race Condition Testing + +```bash +# Concurrent counter increment — final value should equal attempt count +curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \ + -d '{"value": 0}' "https://api.example.com/api/counters/counter_001" + +for i in $(seq 1 50); do + curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \ + -d '{"increment": 1}' "https://api.example.com/api/counters/counter_001/increment" & +done +wait + +FINAL=$(curl -s -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/counters/counter_001" | python3 -c "import sys,json; print(json.load(sys.stdin)['value'])") +[ "$FINAL" = "50" ] && echo "PASS: No race condition" || echo "FAIL: Lost $((50 - FINAL)) increments" +``` + +**Optimistic locking test**: Two concurrent PUTs with same `If-Match` ETag — one should get 200, the other 409 Conflict. + +### Pagination Edge Cases + +| Input | Expected Behavior | +|-------|------------------| +| `page=0` | 400, or treat as page 1 | +| `page=-1` | 400 | +| `page=99999` (beyond data) | 200 with empty array, not error | +| `per_page=0` | 400 or use default | +| `per_page=100000` | Capped to server max (e.g., 100) | +| Delete item mid-pagination | No items skipped or duplicated on next page | + +### Timezone Handling Bugs + +Test that equivalent timestamps in different offset formats are stored identically: + +```bash +# All four represent the same moment — stored values should be equivalent +for TZ in "2025-06-15T10:00:00Z" "2025-06-15T10:00:00+00:00" "2025-06-15T18:00:00+08:00" "2025-06-15T05:00:00-05:00"; do + STORED=$(curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \ + -d "{\"title\": \"tz_test\", \"scheduled_at\": \"$TZ\"}" \ + "https://api.example.com/api/events" | python3 -c "import sys,json; print(json.load(sys.stdin).get('scheduled_at','ERROR'))") + echo "Input: $TZ -> Stored: $STORED" +done +``` + +**Also test**: date range filters across timezone boundaries, midnight boundary inclusion/exclusion behavior. + +### Character Encoding Issues + +Test that the API correctly round-trips various Unicode inputs. Key test values: + +| Category | Example | What Breaks | +|----------|---------|-------------| +| Emoji | `Hello 🌍🚀` | UTF-8 4-byte sequences, database column width | +| CJK | `你好世界` | Multi-byte encoding, string length vs byte length | +| Diacritics | `café` (composed vs decomposed) | Unicode normalization (NFC vs NFD) | +| Zero-width | `test\u200Bword` | Invisible characters in search/comparison | +| Null byte | `test\u0000value` | String termination in C-based systems | + +```bash +# Round-trip test pattern: POST a value, verify GET returns the same +for VALUE in "Hello 🌍🚀" "你好世界" "café"; do + RESPONSE=$(curl -s -X POST -H "Content-Type: application/json; charset=utf-8" \ + -H "Authorization: Bearer $TOKEN" \ + -d "{\"name\": \"$VALUE\"}" \ + "https://api.example.com/api/items") + RETURNED=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('name','ERROR'))") + [ "$VALUE" = "$RETURNED" ] && echo "PASS: $VALUE" || echo "FAIL: sent='$VALUE' got='$RETURNED'" +done +``` + +--- + +## Advanced curl Patterns + +### File Upload Testing + +```bash +# Single file upload +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Authorization: Bearer $TOKEN" \ + -F "file=@/path/to/document.pdf" \ + -F "description=Test upload" \ + "https://api.example.com/api/uploads") +echo "Single file upload: $STATUS" + +# Multiple file upload +STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Authorization: Bearer $TOKEN" \ + -F "files[]=@/path/to/file1.png" \ + -F "files[]=@/path/to/file2.png" \ + -F "category=images" \ + "https://api.example.com/api/uploads/batch") +echo "Multi-file upload: $STATUS" +``` + +**Edge cases to also test**: oversized files (expect 413), wrong content type (e.g., `script.sh` declared as `image/png`), zero-byte files (expect 400). + +### Multipart Form Data + +```bash +# Mixed multipart: file + JSON metadata +curl -s -X POST \ + -H "Authorization: Bearer $TOKEN" \ + -F "metadata={\"title\":\"Report Q4\",\"tags\":[\"finance\",\"quarterly\"]};type=application/json" \ + -F "file=@/path/to/report.pdf" \ + "https://api.example.com/api/documents" + +# Form-encoded data (not JSON) +curl -s -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "username=testuser&password=testpass&remember=true" \ + "https://api.example.com/auth/login" +``` + +### Cookie-Based Session Testing + +```bash +# Full session lifecycle with cookie jar +COOKIE_JAR=$(mktemp) + +# Login — store cookies +curl -s -c "$COOKIE_JAR" -X POST \ + -H "Content-Type: application/json" \ + -d '{"username": "testuser", "password": "testpass"}' \ + "https://api.example.com/auth/login" + +# Authenticated request — send cookies +curl -s -b "$COOKIE_JAR" -c "$COOKIE_JAR" \ + "https://api.example.com/api/profile" + +# Logout and verify session invalidated +curl -s -b "$COOKIE_JAR" -c "$COOKIE_JAR" -X POST \ + "https://api.example.com/auth/logout" +STATUS=$(curl -s -b "$COOKIE_JAR" -o /dev/null -w "%{http_code}" \ + "https://api.example.com/api/profile") +[ "$STATUS" = "401" ] && echo "PASS: Session invalidated" || echo "FAIL: Got $STATUS" +rm "$COOKIE_JAR" +``` + +**Also verify**: HttpOnly/Secure/SameSite cookie attributes, session ID rotation on login (session fixation prevention). + +### Following Redirects + +```bash +# Follow redirects automatically +curl -s -L -o /dev/null -w "final_url:%{url_effective} status:%{http_code} redirects:%{num_redirects}\n" \ + "https://api.example.com/old-endpoint" + +# Don't follow — inspect redirect target +curl -s -D- -o /dev/null \ + "https://api.example.com/old-endpoint" | grep -i "location:" + +# Open redirect vulnerability test +LOCATION=$(curl -s -D- -o /dev/null \ + "https://api.example.com/redirect?url=https://evil.example.com" | grep -i "location:" | tr -d '\r') +echo "$LOCATION" | grep -q "evil.example.com" && echo "FAIL: Open redirect vulnerability" || echo "PASS: Redirect restricted" + +# HTTP to HTTPS redirect check +STATUS=$(curl -s -o /dev/null -w "%{http_code}" "http://api.example.com/api/data") +[ "$STATUS" = "301" ] || [ "$STATUS" = "308" ] && echo "PASS: HTTP redirects to HTTPS" || echo "WARN: No HTTPS redirect (got $STATUS)" +``` + +### HEAD, OPTIONS, and CORS + +```bash +# HEAD request — verify no body returned +curl -s -I -w "status:%{http_code} size:%{size_download}\n" \ + -H "Authorization: Bearer $TOKEN" \ + "https://api.example.com/api/data" + +# OPTIONS request — check CORS and allowed methods +curl -s -X OPTIONS -D- -o /dev/null \ + -H "Origin: https://myapp.example.com" \ + -H "Access-Control-Request-Method: POST" \ + "https://api.example.com/api/data" | grep -iE "(allow|access-control)" +``` diff --git a/hands/browser/HAND.toml b/hands/browser/HAND.toml index 3ff4f86..cad8f0d 100644 --- a/hands/browser/HAND.toml +++ b/hands/browser/HAND.toml @@ -296,6 +296,169 @@ token_consumption = "low" default_active = true activation_warning = "Browser hand runs continuously but mainly consumes tokens when actively performing web tasks." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "浏览器 Hand" description = "自主网页浏览器——导航网站、填写表单、点击按钮,经用户批准后完成多步骤网页任务" +category = "生产力" + +[i18n.zh.settings.headless] +label = "无头模式" +description = "在不显示浏览器窗口的情况下运行(推荐用于服务器环境)" + +[i18n.zh.settings.approval_mode] +label = "购买审批" +description = "在完成任何购买或支付操作前,需要用户明确确认" + +[i18n.zh.settings.max_pages_per_task] +label = "每任务最大页面数" +description = "每个任务允许的最大页面导航次数,防止无限浏览" + +[i18n.zh.settings.default_wait] +label = "操作后默认等待" +description = "点击或导航后等待页面稳定的时长" + +[i18n.zh.settings.screenshot_on_action] +label = "操作后截图" +description = "每次点击/导航后自动截图,用于视觉验证" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "ブラウザ Hand" +description = "自律型ウェブブラウザ——サイトのナビゲーション、フォーム入力、ボタンクリック、ユーザー承認付きの複数ステップWebタスクの実行" +category = "生産性" + +[i18n.ja.settings.headless] +label = "ヘッドレスモード" +description = "ブラウザウィンドウを表示せずに実行する(サーバー環境に推奨)" + +[i18n.ja.settings.approval_mode] +label = "購入承認" +description = "購入や支払いを完了する前にユーザーの明示的な確認を求める" + +[i18n.ja.settings.max_pages_per_task] +label = "タスクあたりの最大ページ数" +description = "暴走的なブラウジングを防ぐため、タスクごとに許可されるページ遷移の最大数" + +[i18n.ja.settings.default_wait] +label = "操作後のデフォルト待機時間" +description = "クリックやナビゲーション後、ページが安定するまでの待機時間" + +[i18n.ja.settings.screenshot_on_action] +label = "操作後のスクリーンショット" +description = "クリック/ナビゲーションのたびに自動的にスクリーンショットを撮影し、視覚的に確認する" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Navegador" +description = "Navegador web autónomo — navega sitios, completa formularios, hace clic en botones y realiza tareas web de múltiples pasos con aprobación del usuario para compras" +category = "Productividad" + +[i18n.es.settings.headless] +label = "Modo sin interfaz" +description = "Ejecutar el navegador sin ventana visible (recomendado para servidores)" + +[i18n.es.settings.approval_mode] +label = "Aprobación de compras" +description = "Requerir confirmación explícita del usuario antes de completar cualquier compra o pago" + +[i18n.es.settings.max_pages_per_task] +label = "Máximo de páginas por tarea" +description = "Número máximo de navegaciones de página permitidas por tarea para evitar navegación descontrolada" + +[i18n.es.settings.default_wait] +label = "Espera predeterminada tras acción" +description = "Cuánto tiempo esperar después de hacer clic o navegar para que la página se estabilice" + +[i18n.es.settings.screenshot_on_action] +label = "Captura de pantalla tras acciones" +description = "Tomar automáticamente una captura de pantalla después de cada clic/navegación para verificación visual" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Navigateur" +description = "Navigateur web autonome — navigue sur les sites, remplit les formulaires, clique sur les boutons et exécute des tâches web multi-étapes avec approbation utilisateur pour les achats" +category = "Productivité" + +[i18n.fr.settings.headless] +label = "Mode sans interface" +description = "Exécuter le navigateur sans fenêtre visible (recommandé pour les serveurs)" + +[i18n.fr.settings.approval_mode] +label = "Approbation des achats" +description = "Exiger la confirmation explicite de l'utilisateur avant de finaliser tout achat ou paiement" + +[i18n.fr.settings.max_pages_per_task] +label = "Pages maximum par tâche" +description = "Nombre maximum de navigations de page autorisées par tâche pour éviter une navigation incontrôlée" + +[i18n.fr.settings.default_wait] +label = "Attente par défaut après action" +description = "Durée d'attente après un clic ou une navigation pour que la page se stabilise" + +[i18n.fr.settings.screenshot_on_action] +label = "Capture d'écran après action" +description = "Prendre automatiquement une capture d'écran après chaque clic/navigation pour vérification visuelle" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Browser-Hand" +description = "Autonomer Webbrowser — navigiert Websites, füllt Formulare aus, klickt Schaltflächen und führt mehrstufige Webaufgaben mit Benutzerfreigabe für Käufe aus" +category = "Produktivität" + +[i18n.de.settings.headless] +label = "Headless-Modus" +description = "Browser ohne sichtbares Fenster ausführen (empfohlen für Server)" + +[i18n.de.settings.approval_mode] +label = "Kaufgenehmigung" +description = "Ausdrückliche Benutzerbestätigung vor dem Abschluss eines Kaufs oder einer Zahlung erforderlich" + +[i18n.de.settings.max_pages_per_task] +label = "Maximale Seiten pro Aufgabe" +description = "Maximale Anzahl erlaubter Seitennavigationen pro Aufgabe, um unkontrolliertes Surfen zu verhindern" + +[i18n.de.settings.default_wait] +label = "Standard-Wartezeit nach Aktion" +description = "Wartezeit nach einem Klick oder einer Navigation, bis sich die Seite stabilisiert hat" + +[i18n.de.settings.screenshot_on_action] +label = "Screenshot nach Aktion" +description = "Nach jedem Klick/jeder Navigation automatisch einen Screenshot für visuelle Überprüfung erstellen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "브라우저 Hand" +description = "자율 웹 브라우저 — 사이트 탐색, 양식 작성, 버튼 클릭, 구매 시 사용자 승인을 받아 다단계 웹 작업 수행" +category = "생산성" + +[i18n.ko.settings.headless] +label = "헤드리스 모드" +description = "브라우저 창을 표시하지 않고 실행 (서버 환경에 권장)" + +[i18n.ko.settings.approval_mode] +label = "구매 승인" +description = "구매 또는 결제 완료 전 사용자의 명시적 확인 필요" + +[i18n.ko.settings.max_pages_per_task] +label = "작업당 최대 페이지 수" +description = "작업당 허용되는 최대 페이지 탐색 횟수 (무한 브라우징 방지)" + +[i18n.ko.settings.default_wait] +label = "동작 후 기본 대기" +description = "클릭 또는 탐색 후 페이지가 안정될 때까지 대기하는 시간" + +[i18n.ko.settings.screenshot_on_action] +label = "동작 후 스크린샷" +description = "클릭/탐색 후 자동으로 스크린샷을 캡처하여 시각적으로 검증" diff --git a/hands/clip/HAND.toml b/hands/clip/HAND.toml index ec0a22a..e31a520 100644 --- a/hands/clip/HAND.toml +++ b/hands/clip/HAND.toml @@ -645,6 +645,289 @@ frequency = "on-demand" token_consumption = "medium" default_active = false +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "视频剪辑 Hand" description = "将长视频自动剪辑为病毒式短视频,配有字幕和缩略图" +category = "内容" + +[i18n.zh.settings.stt_provider] +label = "语音转文字服务" +description = "用于生成字幕和片段选择的音频转录方式" + +[i18n.zh.settings.tts_provider] +label = "文字转语音服务" +description = "可选的配音或旁白生成服务" + +[i18n.zh.settings.elevenlabs_api_key] +label = "ElevenLabs API 密钥" +description = "来自 elevenlabs.io 的高质量文字转语音 API 密钥。选择 ElevenLabs TTS 时必填。" + +[i18n.zh.settings.publish_target] +label = "发布目标" +description = "处理完成后将短视频发送到哪里。选择"仅本地"则跳过发布。" + +[i18n.zh.settings.telegram_bot_token] +label = "Telegram 机器人令牌" +description = "从 Telegram 的 @BotFather 获取(例如 123456:ABC-DEF...)。机器人需为目标频道管理员。" + +[i18n.zh.settings.telegram_chat_id] +label = "Telegram 聊天 ID" +description = "频道:-100XXXXXXXXXX 或 @频道名。群组:数字 ID。可通过 @userinfobot 获取。" + +[i18n.zh.settings.whatsapp_token] +label = "WhatsApp 访问令牌" +description = "从 Meta 商务管理平台 > 系统用户获取的永久令牌。临时令牌 24 小时后过期。" + +[i18n.zh.settings.whatsapp_phone_id] +label = "WhatsApp 电话号码 ID" +description = "从 Meta 开发者门户 > WhatsApp > API 设置获取(例如 1234567890)" + +[i18n.zh.settings.whatsapp_recipient] +label = "WhatsApp 接收方" +description = "国际格式的电话号码,不含 + 号或空格(例如 14155551234)" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "发布到频道前将短视频加入队列供审核" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "動画クリップ Hand" +description = "長尺動画をキャプション付きサムネイル付きのバイラルショートクリップに変換" +category = "コンテンツ" + +[i18n.ja.settings.stt_provider] +label = "音声テキスト変換プロバイダー" +description = "字幕生成とクリップ選択に使用する音声の文字起こし方法" + +[i18n.ja.settings.tts_provider] +label = "テキスト音声変換プロバイダー" +description = "クリップへのオプションのボイスオーバーまたはナレーション生成" + +[i18n.ja.settings.elevenlabs_api_key] +label = "ElevenLabs APIキー" +description = "elevenlabs.ioの高品質テキスト音声変換用APIキー。ElevenLabs TTSを選択した場合に必須。" + +[i18n.ja.settings.publish_target] +label = "公開先" +description = "処理完了後にクリップを送信する先。「ローカルのみ」を選択すると公開をスキップします。" + +[i18n.ja.settings.telegram_bot_token] +label = "Telegramボットトークン" +description = "Telegramの@BotFatherから取得(例: 123456:ABC-DEF...)。ボットは対象チャンネルの管理者である必要があります。" + +[i18n.ja.settings.telegram_chat_id] +label = "TelegramチャットID" +description = "チャンネル: -100XXXXXXXXXX または @チャンネル名。グループ: 数値ID。@userinfobot で取得可能。" + +[i18n.ja.settings.whatsapp_token] +label = "WhatsAppアクセストークン" +description = "Metaビジネス設定 > システムユーザーから取得した永続トークン。一時トークンは24時間で期限切れになります。" + +[i18n.ja.settings.whatsapp_phone_id] +label = "WhatsApp電話番号ID" +description = "Meta開発者ポータル > WhatsApp > APIセットアップから取得(例: 1234567890)" + +[i18n.ja.settings.whatsapp_recipient] +label = "WhatsApp送信先" +description = "国際形式の電話番号(+やスペースなし、例: 14155551234)" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "チャンネルに公開する前にクリップをレビュー用キューに追加する" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Clips de Video" +description = "Convierte videos largos en clips cortos virales con subtítulos y miniaturas" +category = "Contenido" + +[i18n.es.settings.stt_provider] +label = "Proveedor de voz a texto" +description = "Cómo se transcribe el audio a texto para subtítulos y selección de clips" + +[i18n.es.settings.tts_provider] +label = "Proveedor de texto a voz" +description = "Generación opcional de locución o narración para los clips" + +[i18n.es.settings.elevenlabs_api_key] +label = "Clave API de ElevenLabs" +description = "Clave API de elevenlabs.io para texto a voz de alta calidad. Requerida cuando se selecciona ElevenLabs TTS." + +[i18n.es.settings.publish_target] +label = "Destino de publicación" +description = "Dónde enviar los clips terminados después del procesamiento. Seleccionar 'Solo local' para omitir la publicación." + +[i18n.es.settings.telegram_bot_token] +label = "Token del bot de Telegram" +description = "De @BotFather en Telegram (ej. 123456:ABC-DEF...). El bot debe ser administrador del canal de destino." + +[i18n.es.settings.telegram_chat_id] +label = "ID de chat de Telegram" +description = "Canal: -100XXXXXXXXXX o @nombrechannel. Grupo: ID numérico. Obtener mediante @userinfobot." + +[i18n.es.settings.whatsapp_token] +label = "Token de acceso de WhatsApp" +description = "Token permanente de Meta Business Settings > Usuarios del sistema. Los tokens temporales expiran en 24h." + +[i18n.es.settings.whatsapp_phone_id] +label = "ID de número de teléfono de WhatsApp" +description = "Desde el Portal de Desarrolladores de Meta > WhatsApp > Configuración de API (ej. 1234567890)" + +[i18n.es.settings.whatsapp_recipient] +label = "Destinatario de WhatsApp" +description = "Número de teléfono en formato internacional, sin + ni espacios (ej. 14155551234)" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Poner clips en cola para revisión antes de publicarlos en los canales" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Clips Vidéo" +description = "Transforme les longues vidéos en clips courts viraux avec sous-titres et miniatures" +category = "Contenu" + +[i18n.fr.settings.stt_provider] +label = "Fournisseur de reconnaissance vocale" +description = "Méthode de transcription audio pour les sous-titres et la sélection de clips" + +[i18n.fr.settings.tts_provider] +label = "Fournisseur de synthèse vocale" +description = "Génération optionnelle de voix off ou de narration pour les clips" + +[i18n.fr.settings.elevenlabs_api_key] +label = "Clé API ElevenLabs" +description = "Clé API de elevenlabs.io pour la synthèse vocale haute qualité. Requise lorsque ElevenLabs TTS est sélectionné." + +[i18n.fr.settings.publish_target] +label = "Destination de publication" +description = "Où envoyer les clips terminés après traitement. Sélectionner 'Local uniquement' pour ignorer la publication." + +[i18n.fr.settings.telegram_bot_token] +label = "Jeton du bot Telegram" +description = "De @BotFather sur Telegram (ex. 123456:ABC-DEF...). Le bot doit être administrateur du canal cible." + +[i18n.fr.settings.telegram_chat_id] +label = "ID de chat Telegram" +description = "Canal : -100XXXXXXXXXX ou @nomducanal. Groupe : ID numérique. Obtenir via @userinfobot." + +[i18n.fr.settings.whatsapp_token] +label = "Jeton d'accès WhatsApp" +description = "Jeton permanent depuis Meta Business Settings > Utilisateurs système. Les jetons temporaires expirent en 24h." + +[i18n.fr.settings.whatsapp_phone_id] +label = "ID de numéro de téléphone WhatsApp" +description = "Depuis le Portail Développeurs Meta > WhatsApp > Configuration API (ex. 1234567890)" + +[i18n.fr.settings.whatsapp_recipient] +label = "Destinataire WhatsApp" +description = "Numéro de téléphone au format international, sans + ni espaces (ex. 14155551234)" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Mettre les clips en file d'attente pour révision avant publication sur les canaux" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Videoclip-Hand" +description = "Verwandelt lange Videos in virale Kurzclips mit Untertiteln und Vorschaubildern" +category = "Inhalt" + +[i18n.de.settings.stt_provider] +label = "Sprache-zu-Text-Anbieter" +description = "Methode der Audiotranskription für Untertitel und Clipauswahl" + +[i18n.de.settings.tts_provider] +label = "Text-zu-Sprache-Anbieter" +description = "Optionale Voiceover- oder Erzählungsgenerierung für Clips" + +[i18n.de.settings.elevenlabs_api_key] +label = "ElevenLabs API-Schlüssel" +description = "API-Schlüssel von elevenlabs.io für hochwertige Text-zu-Sprache. Erforderlich bei Auswahl von ElevenLabs TTS." + +[i18n.de.settings.publish_target] +label = "Veröffentlichungsziel" +description = "Wohin fertige Clips nach der Verarbeitung gesendet werden. 'Nur lokal' wählen, um die Veröffentlichung zu überspringen." + +[i18n.de.settings.telegram_bot_token] +label = "Telegram-Bot-Token" +description = "Von @BotFather auf Telegram (z.B. 123456:ABC-DEF...). Der Bot muss Administrator des Zielkanals sein." + +[i18n.de.settings.telegram_chat_id] +label = "Telegram-Chat-ID" +description = "Kanal: -100XXXXXXXXXX oder @Kanalname. Gruppe: Numerische ID. Über @userinfobot abrufbar." + +[i18n.de.settings.whatsapp_token] +label = "WhatsApp-Zugriffstoken" +description = "Permanentes Token aus Meta Business Settings > Systembenutzer. Temporäre Token laufen nach 24h ab." + +[i18n.de.settings.whatsapp_phone_id] +label = "WhatsApp-Telefonnummer-ID" +description = "Aus dem Meta-Entwicklerportal > WhatsApp > API-Einrichtung (z.B. 1234567890)" + +[i18n.de.settings.whatsapp_recipient] +label = "WhatsApp-Empfänger" +description = "Telefonnummer im internationalen Format, ohne + oder Leerzeichen (z.B. 14155551234)" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Clips zur Überprüfung in die Warteschlange stellen, bevor sie auf Kanälen veröffentlicht werden" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "비디오 클립 Hand" +description = "장편 영상을 자막과 썸네일이 포함된 바이럴 숏폼 클립으로 변환" +category = "콘텐츠" + +[i18n.ko.settings.stt_provider] +label = "음성-텍스트 변환 서비스" +description = "자막 생성 및 클립 선택을 위한 오디오 전사 방식" + +[i18n.ko.settings.tts_provider] +label = "텍스트-음성 변환 서비스" +description = "선택적 더빙 또는 나레이션 생성 서비스" + +[i18n.ko.settings.elevenlabs_api_key] +label = "ElevenLabs API 키" +description = "elevenlabs.io의 고품질 텍스트-음성 변환 API 키. ElevenLabs TTS 선택 시 필수." + +[i18n.ko.settings.publish_target] +label = "게시 대상" +description = "처리 완료 후 숏폼 클립을 전송할 위치. '로컬 전용'을 선택하면 게시를 건너뜁니다." + +[i18n.ko.settings.telegram_bot_token] +label = "Telegram 봇 토큰" +description = "Telegram의 @BotFather에서 발급 (예: 123456:ABC-DEF...). 봇이 대상 채널의 관리자여야 합니다." + +[i18n.ko.settings.telegram_chat_id] +label = "Telegram 채팅 ID" +description = "채널: -100XXXXXXXXXX 또는 @채널명. 그룹: 숫자 ID. @userinfobot으로 확인 가능." + +[i18n.ko.settings.whatsapp_token] +label = "WhatsApp 액세스 토큰" +description = "Meta 비즈니스 설정 > 시스템 사용자에서 발급한 영구 토큰. 임시 토큰은 24시간 후 만료." + +[i18n.ko.settings.whatsapp_phone_id] +label = "WhatsApp 전화번호 ID" +description = "Meta 개발자 포털 > WhatsApp > API 설정에서 확인 (예: 1234567890)" + +[i18n.ko.settings.whatsapp_recipient] +label = "WhatsApp 수신자" +description = "+ 기호나 공백 없이 국제 형식의 전화번호 (예: 14155551234)" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "채널에 게시하기 전 클립을 대기열에 추가하여 검토" diff --git a/hands/collector/HAND.toml b/hands/collector/HAND.toml index 930559e..ac9e419 100644 --- a/hands/collector/HAND.toml +++ b/hands/collector/HAND.toml @@ -391,6 +391,241 @@ token_consumption = "high" default_active = false activation_warning = "Collector hand runs continuously and monitors targets, consuming tokens." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "情报采集 Hand" description = "自主情报采集智能体——持续监控目标,支持变更检测和知识图谱" +category = "数据" + +[i18n.zh.settings.target_subject] +label = "监控目标" +description = "要监控的对象(公司名称、人物、技术、市场、话题)" + +[i18n.zh.settings.collection_depth] +label = "采集深度" +description = "每个采集周期的挖掘深度" + +[i18n.zh.settings.update_frequency] +label = "更新频率" +description = "执行采集扫描的频率" + +[i18n.zh.settings.focus_area] +label = "关注领域" +description = "分析采集情报时的侧重角度" + +[i18n.zh.settings.alert_on_changes] +label = "变更告警" +description = "检测到重大变更时发布事件通知" + +[i18n.zh.settings.report_format] +label = "报告格式" +description = "情报报告的输出格式" + +[i18n.zh.settings.max_sources_per_cycle] +label = "每周期最大来源数" +description = "每次采集扫描处理的最大来源数量" + +[i18n.zh.settings.track_sentiment] +label = "情感追踪" +description = "分析并追踪随时间变化的情感趋势" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "インテリジェンス収集 Hand" +description = "自律型インテリジェンス収集エージェント——変更検出とナレッジグラフによる対象の継続的監視" +category = "データ" + +[i18n.ja.settings.target_subject] +label = "監視対象" +description = "監視する対象(企業名、人物、技術、市場、トピック)" + +[i18n.ja.settings.collection_depth] +label = "収集深度" +description = "各収集サイクルでの調査の深さ" + +[i18n.ja.settings.update_frequency] +label = "更新頻度" +description = "収集スキャンの実行頻度" + +[i18n.ja.settings.focus_area] +label = "フォーカスエリア" +description = "収集したインテリジェンスを分析する際の視点" + +[i18n.ja.settings.alert_on_changes] +label = "変更アラート" +description = "重大な変更が検出された場合にイベント通知を発行する" + +[i18n.ja.settings.report_format] +label = "レポート形式" +description = "インテリジェンスレポートの出力形式" + +[i18n.ja.settings.max_sources_per_cycle] +label = "サイクルあたりの最大ソース数" +description = "各収集スキャンで処理するソースの最大数" + +[i18n.ja.settings.track_sentiment] +label = "センチメント追跡" +description = "時間の経過に伴うセンチメントの傾向を分析・追跡する" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Recopilación de Inteligencia" +description = "Recopilador autónomo de inteligencia — monitorea cualquier objetivo de forma continua con detección de cambios y grafos de conocimiento" +category = "Datos" + +[i18n.es.settings.target_subject] +label = "Objetivo de monitoreo" +description = "Qué monitorear (nombre de empresa, persona, tecnología, mercado, tema)" + +[i18n.es.settings.collection_depth] +label = "Profundidad de recopilación" +description = "Qué tan profundo investigar en cada ciclo" + +[i18n.es.settings.update_frequency] +label = "Frecuencia de actualización" +description = "Con qué frecuencia ejecutar los barridos de recopilación" + +[i18n.es.settings.focus_area] +label = "Área de enfoque" +description = "Perspectiva desde la cual analizar la inteligencia recopilada" + +[i18n.es.settings.alert_on_changes] +label = "Alertar ante cambios" +description = "Publicar un evento cuando se detecten cambios significativos" + +[i18n.es.settings.report_format] +label = "Formato de informe" +description = "Formato de salida para los informes de inteligencia" + +[i18n.es.settings.max_sources_per_cycle] +label = "Máximo de fuentes por ciclo" +description = "Número máximo de fuentes a procesar por barrido de recopilación" + +[i18n.es.settings.track_sentiment] +label = "Seguimiento de sentimiento" +description = "Analizar y rastrear las tendencias de sentimiento a lo largo del tiempo" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Collecteur de Renseignements" +description = "Collecteur autonome de renseignements — surveille toute cible en continu avec détection de changements et graphes de connaissances" +category = "Données" + +[i18n.fr.settings.target_subject] +label = "Sujet cible" +description = "Objet de la surveillance (nom d'entreprise, personne, technologie, marché, sujet)" + +[i18n.fr.settings.collection_depth] +label = "Profondeur de collecte" +description = "Niveau d'approfondissement à chaque cycle de collecte" + +[i18n.fr.settings.update_frequency] +label = "Fréquence de mise à jour" +description = "Fréquence d'exécution des cycles de collecte" + +[i18n.fr.settings.focus_area] +label = "Domaine d'intérêt" +description = "Angle d'analyse des renseignements collectés" + +[i18n.fr.settings.alert_on_changes] +label = "Alerte sur changements" +description = "Publier un événement lorsque des changements significatifs sont détectés" + +[i18n.fr.settings.report_format] +label = "Format de rapport" +description = "Format de sortie pour les rapports de renseignements" + +[i18n.fr.settings.max_sources_per_cycle] +label = "Sources maximum par cycle" +description = "Nombre maximum de sources à traiter par cycle de collecte" + +[i18n.fr.settings.track_sentiment] +label = "Suivi du sentiment" +description = "Analyser et suivre les tendances de sentiment au fil du temps" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Informationssammlungs-Hand" +description = "Autonomer Informationssammler — überwacht jedes Ziel kontinuierlich mit Änderungserkennung und Wissensgraphen" +category = "Daten" + +[i18n.de.settings.target_subject] +label = "Zielobjekt" +description = "Was überwacht werden soll (Firmenname, Person, Technologie, Markt, Thema)" + +[i18n.de.settings.collection_depth] +label = "Sammlungstiefe" +description = "Wie tief in jedem Sammlungszyklus recherchiert wird" + +[i18n.de.settings.update_frequency] +label = "Aktualisierungshäufigkeit" +description = "Wie oft Sammlungszyklen ausgeführt werden" + +[i18n.de.settings.focus_area] +label = "Fokusbereich" +description = "Perspektive für die Analyse der gesammelten Informationen" + +[i18n.de.settings.alert_on_changes] +label = "Warnung bei Änderungen" +description = "Ein Ereignis veröffentlichen, wenn bedeutende Änderungen erkannt werden" + +[i18n.de.settings.report_format] +label = "Berichtsformat" +description = "Ausgabeformat für Informationsberichte" + +[i18n.de.settings.max_sources_per_cycle] +label = "Maximale Quellen pro Zyklus" +description = "Maximale Anzahl der pro Sammlungszyklus zu verarbeitenden Quellen" + +[i18n.de.settings.track_sentiment] +label = "Stimmungsverfolgung" +description = "Stimmungstrends im Zeitverlauf analysieren und verfolgen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "정보 수집 Hand" +description = "자율 정보 수집 에이전트 — 대상을 지속적으로 모니터링하며 변경 감지 및 지식 그래프 지원" +category = "데이터" + +[i18n.ko.settings.target_subject] +label = "모니터링 대상" +description = "모니터링할 대상 (회사명, 인물, 기술, 시장, 주제)" + +[i18n.ko.settings.collection_depth] +label = "수집 깊이" +description = "각 수집 주기의 조사 깊이" + +[i18n.ko.settings.update_frequency] +label = "업데이트 빈도" +description = "수집 스캔 실행 주기" + +[i18n.ko.settings.focus_area] +label = "관심 분야" +description = "수집된 정보를 분석하는 관점" + +[i18n.ko.settings.alert_on_changes] +label = "변경 알림" +description = "중요한 변경 사항 감지 시 이벤트 알림 발행" + +[i18n.ko.settings.report_format] +label = "보고서 형식" +description = "정보 보고서의 출력 형식" + +[i18n.ko.settings.max_sources_per_cycle] +label = "주기당 최대 소스 수" +description = "수집 스캔당 처리할 최대 소스 수" + +[i18n.ko.settings.track_sentiment] +label = "감성 추적" +description = "시간에 따른 감성 추세 분석 및 추적" diff --git a/hands/collector/SKILL.md b/hands/collector/SKILL.md index 41c03fa..48037fd 100644 --- a/hands/collector/SKILL.md +++ b/hands/collector/SKILL.md @@ -269,3 +269,744 @@ Before including data in the knowledge graph, evaluate: 6. **Track record**: Has this source been reliable in the past? If a claim fails 3+ checks, downgrade its confidence to "low". + +--- + +## Worked Examples + +### Example 1: Competitor Monitoring Campaign + +**Scenario**: A B2B SaaS company wants continuous intelligence on three direct competitors: AlphaCloud, BetaStack, and GammaSuite. + +**Step 1 — Define targets and collection requirements** + +Configure the hand with: +``` +target_subject: "AlphaCloud, BetaStack, GammaSuite" +focus_area: competitor +collection_depth: deep +update_frequency: daily +alert_on_changes: true +track_sentiment: true +max_sources_per_cycle: 50 +``` + +Build the initial query set: +``` +"AlphaCloud" pricing OR plans OR tiers +"AlphaCloud" product launch OR release OR update +"AlphaCloud" review site:g2.com OR site:capterra.com +"AlphaCloud" customer case study +"AlphaCloud" hiring site:linkedin.com OR site:greenhouse.io +"switch from AlphaCloud to" +(repeat for BetaStack and GammaSuite) +``` + +**Step 2 — Run first collection cycle** + +Execute queries, fetch top results, extract entities: +```json +[ + {"type": "product", "name": "AlphaCloud v4.2", "company": "AlphaCloud", "launch_date": "2025-11-15", "source": "alphacloud.com/blog"}, + {"type": "person", "name": "Sarah Chen", "role": "New VP Engineering", "company": "BetaStack", "source": "linkedin.com/in/sarachen"}, + {"type": "event", "name": "GammaSuite Series C", "amount": "$85M", "date": "2025-11-10", "source": "techcrunch.com/2025/11/10/gammasuite-series-c"} +] +``` + +**Step 3 — Build knowledge graph entries** + +``` +knowledge_add_entity type=company name="AlphaCloud" industry="SaaS" funding_stage="Series B" +knowledge_add_entity type=product name="AlphaCloud v4.2" category="cloud platform" +knowledge_add_entity type=person name="Sarah Chen" role="VP Engineering" company="BetaStack" +knowledge_add_relation source="AlphaCloud" relation="launched" target="AlphaCloud v4.2" +knowledge_add_relation source="Sarah Chen" relation="works_at" target="BetaStack" +``` + +**Step 4 — Process findings into change detection** + +| Change | Type | Significance | Action | +|--------|------|-------------|--------| +| AlphaCloud released v4.2 with AI features | Product launch | IMPORTANT | Include in report, compare against own roadmap | +| BetaStack hired VP Engineering from FAANG | Leadership change | IMPORTANT | Track subsequent hiring patterns | +| GammaSuite raised $85M Series C | Major funding | CRITICAL | Immediate alert, expect aggressive expansion | + +**Step 5 — Generate intelligence brief** + +```markdown +# Competitor Intelligence Brief +**Date**: 2025-11-16 | **Cycle**: 1 | **Sources**: 47 + +## Priority Changes +1. [CRITICAL] GammaSuite closed $85M Series C led by Sequoia (TechCrunch, confirmed via Crunchbase) +2. [IMPORTANT] AlphaCloud shipped v4.2 with AI-assisted workflow builder +3. [IMPORTANT] BetaStack hired Sarah Chen (ex-Google) as VP Engineering + +## Executive Summary +GammaSuite's large funding round signals intent to accelerate growth — expect increased +marketing spend and possible M&A activity in the next 6 months. AlphaCloud's v4.2 +introduces direct feature overlap with our AI pipeline. BetaStack's engineering +leadership hire suggests a product quality push. + +## Recommended Actions +- Review AlphaCloud v4.2 feature parity against our roadmap +- Monitor GammaSuite job postings for expansion signals +- Track BetaStack engineering team growth over next 3 cycles +``` + +--- + +### Example 2: Technology Landscape Mapping + +**Scenario**: Map the emerging real-time AI inference landscape — track frameworks, adoption signals, key players, and performance benchmarks. + +**Step 1 — Define scope and seed entities** + +``` +target_subject: "real-time AI inference (vLLM, TensorRT-LLM, Triton, Ollama, llama.cpp)" +focus_area: technology +collection_depth: exhaustive +update_frequency: weekly +``` + +Initial seed queries: +``` +"real-time AI inference" benchmark 2025 +"vLLM" vs "TensorRT-LLM" performance +"llama.cpp" release changelog +"AI inference" startup funding 2025 +"edge AI inference" adoption enterprise +"AI inference" tokens per second benchmark +site:github.com "vLLM" stars OR contributors +site:arxiv.org "inference optimization" 2025 +``` + +**Step 2 — Build entity graph from first sweep** + +Entities collected: +```json +[ + {"type": "technology", "name": "vLLM", "version": "0.6.3", "vendor": "UC Berkeley / community", "category": "inference engine"}, + {"type": "technology", "name": "TensorRT-LLM", "version": "0.15", "vendor": "NVIDIA", "category": "inference engine"}, + {"type": "company", "name": "Groq", "industry": "AI hardware", "product": "LPU Inference Engine"}, + {"type": "number", "metric": "tokens_per_second", "value": 523, "context": "Groq Llama 3 70B", "date": "2025-10"}, + {"type": "number", "metric": "github_stars", "value": 32400, "context": "vLLM", "date": "2025-11"} +] +``` + +Relationships: +``` +vLLM --competes_with--> TensorRT-LLM +vLLM --competes_with--> Ollama +Groq --launched--> "LPU Inference Engine" +NVIDIA --launched--> TensorRT-LLM +llama.cpp --uses--> GGUF format +``` + +**Step 3 — Track adoption signals across cycles** + +| Signal Type | What to Watch | Detection Method | +|-------------|--------------|-----------------| +| GitHub velocity | Stars, forks, contributor count week-over-week | Snapshot comparison | +| Enterprise adoption | Case studies, "we migrated to X" blog posts | Keyword search | +| Benchmark results | Tokens/sec, latency, cost-per-token comparisons | Structured extraction | +| Job postings | "Experience with vLLM" in job descriptions | Job board queries | +| Conference talks | Accepted papers, keynote mentions | Conference program search | + +**Step 4 — Detect trends over 4 weekly cycles** + +``` +Cycle 1: vLLM 31,800 stars | TensorRT-LLM 9,200 stars | Ollama 98,000 stars +Cycle 2: vLLM 32,400 stars | TensorRT-LLM 9,500 stars | Ollama 101,000 stars +Cycle 3: vLLM 33,500 stars | TensorRT-LLM 9,600 stars | Ollama 103,500 stars +Cycle 4: vLLM 35,200 stars | TensorRT-LLM 9,700 stars | Ollama 105,000 stars + +Trend: vLLM accelerating (+1,700/wk avg → +1,700 last week) + Ollama decelerating (+3,000/wk → +1,500/wk) + TensorRT-LLM flat (~200/wk) +``` + +**Step 5 — Produce technology landscape report** + +Include a positioning summary: + +| Framework | Strengths | Weaknesses | Momentum | Best For | +|-----------|-----------|------------|----------|----------| +| vLLM | High throughput, PagedAttention | GPU-only, complex setup | Accelerating | Production serving at scale | +| TensorRT-LLM | NVIDIA optimization, low latency | Vendor lock-in, NVIDIA GPUs only | Flat | NVIDIA-stack deployments | +| Ollama | Simple UX, local-first | Lower throughput, less tunable | Decelerating | Developer experimentation | +| llama.cpp | CPU support, portable | Manual optimization needed | Steady | Edge/embedded inference | +| Groq LPU | Extreme speed, low latency | Limited model support, cloud-only | Growing | Latency-critical applications | + +--- + +### Example 3: M&A Signal Detection + +**Scenario**: Detect early acquisition indicators for companies in the enterprise observability space (Datadog, Grafana Labs, Chronosphere, Honeycomb). + +**Step 1 — Define M&A signal categories** + +| Signal Category | Indicators | Weight | +|----------------|-----------|--------| +| Executive changes | CEO/CFO departure, new "Chief Strategy Officer", board additions | High | +| Hiring patterns | Sudden corporate development/M&A roles, legal team expansion | High | +| Financial signals | Unusual funding, secondary sales, down round, runway concerns | High | +| Strategic moves | Exclusive partnerships, technology licensing, IP transfers | Medium | +| Market behavior | Quiet period (no product updates), website changes, domain changes | Medium | +| Social signals | Founder tone shifts, "exciting news soon" posts, unusual silence | Low | + +**Step 2 — Build targeted queries** + +``` +"Chronosphere" AND ("acquisition" OR "acquire" OR "acqui-hire" OR "merger") +"Honeycomb" AND ("strategic alternatives" OR "exploring options" OR "advisors") +"Grafana Labs" AND ("corporate development" OR "M&A" OR "strategic partnership") +site:linkedin.com "Chronosphere" "corporate development" OR "M&A" +site:sec.gov "Honeycomb" OR "Hound Technology" +"[company]" "quiet period" OR "exciting announcement" +"[company]" hiring "corporate development" OR "business development director" +"[company]" board of directors new appointment +``` + +**Step 3 — Entity and event extraction** + +From collected sources, extract and classify: + +```json +[ + { + "type": "event", + "name": "Chronosphere CFO departure", + "date": "2025-10-28", + "entities": ["Chronosphere", "Lisa Park"], + "signal_category": "executive_change", + "m_and_a_weight": "high", + "source": "linkedin.com/posts/lisapark-farewell" + }, + { + "type": "event", + "name": "Honeycomb hires Goldman Sachs advisor", + "date": "2025-11-02", + "entities": ["Honeycomb", "Goldman Sachs"], + "signal_category": "financial", + "m_and_a_weight": "high", + "source": "theinformation.com/articles/honeycomb-advisors" + }, + { + "type": "event", + "name": "Datadog acquires incident.io", + "date": "2025-11-08", + "entities": ["Datadog", "incident.io"], + "signal_category": "strategic", + "m_and_a_weight": "confirmed_event", + "source": "datadog.com/blog/incident-io-acquisition" + } +] +``` + +**Step 4 — Score composite M&A probability** + +Aggregate signals per company over a rolling 90-day window: + +``` +Chronosphere: + - CFO departed (high) +3 + - 2 corp dev job postings +2 + - No product release in 90d +1 + - Composite score: 6/10 → ELEVATED + +Honeycomb: + - Hired investment bank +4 + - Board added PE partner +2 + - Founder "grateful" post +1 + - Composite score: 7/10 → HIGH + +Grafana Labs: + - New enterprise partnerships +1 + - Active hiring across all -1 (normal growth, reduces M&A signal) + - Composite score: 0/10 → LOW +``` + +**Step 5 — Generate M&A signal alert** + +```markdown +# M&A Signal Alert: Enterprise Observability Sector +**Date**: 2025-11-10 | **Window**: 90 days + +## HIGH probability +- **Honeycomb**: Investment bank engagement + board changes suggest active process. + Key evidence: Goldman Sachs advisory (The Information), new PE board member. + Likely acquirers: Datadog, Cisco, ServiceNow. + +## ELEVATED probability +- **Chronosphere**: Leadership turnover + hiring freeze + corp dev roles. + Key evidence: CFO departure, no product releases, corp dev postings on LinkedIn. + Could indicate: acquisition target OR internal restructuring. + +## LOW probability +- **Grafana Labs**: Normal operating patterns, active hiring, regular releases. +- **Datadog**: Active acquirer (incident.io deal closed), not a target. +``` + +--- + +## Advanced Entity Extraction + +### Relationship Mapping from Unstructured Text + +Extract relationships by identifying sentence-level patterns that connect two named entities. + +**Pattern templates**: +``` +[Person] joined [Company] as [Role] + → relation: works_at, attributes: {role: Role, event: "joined"} + +[Company] acquired [Company] for [Amount] + → relation: acquired, attributes: {amount: Amount} + +[Person] and [Person] co-founded [Company] + → relations: founded (x2), co_founded_with (between persons) + +[Company] partnered with [Company] to [Purpose] + → relation: partnered_with, attributes: {purpose: Purpose} + +[Person] left [Company] to join [Company] + → relation: left (old), works_at (new), attributes: {event: "departure"} +``` + +**Multi-hop relationships**: When A relates to B and B relates to C, infer indirect connections: +``` +Sarah Chen works_at BetaStack +BetaStack competes_with AlphaCloud +→ Indirect: Sarah Chen is key_person_at competitor of AlphaCloud +``` + +**Negation detection**: Watch for negated relationships that should NOT be added: +``` +"Company X denied it was in acquisition talks with Company Y" +→ Do NOT add acquired relation. Add entity note: "denied acquisition rumor, [date]" + +"Former CEO of Company X" → Person left. Mark works_at as ended. +``` + +### Temporal Event Extraction (Timeline Construction) + +Extract dates and temporal markers to build event timelines. + +**Explicit dates**: +``` +"On March 15, 2025, Acme launched ProductX" + → event: product_launch, date: 2025-03-15, entities: [Acme, ProductX] +``` + +**Relative dates** (resolve against article publication date): +``` +"last week" → pub_date - 7 days +"earlier today" → pub_date +"next quarter" → pub_date + next fiscal quarter boundary +"in Q3" → July-September of article's year +"recently" → pub_date - 30 days (approximate, confidence: medium) +``` + +**Temporal ordering heuristics**: +``` +"before the acquisition" → event precedes known acquisition date +"following the launch" → event follows known launch date +"amid layoffs" → event concurrent with layoff period +``` + +**Timeline output format**: +```json +{ + "entity": "Acme Corp", + "timeline": [ + {"date": "2025-01-15", "event": "Series B ($40M)", "type": "funding", "confidence": "high"}, + {"date": "2025-03-20", "event": "Hired new CTO (Jane Lee)", "type": "leadership", "confidence": "high"}, + {"date": "2025-06-01", "event": "Launched v3.0", "type": "product", "confidence": "high"}, + {"date": "2025-08-10", "event": "Partnership with CloudCo", "type": "partnership", "confidence": "medium"}, + {"date": "2025-11-05", "event": "Acquired by BigCorp", "type": "acquisition", "confidence": "high"} + ] +} +``` + +### Quantitative Data Extraction + +Extract numerical data points with units, context, and time reference. + +**Financial figures**: +``` +Pattern: "[Company] raised $[amount][M/B] in [round]" +Example: "Acme raised $40M in Series B" + → {metric: "funding", value: 40000000, currency: "USD", context: "Series B", entity: "Acme"} + +Pattern: "[Company] revenue of $[amount][M/B]" +Example: "reported annual revenue of $120M" + → {metric: "revenue", value: 120000000, currency: "USD", period: "annual", entity: subject} +``` + +**Growth rates**: +``` +Pattern: "[metric] grew [X]% [period]" +Example: "ARR grew 45% year-over-year" + → {metric: "ARR_growth", value: 0.45, period: "YoY", entity: subject} + +Pattern: "from [X] to [Y]" +Example: "headcount grew from 200 to 350" + → {metric: "headcount", previous: 200, current: 350, growth: 0.75, entity: subject} +``` + +**Headcounts and scale metrics**: +``` +"[Company] now has [N] employees" +"[Company] serves [N] customers" +"[Product] has [N] monthly active users" +"[Company] operates in [N] countries" +``` + +**Extraction validation rules**: +- Currency amounts without a clear entity reference: discard or mark confidence "low" +- Growth percentages without a base period: mark confidence "medium" +- Round numbers (e.g., "about 1,000 employees"): flag as approximate +- Conflicting numbers from different sources: record both, note discrepancy + +### Multi-Source Entity Resolution + +When the same entity appears across different sources with variations, deduplicate. + +**Company name normalization**: +``` +"Acme Corp" = "Acme Corporation" = "Acme, Inc." = "ACME" (when context matches) +"Google" = "Alphabet" (parent) — but keep as separate entities with parent_of relation +``` + +**Resolution rules**: +| Signal | Match Confidence | Action | +|--------|-----------------|--------| +| Exact name match | High | Merge immediately | +| Name + same industry + same location | High | Merge | +| Abbreviated name + same context | Medium | Merge with note | +| Similar name, different industry | Low | Keep separate, flag for review | +| Person same name, different company | Low | Keep separate unless linked by career event | + +**Deduplication process**: +1. Normalize: lowercase, strip legal suffixes, expand abbreviations +2. Match: compare against existing entity list using normalized form +3. Verify: check at least one corroborating attribute (industry, location, person association) +4. Merge: combine attributes, keep all source references, use highest confidence level +5. Log: record the merge decision for audit + +```json +{ + "canonical": "entity_acme_corp", + "aliases": ["Acme Corp", "Acme Corporation", "Acme, Inc.", "ACME"], + "merged_from": ["source_techcrunch_entity_12", "source_linkedin_entity_89"], + "merge_confidence": "high", + "merge_reason": "exact name + same industry (SaaS) + same HQ (San Francisco)" +} +``` + +--- + +## Collection Automation Patterns + +### Scheduled Collection Workflows + +Define collection cadences matched to intelligence needs. + +**Daily cycle** (for active competitive monitoring): +``` +06:00 UTC — Run news queries for all targets (surface scan) +06:15 UTC — Check social media and forums for overnight mentions +06:30 UTC — Compare against yesterday's snapshot, flag changes +06:45 UTC — Generate daily brief, send alerts for CRITICAL items +``` + +**Weekly cycle** (for technology landscape and market mapping): +``` +Monday — Full source sweep: news, blogs, official sites +Tuesday — Job board scan: new postings, closed postings, pattern analysis +Wednesday — Financial data: funding rounds, SEC filings, earnings +Thursday — Community signals: GitHub activity, forum discussions, reviews +Friday — Synthesis: generate weekly report, update entity graph, adjust queries +``` + +**Event-triggered cycle** (supplement scheduled runs): +``` +Trigger: CRITICAL change detected in any cycle + → Immediately run deep collection on the affected entity + → Expand query set to cover related entities + → Generate ad-hoc alert report + → Shorten next scheduled cycle interval (e.g., weekly → daily for 7 days) +``` + +### Source Prioritization Based on Hit Rate + +Track which sources consistently produce actionable intelligence and allocate collection effort accordingly. + +**Hit rate calculation**: +``` +hit_rate = (data_points_extracted / fetches_from_source) over last 10 cycles +``` + +**Priority tiers**: +| Hit Rate | Priority | Collection Behavior | +|----------|----------|-------------------| +| > 60% | Tier 1 | Always fetch, process first | +| 30-60% | Tier 2 | Fetch on every cycle | +| 10-30% | Tier 3 | Fetch every other cycle | +| < 10% | Tier 4 | Fetch weekly regardless of cycle frequency | +| 0% for 5+ cycles | Drop | Remove from active source list, log reason | + +**Source performance tracking**: +```json +{ + "source": "techcrunch.com", + "total_fetches": 48, + "data_points_extracted": 31, + "hit_rate": 0.65, + "tier": 1, + "avg_confidence": "medium-high", + "last_hit": "2025-11-15", + "best_queries": ["[company] funding", "[company] acquisition"] +} +``` + +### Incremental Collection (Only New/Changed Content) + +Avoid re-processing unchanged content across cycles. + +**Techniques**: +1. **URL deduplication**: Maintain a set of already-processed URLs. Skip on subsequent cycles. +2. **Content hashing**: Hash the extracted text body. If hash matches previous cycle, skip processing. +3. **Date filtering**: Append date ranges to queries to limit results to new content. +4. **Pagination cursors**: For APIs and structured sources, store the last-seen ID or timestamp. + +**Query date narrowing**: +``` +Cycle runs daily at 06:00 UTC: + "AlphaCloud" after:2025-11-15 before:2025-11-16 + "AlphaCloud" news past 24 hours + +Cycle runs weekly: + "AlphaCloud" after:2025-11-08 before:2025-11-15 +``` + +**State tracking for incremental collection**: +```json +{ + "processed_urls": ["https://example.com/article-1", "..."], + "content_hashes": {"url1": "sha256:abc123", "url2": "sha256:def456"}, + "last_collection_time": "2025-11-15T06:00:00Z", + "query_cursors": { + "techcrunch_rss": "2025-11-15T05:30:00Z", + "github_api_events": "event_id_98765" + } +} +``` + +### Alert Trigger Conditions and Escalation Rules + +Define when and how to escalate detected changes. + +**Trigger conditions**: +``` +IMMEDIATE ALERT (publish event_publish within the cycle): + - Leadership change at target company (CEO, CTO, CFO) + - Acquisition or merger announcement + - Funding round > $10M + - Product discontinuation or major pivot + - Regulatory action or legal filing + - Data breach or security incident + +DAILY DIGEST (batch into next daily report): + - New product feature or version release + - New partnership announcement + - Hiring surge (> 5 new roles in a category) + - Pricing or packaging change + - Significant sentiment shift (score delta > 2 in one cycle) + +WEEKLY SUMMARY (include in weekly report only): + - Blog posts and thought leadership + - Conference appearances + - Minor version updates or patches + - Individual job postings + - Social media activity within normal range +``` + +**Escalation rules**: +``` +Level 1 — Auto-include in next scheduled report (default for all changes) +Level 2 — event_publish immediately (for CRITICAL significance changes) +Level 3 — event_publish + re-run deep collection on affected entity (for M&A, major crises) +``` + +**False positive suppression**: +- Require 2+ independent sources before triggering Level 2 alerts +- Ignore "rumor" or "speculation" tagged content for immediate alerts +- If the same alert fired in the previous cycle with no new corroboration, suppress repeat + +--- + +## Analysis Techniques + +### Link Analysis (Connection Mapping) + +Map the network of relationships between entities to reveal hidden connections, influence patterns, and structural vulnerabilities. + +**Building the adjacency map**: +``` +From the knowledge graph, extract all relations and build: + +Nodes: [Acme, BetaCo, GammaSuite, Jane Lee, CloudCo, InvestorX] +Edges: + Acme --competes_with--> BetaCo + Acme --partnered_with--> CloudCo + Jane Lee --works_at--> Acme + Jane Lee --formerly--> BetaCo + InvestorX --invested_in--> Acme + InvestorX --invested_in--> GammaSuite +``` + +**Key metrics to compute**: +| Metric | Meaning | Use | +|--------|---------|-----| +| Degree centrality | Number of direct connections | Identifies most-connected entities | +| Shared connections | Entities with overlapping relationships | Reveals indirect competition or collaboration | +| Bridge nodes | Entities connecting otherwise separate clusters | Identifies key influencers or gatekeepers | +| Cluster density | Ratio of actual to possible connections in a group | Measures how tightly coupled a set of entities is | + +**Practical analysis patterns**: +``` +Investor overlap: + InvestorX invested_in Acme AND GammaSuite + → Potential: board-level information sharing, future merger pressure + +Talent flow: + Jane Lee: BetaCo (2020-2024) → Acme (2024-present) + 3 other engineers: BetaCo → Acme in same period + → Pattern: talent drain from BetaCo to Acme, possible IP risk + +Supply chain dependency: + Acme uses CloudCo infrastructure + BetaCo uses CloudCo infrastructure + → Shared dependency: CloudCo outage affects both competitors +``` + +### Timeline Analysis (Event Sequencing and Pattern Detection) + +Arrange extracted events chronologically to detect causal chains, recurring patterns, and anomalous timing. + +**Constructing the timeline**: +``` +2025-01 Acme raises Series B ($40M) +2025-02 Acme posts 15 engineering roles +2025-03 Acme hires CTO from Google +2025-05 Acme acquires small startup (data pipeline tool) +2025-06 Acme launches v3.0 with data pipeline features +2025-08 Acme announces enterprise pricing tier +``` + +**Pattern detection rules**: + +| Pattern | Sequence | Interpretation | +|---------|----------|---------------| +| Build-up to launch | Funding → Hiring surge → Leadership hire → Product release | Normal growth execution | +| Acquisition integration | Acquire company → Quiet period (2-4 months) → Feature launch using acquired tech | Successful integration | +| Pre-acquisition signals | Advisor hire → Leadership departures → Quiet period → Announcement | Target company being acquired | +| Distress pattern | Layoffs → Pricing cuts → Leadership change → Pivot or shutdown | Company in trouble | +| Expansion play | Funding → New market entry → Localized hiring → Regional partnerships | Geographic or vertical expansion | + +**Anomaly detection**: +``` +Expected: Funding round → hiring surge within 60 days +Observed: Funding round → no hiring after 90 days +→ Flag: "Post-funding hiring anomaly — possible pivot, internal issues, or stealth project" + +Expected: Product launch → marketing push within 30 days +Observed: Product launch → silence +→ Flag: "Launch without marketing — possible soft launch, or product issues" +``` + +### Trend Detection (Acceleration, Deceleration, Inflection Points) + +Track metrics across collection cycles to identify directional shifts. + +**Metric tracking format**: +```json +{ + "entity": "Acme Corp", + "metric": "job_postings", + "series": [ + {"cycle": 1, "date": "2025-09-01", "value": 12}, + {"cycle": 2, "date": "2025-09-08", "value": 18}, + {"cycle": 3, "date": "2025-09-15", "value": 31}, + {"cycle": 4, "date": "2025-09-22", "value": 45}, + {"cycle": 5, "date": "2025-09-29", "value": 42} + ] +} +``` + +**Trend classification**: +| Pattern | Detection Rule | Meaning | +|---------|---------------|---------| +| Accelerating | Growth rate increasing cycle-over-cycle | Expanding investment in area | +| Decelerating | Growth rate decreasing but still positive | Approaching saturation or shift in priorities | +| Inflection point | Direction change (growth → decline or vice versa) | Strategic shift, market event, or external shock | +| Plateau | Value stable within 10% for 3+ cycles | Steady state, maintenance mode | +| Spike | Single-cycle jump > 2x previous value | One-time event (launch, announcement, crisis) | +| Cliff | Single-cycle drop > 50% | Sudden change (layoff, shutdown, policy change) | + +**Multi-metric correlation**: +``` +When two metrics move together, the correlation strengthens the signal: + +Acme job_postings: accelerating +Acme github_commits: accelerating +→ Corroborated signal: major development push underway + +BetaCo job_postings: cliff (-60%) +BetaCo glassdoor_rating: declining +→ Corroborated signal: organizational distress +``` + +### Competitive Positioning Maps + +Synthesize collected intelligence into comparative frameworks. + +**Feature parity matrix**: +| Capability | Acme | BetaCo | GammaSuite | Your Product | +|-----------|------|--------|------------|-------------| +| Real-time dashboards | Yes (v2.0+) | Yes | Limited | Yes | +| AI-powered alerts | Yes (new in v4.2) | No | Beta | Planned Q1 | +| On-prem deployment | No | Yes | Yes | Yes | +| SOC2 compliance | Yes | Yes | In progress | Yes | +| Free tier | No | Yes (limited) | Yes | Yes | + +**Market position quadrant** (based on collected metrics): +``` + High Market Share + | + Leaders | Challengers + (Acme) | (GammaSuite) + | + Low Growth ────────────┼──────────── High Growth + | + Declining | Emerging + (Legacy Co) | (BetaCo) + | + Low Market Share +``` + +Inputs for positioning: +- **Market share proxy**: mention frequency, customer count, job posting volume +- **Growth proxy**: funding recency, hiring rate, product release velocity, GitHub star velocity + +**Pricing intelligence table**: +| Tier | Acme | BetaCo | GammaSuite | Notes | +|------|------|--------|------------|-------| +| Free | -- | 5 users | 10 users | BetaCo most restrictive | +| Team | $15/user/mo | $12/user/mo | $20/user/mo | BetaCo cheapest | +| Enterprise | Custom | $35/user/mo | Custom | BetaCo only one with public enterprise pricing | +| Notable changes | Raised Team tier 20% in Q3 | Unchanged 12 months | New tier added Q4 | Acme pricing pressure | + +Track pricing changes across cycles — pricing increases signal confidence, decreases signal competitive pressure or churn concerns. diff --git a/hands/devops/HAND.toml b/hands/devops/HAND.toml index 5527f79..bfd0e4b 100644 --- a/hands/devops/HAND.toml +++ b/hands/devops/HAND.toml @@ -490,6 +490,265 @@ token_consumption = "high" default_active = false activation_warning = "DevOps hand runs continuously and monitors infrastructure, consuming tokens." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "DevOps Hand" description = "自主 DevOps 工程师——CI/CD 管理、基础设施监控、部署自动化和事件响应" +category = "开发" + +[i18n.zh.settings.infrastructure] +label = "基础设施类型" +description = "主要基础设施平台" + +[i18n.zh.settings.ci_platform] +label = "CI/CD 平台" +description = "主要 CI/CD 平台" + +[i18n.zh.settings.monitoring_focus] +label = "监控重点" +description = "主要监控和告警的关注方向" + +[i18n.zh.settings.auto_monitor] +label = "自动监控" +description = "自动监控基础设施并在出现问题时告警" + +[i18n.zh.settings.check_interval] +label = "健康检查间隔" +description = "自动健康检查的执行频率" + +[i18n.zh.settings.service_urls] +label = "服务 URL" +description = "要监控的 URL 列表,以逗号分隔(例如 https://api.example.com/health,https://app.example.com)" + +[i18n.zh.settings.alert_on_failure] +label = "故障告警" +description = "健康检查失败时发布事件通知" + +[i18n.zh.settings.rollback_strategy] +label = "回滚策略" +description = "部署失败时的默认回滚方式" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将部署和基础设施操作加入队列供审核,而非直接执行" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "DevOps Hand" +description = "自律型DevOpsエンジニア——CI/CD管理、インフラ監視、デプロイ自動化、インシデント対応" +category = "開発" + +[i18n.ja.settings.infrastructure] +label = "インフラタイプ" +description = "主要なインフラプラットフォーム" + +[i18n.ja.settings.ci_platform] +label = "CI/CDプラットフォーム" +description = "主要なCI/CDプラットフォーム" + +[i18n.ja.settings.monitoring_focus] +label = "監視の重点" +description = "監視とアラートの主な対象分野" + +[i18n.ja.settings.auto_monitor] +label = "自動監視" +description = "インフラを自動監視し、問題発生時にアラートを出す" + +[i18n.ja.settings.check_interval] +label = "ヘルスチェック間隔" +description = "自動ヘルスチェックの実行間隔" + +[i18n.ja.settings.service_urls] +label = "サービスURL" +description = "監視対象のURL一覧(カンマ区切り、例: https://api.example.com/health,https://app.example.com)" + +[i18n.ja.settings.alert_on_failure] +label = "障害アラート" +description = "ヘルスチェック失敗時にイベント通知を発行する" + +[i18n.ja.settings.rollback_strategy] +label = "ロールバック戦略" +description = "デプロイ失敗時のデフォルトのロールバック方法" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "デプロイやインフラ操作を直接実行せず、レビュー用キューに追加する" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de DevOps" +description = "Ingeniero DevOps autónomo — gestión de CI/CD, monitoreo de infraestructura, automatización de despliegues y respuesta a incidentes" +category = "Desarrollo" + +[i18n.es.settings.infrastructure] +label = "Tipo de infraestructura" +description = "Plataforma de infraestructura principal" + +[i18n.es.settings.ci_platform] +label = "Plataforma CI/CD" +description = "Plataforma principal de CI/CD" + +[i18n.es.settings.monitoring_focus] +label = "Enfoque de monitoreo" +description = "Área principal de monitoreo y alertas" + +[i18n.es.settings.auto_monitor] +label = "Monitoreo automático" +description = "Monitorear automáticamente la infraestructura y alertar ante problemas" + +[i18n.es.settings.check_interval] +label = "Intervalo de comprobación de salud" +description = "Con qué frecuencia ejecutar las comprobaciones de salud automatizadas" + +[i18n.es.settings.service_urls] +label = "URLs de servicios" +description = "Lista de URLs a monitorear separadas por comas (ej. https://api.example.com/health,https://app.example.com)" + +[i18n.es.settings.alert_on_failure] +label = "Alertar ante fallos" +description = "Publicar eventos cuando las comprobaciones de salud fallen" + +[i18n.es.settings.rollback_strategy] +label = "Estrategia de reversión" +description = "Enfoque de reversión predeterminado para despliegues fallidos" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Poner acciones de despliegue e infraestructura en cola para revisión en lugar de ejecutarlas directamente" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand DevOps" +description = "Ingénieur DevOps autonome — gestion CI/CD, surveillance d'infrastructure, automatisation des déploiements et réponse aux incidents" +category = "Développement" + +[i18n.fr.settings.infrastructure] +label = "Type d'infrastructure" +description = "Plateforme d'infrastructure principale" + +[i18n.fr.settings.ci_platform] +label = "Plateforme CI/CD" +description = "Plateforme CI/CD principale" + +[i18n.fr.settings.monitoring_focus] +label = "Axe de surveillance" +description = "Domaine principal de surveillance et d'alerte" + +[i18n.fr.settings.auto_monitor] +label = "Surveillance automatique" +description = "Surveiller automatiquement l'infrastructure et alerter en cas de problèmes" + +[i18n.fr.settings.check_interval] +label = "Intervalle de vérification de santé" +description = "Fréquence d'exécution des vérifications de santé automatisées" + +[i18n.fr.settings.service_urls] +label = "URLs des services" +description = "Liste d'URLs à surveiller séparées par des virgules (ex. https://api.example.com/health,https://app.example.com)" + +[i18n.fr.settings.alert_on_failure] +label = "Alerte en cas d'échec" +description = "Publier des événements lorsque les vérifications de santé échouent" + +[i18n.fr.settings.rollback_strategy] +label = "Stratégie de retour en arrière" +description = "Approche de retour en arrière par défaut pour les déploiements échoués" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Mettre les actions de déploiement et d'infrastructure en file d'attente pour révision au lieu de les exécuter directement" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "DevOps-Hand" +description = "Autonomer DevOps-Ingenieur — CI/CD-Verwaltung, Infrastrukturüberwachung, Deployment-Automatisierung und Incident-Response" +category = "Entwicklung" + +[i18n.de.settings.infrastructure] +label = "Infrastrukturtyp" +description = "Primäre Infrastrukturplattform" + +[i18n.de.settings.ci_platform] +label = "CI/CD-Plattform" +description = "Primäre CI/CD-Plattform" + +[i18n.de.settings.monitoring_focus] +label = "Überwachungsschwerpunkt" +description = "Hauptbereich für Überwachung und Alarme" + +[i18n.de.settings.auto_monitor] +label = "Automatische Überwachung" +description = "Infrastruktur automatisch überwachen und bei Problemen alarmieren" + +[i18n.de.settings.check_interval] +label = "Gesundheitscheck-Intervall" +description = "Ausführungshäufigkeit der automatisierten Gesundheitschecks" + +[i18n.de.settings.service_urls] +label = "Service-URLs" +description = "Kommagetrennte Liste der zu überwachenden URLs (z.B. https://api.example.com/health,https://app.example.com)" + +[i18n.de.settings.alert_on_failure] +label = "Warnung bei Ausfall" +description = "Ereignisse veröffentlichen, wenn Gesundheitschecks fehlschlagen" + +[i18n.de.settings.rollback_strategy] +label = "Rollback-Strategie" +description = "Standard-Rollback-Ansatz für fehlgeschlagene Deployments" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Deployment- und Infrastrukturaktionen zur Überprüfung in die Warteschlange stellen, anstatt sie direkt auszuführen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "DevOps Hand" +description = "자율 DevOps 엔지니어 — CI/CD 관리, 인프라 모니터링, 배포 자동화 및 인시던트 대응" +category = "개발" + +[i18n.ko.settings.infrastructure] +label = "인프라 유형" +description = "주요 인프라 플랫폼" + +[i18n.ko.settings.ci_platform] +label = "CI/CD 플랫폼" +description = "주요 CI/CD 플랫폼" + +[i18n.ko.settings.monitoring_focus] +label = "모니터링 중점" +description = "주요 모니터링 및 알림 방향" + +[i18n.ko.settings.auto_monitor] +label = "자동 모니터링" +description = "인프라를 자동으로 모니터링하고 문제 발생 시 알림" + +[i18n.ko.settings.check_interval] +label = "상태 점검 간격" +description = "자동 상태 점검 실행 주기" + +[i18n.ko.settings.service_urls] +label = "서비스 URL" +description = "모니터링할 URL 목록 (쉼표로 구분, 예: https://api.example.com/health,https://app.example.com)" + +[i18n.ko.settings.alert_on_failure] +label = "장애 알림" +description = "상태 점검 실패 시 이벤트 알림 발행" + +[i18n.ko.settings.rollback_strategy] +label = "롤백 전략" +description = "배포 실패 시 기본 롤백 방식" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "배포 및 인프라 작업을 직접 실행하지 않고 대기열에 추가하여 검토" diff --git a/hands/devops/SKILL.md b/hands/devops/SKILL.md index b4403a3..47fd3ad 100644 --- a/hands/devops/SKILL.md +++ b/hands/devops/SKILL.md @@ -330,3 +330,541 @@ for domain in api.example.com app.example.com; do echo "$domain: $expiry" done ``` + +--- + +## Worked Examples + +### Example 1: Zero-Downtime Deployment Pipeline + +Full lifecycle from code merge to production traffic switch with rollback safety. + +**Phases**: CI build and push image -> deploy to Green -> health-gate -> traffic switch -> monitor -> done (or rollback). + +**Traffic switch script** (the critical step): +```bash +#!/bin/bash +set -euo pipefail +# Record current slot for rollback, then switch +CURRENT=$(kubectl get svc myapp-active -n production -o jsonpath='{.spec.selector.slot}') +echo "$CURRENT" > /tmp/rollback-slot +kubectl patch svc myapp-active -n production -p '{"spec":{"selector":{"slot":"green"}}}' +# Verify +sleep 5 && curl -sf https://api.example.com/api/health | jq '.version' +``` + +**Rollback**: read `/tmp/rollback-slot`, patch the service selector back, verify health. + +**Decision flowchart**: +``` +Code merged to main + | + v +CI build + test ----[FAIL]----> Block merge, notify author + | + [PASS] + v +Deploy to Green + | + v +Health checks ------[FAIL]----> Alert on-call, keep Blue active + | + [PASS] + v +Switch traffic to Green + | + v +Monitor 15 min -----[ERROR SPIKE]----> Rollback to Blue, open incident + | + [STABLE] + v +Mark Green as new Blue, done +``` + +--- + +### Example 2: Production Incident Response + +Walkthrough of a real-world SEV1 incident: API latency spike caused by a database connection pool exhaustion. + +**Timeline** + +| Time (UTC) | Event | Actor | +|------------|-------|-------| +| 14:02 | PagerDuty alert: P95 latency > 2s on `/api/orders` | Monitoring | +| 14:04 | On-call acknowledges, opens incident channel `#inc-2025-0312` | On-call engineer | +| 14:06 | Check dashboard: request queue depth spiking, error rate at 12% | On-call engineer | +| 14:10 | Identify DB connection pool at 100% utilization | On-call engineer | +| 14:12 | Find long-running query from analytics job (started 13:55) | On-call engineer | +| 14:14 | Kill the runaway query, pool starts draining | On-call engineer | +| 14:18 | Latency returns to normal, error rate drops to 0.2% | Monitoring | +| 14:20 | Incident mitigated, continue monitoring | On-call engineer | +| 14:45 | Root cause confirmed: analytics cron job without query timeout | Investigation | +| 15:00 | Incident resolved, post-mortem scheduled | Incident commander | + +**Detection -- Alerting rules that fired** + +```yaml +# Prometheus alerting rule +groups: + - name: api-latency + rules: + - alert: HighAPILatency + expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job="api"}[5m])) > 2 + for: 2m + labels: + severity: critical + annotations: + summary: "P95 latency above 2s for 2+ minutes" + runbook: "https://wiki.internal/runbooks/high-latency" +``` + +**Triage -- Quick diagnosis commands** + +```bash +# 1. Check if it's a specific endpoint or global +curl -s "http://prometheus:9090/api/v1/query?query=topk(5,rate(http_request_duration_seconds_sum[5m])/rate(http_request_duration_seconds_count[5m]))" | jq '.data.result[] | {endpoint: .metric.handler, avg_latency: .value[1]}' + +# 2. Check database connection pool +psql -c "SELECT count(*) as total, state FROM pg_stat_activity GROUP BY state;" + +# 3. Find the blocking query +psql -c "SELECT pid, now() - query_start AS duration, query + FROM pg_stat_activity + WHERE state = 'active' AND now() - query_start > interval '1 minute' + ORDER BY duration DESC LIMIT 5;" +``` + +**Mitigation -- Kill the offending query** + +```bash +# Kill the long-running query by PID +psql -c "SELECT pg_terminate_backend(12345);" + +# Verify pool is recovering +watch -n 2 'psql -t -c "SELECT count(*) FROM pg_stat_activity WHERE state = '\''active'\'';"' +``` + +**Prevention -- Fix applied after incident** + +```sql +-- Set statement timeout for analytics role +ALTER ROLE analytics_readonly SET statement_timeout = '300s'; +``` + +```yaml +# Add connection pool monitoring alert +- alert: DBConnectionPoolNearCapacity + expr: pg_stat_activity_count / pg_settings_max_connections > 0.8 + for: 1m + labels: + severity: warning + annotations: + summary: "DB connection pool above 80% capacity" +``` + +**Post-mortem action items**: +- [ ] Add `statement_timeout` to all non-interactive database roles +- [ ] Add connection pool utilization alerts (threshold: 80%) +- [ ] Move analytics queries to read replica +- [ ] Add circuit breaker to API when pool utilization exceeds 90% + +--- + +### Example 3: Infrastructure Scaling Event + +Scaling a Kubernetes deployment in response to sustained load increase. + +**Phase 1 -- Alert triggers** + +``` +Alert: HighCPUUtilization + Condition: avg(cpu_usage) > 80% for 10 minutes + Current: 87% across 3 pods + Namespace: production + Deployment: order-service +``` + +**Phase 2 -- Capacity analysis** + +```bash +kubectl top pods -l app=order-service -n production # Per-pod CPU/memory +kubectl describe nodes | grep -A 5 "Allocated resources" # Node headroom +kubectl get hpa order-service -n production # Current HPA state +# Result: 87% CPU across 3 pods, 842 req/s (2x baseline) +``` + +**Phase 3 -- Scaling decision matrix** + +| Metric | Current | Target | Action | +|--------|---------|--------|--------| +| CPU usage | 87% | < 70% | Scale out | +| Request rate | 842/s | - | 2x normal, sustained | +| Memory | 258Mi avg | 512Mi limit | Headroom OK | +| Pod count | 3 | 6 (estimated) | Double replicas | +| Node capacity | 72% | < 85% | Sufficient for 6 pods | + +**Phase 4 -- Implement scaling** + +```bash +# Option A: Manual scale (immediate) +kubectl scale deployment order-service -n production --replicas=6 + +# Option B: Adjust HPA for sustained load (preferred) +kubectl patch hpa order-service -n production \ + -p '{"spec":{"minReplicas":5,"maxReplicas":15}}' + +# Monitor rollout +kubectl rollout status deployment/order-service -n production + +# Watch pods come up +kubectl get pods -l app=order-service -n production -w +``` + +**Phase 5 -- Verify scaling** + +Confirm via `kubectl top pods` (CPU should drop to ~45% per pod), check P95 latency is back below SLO, and verify error rate < 1%. + +**Post-scaling actions**: +- [ ] Investigate root cause of traffic increase (marketing event? bot traffic? organic growth?) +- [ ] Update capacity planning spreadsheet +- [ ] If sustained, adjust resource requests/limits and HPA baselines +- [ ] Set calendar reminder to review and potentially scale down in 48h + +--- + +## Observability Deep Dive + +### Structured Logging + +Use consistent JSON log format across all services for machine-parseable aggregation. + +**Log format standard**: JSON with required fields: `timestamp`, `level`, `service`, `trace_id`, `span_id`, `request_id`, `message`. Add `error` and `context` (structured key-value) as needed. + +**Log levels -- when to use each**: + +| Level | Purpose | Example | Persisted | +|-------|---------|---------|-----------| +| `error` | Requires human attention | Payment processing failed | 90 days | +| `warn` | Degraded but recoverable | Retry succeeded on 2nd attempt | 30 days | +| `info` | Business-significant events | Order placed, user logged in | 14 days | +| `debug` | Developer troubleshooting | Cache hit/miss, query timing | 3 days | +| `trace` | Fine-grained flow tracking | Function entry/exit, variable state | 1 day (sampled) | + +**Correlation IDs**: generate `X-Request-ID` at API gateway, propagate through all downstream calls. Query across services by filtering on `request_id.keyword` in Elasticsearch/OpenSearch. + +### Distributed Tracing + +**Core concepts**: A Trace is the end-to-end request path. Each service call is a Span with timing. Spans nest to show the call tree (e.g., API Gateway -> Order Service -> DB Query + Payment Service -> Stripe API). + +**OpenTelemetry propagation**: `traceparent: 00---`, `tracestate: vendor=value`. + +**Useful trace queries (Jaeger/Tempo)**: +```bash +curl -s "http://jaeger:16686/api/traces?service=order-service&minDuration=1s&limit=20" # Slow traces +curl -s "http://jaeger:16686/api/traces?service=order-service&tags=error%3Dtrue&limit=20" # Error traces +``` + +### Alerting Best Practices + +**Avoid alert fatigue -- rules of thumb**: +- Every alert must have a runbook link +- Every alert must be actionable (if no one needs to act, it is a log, not an alert) +- Group related alerts to avoid notification storms +- Use inhibition rules: if the cluster is down, suppress per-pod alerts + +**SLO-based alerting (burn rate)**: +```yaml +# SLO: 99.9% availability = 43.2 min/month error budget +# Fast burn (exhausts budget in 2h): error_ratio > 14.4 * 0.001 for 2m -> critical +# Slow burn (exhausts budget in 3d): error_ratio > 3 * 0.001 for 15m -> warning +groups: + - name: slo-burn-rate + rules: + - alert: SLOBurnRateCritical + expr: sum(rate(http_requests_total{code=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > (14.4 * 0.001) + for: 2m + labels: { severity: critical } + - alert: SLOBurnRateWarning + expr: sum(rate(http_requests_total{code=~"5.."}[1h])) / sum(rate(http_requests_total[1h])) > (3 * 0.001) + for: 15m + labels: { severity: warning } +``` + +**Runbook template**: Each alert runbook should cover: what the alert means (one sentence), impact scope, diagnosis steps (dashboard + commands), mitigation (quick fix vs proper fix), and escalation path (who to contact after 15 min). + +### Metrics Collection Patterns + +**RED Method (request-scoped services)**: + +| Metric | What | PromQL Example | +|--------|------|----------------| +| **R**ate | Requests per second | `sum(rate(http_requests_total[5m]))` | +| **E**rrors | Failed requests per second | `sum(rate(http_requests_total{code=~"5.."}[5m]))` | +| **D**uration | Latency distribution | `histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))` | + +**USE Method (infrastructure resources)**: + +| Metric | What | Example Check | +|--------|------|---------------| +| **U**tilization | % time resource is busy | `avg(rate(node_cpu_seconds_total{mode!="idle"}[5m]))` | +| **S**aturation | Queue depth / backlog | `node_load1 / count(node_cpu_seconds_total{mode="idle"})` | +| **E**rrors | Error event count | `rate(node_disk_io_time_weighted_seconds_total[5m])` | + +**When to use which**: +- RED for services that handle requests (APIs, web servers, message consumers) +- USE for infrastructure (CPU, memory, disk, network interfaces, queues) +- Combine both for a complete picture + +--- + +## Security Operations + +### Secret Management + +**Principles**: +- Never store secrets in source code, environment variables (in Dockerfiles), or container images +- Use a secrets manager (Vault, AWS Secrets Manager, K8s Secrets with encryption at rest) +- Rotate secrets on a schedule and immediately after any suspected compromise +- Audit all secret access + +**Vault pattern -- inject secrets at runtime**: +```bash +# Store a secret +vault kv put secret/myapp/db \ + username="app_user" \ + password="$(openssl rand -base64 32)" + +# Read a secret (application startup) +vault kv get -format=json secret/myapp/db | jq -r '.data.data.password' + +# Enable audit logging +vault audit enable file file_path=/var/log/vault-audit.log +``` + +**Kubernetes secrets -- from Vault using sidecar injector**: + +Annotate the pod template with `vault.hashicorp.com/agent-inject: "true"`, specify the role and secret path. The Vault agent sidecar renders secrets to `/vault/secrets/` and the app sources them at startup. Key annotations: `agent-inject-secret-` for the path, `agent-inject-template-` for the rendering template. + +**Secret rotation checklist**: +- [ ] Generate new secret value +- [ ] Update secret in secrets manager +- [ ] Restart/reload affected services (rolling, not all-at-once) +- [ ] Verify services authenticate with new secret +- [ ] Revoke the old secret value +- [ ] Confirm no services are still using the old secret + +### Container Security Scanning + +```bash +# Scan image for vulnerabilities (Trivy) -- fail CI on critical +trivy image --exit-code 1 --severity CRITICAL registry.example.com/myapp:$CI_COMMIT_SHA + +# Scan K8s cluster for misconfigurations +trivy k8s --report summary cluster +``` + +**Dockerfile security essentials**: use pinned base image tags (not `:latest`), run as non-root (`USER app`), copy only needed files, never bake secrets into image layers. + +### Network Security Policies + +**Kubernetes NetworkPolicy -- default deny with explicit allow**: +```yaml +# Default deny all ingress, then allow specific paths +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-gateway-to-orders + namespace: production +spec: + podSelector: + matchLabels: { app: order-service } + ingress: + - from: + - podSelector: + matchLabels: { app: api-gateway } + ports: + - { protocol: TCP, port: 8080 } +``` + +Apply a `default-deny-ingress` policy (empty `podSelector`, `policyTypes: [Ingress]`) per namespace first, then layer allow rules on top. + +### Compliance as Code + +**Policy enforcement with OPA/Gatekeeper**: use `K8sRequiredResources` constraints to enforce `limits.cpu`, `limits.memory`, `requests.cpu`, `requests.memory` on all pods in production namespaces. + +**Quick compliance audit commands**: +```bash +# Find pods without resource limits +kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[].resources.limits == null) | .metadata.namespace + "/" + .metadata.name' +# Find containers running as root +kubectl get pods -A -o json | jq -r '.items[] | select(.spec.containers[].securityContext.runAsNonRoot != true) | .metadata.namespace + "/" + .metadata.name' +# Find ingress without TLS +kubectl get ingress -A -o json | jq -r '.items[] | select(.spec.tls == null) | .metadata.namespace + "/" + .metadata.name' +``` + +--- + +## Automation Patterns + +### Auto-Remediation + +**Restart on OOM (Kubernetes)**: +```yaml +# Built-in: set resource limits and let K8s handle OOM restarts +apiVersion: apps/v1 +kind: Deployment +spec: + template: + spec: + containers: + - name: myapp + resources: + limits: + memory: "512Mi" + requests: + memory: "256Mi" + # Liveness probe: restart if unhealthy + livenessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 + failureThreshold: 3 +``` + +**Scale on load (HPA with custom metrics)**: +```yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: order-service +spec: + scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: order-service } + minReplicas: 3 + maxReplicas: 20 + behavior: + scaleUp: { stabilizationWindowSeconds: 60, policies: [{ type: Percent, value: 50, periodSeconds: 60 }] } + scaleDown: { stabilizationWindowSeconds: 300, policies: [{ type: Percent, value: 25, periodSeconds: 120 }] } + metrics: + - type: Resource + resource: { name: cpu, target: { type: Utilization, averageUtilization: 70 } } + - type: Pods + pods: { metric: { name: http_requests_per_second }, target: { type: AverageValue, averageValue: "1000" } } +``` + +**Rotate secrets on expiry (CronJob)**: + +Use a K8s CronJob (e.g., monthly `"0 2 1 * *"`) with a `secret-rotator` service account that: generates new password -> updates Vault -> alters DB role password -> triggers rolling restart via `kubectl rollout restart`. + +### GitOps Workflow + +**Repository as source of truth**: +``` +infrastructure-repo/ + |-- apps/ + | |-- order-service/ + | | |-- deployment.yaml + | | |-- service.yaml + | | |-- hpa.yaml + | | `-- kustomization.yaml + | `-- payment-service/ + | |-- deployment.yaml + | `-- kustomization.yaml + |-- base/ + | |-- namespace.yaml + | |-- network-policies.yaml + | `-- resource-quotas.yaml + `-- overlays/ + |-- staging/ + | `-- kustomization.yaml + `-- production/ + `-- kustomization.yaml +``` + +**Reconciliation loop (ArgoCD application)**: +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: order-service + namespace: argocd +spec: + project: default + source: + repoURL: https://github.com/org/infrastructure-repo.git + targetRevision: main + path: apps/order-service + destination: { server: "https://kubernetes.default.svc", namespace: production } + syncPolicy: + automated: { prune: true, selfHeal: true } + syncOptions: [CreateNamespace=true] + retry: { limit: 3, backoff: { duration: 5s, factor: 2, maxDuration: 3m } } +``` + +**GitOps deployment flow**: +``` +Developer pushes image tag update to infrastructure-repo + | + v +ArgoCD detects drift between git state and cluster state + | + v +ArgoCD syncs: applies manifests from git to cluster + | + v +Kubernetes rolls out new pods + | + v +ArgoCD verifies health (readiness probes pass) + | + [HEALTHY] --> Done + [DEGRADED] --> ArgoCD marks sync as failed, alerts on-call +``` + +### Database Backup and Restore + +**Automated backup (PostgreSQL)** -- run via cron `0 */6 * * *`: +```bash +#!/bin/bash +set -euo pipefail +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +DB_NAME="production" +BACKUP_DIR="/backups/postgres" + +pg_dump -Fc -Z 9 "$DB_NAME" > "${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.dump" +aws s3 cp "${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.dump" \ + "s3://backups-bucket/postgres/" --storage-class STANDARD_IA +find "$BACKUP_DIR" -name "*.dump" -mtime +30 -delete +``` + +**Restore procedure**: +```bash +#!/bin/bash +set -euo pipefail +BACKUP_FILE=$1 # e.g., "production_20250315_060000.dump" +RESTORE_DB="production_restore" + +aws s3 cp "s3://backups-bucket/postgres/$BACKUP_FILE" /tmp/restore.dump +psql -c "DROP DATABASE IF EXISTS $RESTORE_DB;" && psql -c "CREATE DATABASE $RESTORE_DB;" +pg_restore -d "$RESTORE_DB" -j 4 --no-owner /tmp/restore.dump +# Verify: check row counts on key tables, then clean up +rm /tmp/restore.dump +``` + +### Disaster Recovery Runbook Template + +**Recovery Objectives**: Define RTO (e.g., 1 hour) and RPO (e.g., 6 hours) per service. + +**Prerequisites**: backup storage access, Terraform state access, DNS management access, stakeholder comms channel. + +| Scenario | Key Steps | +|----------|-----------| +| **Single service failure** | Check pod status -> restart deployment -> if fails, `kubectl rollout undo` -> verify health | +| **Database failure** | `pg_isready` -> promote replica (or restore from backup) -> update connection strings -> verify data integrity | +| **Full region outage** | Confirm via provider status page -> notify stakeholders -> switch DNS to DR region -> verify traffic -> failback when primary recovers | + +**Communication template**: Subject `[INCIDENT] Service -- Status`. Body: what happened, impact, current status, ETA, next update time. + +**Post-recovery checklist**: health checks passing, data integrity verified, monitoring restored, backups resumed, incident report filed, post-mortem scheduled within 48h. diff --git a/hands/lead/HAND.toml b/hands/lead/HAND.toml index b25f6b4..ea855e0 100644 --- a/hands/lead/HAND.toml +++ b/hands/lead/HAND.toml @@ -380,6 +380,265 @@ token_consumption = "medium" default_active = false activation_warning = "Lead hand runs continuously and generates leads on schedule, consuming tokens." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "线索生成 Hand" description = "自主线索生成——按计划发现、充实并交付合格的潜在客户" +category = "数据" + +[i18n.zh.settings.target_industry] +label = "目标行业" +description = "重点关注的行业垂直领域(例如 SaaS、金融科技、医疗健康、电子商务)" + +[i18n.zh.settings.target_role] +label = "目标职位" +description = "要触达的决策者头衔(例如 CTO、工程副总裁、产品负责人)" + +[i18n.zh.settings.company_size] +label = "公司规模" +description = "按公司规模筛选线索" + +[i18n.zh.settings.lead_source] +label = "线索来源" +description = "发现线索的主要方式" + +[i18n.zh.settings.output_format] +label = "输出格式" +description = "报告交付格式" + +[i18n.zh.settings.leads_per_report] +label = "每份报告线索数" +description = "每份报告中包含的线索数量" + +[i18n.zh.settings.delivery_schedule] +label = "交付计划" +description = "生成和交付线索报告的时间安排" + +[i18n.zh.settings.geo_focus] +label = "地域重点" +description = "优先关注的地理区域(例如美国、欧洲、亚太、全球)" + +[i18n.zh.settings.enrichment_depth] +label = "信息丰富度" +description = "对每条线索收集多少上下文信息" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "리드 생성 Hand" +description = "자율 리드 생성 — 일정에 따라 적격 리드를 탐색, 보강 및 전달" +category = "데이터" + +[i18n.ko.settings.target_industry] +label = "대상 산업" +description = "집중할 산업 분야 (예: SaaS, 핀테크, 헬스케어, 이커머스)" + +[i18n.ko.settings.target_role] +label = "대상 직책" +description = "타겟할 의사결정자 직함 (예: CTO, 엔지니어링 VP, 프로덕트 총괄)" + +[i18n.ko.settings.company_size] +label = "회사 규모" +description = "회사 규모별 리드 필터링" + +[i18n.ko.settings.lead_source] +label = "리드 소스" +description = "리드를 발굴하는 주요 방법" + +[i18n.ko.settings.output_format] +label = "출력 형식" +description = "보고서 전달 형식" + +[i18n.ko.settings.leads_per_report] +label = "보고서당 리드 수" +description = "각 보고서에 포함할 리드 수" + +[i18n.ko.settings.delivery_schedule] +label = "전달 일정" +description = "리드 보고서 생성 및 전달 시간" + +[i18n.ko.settings.geo_focus] +label = "지역 중점" +description = "우선적으로 집중할 지역 (예: 미국, 유럽, 아시아 태평양, 글로벌)" + +[i18n.ko.settings.enrichment_depth] +label = "보강 깊이" +description = "리드당 수집할 컨텍스트 정보의 수준" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "リード生成 Hand" +description = "自律型リード生成エージェント——スケジュールに基づき見込み客を発見・情報付加・配信" +category = "データ" + +[i18n.ja.settings.target_industry] +label = "ターゲット業界" +description = "注力する業界バーティカル(例: SaaS、フィンテック、ヘルスケア、EC)" + +[i18n.ja.settings.target_role] +label = "ターゲット職種" +description = "アプローチする意思決定者の肩書き(例: CTO、VP Engineering、プロダクト責任者)" + +[i18n.ja.settings.company_size] +label = "企業規模" +description = "企業規模でリードをフィルタリング" + +[i18n.ja.settings.lead_source] +label = "リードソース" +description = "リードを発見する主な方法" + +[i18n.ja.settings.output_format] +label = "出力形式" +description = "レポートの配信形式" + +[i18n.ja.settings.leads_per_report] +label = "レポートあたりのリード数" +description = "各レポートに含めるリードの数" + +[i18n.ja.settings.delivery_schedule] +label = "配信スケジュール" +description = "リードレポートの生成・配信タイミング" + +[i18n.ja.settings.geo_focus] +label = "地域フォーカス" +description = "優先する地理的リージョン(例: 米国、欧州、APAC、グローバル)" + +[i18n.ja.settings.enrichment_depth] +label = "情報付加の深さ" +description = "リードごとに収集するコンテキスト情報の量" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Generación de Leads" +description = "Generación autónoma de leads — descubre, enriquece y entrega leads cualificados según un calendario" +category = "Datos" + +[i18n.es.settings.target_industry] +label = "Industria objetivo" +description = "Vertical de industria en la que enfocarse (ej. SaaS, fintech, salud, e-commerce)" + +[i18n.es.settings.target_role] +label = "Rol objetivo" +description = "Títulos de tomadores de decisiones a los que dirigirse (ej. CTO, VP de Ingeniería, Director de Producto)" + +[i18n.es.settings.company_size] +label = "Tamaño de empresa" +description = "Filtrar leads por tamaño de empresa" + +[i18n.es.settings.lead_source] +label = "Fuente de leads" +description = "Método principal para descubrir leads" + +[i18n.es.settings.output_format] +label = "Formato de salida" +description = "Formato de entrega del informe" + +[i18n.es.settings.leads_per_report] +label = "Leads por informe" +description = "Número de leads a incluir en cada informe" + +[i18n.es.settings.delivery_schedule] +label = "Calendario de entrega" +description = "Cuándo generar y entregar los informes de leads" + +[i18n.es.settings.geo_focus] +label = "Enfoque geográfico" +description = "Región geográfica a priorizar (ej. EE.UU., Europa, Asia-Pacífico, global)" + +[i18n.es.settings.enrichment_depth] +label = "Profundidad de enriquecimiento" +description = "Cuánto contexto recopilar por cada lead" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Génération de Prospects" +description = "Génération autonome de prospects — découvre, enrichit et livre des prospects qualifiés selon un calendrier" +category = "Données" + +[i18n.fr.settings.target_industry] +label = "Secteur cible" +description = "Secteur d'activité cible (ex. SaaS, fintech, santé, e-commerce)" + +[i18n.fr.settings.target_role] +label = "Poste cible" +description = "Titres de décideurs à cibler (ex. CTO, VP Engineering, Directeur Produit)" + +[i18n.fr.settings.company_size] +label = "Taille d'entreprise" +description = "Filtrer les prospects par taille d'entreprise" + +[i18n.fr.settings.lead_source] +label = "Source de prospects" +description = "Méthode principale de découverte des prospects" + +[i18n.fr.settings.output_format] +label = "Format de sortie" +description = "Format de livraison des rapports" + +[i18n.fr.settings.leads_per_report] +label = "Prospects par rapport" +description = "Nombre de prospects à inclure dans chaque rapport" + +[i18n.fr.settings.delivery_schedule] +label = "Calendrier de livraison" +description = "Quand générer et livrer les rapports de prospects" + +[i18n.fr.settings.geo_focus] +label = "Focus géographique" +description = "Région géographique prioritaire (ex. USA, Europe, Asie-Pacifique, Mondial)" + +[i18n.fr.settings.enrichment_depth] +label = "Profondeur d'enrichissement" +description = "Niveau d'informations contextuelles à collecter par prospect" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Lead-Generierungs-Hand" +description = "Autonome Lead-Generierung — entdeckt, bereichert und liefert qualifizierte Leads nach Zeitplan" +category = "Daten" + +[i18n.de.settings.target_industry] +label = "Zielbranche" +description = "Branchenvertikale für den Fokus (z.B. SaaS, Fintech, Gesundheitswesen, E-Commerce)" + +[i18n.de.settings.target_role] +label = "Zielposition" +description = "Titel der Entscheidungsträger (z.B. CTO, VP Engineering, Produktleiter)" + +[i18n.de.settings.company_size] +label = "Unternehmensgröße" +description = "Leads nach Unternehmensgröße filtern" + +[i18n.de.settings.lead_source] +label = "Lead-Quelle" +description = "Primäre Methode zur Lead-Entdeckung" + +[i18n.de.settings.output_format] +label = "Ausgabeformat" +description = "Berichtslieferformat" + +[i18n.de.settings.leads_per_report] +label = "Leads pro Bericht" +description = "Anzahl der Leads pro Bericht" + +[i18n.de.settings.delivery_schedule] +label = "Lieferzeitplan" +description = "Wann Lead-Berichte generiert und geliefert werden" + +[i18n.de.settings.geo_focus] +label = "Geografischer Fokus" +description = "Priorisierte geografische Region (z.B. USA, Europa, Asien-Pazifik, Global)" + +[i18n.de.settings.enrichment_depth] +label = "Anreicherungstiefe" +description = "Umfang der pro Lead gesammelten Kontextinformationen" diff --git a/hands/lead/SKILL.md b/hands/lead/SKILL.md index e12adf1..6fb4b26 100644 --- a/hands/lead/SKILL.md +++ b/hands/lead/SKILL.md @@ -62,6 +62,88 @@ site:builtwith.com "[company]" 7. **News articles** — recent activity, reputation 8. **Social media** — engagement, company culture +### Industry-Specific Search Patterns + +#### SaaS / Technology +``` +# Company directories +site:g2.com/products "[category]" +site:capterra.com "[category] software" +site:producthunt.com "[product type]" "[year]" +"[category] software" site:crunchbase.com/organization + +# Tech stack signals +site:stackshare.io "[technology]" decisions +site:builtwith.com/websites/[technology] + +# Growth signals +"[company] SOC 2" OR "[company] ISO 27001" — enterprise readiness +"[company] API" OR "[company] integration" — platform maturity +"[company] case study" OR "[company] customer story" — traction evidence +``` + +#### Healthcare +``` +# Directories & registries +site:healthcareittoday.com "[company]" +"digital health companies" site:crunchbase.com +"health tech" "[city/state]" site:angellist.co +"HIPAA compliant" "[category] software" + +# Regulatory signals +"[company] FDA clearance" OR "[company] 510(k)" +"[company] HIPAA" OR "[company] HITRUST" +"[company] clinical trial" site:clinicaltrials.gov +``` + +#### Financial Services +``` +# Directories & databases +site:fintechmagazine.com "top" "[category]" +"fintech companies" "[region]" site:crunchbase.com +"banking technology" OR "insurtech" site:cbinsights.com + +# Compliance signals +"[company] SOX compliance" OR "[company] PCI DSS" +"[company] banking license" OR "[company] money transmitter" +"[company] Series [A/B/C]" "fintech" +``` + +#### E-commerce +``` +# Directories & tools +site:apps.shopify.com "[category]" +site:store.bigcommerce.com "[category]" +"ecommerce brands" "[niche]" site:2pm.com OR site:modernretail.co + +# Revenue signals +"[company] GMV" OR "[company] ARR" +"[company] warehouse" OR "[company] fulfillment center" +"[brand] DTC" OR "[brand] direct to consumer" +``` + +#### Manufacturing +``` +# Directories +site:thomasnet.com "[product category]" +"manufacturing companies" "[city/state]" site:mfg.com +"industrial [category]" site:dnb.com + +# Modernization signals +"[company] Industry 4.0" OR "[company] smart factory" +"[company] ERP" OR "[company] digital transformation" +"[company] ISO 9001" OR "[company] ISO 14001" +``` + +#### Industry Source Quick Reference +| Vertical | Primary Directories | Key Signal Keywords | +|----------|-------------------|---------------------| +| SaaS/Tech | G2, Capterra, ProductHunt, Crunchbase | "API launch", "SOC 2", "Series X" | +| Healthcare | HealthcareIT, ClinicalTrials.gov | "HIPAA", "FDA", "clinical trial" | +| Financial Services | CBInsights, Crunchbase | "PCI DSS", "banking license", "Series X" | +| E-commerce | Shopify App Store, ModernRetail | "GMV", "DTC", "fulfillment" | +| Manufacturing | ThomasNet, MFG.com | "Industry 4.0", "ISO 9001", "ERP" | + --- ## Lead Enrichment Patterns @@ -145,6 +227,63 @@ Accessibility (15 points max): --- +## Lead Qualification Frameworks + +### BANT Framework + +Use BANT to quickly qualify leads during or after enrichment. Each dimension maps to data you can discover through web research. + +| Dimension | Question | Research Signals | +|-----------|----------|-----------------| +| **Budget** | Can they afford the solution? | Funding rounds, revenue estimates, job postings for related roles, pricing tier of current tools | +| **Authority** | Is this person a decision-maker? | Title seniority (VP+, C-level, Director), reports to CEO/CTO, listed on "Leadership" page | +| **Need** | Do they have the problem you solve? | Job postings mentioning the pain point, tech stack gaps, competitor tool usage, complaints on forums | +| **Timeline** | Is there urgency to buy? | Contract renewals, compliance deadlines, product launches, recent leadership changes | + +#### BANT Scoring Overlay +Apply these modifiers on top of the base lead score: +``` +Budget confirmed (funding, revenue signal): +5 +Authority confirmed (VP+ or C-level): +5 +Need confirmed (pain point evidence): +5 +Timeline confirmed (urgency signal): +5 + Max bonus: +20 +``` + +### MEDDIC Framework + +Use MEDDIC for complex / enterprise sales qualification where longer deal cycles demand deeper research. + +| Dimension | Definition | What to Look For | +|-----------|-----------|-----------------| +| **Metrics** | Quantifiable outcomes the buyer cares about | Case studies they publish, KPIs in job postings, analyst reports, earnings calls | +| **Economic Buyer** | Person with budget authority to sign | CFO, CEO, VP Finance, or "Head of Procurement" listed on team pages | +| **Decision Criteria** | Factors they use to evaluate vendors | RFP documents, vendor comparison blog posts, compliance requirements, review site feedback | +| **Decision Process** | Steps from evaluation to purchase | Procurement team presence, legal/compliance review cycles, pilot program mentions | +| **Identify Pain** | Specific problems driving the purchase | Support forums, Glassdoor reviews, social media complaints, analyst reports on industry challenges | +| **Champion** | Internal advocate for your solution | Conference speakers, blog authors, open-source contributors, people who engage with your content | + +#### MEDDIC Research Checklist +``` +For each enterprise lead, attempt to discover: +[ ] At least one quantifiable metric they care about +[ ] The economic buyer's name and title +[ ] 2+ decision criteria (compliance, performance, price, integration) +[ ] Whether they run formal procurement (RFP, committee) +[ ] 1+ specific pain point with evidence +[ ] A potential internal champion (engaged user, tech advocate) +``` + +### Choosing Between BANT and MEDDIC +| Scenario | Recommended Framework | +|----------|----------------------| +| SMB / startup targets, short sales cycle | BANT | +| Enterprise targets, $100K+ deal size | MEDDIC | +| Mixed list with varied company sizes | BANT first pass, MEDDIC for A-grade enterprise leads | +| Time-constrained research | BANT (faster to assess) | + +--- + ## Deduplication Strategies ### Matching Algorithm @@ -212,6 +351,166 @@ Name,Title,Company,Company URL,LinkedIn,Industry,Size,Score,Discovered,Notes --- +## Worked Examples + +### Example 1: Fintech SaaS Series A/B Companies (50-200 Employees) + +**Objective**: Find 10 SaaS companies in the fintech space with 50-200 employees that recently raised Series A or B. + +#### Step 1 — Define ICP +``` +Industry: Fintech / Financial Technology +Company size: 50-200 employees (SMB) +Funding stage: Series A or Series B (raised within last 18 months) +Geography: United States (primary), UK/EU (secondary) +Decision-maker: VP Engineering, CTO, or Head of Product +Pain points: Scaling infrastructure, compliance automation, developer tooling +``` + +#### Step 2 — Execute Search Queries +``` +# Primary discovery queries +"fintech" "series A" OR "series B" site:crunchbase.com/organization +"fintech startup" "raised" "$" "2025" OR "2024" site:techcrunch.com +site:news.crunchbase.com "fintech" "series A" OR "series B" + +# Employee count validation +"fintech" "50" OR "100" OR "150" "employees" site:linkedin.com/company +site:builtin.com/companies/fintech "51-200 employees" + +# Growth signals +"fintech" hiring "senior engineer" OR "staff engineer" site:linkedin.com/jobs +"fintech startup" "SOC 2" OR "PCI DSS" — compliance-ready = selling to banks +``` + +#### Step 3 — Enrich and Score Each Lead +``` +For each discovered company, gather: + 1. Company website → About page → leadership team, employee count + 2. Crunchbase profile → funding amount, date, investors, total raised + 3. LinkedIn company page → exact employee count, recent hires + 4. Job boards → open roles (signals growth and tech stack) + 5. Press releases → product launches, partnerships, customer wins + +Scoring example for "PayFlow Inc": + ICP Match: 25/30 (fintech ✓, 130 employees ✓, US ✓, CTO found ✓, no geography bonus) + Growth Signals: 18/20 (Series B $18M ✓, hiring 8 engineers ✓, product launch ✓) + Enrichment: 15/20 (LinkedIn ✓, full company data ✓, tech stack ✓, no direct email) + Recency: 15/15 (funding announced 3 weeks ago) + Accessibility: 10/15 (company contact form, CTO LinkedIn) + TOTAL: 83/100 → Grade A +``` + +#### Step 4 — Final Output (top 3 of 10) +| # | Name | Title | Company | Employees | Funding | Score | Key Signal | +|---|------|-------|---------|-----------|---------|-------|------------| +| 1 | Sarah Chen | CTO | PayFlow Inc | 130 | Series B, $18M | 83 | Funded 3 weeks ago, hiring 8 engineers | +| 2 | Marcus Rivera | VP Engineering | LendStack | 85 | Series A, $12M | 78 | Launched API platform Q4, SOC 2 certified | +| 3 | Priya Patel | Head of Product | ComplianceAI | 62 | Series A, $8M | 75 | Hiring product + eng, regulatory focus | + +--- + +### Example 2: Enterprise AI/ML Decision-Makers + +**Objective**: Identify decision-makers at enterprise companies (500+ employees) that are actively adopting AI/ML tools. + +#### Step 1 — Define ICP +``` +Industry: Any (cross-industry AI adoption) +Company size: 500+ employees (Enterprise) +Signals: Active AI/ML adoption (hiring, projects, tool procurement) +Geography: North America +Decision-maker: VP/Director of Data Science, Head of AI/ML, CTO, Chief Data Officer +Pain points: ML model deployment, data pipeline scaling, AI governance +``` + +#### Step 2 — Execute Search Queries +``` +# Identify companies investing in AI +"head of AI" OR "VP data science" OR "chief data officer" hiring site:linkedin.com +"[company] machine learning" "team" OR "department" site:linkedin.com/company +"AI adoption" OR "ML platform" "enterprise" site:venturebeat.com OR site:techcrunch.com + +# Conference and community signals +"speaker" "machine learning" OR "AI" site:neurips.cc OR site:icml.cc +"[company] MLOps" OR "[company] AI infrastructure" site:github.com + +# Budget and procurement signals +"AI budget" OR "ML tools" RFP site:gov OR site:rfpdb.com +"[company] partnership" "AI" OR "machine learning" press release +``` + +#### Step 3 — Multi-Source Enrichment +``` +For enterprise targets, cross-reference at least 3 sources per lead: + + Source 1: LinkedIn + → Title confirmation, tenure, reporting structure + → Company employee count, growth rate + → Recent posts about AI/ML topics (champion signal) + + Source 2: Company website + press + → AI/ML team page, published case studies + → Press releases about AI initiatives + → Open positions on careers page + + Source 3: Community / conferences + → Conference talks (NeurIPS, ICML, KDD, MLOps World) + → GitHub contributions (open-source ML projects) + → Blog posts or whitepapers on AI strategy + + MEDDIC qualification pass: + Metrics: "Reduced model deployment time by 60%" (from case study) + Economic Buyer: Chief Data Officer, reports to CEO + Decision Criteria: SOC 2 compliance, on-prem option, Python SDK + Decision Process: Procurement committee, 90-day eval period + Pain: "Manual ML pipeline taking 3 weeks per model" (job posting) + Champion: Sr. ML Engineer who spoke at MLOps World about tooling gaps +``` + +#### Step 4 — Final Output (top 3) +| # | Name | Title | Company | Employees | Score | Qualification | +|---|------|-------|---------|-----------|-------|---------------| +| 1 | David Kim | Chief Data Officer | GlobalRetail Corp | 3,200 | 91 | MEDDIC 5/6: metrics, buyer, criteria, pain, champion | +| 2 | Lisa Zhang | VP Data Science | HealthFirst Systems | 1,800 | 86 | MEDDIC 4/6: buyer, criteria, pain, champion | +| 3 | James O'Brien | Director of AI | MegaBank Financial | 12,000 | 80 | MEDDIC 4/6: metrics, buyer, decision process, pain | + +--- + +### Example 3: Quick-Turn SMB List Build + +**Objective**: Build a 20-lead list of SMB e-commerce brands using Shopify that might need an email marketing tool. Time budget: 30 minutes. + +#### Abbreviated Flow +``` +ICP (quick): + Industry: E-commerce / DTC brands + Size: 10-100 employees + Platform: Shopify + Signal: Active store, social media presence, no advanced email tool detected + +Search queries (5 minutes): + site:myshopify.com "[niche]" + "[niche] brand" "shopify" site:linkedin.com/company + site:apps.shopify.com/reviews "[competitor email tool]" — negative reviews = opportunity + "DTC brands" "[niche]" "founded 2022" OR "founded 2023" + +Enrichment (15 minutes, per lead): + 1. Shopify store URL → active? recent products? + 2. LinkedIn company page → employee count, founded year + 3. BuiltWith → check for existing email/marketing tools + 4. Instagram/TikTok → follower count (engagement proxy) + +Scoring (5 minutes): + Use simplified scoring: ICP match (40%) + Growth signals (30%) + Reachability (30%) + Skip MEDDIC for SMB — use BANT quick-check instead + +Output (5 minutes): + Deliver as CSV with columns: Brand, URL, Employees, Platform, Current Email Tool, Score, Contact +``` + +--- + ## Compliance & Ethics ### DO @@ -233,3 +532,81 @@ Name,Title,Company,Company URL,LinkedIn,Industry,Size,Score,Discovered,Notes - Keep lead data in local files only — never exfiltrate - Mark stale leads (>90 days without activity) for review - Provide clear data export in all supported formats + +--- + +## Common Pitfalls + +### 1. Outdated Data +**Problem**: Company details change fast — people change jobs, startups pivot, funding info ages. +**Mitigation**: +- Verify every lead against at least 2 sources, and prefer sources updated within the last 90 days +- Flag any data point older than 6 months as "needs re-verification" +- Check LinkedIn tenure: if a contact joined their current role <3 months ago, they may not have budget authority yet + +### 2. Over-Relying on a Single Source +**Problem**: Crunchbase has gaps in non-US companies. LinkedIn employee counts lag. News articles are biased toward funded companies. +**Mitigation**: +- Always cross-reference: Crunchbase funding + LinkedIn headcount + company website team page +- Use at least 2 sources for employee count (the numbers often diverge by 20-30%) +- If a company has zero press coverage, check industry-specific directories rather than discarding it + +### 3. Ignoring Enrichment Quality +**Problem**: A lead list with 50 names but only 10 have titles and 5 have company size data is not actionable. +**Mitigation**: +- Set a minimum enrichment threshold before including a lead (e.g., must have: name + title + company + at least one signal) +- Track an "enrichment completeness" percentage per lead +- Return to partially-enriched leads in a second pass rather than shipping incomplete data + +### 4. Vanity List Sizes +**Problem**: Delivering 100 leads when only 15 are qualified wastes the user's time and erodes trust. +**Mitigation**: +- Better to deliver 10 A-grade leads than 50 C-grade leads +- Always sort by score descending and include a clear recommendation on where to draw the cut-off line +- If the target count cannot be met at acceptable quality, say so: "Found 7 leads meeting all criteria; 13 additional leads are partial matches" + +### 5. Confusing Company Name Variants +**Problem**: "Stripe, Inc.", "Stripe", and "Stripe Payments Europe Ltd" can appear as three separate leads. +**Mitigation**: +- Always normalize company names before deduplication (see Normalization Rules above) +- Match on website domain as the primary key — it is the most stable identifier +- Be especially careful with common words as company names ("Bolt", "Block", "Square") + +### 6. Mistaking Hiring Activity for Purchase Intent +**Problem**: A company hiring engineers does not necessarily mean they are buying your product. +**Mitigation**: +- Hiring is a **growth signal**, not a **purchase signal** — score it accordingly (contributor, not decisive) +- Look for more direct signals: RFPs, vendor comparison blog posts, demo requests, event attendance +- Combine hiring data with tech stack analysis: hiring a "Salesforce Admin" means Salesforce budget exists + +### 7. Neglecting Negative Signals +**Problem**: Focusing only on positive signals and missing red flags. +**Mitigation**: +- Check for layoffs, lawsuits, or executive departures — these reduce lead quality +- A company that just went through a 30% layoff is unlikely to approve new vendor spend +- Apply negative score modifiers: +``` +Recent layoffs (>10% headcount): -10 +Lawsuit / regulatory action: -5 +Executive turnover (CEO/CTO left): -5 +Declining web traffic (per SimilarWeb): -3 +``` + +### 8. Skipping the ICP Step +**Problem**: Jumping straight into search without a clear ICP produces scattered, low-quality results. +**Mitigation**: +- Always define the ICP **before** the first search query, even if it takes 5 extra minutes +- Write the ICP down explicitly (industry, size, geography, role, pain point, budget signal) +- Revisit and tighten the ICP after the first 10 leads if results are too broad + +### Pitfall Severity Quick Reference +| Pitfall | Severity | Frequency | Fix Effort | +|---------|----------|-----------|------------| +| Outdated data | High | Very common | Medium (multi-source verification) | +| Single source reliance | High | Common | Low (add 1-2 extra sources) | +| Poor enrichment quality | Medium | Common | Medium (set thresholds, second pass) | +| Vanity list sizes | Medium | Common | Low (enforce scoring cut-off) | +| Company name variants | Medium | Very common | Low (normalize + domain match) | +| Hiring != purchase intent | Low | Occasional | Low (adjust scoring weight) | +| Ignoring negative signals | High | Common | Medium (add negative modifiers) | +| Skipping ICP | High | Occasional | Low (5-minute discipline) | diff --git a/hands/linkedin/HAND.toml b/hands/linkedin/HAND.toml index ab515b5..a9e8b9d 100644 --- a/hands/linkedin/HAND.toml +++ b/hands/linkedin/HAND.toml @@ -394,6 +394,241 @@ frequency = "daily" token_consumption = "medium" default_active = false +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "LinkedIn Hand" description = "自主 LinkedIn 管理——个人资料优化、内容创作、人脉拓展和职业互动" +category = "通信" + +[i18n.zh.settings.content_style] +label = "内容风格" +description = "LinkedIn 帖子的语气和风格" + +[i18n.zh.settings.post_frequency] +label = "发布频率" +description = "创建和发布内容的频率" + +[i18n.zh.settings.content_topics] +label = "内容主题" +description = "要创作内容的主题(逗号分隔,例如 AI、领导力、创业)" + +[i18n.zh.settings.auto_engage] +label = "自动互动" +description = "自动对人脉网络中的相关帖子点赞和评论" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将帖子加入队列等待审核,而非直接发布" + +[i18n.zh.settings.hashtag_count] +label = "话题标签数量" +description = "每篇帖子包含的话题标签数量" + +[i18n.zh.settings.target_audience] +label = "目标受众" +description = "内容的主要目标受众" + +[i18n.zh.settings.language] +label = "语言" +description = "帖子和互动使用的语言" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "LinkedIn Hand" +description = "自律型LinkedInマネージャー——プロフィール最適化、コンテンツ作成、ネットワーキング、プロフェッショナルエンゲージメント" +category = "コミュニケーション" + +[i18n.ja.settings.content_style] +label = "コンテンツスタイル" +description = "LinkedIn投稿の語調とスタイル" + +[i18n.ja.settings.post_frequency] +label = "投稿頻度" +description = "コンテンツの作成・投稿の頻度" + +[i18n.ja.settings.content_topics] +label = "コンテンツトピック" +description = "作成するコンテンツのトピック(カンマ区切り、例: AI、リーダーシップ、スタートアップ)" + +[i18n.ja.settings.auto_engage] +label = "自動エンゲージメント" +description = "ネットワーク内の関連投稿に自動でいいねやコメントをする" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "投稿を直接公開せず、レビュー用キューに追加する" + +[i18n.ja.settings.hashtag_count] +label = "ハッシュタグ数" +description = "各投稿に含めるハッシュタグの数" + +[i18n.ja.settings.target_audience] +label = "ターゲットオーディエンス" +description = "コンテンツの主なターゲット層" + +[i18n.ja.settings.language] +label = "言語" +description = "投稿とエンゲージメントに使用する言語" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de LinkedIn" +description = "Gestor autónomo de LinkedIn — optimización de perfil, creación de contenido, networking y engagement profesional" +category = "Comunicación" + +[i18n.es.settings.content_style] +label = "Estilo de contenido" +description = "Voz y tono para las publicaciones de LinkedIn" + +[i18n.es.settings.post_frequency] +label = "Frecuencia de publicación" +description = "Con qué frecuencia crear y publicar contenido" + +[i18n.es.settings.content_topics] +label = "Temas de contenido" +description = "Temas sobre los que crear contenido (separados por comas, ej. IA, liderazgo, startups)" + +[i18n.es.settings.auto_engage] +label = "Engagement automático" +description = "Dar like y comentar automáticamente en publicaciones relevantes de tu red" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Poner publicaciones en cola para revisión en lugar de publicarlas directamente" + +[i18n.es.settings.hashtag_count] +label = "Cantidad de hashtags" +description = "Número de hashtags a incluir por publicación" + +[i18n.es.settings.target_audience] +label = "Audiencia objetivo" +description = "Audiencia principal para tu contenido" + +[i18n.es.settings.language] +label = "Idioma" +description = "Idioma para publicaciones e interacciones" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand LinkedIn" +description = "Gestionnaire LinkedIn autonome — optimisation de profil, création de contenu, réseautage et engagement professionnel" +category = "Communication" + +[i18n.fr.settings.content_style] +label = "Style de contenu" +description = "Ton et style pour les publications LinkedIn" + +[i18n.fr.settings.post_frequency] +label = "Fréquence de publication" +description = "Fréquence de création et de publication de contenu" + +[i18n.fr.settings.content_topics] +label = "Sujets de contenu" +description = "Sujets sur lesquels créer du contenu (séparés par des virgules, ex. IA, leadership, startups)" + +[i18n.fr.settings.auto_engage] +label = "Engagement automatique" +description = "Aimer et commenter automatiquement les publications pertinentes de votre réseau" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Mettre les publications en file d'attente pour révision au lieu de les publier directement" + +[i18n.fr.settings.hashtag_count] +label = "Nombre de hashtags" +description = "Nombre de hashtags à inclure par publication" + +[i18n.fr.settings.target_audience] +label = "Public cible" +description = "Public principal pour votre contenu" + +[i18n.fr.settings.language] +label = "Langue" +description = "Langue pour les publications et les interactions" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "LinkedIn-Hand" +description = "Autonomer LinkedIn-Manager — Profiloptimierung, Content-Erstellung, Networking und professionelles Engagement" +category = "Kommunikation" + +[i18n.de.settings.content_style] +label = "Inhaltsstil" +description = "Ton und Stil für LinkedIn-Beiträge" + +[i18n.de.settings.post_frequency] +label = "Veröffentlichungshäufigkeit" +description = "Wie oft Inhalte erstellt und veröffentlicht werden" + +[i18n.de.settings.content_topics] +label = "Inhaltsthemen" +description = "Themen für die Content-Erstellung (kommagetrennt, z.B. KI, Führung, Startups)" + +[i18n.de.settings.auto_engage] +label = "Automatisches Engagement" +description = "Relevante Beiträge im Netzwerk automatisch liken und kommentieren" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Beiträge zur Überprüfung in die Warteschlange stellen, anstatt sie direkt zu veröffentlichen" + +[i18n.de.settings.hashtag_count] +label = "Anzahl Hashtags" +description = "Anzahl der Hashtags pro Beitrag" + +[i18n.de.settings.target_audience] +label = "Zielgruppe" +description = "Primäre Zielgruppe für Ihre Inhalte" + +[i18n.de.settings.language] +label = "Sprache" +description = "Sprache für Beiträge und Interaktionen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "LinkedIn Hand" +description = "자율 LinkedIn 관리 — 프로필 최적화, 콘텐츠 제작, 네트워킹 및 전문적 소통" +category = "커뮤니케이션" + +[i18n.ko.settings.content_style] +label = "콘텐츠 스타일" +description = "LinkedIn 게시물의 어조와 스타일" + +[i18n.ko.settings.post_frequency] +label = "게시 빈도" +description = "콘텐츠를 작성하고 게시하는 주기" + +[i18n.ko.settings.content_topics] +label = "콘텐츠 주제" +description = "콘텐츠를 작성할 주제 (쉼표로 구분, 예: AI, 리더십, 스타트업)" + +[i18n.ko.settings.auto_engage] +label = "자동 소통" +description = "네트워크 내 관련 게시물에 자동으로 좋아요 및 댓글" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "게시물을 직접 게시하지 않고 대기열에 추가하여 검토" + +[i18n.ko.settings.hashtag_count] +label = "해시태그 수" +description = "게시물당 포함할 해시태그 수" + +[i18n.ko.settings.target_audience] +label = "대상 독자" +description = "콘텐츠의 주요 대상 독자" + +[i18n.ko.settings.language] +label = "언어" +description = "게시물 및 소통에 사용하는 언어" diff --git a/hands/linkedin/SKILL.md b/hands/linkedin/SKILL.md index 084990d..a136372 100644 --- a/hands/linkedin/SKILL.md +++ b/hands/linkedin/SKILL.md @@ -218,3 +218,753 @@ Before posting any content, classify it: - Credit sources and tag collaborators - Disclose affiliations when discussing products or services - Respect intellectual property and copyright + +--- + +## Advanced API Patterns + +### Image Post Creation (Media Upload Flow) + +Posting an image requires a 3-step flow: register upload, upload binary, then create post. + +**Step 1 -- Register the upload**: +```bash +curl -s -X POST "https://api.linkedin.com/rest/images?action=initializeUpload" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "initializeUploadRequest": { + "owner": "urn:li:person:MEMBER_ID" + } + }' +``` +Response contains `uploadUrl` and `image` URN (e.g., `urn:li:image:C4E...`). + +**Step 2 -- Upload the binary**: +```bash +curl -s -X PUT "$UPLOAD_URL" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: image/png" \ + --data-binary "@/path/to/image.png" +``` + +**Step 3 -- Create post with image**: +```bash +curl -s -X POST "https://api.linkedin.com/rest/posts" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "author": "urn:li:person:MEMBER_ID", + "lifecycleState": "PUBLISHED", + "commentary": "Check out our Q3 results!", + "visibility": "PUBLIC", + "distribution": {"feedDistribution": "MAIN_FEED"}, + "content": { + "media": { + "id": "urn:li:image:IMAGE_URN", + "title": "Q3 Performance Summary" + } + } + }' +``` + +### Document Post Creation (PDF/Carousel) + +LinkedIn "document posts" (carousels) follow the same register-upload-post pattern but use the documents API. + +**Register document upload**: +```bash +curl -s -X POST "https://api.linkedin.com/rest/documents?action=initializeUpload" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "initializeUploadRequest": { + "owner": "urn:li:person:MEMBER_ID" + } + }' +``` + +**Upload the PDF and create post** (same pattern as image -- PUT binary, then POST with `content.media.id` set to the document URN). + +### Article Publishing via API + +**Create an article post** (link article hosted externally): +```bash +curl -s -X POST "https://api.linkedin.com/rest/posts" \ + -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -H "LinkedIn-Version: 202405" \ + -d '{ + "author": "urn:li:person:MEMBER_ID", + "lifecycleState": "PUBLISHED", + "commentary": "I wrote about why most engineering teams get incident response wrong.\n\nKey insight: the 5-minute rule changes everything.", + "visibility": "PUBLIC", + "distribution": {"feedDistribution": "MAIN_FEED"}, + "content": { + "article": { + "source": "https://yourblog.com/incident-response", + "title": "The 5-Minute Rule for Incident Response", + "description": "A practical framework for engineering teams" + } + } + }' +``` + +> **Note**: Article-link posts get reduced reach vs native text posts. Prefer putting links in the first comment. + +### Analytics Endpoints + +**Get post statistics (organic)**: +```bash +curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "LinkedIn-Version: 202405" \ + "https://api.linkedin.com/rest/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:ORG_ID&timeIntervals.timeGranularityType=DAY&timeIntervals.timeRange.start=1704067200000&timeIntervals.timeRange.end=1706745600000" +``` + +**Get share statistics for a specific post**: +```bash +curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "LinkedIn-Version: 202405" \ + "https://api.linkedin.com/rest/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:ORG_ID&shares=urn:li:share:SHARE_ID" +``` + +Response fields: +| Field | Description | +|-------|-------------| +| `totalShareStatistics.impressionCount` | Total times the post appeared in feeds | +| `totalShareStatistics.uniqueImpressionsCount` | Unique viewers | +| `totalShareStatistics.clickCount` | Total clicks (content + read more) | +| `totalShareStatistics.likeCount` | Total likes/reactions | +| `totalShareStatistics.commentCount` | Total comments | +| `totalShareStatistics.shareCount` | Total reposts | +| `totalShareStatistics.engagement` | Engagement rate (decimal) | + +**Get follower statistics** (organization pages): +```bash +curl -s -H "Authorization: Bearer $LINKEDIN_ACCESS_TOKEN" \ + -H "LinkedIn-Version: 202405" \ + "https://api.linkedin.com/rest/organizationalEntityFollowerStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:ORG_ID" +``` + +### Webhook / Notification Patterns + +LinkedIn does not offer real-time webhooks for most events. Use polling instead: + +``` +Polling strategy: + - Post engagement: Poll every 15 minutes for first 4 hours after posting + - Mentions/comments: Poll every 5 minutes during engagement_hours + - Follower counts: Poll once per day + - Analytics: Poll once per day (data lags 24-48 hours) +``` + +### Error Handling and Rate Limit Retry + +``` +Rate limit response headers: + X-RateLimit-Limit: 100 + X-RateLimit-Remaining: 0 + X-RateLimit-Reset: 1706745600 + +HTTP 429 response: + {"status": 429, "message": "Resource level throttle limit..."} +``` + +**Retry strategy**: +``` +1. On HTTP 429: Read X-RateLimit-Reset header +2. Calculate wait_seconds = reset_timestamp - current_timestamp +3. Sleep for wait_seconds + 1 (buffer) +4. Retry the request (max 3 retries) +5. On 3 consecutive 429s: back off for 15 minutes + +On HTTP 5xx (server error): +1. Retry with exponential backoff: 1s, 2s, 4s +2. Max 3 retries +3. Log failure and queue for later retry + +On HTTP 401 (expired token): +1. Trigger OAuth 2.0 refresh flow +2. Update stored token +3. Retry original request once +``` + +--- + +## Content Calendar Template + +### Monthly Content Planning Framework + +Organize content around weekly themes that rotate through your content pillars. + +``` +MONTH: [Month Year] +THEME ROTATION: + Week 1: [Pillar 1 -- e.g., Engineering Leadership] + Week 2: [Pillar 2 -- e.g., Industry Trends] + Week 3: [Pillar 3 -- e.g., Career Growth] + Week 4: [Pillar 1 deep dive OR seasonal/timely topic] +``` + +### Weekly Content Schedule + +``` +WEEK OF [DATE] — Theme: [Weekly Theme] + +Monday: + - 8:30 AM: [Personal story] tied to weekly theme + Format: Hook + narrative + lesson + question + Goal: High engagement to start the week + +Tuesday: + - 9:00 AM: [Step-by-step guide] or [How-to] + Format: Numbered list with tactical advice + Goal: Saves and shares (authority building) + +Wednesday: + - 8:30 AM: [Data/insight post] with original analysis + Format: Stat + context + your take + question + Goal: Credibility and thought leadership + +Thursday: + - 9:00 AM: [Contrarian take] or [Industry opinion] + Format: Bold statement + reasoning + invitation to debate + Goal: Comments and discussion (algorithm boost) + +Friday: + - 8:00 AM: [Engagement post] — poll, question, or lightweight personal content + Format: Short, conversational, easy to respond to + Goal: Community building before weekend +``` + +### Content Mix Ratios + +| Category | % of Posts | Examples | +|----------|-----------|----------| +| Educational / Value | 40% | How-tos, frameworks, lessons learned | +| Personal / Storytelling | 25% | Career stories, failures, reflections | +| Engagement / Discussion | 20% | Questions, polls, contrarian takes | +| Promotional / Company | 10% | Product launches, hiring, milestones | +| Curated / Commentary | 5% | Industry news with your analysis | + +**Rule**: Never let promotional content exceed 15%. LinkedIn penalizes overtly sales-y accounts. + +### Engagement Windows and Response Strategy + +``` +Post published at 8:30 AM: + Minutes 0-15: Reply to EVERY comment immediately (signals activity to algorithm) + Minutes 15-60: Reply within 5 minutes of each new comment + Hours 1-4: Reply within 30 minutes + Hours 4-24: Reply within 2 hours (during business hours) + Day 2+: Reply within 24 hours + +First-comment strategy: + - Post your own comment within 2 minutes of publishing + - Use it for: link to resource, additional context, question to spark discussion + - This comment acts as engagement seed +``` + +--- + +## Analytics & Optimization + +### Key Metrics to Track + +| Metric | Formula | Good Benchmark | Great Benchmark | +|--------|---------|----------------|-----------------| +| Engagement rate | (reactions + comments + reposts) / impressions | > 2% | > 5% | +| Comment rate | comments / impressions | > 0.3% | > 1% | +| Follower growth rate | net new followers / total followers per week | > 0.5% | > 2% | +| Profile views | weekly profile views trend | Consistent growth | 2x after viral post | +| SSI (Social Selling Index) | LinkedIn's built-in score (0-100) | > 50 | > 70 | +| Content saves | saves / impressions | > 0.5% | > 2% | +| Click-through rate | clicks / impressions | > 1% | > 3% | + +### Engagement Rate Calculation + +``` +engagement_rate = (reactions + comments + reposts) / impressions * 100 + +Example: + 120 reactions + 35 comments + 8 reposts = 163 engagements + 163 / 5,200 impressions = 3.13% engagement rate + +Per-post tracking: + | Post Date | Topic | Format | Impressions | Eng Rate | Comments | + |-----------|-------|--------|-------------|----------|----------| + | Mon 03/03 | Leadership | Story | 5,200 | 3.13% | 35 | + | Tue 03/04 | AI Tools | How-to | 3,800 | 4.21% | 22 | + | Wed 03/05 | Hiring | Data | 2,100 | 2.85% | 12 | +``` + +### A/B Testing Strategies + +Test one variable at a time across pairs of similar posts: + +| Variable | Option A | Option B | Track | +|----------|----------|----------|-------| +| Hook style | Question hook | Bold statement hook | Click-through rate | +| Post length | Short (< 800 chars) | Long (1200+ chars) | Dwell time, engagement | +| Posting time | 8:00 AM | 9:30 AM | Impressions after 4 hours | +| CTA type | Question CTA | "Agree? Repost" CTA | Comment rate vs repost rate | +| Hashtag count | 3 hashtags | 0 hashtags | Reach beyond network | +| Format | Plain text | Text + image | Engagement rate | + +**How to run a test**: +1. Pick one variable to test (e.g., posting time) +2. Keep everything else constant (same pillar, similar format, similar length) +3. Run for 2 weeks (minimum 4 posts per variant) +4. Compare average metrics -- ignore outliers +5. Adopt the winner and move to next variable + +### Identifying Top-Performing Content Patterns + +After 30+ posts, analyze your data to find patterns: + +``` +Sort all posts by engagement rate (descending): + 1. Look at your top 5 posts — what do they share? + - Same content pillar? + - Same format (story, how-to, contrarian)? + - Same hook style? + - Similar length range? + - Same posting day/time? + 2. Look at your bottom 5 posts — what went wrong? + - External links in body? + - Promotional tone? + - Published on Friday/weekend? + - Weak hook? + 3. Create your "hit formula": + Best combo: [Pillar] + [Format] + [Hook style] + [Day/Time] + Example: "Engineering Leadership + Personal Story + Confession Hook + Tuesday 8:30 AM" +``` + +--- + +## Audience Growth Strategies + +### Comment-First Strategy + +The fastest way to grow on LinkedIn is strategic commenting on high-visibility posts. + +**How it works**: +1. Identify 15-20 active creators in your niche (10K+ followers) +2. Turn on notifications for their posts +3. Be among the first 5 comments on their new posts +4. Write substantive comments (3-5 sentences) that add genuine value + +**Comment templates for growth**: +``` +Adding a data point: + "This resonates. At [Company/Role], we saw [specific metric] when we + implemented [related approach]. The key difference was [insight]. + Curious if others have seen similar results?" + +Respectful counterpoint: + "Interesting perspective. I'd push back slightly on [point] — in my + experience with [context], the opposite was true because [reason]. + That said, I think [original point] absolutely holds for [use case]." + +Extending the idea: + "Building on this — one thing I'd add is [new angle]. I wrote about + this recently and the biggest takeaway was [specific insight]. + [Question that invites further discussion]?" +``` + +**Target**: 5-10 thoughtful comments per day during peak hours (8-10 AM). + +### Collaborative Content Patterns + +**Tagging strategy**: +- Tag 1-3 people who would genuinely find the content relevant +- Always explain WHY you're tagging them (not drive-by tags) +- Tag people you've already engaged with (they're more likely to respond) + +``` +Example post with strategic tags: + "I've been thinking about how engineering teams handle on-call rotations. + + After talking to 20+ eng managers, here are the 3 models that actually work: + + 1. Follow-the-sun (best for distributed teams) + 2. Volunteer-first rotation (best for small teams) + 3. Tiered escalation (best for complex systems) + + @Name1 — your team's approach to #2 was eye-opening. + @Name2 — curious if your distributed team uses #1 or something else? + + What model does your team use? Reply with your team size." +``` + +**Co-creation patterns**: +- Interview a peer and post key insights (tag them, they reshare) +- "X people I learned from this year" posts (mass tagging, high reshare rate) +- Collaborative lists: "Drop your best [resource] in the comments, I'll compile and share" + +### LinkedIn Newsletter Strategy + +Newsletters convert profile visitors into subscribers with direct inbox delivery. + +**Newsletter setup checklist**: +``` +1. Name: Clear, specific, benefit-driven + Good: "The Engineering Leader's Playbook" + Bad: "My Thoughts on Things" + +2. Cadence: Weekly or biweekly (consistency > frequency) + +3. Format: + - 800-1500 words (longer than posts, shorter than blog articles) + - One core idea per issue + - Actionable takeaways or frameworks + - End with a question to drive comments + +4. Promotion: + - Announce each issue with a teaser post (don't just auto-share) + - Reference newsletter content in regular posts + - Cross-promote with other newsletter authors +``` + +**Newsletter content structure**: +``` +Issue #[N]: [Compelling Title] + +[Hook paragraph -- why this matters NOW] + +[Section 1: The Problem / Context] + - 2-3 paragraphs with specific examples + +[Section 2: The Framework / Solution] + - Numbered steps or clear model + - Real-world application examples + +[Section 3: How to Apply This] + - Actionable next steps the reader can take today + +[Closing: Question + CTA] + "What's your experience with [topic]? Reply in the comments." + "If you found this useful, share it with your team." +``` + +### LinkedIn Live and Events + +**LinkedIn Live** broadcasts get 7x more reactions and 24x more comments than regular video posts. + +**Live session framework**: +``` +Pre-event (1 week before): + - Create LinkedIn Event and post announcement + - Send invites to relevant connections + - Post 2-3 teaser posts building anticipation + +During event: + - Start 2 minutes early for tech check + - Open with clear agenda (30 seconds) + - Acknowledge live commenters by name + - Keep sessions 20-40 minutes + +Post-event: + - Post key takeaways within 2 hours + - Reply to all comments on the event post + - Repurpose recording into 3-5 short clips for future posts +``` + +**Event types that work**: +| Type | Duration | Best For | Frequency | +|------|----------|----------|-----------| +| AMA (Ask Me Anything) | 30 min | Engagement, authority | Monthly | +| Industry deep dive | 20 min | Thought leadership | Biweekly | +| Interview / fireside chat | 40 min | Network growth | Monthly | +| Quick tip / hot take | 10 min | Visibility | Weekly | + +--- + +## Worked Examples + +### Example 1: Thought Leadership Campaign + +**Scenario**: VP of Engineering building authority in "engineering culture" niche. + +**Content pillars**: +``` +Pillar 1: Engineering Management (40%) +Pillar 2: Scaling Teams (30%) +Pillar 3: Career Advice (20%) +Pillar 4: Personal Lessons (10%) +``` + +**Week 1 posting schedule with sample posts**: + +**Monday 8:30 AM -- Personal Story (Pillar 1)**: +``` +I promoted my worst interviewer to Head of Recruiting. + +Sounds crazy. Here's what happened. + +She kept rejecting candidates everyone else loved. +Her "pass rate" was 15%. Team average was 60%. + +But after 12 months, something became clear: + +Her hires had: +→ 94% retention rate (team avg: 71%) +→ 2.3x faster time to first meaningful contribution +→ Zero PIPs in their first year + +She wasn't a bad interviewer. +She was the only one actually doing it right. + +The lesson? +Measure what matters. Pass rates reward speed. +Retention rates reward judgment. + +What's one metric your team optimizes for +that might be the wrong one? + +#EngineeringLeadership #Hiring #TechManagement +``` + +**Tuesday 9:00 AM -- How-To Guide (Pillar 2)**: +``` +How to run a team retrospective that people actually enjoy +(not the soul-crushing ones everyone dreads): + +Step 1: Kill the "what went well / what didn't" format +→ Use "I wish... I wonder... I'm proud of..." instead + +Step 2: Timebox ruthlessly +→ 45 minutes max. If it takes longer, your team is too big for one retro. + +Step 3: One action item per person, max +→ A retro with 20 action items produces zero change. +→ One item per person = accountability. + +Step 4: Start with appreciation +→ First 5 minutes: each person thanks someone else on the team. +→ This changes the entire energy of the room. + +Step 5: Rotate the facilitator +→ The manager should NOT always run retros. +→ It changes what people feel safe saying. + +I've used this format with teams of 5 to teams of 50. + +What's your retro format? Drop it below -- +I'm always looking for new approaches. + +#Agile #EngineeringCulture #TeamManagement +``` + +**Wednesday 8:30 AM -- Data + Insight (Pillar 2)**: +``` +We tracked every engineering team meeting for 6 months. + +The data was uncomfortable. + +→ Average engineer: 11.2 hours/week in meetings +→ Senior engineers: 16.4 hours/week +→ Time spent in meetings that could've been async: 62% + +We cut 40% of recurring meetings. + +Result after 3 months: +→ Sprint velocity: +23% +→ Engineer satisfaction: +31% (internal survey) +→ "Deep work" blocks per week: 2.1 → 4.7 + +The surprising part? +Nobody missed the deleted meetings. +Not one person asked to bring them back. + +If you haven't audited your meeting load recently, +you're probably burning 30-40% of your team's capacity. + +What % of your meetings could be an async update? + +#Engineering #Productivity #Leadership +``` + +**Thursday 9:00 AM -- Contrarian Take (Pillar 3)**: +``` +Unpopular opinion: "Culture fit" interviews should be illegal. + +Here's why: + +Culture fit = "do I want to get a beer with this person?" +That's not hiring. That's friend-making. + +What actually matters: +→ Values alignment (do they care about the same outcomes?) +→ Working style compatibility (async vs sync, docs vs meetings) +→ Growth trajectory (will they push the team forward?) + +None of those require "fitting in." + +The best hire I ever made was someone who challenged +every assumption we had. They didn't "fit" our culture. + +They made it better. + +Replace "culture fit" with "culture add." + +Agree or disagree? I'd love to hear your take. + +#Hiring #Diversity #EngineeringCulture #Leadership +``` + +**Friday 8:00 AM -- Engagement Post (Pillar 4)**: +``` +Fill in the blank: + +"The best career advice I ever received was ___________." + +I'll go first: + +"Stop optimizing for your next promotion. +Start optimizing for your next learning curve." + +Changed how I made every career decision since. + +Your turn. + +#CareerAdvice #ProfessionalGrowth +``` + +### Example 2: Company Page Management + +**Scenario**: B2B SaaS company (Series B, 80 employees) managing their LinkedIn company page. + +**Posting cadence**: +``` +Company page: 4-5 posts per week +Employee advocacy: 2-3 employees reshare/post per week +Executive accounts: CEO + CTO post 2-3x/week each +``` + +**Weekly company page schedule**: +``` +Monday: Industry insight or thought leadership (educational) +Tuesday: Product tip or customer use case (value-driven) +Wednesday: Team/culture spotlight (employer branding) +Thursday: Data or trend analysis (authority) +Friday: Milestone, hiring, or community post (engagement) +``` + +**Sample company page posts**: + +**Tuesday -- Customer Use Case**: +``` +"We used to spend 3 hours every Monday pulling reports manually." + +That's what @CustomerName's ops team told us last quarter. + +After switching to [Product] automated workflows: +→ Report generation: 3 hours → 12 minutes +→ Data accuracy: 89% → 99.7% +→ Team freed up: 12 hours/week for strategic work + +The best part? They set it up in a single afternoon. + +Read the full story: [link in first comment] + +#DataAutomation #Operations #CustomerSuccess +``` + +**Wednesday -- Team Culture Spotlight**: +``` +This is Sarah. She joined us as intern #3 two years ago. + +Last week she deployed our new ML pipeline to production. +By herself. On a Tuesday. No drama. + +What happened in between: +→ Mentored by 4 different senior engineers +→ Shipped 47 PRs in her first year +→ Gave her first conference talk at 23 +→ Now leads a team of 3 + +We don't hire for credentials. +We hire for curiosity and grit. + +Sarah had both. + +We're hiring 5 more engineers just like her. +Link in the comments. + +#Hiring #Engineering #StartupCulture #WomenInTech +``` + +**Employee advocacy tracking**: +``` +| Employee | Role | Posts/Week | Avg Reach | Topics | +|----------|------|-----------|-----------|--------| +| CEO | Executive | 3 | 8,500 | Vision, industry, leadership | +| CTO | Executive | 2 | 5,200 | Technical, architecture, hiring | +| VP Eng | Leader | 2 | 3,100 | Engineering culture, management | +| DevRel | IC | 3 | 4,800 | Tutorials, product, community | +``` + +**Analytics tracking cadence**: +``` +Daily: Check post-level engagement (reactions, comments, shares) +Weekly: Follower growth, top-performing post, engagement rate trend +Monthly: Content audit — which pillars/formats performed best + Adjust next month's content mix based on data +Quarterly: Competitor benchmarking, SSI review, strategy refresh +``` + +### Example 3: Job Seeker Profile Optimization Campaign + +**Scenario**: Senior developer transitioning to engineering management role. + +**4-week content plan**: +``` +Week 1: Establish expertise + - Post about a technical decision you led and its business impact + - Share a "lessons from my first year managing" story + - Comment on 10 engineering leadership posts + +Week 2: Demonstrate thought leadership + - Publish a how-to post: "How I transitioned from IC to manager" + - Share data or a framework you've developed + - Start engaging with hiring managers' content in target companies + +Week 3: Build social proof + - Post about a mentoring success story (tag the mentee with permission) + - Share a "things I wish I knew" post targeting new managers + - Request 3-5 recommendations from colleagues and reports + +Week 4: Signal availability + - Post about what you're looking for (without desperation) + - Engage heavily in target company employees' content + - Send personalized connection requests to hiring managers +``` + +**Sample "open to opportunities" post**: +``` +After 8 years of writing code and 2 years of leading teams, +I'm looking for my next engineering management challenge. + +What I bring to the table: +→ Scaled a team from 4 to 22 engineers +→ Reduced deployment failures by 73% through better process +→ Mentored 6 engineers into senior roles +→ Built hiring pipelines that maintained 85%+ offer acceptance + +What I'm looking for: +→ Series A-C company building something meaningful +→ Team of 8-20 engineers who care about craft +→ Leadership that values engineering culture, not just velocity + +If your team is growing and you value +managers who still understand the code -- +I'd love to chat. + +DMs are open. Or drop a comment and I'll reach out. + +#OpenToWork #EngineeringManager #Hiring #Leadership +``` diff --git a/hands/predictor/HAND.toml b/hands/predictor/HAND.toml index 3d87eee..c0c3d7e 100644 --- a/hands/predictor/HAND.toml +++ b/hands/predictor/HAND.toml @@ -425,6 +425,241 @@ token_consumption = "high" default_active = false activation_warning = "Predictor hand runs continuously and generates predictions, consuming tokens." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "预测 Hand" description = "自主预测智能体——收集信号、构建推理链、做出校准预测并追踪准确度" +category = "数据" + +[i18n.zh.settings.prediction_domain] +label = "预测领域" +description = "预测的主要关注领域" + +[i18n.zh.settings.time_horizon] +label = "时间跨度" +description = "预测的前瞻时间范围" + +[i18n.zh.settings.data_sources] +label = "数据来源" +description = "监控信号的来源类型" + +[i18n.zh.settings.report_frequency] +label = "报告频率" +description = "生成预测报告的频率" + +[i18n.zh.settings.predictions_per_report] +label = "每份报告预测数" +description = "每份报告包含的预测条目数量" + +[i18n.zh.settings.track_accuracy] +label = "追踪准确度" +description = "在预测时间窗口到期后对历史预测进行评分" + +[i18n.zh.settings.confidence_threshold] +label = "置信度阈值" +description = "纳入预测报告的最低置信度" + +[i18n.zh.settings.contrarian_mode] +label = "逆向思维模式" +description = "主动寻找并展示与主流共识相反的预测" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "予測 Hand" +description = "自律型予測エージェント——シグナル収集、推論チェーン構築、キャリブレーション済み予測、精度追跡" +category = "データ" + +[i18n.ja.settings.prediction_domain] +label = "予測ドメイン" +description = "予測の主な対象分野" + +[i18n.ja.settings.time_horizon] +label = "予測期間" +description = "どのくらい先まで予測するか" + +[i18n.ja.settings.data_sources] +label = "データソース" +description = "シグナルを監視するソースの種類" + +[i18n.ja.settings.report_frequency] +label = "レポート頻度" +description = "予測レポートの生成頻度" + +[i18n.ja.settings.predictions_per_report] +label = "レポートあたりの予測数" +description = "各レポートに含める予測項目の数" + +[i18n.ja.settings.track_accuracy] +label = "精度追跡" +description = "予測期間が終了した過去の予測にスコアを付ける" + +[i18n.ja.settings.confidence_threshold] +label = "信頼度しきい値" +description = "予測をレポートに含めるための最低信頼度" + +[i18n.ja.settings.contrarian_mode] +label = "逆張りモード" +description = "コンセンサスに反する予測を積極的に探索・提示する" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Predicciones" +description = "Predictor autónomo del futuro — recopila señales, construye cadenas de razonamiento, genera predicciones calibradas y rastrea la precisión" +category = "Datos" + +[i18n.es.settings.prediction_domain] +label = "Dominio de predicción" +description = "Dominio principal para las predicciones" + +[i18n.es.settings.time_horizon] +label = "Horizonte temporal" +description = "Qué tan lejos en el futuro predecir" + +[i18n.es.settings.data_sources] +label = "Fuentes de datos" +description = "Qué tipos de fuentes monitorear para señales" + +[i18n.es.settings.report_frequency] +label = "Frecuencia de informes" +description = "Con qué frecuencia generar informes de predicción" + +[i18n.es.settings.predictions_per_report] +label = "Predicciones por informe" +description = "Número de predicciones a incluir por informe" + +[i18n.es.settings.track_accuracy] +label = "Rastrear precisión" +description = "Puntuar predicciones pasadas cuando su horizonte temporal expire" + +[i18n.es.settings.confidence_threshold] +label = "Umbral de confianza" +description = "Confianza mínima para incluir una predicción" + +[i18n.es.settings.contrarian_mode] +label = "Modo contrario" +description = "Buscar y presentar activamente predicciones contrarias al consenso" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand de Prédictions" +description = "Prédicteur autonome — collecte de signaux, construction de chaînes de raisonnement, prédictions calibrées et suivi de la précision" +category = "Données" + +[i18n.fr.settings.prediction_domain] +label = "Domaine de prédiction" +description = "Domaine principal pour les prédictions" + +[i18n.fr.settings.time_horizon] +label = "Horizon temporel" +description = "Jusqu'où prédire dans le futur" + +[i18n.fr.settings.data_sources] +label = "Sources de données" +description = "Types de sources à surveiller pour les signaux" + +[i18n.fr.settings.report_frequency] +label = "Fréquence des rapports" +description = "Fréquence de génération des rapports de prédiction" + +[i18n.fr.settings.predictions_per_report] +label = "Prédictions par rapport" +description = "Nombre de prédictions à inclure par rapport" + +[i18n.fr.settings.track_accuracy] +label = "Suivi de la précision" +description = "Évaluer les prédictions passées lorsque leur horizon temporel expire" + +[i18n.fr.settings.confidence_threshold] +label = "Seuil de confiance" +description = "Confiance minimale pour inclure une prédiction" + +[i18n.fr.settings.contrarian_mode] +label = "Mode contraire" +description = "Rechercher et présenter activement des prédictions contraires au consensus" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Vorhersage-Hand" +description = "Autonomer Vorhersage-Agent — Signalerfassung, Aufbau von Argumentationsketten, kalibrierte Vorhersagen und Genauigkeitsverfolgung" +category = "Daten" + +[i18n.de.settings.prediction_domain] +label = "Vorhersagedomäne" +description = "Hauptdomäne für Vorhersagen" + +[i18n.de.settings.time_horizon] +label = "Zeithorizont" +description = "Wie weit in die Zukunft vorhergesagt werden soll" + +[i18n.de.settings.data_sources] +label = "Datenquellen" +description = "Welche Quellentypen auf Signale überwacht werden" + +[i18n.de.settings.report_frequency] +label = "Berichtshäufigkeit" +description = "Wie oft Vorhersageberichte generiert werden" + +[i18n.de.settings.predictions_per_report] +label = "Vorhersagen pro Bericht" +description = "Anzahl der Vorhersagen pro Bericht" + +[i18n.de.settings.track_accuracy] +label = "Genauigkeitsverfolgung" +description = "Vergangene Vorhersagen bewerten, wenn ihr Zeithorizont abläuft" + +[i18n.de.settings.confidence_threshold] +label = "Konfidenzschwelle" +description = "Mindestvertrauen für die Aufnahme einer Vorhersage" + +[i18n.de.settings.contrarian_mode] +label = "Konträrer Modus" +description = "Aktiv nach Vorhersagen suchen und präsentieren, die dem Konsens widersprechen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "예측 Hand" +description = "자율 미래 예측 에이전트 — 신호 수집, 추론 체인 구축, 보정된 예측 수행 및 정확도 추적" +category = "데이터" + +[i18n.ko.settings.prediction_domain] +label = "예측 분야" +description = "예측의 주요 관심 분야" + +[i18n.ko.settings.time_horizon] +label = "시간 범위" +description = "예측의 미래 전망 기간" + +[i18n.ko.settings.data_sources] +label = "데이터 소스" +description = "신호를 모니터링할 소스 유형" + +[i18n.ko.settings.report_frequency] +label = "보고서 빈도" +description = "예측 보고서 생성 주기" + +[i18n.ko.settings.predictions_per_report] +label = "보고서당 예측 수" +description = "각 보고서에 포함할 예측 항목 수" + +[i18n.ko.settings.track_accuracy] +label = "정확도 추적" +description = "예측 기간 만료 후 과거 예측에 대한 점수 평가" + +[i18n.ko.settings.confidence_threshold] +label = "신뢰도 임계값" +description = "예측 보고서에 포함하기 위한 최소 신뢰도" + +[i18n.ko.settings.contrarian_mode] +label = "역발상 모드" +description = "주류 컨센서스에 반하는 예측을 적극적으로 탐색하고 제시" diff --git a/hands/predictor/SKILL.md b/hands/predictor/SKILL.md index 4e32476..f7eaaf9 100644 --- a/hands/predictor/SKILL.md +++ b/hands/predictor/SKILL.md @@ -184,6 +184,591 @@ PREDICTION: [Specific, falsifiable claim] --- +## Worked Examples + +### Example 1: Corporate Acquisition + +**Question**: "Will Acme Corp be acquired within 12 months?" (asked January 2025) + +``` +PREDICTION: Acme Corp (mid-cap SaaS, $2B market cap) will be acquired by January 2026 + +1. REFERENCE CLASS (Outside View) + Base rate: ~5-7% of publicly traded mid-cap SaaS companies receive + acquisition offers in any given 12-month period. + Reference examples: + - Splunk acquired by Cisco (2023) — similar scale, strategic buyer + - Figma attempted acquisition by Adobe (2022) — regulatory block + - Nuance acquired by Microsoft (2021) — vertical SaaS, strategic fit + - Mandiant acquired by Google (2022) — security vertical + - Cvent acquired by Blackstone (2021) — PE buyout at depressed valuation + + Starting probability: 6% + +2. SPECIFIC EVIDENCE (Inside View) + Signals FOR (+): + a. Board hired Goldman Sachs as advisor (leaked filing) + — strength: STRONG — adjustment: +20% + (Companies that retain M&A advisors complete a transaction ~40% of the time) + b. CEO sold 30% of personal holdings in Q4 (SEC filing) + — strength: MODERATE — adjustment: +5% + c. Two major competitors acquired in past 18 months (market consolidation) + — strength: MODERATE — adjustment: +8% + d. Revenue growth decelerated from 35% to 18% YoY (earnings report) + — strength: MODERATE — adjustment: +5% + (Slower-growth companies more likely to accept acquisition offers) + + Signals AGAINST (-): + a. Founder still holds 25% voting control and has said "we're building for + the long term" (recent interview) + — strength: STRONG — adjustment: -12% + b. Stock price at all-time high — acquirer must pay steep premium + — strength: MODERATE — adjustment: -5% + c. Current antitrust environment — FTC blocking more deals + — strength: WEAK — adjustment: -3% + +3. SYNTHESIS + Starting probability (base rate): 6% + Signals for: +20% +5% +8% +5% = +38% + Signals against: -12% -5% -3% = -20% + Net adjustment: +18% + Raw probability: 24% + + Sanity check: ~1 in 4 feels right given the strong M&A advisor signal + balanced against founder control. + Final probability: 25% + +4. KEY ASSUMPTIONS + - Goldman engagement is for M&A (not debt restructuring): + If wrong, probability drops to 8% + - Founder is willing to sell at the right price: + If wrong (founder vetoes any deal), probability drops to 3% + - Regulatory environment doesn't tighten further: + If wrong, probability drops to 18% + +5. RESOLUTION + Date: January 31, 2026 + Criteria: Definitive merger agreement announced (not just rumors) + Data source: SEC EDGAR (8-K filing), Bloomberg terminal +``` + +### Example 2: Technology Adoption + +**Question**: "Will WebAssembly (Wasm) reach mainstream server-side adoption by 2027?" + +``` +PREDICTION: >20% of new cloud-deployed services will use Wasm runtimes by +end of 2027 + +1. REFERENCE CLASS (Outside View) + Technology adoption lifecycle (Rogers curve): + - Innovators (2.5%) → Early Adopters (13.5%) → Early Majority (34%) + - Crossing from Early Adopters to Early Majority typically takes 3-5 years + after first production deployments + - First serious server-side Wasm deployments: ~2022 (Fermyon, Cosmonic) + - Current status (2025): Late Early Adopter stage + + Historical analogues for infrastructure tech adoption: + - Containers (Docker 2013 → mainstream 2017-2018): ~4-5 years + - Kubernetes (2014 → mainstream 2018-2019): ~4-5 years + - Serverless (Lambda 2014 → mainstream 2018-2020): ~4-6 years + + Base rate for "infrastructure tech reaching 20% adoption within 5 years + of first production use": ~30% + + Starting probability: 30% + +2. SPECIFIC EVIDENCE (Inside View) + Signals FOR (+): + a. WASI standard maturing — WASI Preview 2 shipped, component model + stabilizing (W3C working group) + — strength: STRONG — adjustment: +8% + b. Major cloud providers offering Wasm runtimes (Fastly, Cloudflare Workers, + Azure, AWS exploring) + — strength: STRONG — adjustment: +10% + c. Docker adding Wasm support natively (announced 2022, shipping) + — strength: MODERATE — adjustment: +5% + + Signals AGAINST (-): + a. Ecosystem still fragmented — multiple competing runtimes, toolchain gaps + — strength: STRONG — adjustment: -10% + b. Containers already "good enough" for most workloads — weak forcing + function to switch + — strength: STRONG — adjustment: -8% + c. Wasm language support uneven — great for Rust/C++, mediocre for Python/JS + — strength: MODERATE — adjustment: -5% + + Leading indicators to track: + - CNCF survey: % of respondents evaluating/using Wasm + - Job postings mentioning Wasm (Indeed/LinkedIn trend) + - GitHub stars and contributors for top Wasm runtimes (wasmtime, wasmer) + - WASI spec milestone dates vs planned dates + +3. SYNTHESIS + Starting probability (base rate): 30% + Signals for: +8% +10% +5% = +23% + Signals against: -10% -8% -5% = -23% + Net adjustment: 0% + Final probability: 30% + + Interpretation: The positive and negative signals roughly cancel out. + The base rate from analogous infrastructure technologies holds. + This is genuinely uncertain — the "chasm" crossing is the key risk. + +4. KEY ASSUMPTIONS + - "Mainstream" defined as >20% of NEW deployments (not total installed base) + - WASI component model reaches 1.0 stable by mid-2026 + If delayed beyond 2026: probability drops to 15% + - No competing paradigm emerges (e.g., eBPF expanding scope): + If strong competitor: probability drops to 20% + +5. RESOLUTION + Date: December 31, 2027 + Criteria: CNCF annual survey shows >20% respondents using Wasm in production + Data source: CNCF Annual Survey, Datadog Container Report +``` + +### Example 3: Geopolitical Forecast + +**Question**: "Will US-China trade tensions escalate significantly in 2025?" +(Defined as: new tariffs >25% on >$100B of goods, or export controls expanded +to 3+ new technology categories) + +``` +PREDICTION: Significant escalation of US-China trade tensions in 2025 + +1. REFERENCE CLASS (Outside View) + Historical trade conflict escalation pattern: + - US-China trade relations since 2018: escalation occurred in 4 of 7 years + - In election year +1 (new/returning administration): escalation rate ~60% + - Trade wars historically escalate in steps, with retaliation cycles + + Starting probability: 55% + +2. SPECIFIC EVIDENCE (Inside View) + Signals FOR (+): + a. Administration rhetoric on China hawkish across both parties + — strength: STRONG — adjustment: +10% + b. Semiconductor export controls already expanding (ASML, Tokyo Electron) + — strength: STRONG — adjustment: +8% + c. China retaliating with rare earth export restrictions + — strength: MODERATE — adjustment: +5% + + Signals AGAINST (-): + a. Business lobbying against further tariffs (Chamber of Commerce, farm lobby) + — strength: MODERATE — adjustment: -5% + b. Inflation concerns create political cost for tariffs + — strength: MODERATE — adjustment: -5% + c. Diplomatic channels active (recent bilateral meetings) + — strength: WEAK — adjustment: -3% + + Scenario mapping: + ┌─────────────────────────┬─────────────┬────────────────────┐ + │ Scenario │ Probability │ Key trigger │ + ├─────────────────────────┼─────────────┼────────────────────┤ + │ Major escalation │ 25% │ Taiwan crisis or │ + │ (new tariffs + controls │ │ tech IP theft case │ + │ + retaliatory cycle) │ │ │ + ├─────────────────────────┼─────────────┼────────────────────┤ + │ Moderate escalation │ 40% │ Incremental tariff │ + │ (meets our threshold) │ │ increases + 1-2 │ + │ │ │ new export controls│ + ├─────────────────────────┼─────────────┼────────────────────┤ + │ Status quo / minor │ 30% │ Diplomatic deals, │ + │ changes │ │ election distraction│ + ├─────────────────────────┼─────────────┼────────────────────┤ + │ De-escalation │ 5% │ Grand bargain │ + │ (reduced tariffs) │ │ (historically rare)│ + └─────────────────────────┴─────────────┴────────────────────┘ + + P(meets our escalation threshold) = 25% + 40% = 65% + +3. SYNTHESIS + Starting probability (base rate): 55% + Signals for: +10% +8% +5% = +23% + Signals against: -5% -5% -3% = -13% + Net adjustment: +10% + Raw probability: 65% + + Cross-check with scenario mapping: 65% — consistent. + Final probability: 65% + +4. KEY ASSUMPTIONS + - No major geopolitical crisis (Taiwan strait) that causes extreme + escalation or extreme restraint: If crisis occurs, split to + 80% (escalation) or 20% (restraint/avoidance) + - US economy remains stable: If recession hits, probability drops + to 45% (political cost of tariffs rises) + - China does not make major trade concessions preemptively: + If it does, probability drops to 30% + +5. RESOLUTION + Date: December 31, 2025 + Criteria: Cumulative new tariffs >25% on >$100B goods OR export controls + expanded to 3+ new technology categories (per USTR/BIS announcements) + Data source: USTR tariff schedule, BIS Entity List updates, Congressional + Research Service reports +``` + +--- + +## Fermi Estimation Techniques + +Fermi estimation is the art of making reasonable order-of-magnitude guesses +by breaking unknowable questions into smaller, estimable pieces. + +### Step-by-Step Process + +``` +1. DEFINE the quantity you want to estimate + → Be specific about units, scope, and timeframe + +2. DECOMPOSE into factors you can estimate independently + → Prefer multiplication chains: A × B × C + → Each factor should be something you can reason about + +3. ESTIMATE each factor + → Use round numbers (powers of 10 when possible) + → State your confidence range for each factor + +4. MULTIPLY and sanity-check + → Does the result pass the "smell test"? + → Cross-check with any known anchors + +5. STATE your uncertainty + → Fermi estimates are typically accurate within 1 order of magnitude + → Give a range: [estimate / 3, estimate × 3] is a reasonable default +``` + +### Common Reference Anchors + +Keep these memorized for quick estimation: + +``` +POPULATION + World: ~8 billion + US: ~340 million + EU: ~450 million + China: ~1.4 billion + India: ~1.4 billion + +ECONOMICS + World GDP: ~$100 trillion + US GDP: ~$28 trillion + US median household: ~$75,000/year + US federal budget: ~$6.5 trillion + S&P 500 total cap: ~$45 trillion + +TIME + Seconds in a day: ~86,400 (~10^5) + Seconds in a year: ~31.5 million (~3 × 10^7) + Working hours/year: ~2,000 + +TECHNOLOGY + Global internet users: ~5.5 billion + Global smartphone users: ~4.5 billion + AWS annual revenue: ~$90 billion + Global IT spending: ~$5 trillion + GitHub developers: ~100 million + +INDUSTRY SIZES (annual, global) + Cloud computing: ~$600 billion + Semiconductor: ~$600 billion + Pharmaceutical: ~$1.5 trillion + Automotive: ~$3 trillion + Agriculture: ~$3 trillion + E-commerce: ~$6 trillion +``` + +### Worked Fermi Examples + +**Example A: Estimating the TAM for an AI code review tool** + +``` +Question: What is the annual TAM for an AI-powered code review SaaS? + +Decomposition: + TAM = (Number of professional developers) + × (% who do code reviews regularly) + × (willingness to pay for tooling) + × (average annual price) + +Estimates: + Professional developers worldwide: ~30 million + (GitHub has 100M accounts, but ~30% are professional, and + not all professionals use GitHub) + + % who do code reviews: ~60% + (Standard in companies > 50 engineers, less common in small shops) + + Target market (teams that would buy SaaS): ~40% + (Enterprise and mid-market; small teams use free tools) + + Annual price per seat: ~$300/year + (Comparable: GitHub Copilot ~$200, Snyk ~$400, middle ground) + +Calculation: + 30M × 0.60 × 0.40 × $300 = $2.16 billion + +Sanity check: + - GitHub revenue ~$2B (broader product, ~4M paid users) + - Snyk valued at $7B (code security, related space) + - $2B TAM is plausible for a focused code review tool + +Result: ~$2 billion TAM (range: $700M to $6B) +``` + +**Example B: Estimating daily active queries to a search engine** + +``` +Question: How many search queries does Google process per day? + +Decomposition: + Queries/day = (Internet users who use Google) + × (searches per user per day) + +Estimates: + Global internet users: ~5.5 billion + Google market share: ~90% + Google users: 5.5B × 0.90 = ~5 billion + But not all use it daily: ~50% daily active rate + Daily active Google searchers: ~2.5 billion + + Searches per active user per day: ~3-4 + (Some people search 10+ times, many search once or not at all) + +Calculation: + 2.5 billion × 3.5 = ~8.5 billion queries/day + +Sanity check: + Published figure (Google): ~8.5 billion searches/day (2024) + Our estimate nailed it — sometimes Fermi estimation gets lucky. + +Result: ~8.5 billion/day (range: 3B to 25B) +``` + +### Order of Magnitude Sanity Checks + +After any estimate, verify it makes sense: + +``` +CHECK 1: Per-person reasonableness + Divide by relevant population. Is the per-person number realistic? + "$50B market ÷ 340M Americans = $147/person" — plausible? + +CHECK 2: Comparison to known quantities + Is your estimate bigger or smaller than things you know? + "Our estimate of X is $3B — that's 5% of AWS revenue. Reasonable?" + +CHECK 3: Growth rate implied + If you're estimating a future state, what annual growth rate is implied? + >50% sustained growth for >3 years is extremely rare. + +CHECK 4: Upper bound test + What is the theoretical maximum? Is your estimate within it? + "Total possible customers × maximum price = ceiling" +``` + +--- + +## Prediction Market Patterns + +### Interpreting Market Prices as Probabilities + +Prediction market prices map to probabilities, but with important caveats: + +``` +Market price $0.65 for "Event X occurs" + → Naive interpretation: 65% probability + → Adjusted interpretation: depends on market quality + +Adjustment factors: + Liquid market (Polymarket, Metaculus with many forecasters): + Price ≈ true probability (±3-5%) + + Thin market (<50 traders, <$10K volume): + Price is noisy — treat as ±15% uncertainty + A $0.65 price could represent 50-80% true probability + + Binary vs. multi-outcome: + Binary markets are more reliable + Multi-outcome markets often have probabilities summing to >100% + (overround) — normalize before interpreting +``` + +### Common Prediction Market Biases + +| Bias | Description | Impact | Correction | +|------|-------------|--------|------------| +| Favorite-longshot | Favorites underpriced, longshots overpriced | Longshot events appear ~2-3x more likely than they are | If market says 5%, true probability may be 2-3% | +| Recency | Recent events dominate pricing | Probability spikes after news, then slowly reverts | Wait 24-48h after major news before trusting market prices | +| Liquidity premium | Illiquid contracts trade at a discount | Prices biased toward 50% in thin markets | Weight liquid markets more heavily | +| Expiration clustering | Prices converge to 0 or 1 near expiration | Mid-probability contracts vanish near deadline | Most useful signal is months before resolution | +| Hedging distortion | Traders hedging other positions, not expressing beliefs | Prices reflect risk management, not pure probability | Cross-reference with non-market forecasts | + +### Aggregation Methods + +When combining multiple probability estimates (markets, experts, models): + +``` +SIMPLE AVERAGE + P = (P1 + P2 + P3) / 3 + Use when: Sources are roughly equally credible + Weakness: Susceptible to outliers + +MEDIAN + P = middle value of sorted estimates + Use when: One source might be badly miscalibrated + Weakness: Ignores magnitude of disagreement + +TRIMMED MEAN + Drop highest and lowest, average the rest + P = average(P2 ... Pn-1) after sorting + Use when: 5+ sources, want outlier robustness + +EXTREMIZED AVERAGE + P_avg = simple average + P_extremized = P_avg^a / (P_avg^a + (1-P_avg)^a), where a > 1 + Typical a = 1.5 to 2.5 (more extremizing with more independent sources) + Use when: Sources are genuinely independent (not reading each other) + Rationale: If 5 independent sources all say 70%, the true probability + is likely higher than 70% — shared info should push further from 50% + +CONFIDENCE-WEIGHTED AVERAGE + P = Σ(wi × Pi) / Σ(wi) + where wi = track record score or source reliability + Use when: Sources have known, differing track records +``` + +### When Markets Beat Experts (and Vice Versa) + +``` +MARKETS TEND TO WIN when: + ✓ Large, liquid, diverse participant pool + ✓ Question is well-defined with clear resolution criteria + ✓ Information is widely distributed (no single expert has edge) + ✓ Time horizon is 1 month to 2 years + Examples: Election outcomes, product launch dates, economic indicators + +EXPERTS TEND TO WIN when: + ✓ Question requires deep domain-specific knowledge + ✓ Market is thin or participants lack domain context + ✓ Very long time horizons (>5 years) — markets discount distant futures + ✓ Novel situations with no historical market precedent + Examples: Technical feasibility, scientific breakthroughs, niche regulation + +BEST PRACTICE: Use both + Start with the market price, then adjust using expert insight. + Treat the market as the prior and expert analysis as an update. +``` + +--- + +## Update Protocol + +### Bayesian Updating Worked Example + +``` +SCENARIO: You predicted 30% chance that Company Z launches Product A in Q1. +New evidence: A leaked internal slide shows a Q1 launch timeline. + +STEP 1: State the prior + P(launch in Q1) = 0.30 + +STEP 2: Assess the evidence + E = leaked slide showing Q1 timeline + How likely is this evidence if the launch IS happening in Q1? + P(E | launch) = 0.85 + (Internal slides usually reflect real plans, but plans change) + How likely is this evidence if the launch is NOT in Q1? + P(E | no launch) = 0.15 + (Could be outdated slide, aspirational, or decoy) + +STEP 3: Calculate the likelihood ratio + LR = P(E | launch) / P(E | no launch) = 0.85 / 0.15 = 5.67 + +STEP 4: Convert prior to odds, multiply, convert back + Prior odds = 0.30 / 0.70 = 0.429 + Posterior odds = 0.429 × 5.67 = 2.43 + Posterior probability = 2.43 / (1 + 2.43) = 0.71 + +STEP 5: State the update + Prior: 30% → Posterior: 71% + Update magnitude: +41 percentage points + This is a LARGE update, appropriate because the evidence (internal + planning document) is strong and directly relevant. +``` + +### Evidence Strength Classification + +How much to update based on different types of evidence: + +``` +EVIDENCE TIER 1 — Large update (likelihood ratio 5-20x) + → Official announcement or regulatory filing + → Confirmed internal document (not rumor) + → Directly observed outcome of prerequisite event + → Multiple independent strong sources confirming same fact + Typical update: ±15-30 percentage points + +EVIDENCE TIER 2 — Moderate update (likelihood ratio 2-5x) + → Credible journalist report with named sources + → Statistical data that changes the base rate + → Expert with strong track record changing their view + → Structural/policy change that alters incentives + Typical update: ±5-15 percentage points + +EVIDENCE TIER 3 — Small update (likelihood ratio 1.2-2x) + → Rumor from semi-credible source + → Anecdotal evidence (single data point) + → Social media sentiment shift + → Expert opinion without new information + Typical update: ±2-5 percentage points + +EVIDENCE TIER 4 — Negligible update (likelihood ratio ~1x) + → Repetition of previously known information + → Pundit opinion with no domain expertise + → Vague statement open to multiple interpretations + → Evidence equally consistent with both outcomes + Typical update: ±0-2 percentage points (or skip entirely) +``` + +### When to Make Large vs. Small Updates + +``` +MAKE A LARGE UPDATE when: + • Evidence directly addresses your key uncertainty + • The source has a strong track record on this topic + • The evidence would be very surprising if your prediction were correct + (or very unsurprising if it were wrong) + • Multiple independent signals shift in the same direction simultaneously + +MAKE A SMALL UPDATE when: + • Evidence is tangentially related to your prediction + • The source's reliability is uncertain + • The evidence is consistent with multiple interpretations + • You've already incorporated similar evidence + +RESIST UPDATING when: + • The "evidence" is just someone restating the consensus + • A vivid anecdote feels compelling but carries no statistical weight + • You're reacting emotionally (fear, excitement) rather than analytically + • The evidence source has an obvious incentive to mislead +``` + +### Common Updating Mistakes + +| Mistake | Description | Fix | +|---------|-------------|-----| +| Over-updating on vivid events | A dramatic single event shifts your view by 20+ points when the base rate barely moved | Ask: "Does this event actually change the base rate, or just my emotional state?" | +| Under-updating on base rate changes | New data shows the reference class frequency shifted, but you keep your old anchor | Periodically re-derive the base rate from scratch instead of only adjusting incrementally | +| Asymmetric updating | Updating strongly on confirming evidence, weakly on disconfirming evidence | Force yourself to calculate the likelihood ratio for disconfirming evidence explicitly | +| Double-counting | Updating on a news article, then updating again on a tweet quoting the same article | Track the original source — if two signals share the same root cause, count once | +| Failure to update | Knowing the evidence should change your view but not bothering because your current number "feels right" | Set calendar reminders to review active predictions monthly with fresh evidence | +| Stampede updating | A prediction market spikes, causing you to rush your update to match | Market moves are data, not commands — assess independently, then compare | + +--- + ## Prediction Tracking & Scoring ### Prediction Ledger Format diff --git a/hands/reddit/HAND.toml b/hands/reddit/HAND.toml index f7c2932..eb78b78 100644 --- a/hands/reddit/HAND.toml +++ b/hands/reddit/HAND.toml @@ -423,6 +423,241 @@ frequency = "hourly" token_consumption = "medium" default_active = false +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "Reddit Hand" description = "自主 Reddit 管理——监控子版块、发布内容、回复帖子并追踪 Karma 和互动" +category = "通信" + +[i18n.zh.settings.subreddits] +label = "子版块" +description = "要监控的子版块列表(逗号分隔,例如 rust,programming,machinelearning)" + +[i18n.zh.settings.monitor_mode] +label = "监控模式" +description = "在监控的子版块中追踪哪些内容" + +[i18n.zh.settings.auto_reply] +label = "自动回复" +description = "自动回复相关的帖子和评论" + +[i18n.zh.settings.post_frequency] +label = "发布频率" +description = "创建原创帖子的频率" + +[i18n.zh.settings.content_style] +label = "内容风格" +description = "帖子和回复的语气和风格" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将帖子和回复加入队列等待审核,而非直接发布" + +[i18n.zh.settings.min_karma_to_post] +label = "最低发帖 Karma" +description = "仅在账户拥有至少此数量 Karma 的子版块中发帖" + +[i18n.zh.settings.max_reply_depth] +label = "最大回复深度" +description = "回复的最大评论嵌套深度(深层嵌套的可见度较低)" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Reddit" +description = "Gestor autónomo de Reddit — monitorea subreddits, publica contenido, responde en hilos y rastrea karma e interacciones" +category = "Comunicación" + +[i18n.es.settings.subreddits] +label = "Subreddits" +description = "Lista de subreddits a monitorear separados por comas (ej. rust,programming,machinelearning)" + +[i18n.es.settings.monitor_mode] +label = "Modo de monitoreo" +description = "Qué rastrear en los subreddits monitoreados" + +[i18n.es.settings.auto_reply] +label = "Respuesta automática" +description = "Responder automáticamente a publicaciones y comentarios relevantes" + +[i18n.es.settings.post_frequency] +label = "Frecuencia de publicación" +description = "Con qué frecuencia crear publicaciones originales" + +[i18n.es.settings.content_style] +label = "Estilo de contenido" +description = "Tono y enfoque para publicaciones y respuestas" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Poner publicaciones y respuestas en cola para revisión en lugar de publicarlas directamente" + +[i18n.es.settings.min_karma_to_post] +label = "Karma mínimo para publicar" +description = "Solo publicar en subreddits donde la cuenta tenga al menos este nivel de karma" + +[i18n.es.settings.max_reply_depth] +label = "Profundidad máxima de respuesta" +description = "Profundidad máxima del hilo de comentarios para responder (los hilos más profundos tienen menos visibilidad)" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "Reddit Hand" +description = "自律型Redditマネージャー——サブレディットの監視、コンテンツ投稿、スレッドへの返信、Karmaとエンゲージメントの追跡" +category = "コミュニケーション" + +[i18n.ja.settings.subreddits] +label = "サブレディット" +description = "監視するサブレディットのリスト(カンマ区切り、例: rust,programming,machinelearning)" + +[i18n.ja.settings.monitor_mode] +label = "監視モード" +description = "監視対象のサブレディットで追跡する内容" + +[i18n.ja.settings.auto_reply] +label = "自動返信" +description = "関連する投稿やコメントに自動で返信する" + +[i18n.ja.settings.post_frequency] +label = "投稿頻度" +description = "オリジナル投稿を作成する頻度" + +[i18n.ja.settings.content_style] +label = "コンテンツスタイル" +description = "投稿と返信のトーンとアプローチ" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "投稿や返信を直接公開せず、レビュー用キューに追加する" + +[i18n.ja.settings.min_karma_to_post] +label = "投稿に必要な最低Karma" +description = "アカウントが最低このKarmaを持つサブレディットでのみ投稿する" + +[i18n.ja.settings.max_reply_depth] +label = "最大返信深度" +description = "返信するコメントスレッドの最大ネスト深度(深いスレッドほど可視性が低い)" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Reddit" +description = "Gestionnaire Reddit autonome — surveille les subreddits, publie du contenu, répond dans les fils et suit le karma et l'engagement" +category = "Communication" + +[i18n.fr.settings.subreddits] +label = "Subreddits" +description = "Liste de subreddits à surveiller séparés par des virgules (ex. rust,programming,machinelearning)" + +[i18n.fr.settings.monitor_mode] +label = "Mode de surveillance" +description = "Ce qu'il faut suivre dans les subreddits surveillés" + +[i18n.fr.settings.auto_reply] +label = "Réponse automatique" +description = "Répondre automatiquement aux publications et commentaires pertinents" + +[i18n.fr.settings.post_frequency] +label = "Fréquence de publication" +description = "Fréquence de création de publications originales" + +[i18n.fr.settings.content_style] +label = "Style de contenu" +description = "Ton et approche pour les publications et réponses" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Mettre les publications et réponses en file d'attente pour révision au lieu de les publier directement" + +[i18n.fr.settings.min_karma_to_post] +label = "Karma minimum pour publier" +description = "Ne publier que dans les subreddits où le compte possède au moins ce niveau de karma" + +[i18n.fr.settings.max_reply_depth] +label = "Profondeur maximale de réponse" +description = "Profondeur maximale d'imbrication des commentaires pour répondre (les fils plus profonds ont moins de visibilité)" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Reddit-Hand" +description = "Autonomer Reddit-Manager — überwacht Subreddits, postet Inhalte, antwortet in Threads und verfolgt Karma und Engagement" +category = "Kommunikation" + +[i18n.de.settings.subreddits] +label = "Subreddits" +description = "Kommagetrennte Liste der zu überwachenden Subreddits (z.B. rust,programming,machinelearning)" + +[i18n.de.settings.monitor_mode] +label = "Überwachungsmodus" +description = "Was in den überwachten Subreddits verfolgt werden soll" + +[i18n.de.settings.auto_reply] +label = "Automatische Antwort" +description = "Automatisch auf relevante Beiträge und Kommentare antworten" + +[i18n.de.settings.post_frequency] +label = "Veröffentlichungshäufigkeit" +description = "Wie oft originale Beiträge erstellt werden" + +[i18n.de.settings.content_style] +label = "Inhaltsstil" +description = "Ton und Ansatz für Beiträge und Antworten" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Beiträge und Antworten zur Überprüfung in die Warteschlange stellen, anstatt sie direkt zu veröffentlichen" + +[i18n.de.settings.min_karma_to_post] +label = "Mindest-Karma zum Posten" +description = "Nur in Subreddits posten, in denen das Konto mindestens dieses Karma-Level hat" + +[i18n.de.settings.max_reply_depth] +label = "Maximale Antworttiefe" +description = "Maximale Verschachtelungstiefe für Kommentarantworten (tiefere Threads haben geringere Sichtbarkeit)" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "Reddit Hand" +description = "자율 Reddit 관리 — 서브레딧 모니터링, 콘텐츠 게시, 스레드 댓글 및 카르마와 참여도 추적" +category = "커뮤니케이션" + +[i18n.ko.settings.subreddits] +label = "서브레딧" +description = "모니터링할 서브레딧 목록 (쉼표로 구분, 예: rust,programming,machinelearning)" + +[i18n.ko.settings.monitor_mode] +label = "모니터링 모드" +description = "모니터링 대상 서브레딧에서 추적할 콘텐츠" + +[i18n.ko.settings.auto_reply] +label = "자동 답글" +description = "관련 게시물과 댓글에 자동으로 답글 작성" + +[i18n.ko.settings.post_frequency] +label = "게시 빈도" +description = "원본 게시물 작성 주기" + +[i18n.ko.settings.content_style] +label = "콘텐츠 스타일" +description = "게시물과 답글의 어조와 접근 방식" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "게시물과 답글을 직접 게시하지 않고 대기열에 추가하여 검토" + +[i18n.ko.settings.min_karma_to_post] +label = "최소 게시 카르마" +description = "계정이 최소 이만큼의 카르마를 보유한 서브레딧에서만 게시" + +[i18n.ko.settings.max_reply_depth] +label = "최대 답글 깊이" +description = "답글 작성의 최대 댓글 중첩 깊이 (깊은 중첩일수록 노출도 감소)" diff --git a/hands/reddit/SKILL.md b/hands/reddit/SKILL.md index 6a6130e..fe167b8 100644 --- a/hands/reddit/SKILL.md +++ b/hands/reddit/SKILL.md @@ -247,3 +247,768 @@ Monitor account standing: - Build karma organically through genuine engagement - Avoid posting too frequently (triggers spam filters) - Diversify activity across multiple subreddits + +--- + +## Worked Examples + +### Example 1: Product Launch on Reddit + +**Scenario**: You are launching a developer CLI tool and want to generate awareness on Reddit. + +**Phase 1 — Subreddit Research (Week 1-2 before launch)** + +Identify target subreddits and evaluate each: +``` +Target subreddits (prioritized): +1. r/commandline — 350k members, accepts tool announcements, requires demo/screenshot +2. r/programming — 5M members, strict anti-marketing, only accepts substantial technical posts +3. r/opensource — 200k members, friendly to launches, requires repo link +4. r/devtools — 50k members, niche but highly targeted +5. r/sideproject — 100k members, launch-friendly, expects "what I built" framing +``` + +Fetch subreddit rules programmatically: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/commandline/about/rules" +``` + +**Phase 2 — Karma Building (Week 1-2 before launch)** + +Before posting about your product, build credibility: +``` +Day 1-3: Answer questions in r/commandline and r/programming (3-5 helpful comments/day) +Day 4-7: Share a useful tip or short guide unrelated to your product +Day 8-10: Engage in discussions, upvote good content, reply to others' posts +Day 11-14: Share a technical deep-dive related to your product's domain (not the product itself) +``` + +**Phase 3 — Launch Posts (Launch Day)** + +Craft posts per subreddit culture: + +For **r/sideproject** (casual, story-driven): +``` +Title: "I built a CLI tool that does X — here's what I learned" +Body: +- Paragraph on the problem and motivation +- Short demo (gif/video link or code block) +- What went wrong during development +- Link to repo +- "Would love feedback on X" +``` + +For **r/programming** (technical, anti-fluff): +``` +Title: "X: an open-source CLI for Y written in Rust [with benchmarks]" +Body: +- Link directly to repo or blog post with technical depth +- Performance comparison table +- Architecture decisions +- NO "please star my repo" language +``` + +For **r/commandline** (practical, demo-focused): +``` +Title: "X — does Y in Z seconds from your terminal" +Body: +- Install instructions (one-liner) +- Usage example with real output +- Screenshot or asciinema link +- Comparison to existing tools +``` + +**Phase 4 — Engagement (Launch Day + 48 hours)** + +Response templates: + +| Comment Type | Response Strategy | +|-------------|-------------------| +| "How does this compare to Z?" | Honest comparison table, acknowledge Z's strengths | +| "Why not just use Z?" | Explain specific use cases where yours differs, no FUD | +| "Found a bug" | Thank them, ask for details, open GitHub issue immediately | +| "This is spam" | Do NOT argue. Briefly state this is your project and you're here to discuss | +| "Great work!" | Thank them, ask what feature they'd want next | +| Feature request | Acknowledge, add to roadmap, link to issue tracker | + +**Phase 5 — Follow-Up (Week after launch)** + +- Reply to every comment within 12 hours +- Post an update in r/sideproject if you hit a milestone (e.g., "Hit 500 stars, here's what I changed based on Reddit feedback") +- Do NOT cross-post the same content -- write fresh posts per subreddit + +--- + +### Example 2: Community Monitoring and Sentiment Tracking + +**Scenario**: You manage a brand's Reddit presence and need to track mentions, sentiment, and emerging issues. + +**Step 1 — Set Up Monitoring Queries** + +Search for brand mentions across Reddit: +```bash +# Search all of Reddit for brand mentions +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/search?q=%22BrandName%22+OR+%22brandname%22&sort=new&limit=25&t=day" +``` + +Monitor specific subreddits where your audience lives: +```bash +# Monitor r/technology for relevant topics +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/technology/search?q=BrandName&restrict_sr=on&sort=new&limit=25&t=week" +``` + +**Step 2 — Sentiment Classification** + +Categorize each mention into: +``` +POSITIVE — Praise, recommendation, success story +NEUTRAL — Factual mention, question, comparison +NEGATIVE — Complaint, bug report, frustration +CRITICAL — Security concern, viral complaint, legal risk +``` + +Scoring signals from Reddit data: +``` +score > 100 + sentiment=NEGATIVE → High-priority alert (viral complaint) +score > 50 + sentiment=POSITIVE → Amplification opportunity +num_comments > 20 + any sentiment → Active discussion, monitor closely +upvote_ratio < 0.5 → Controversial, may escalate +``` + +**Step 3 — Alert Thresholds** + +| Condition | Action | +|-----------|--------| +| CRITICAL mention with score > 10 | Immediate alert to team | +| 3+ NEGATIVE mentions in 24 hours | Trend alert, investigate root cause | +| NEGATIVE post in subreddit > 500k members | Monitor hourly for 48 hours | +| Competitor comparison post trending | Prepare factual response (do NOT post defensively) | + +**Step 4 — Weekly Report Template** + +``` +## Reddit Weekly Report — [Date Range] + +### Summary +- Total mentions: X (up/down Y% from last week) +- Sentiment breakdown: X% positive, Y% neutral, Z% negative +- Top subreddits: r/sub1 (N mentions), r/sub2 (N mentions) + +### Trending Topics +1. [Topic] — [Subreddit] — [Sentiment] — [Link] +2. ... + +### Action Items +- [ ] Respond to [specific thread] — negative sentiment, high visibility +- [ ] Engage with [specific thread] — positive, amplification opportunity + +### Competitor Activity +- [Competitor A]: N mentions, trending topics: ... +- [Competitor B]: N mentions, trending topics: ... + +### Metrics +| Metric | This Week | Last Week | Change | +|--------|-----------|-----------|--------| +| Total mentions | | | | +| Positive % | | | | +| Avg post score | | | | +| Response time (hrs) | | | | +``` + +--- + +### Example 3: AMA (Ask Me Anything) Management + +**Scenario**: You are organizing an AMA for a tech CEO in r/technology. + +**Preparation (2 Weeks Before)** + +1. Contact the subreddit moderators: + - Message the mod team through modmail (not individual DMs) + - Propose date, time, and AMA subject + - Ask about specific rules for AMAs (verification, scheduling, flair) + - Confirm the post format they expect + +2. Schedule for peak engagement: + ``` + Recommended AMA times (US-centric subreddits): + - Tuesday-Thursday, 11:00 AM - 1:00 PM EST + - Avoid: weekends, holidays, major news days + - Post the AMA thread 30-60 minutes before the host starts answering + ``` + +3. Prepare the AMA post: + ``` + Title: "I'm [Name], [Role] at [Company]. [One-line hook]. AMA!" + + Body: + - Brief intro (2-3 sentences about credentials) + - Why this AMA is happening (new product, milestone, event) + - Proof/verification (link to tweet, photo with timestamp) + - "I'll start answering at [TIME] [TIMEZONE]. Ask me anything!" + - Links to relevant context (website, blog post, prior work) + ``` + +**During the AMA (2-3 Hours)** + +Real-time engagement strategy: +``` +1. Sort comments by "best" and "new" alternately every 15 minutes +2. Answer top-voted questions first (these set the tone) +3. Answer at least 20-30 questions in a 2-hour session +4. Mix short answers with detailed ones — avoid walls of text for every question +5. Skip hostile/troll questions silently — do NOT acknowledge them +6. For tough questions: answer honestly or say "I can't discuss that yet" +7. Upvote good questions (even tough ones) — shows good faith +``` + +Response length guide: +| Question Type | Response Length | +|--------------|----------------| +| Simple factual | 1-2 sentences | +| Technical deep-dive | 2-3 paragraphs | +| Personal/funny | 1-2 sentences, match the tone | +| Critical/tough | 2-3 sentences, direct and honest | +| Off-topic | Brief redirect or polite decline | + +**Follow-Up (24-48 Hours After)** + +- Post an edit to the original AMA: "Thanks everyone! I answered [N] questions. Check back — I'll try to answer a few more this week." +- Answer 5-10 more highly-upvoted questions that were missed +- Share the AMA link on other platforms (Twitter, LinkedIn) to drive continued engagement +- Compile a "best of" summary with links to the strongest Q&A exchanges + +--- + +## Advanced API Patterns + +### Pagination Handling + +Reddit uses cursor-based pagination with `after` and `before` fullnames. + +**Paginate through subreddit posts**: +```bash +# Page 1 +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100" +# Response includes: "after": "t3_abc123" + +# Page 2 +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100&after=t3_abc123" +# Response includes: "after": "t3_def456" (or null if last page) + +# Page 3 +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100&after=t3_def456" +``` + +Pagination rules: +- `limit` max is 100 per request +- `after` returns items chronologically older than the given fullname +- `before` returns items chronologically newer (useful for "check for new posts since last poll") +- When `after` is `null` in the response, you have reached the last page +- Reddit caps listing depth at ~1000 items regardless of pagination + +**Paginate backward (newer items)**: +```bash +# Get posts newer than a known fullname +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=25&before=t3_abc123" +``` + +### Flair Management + +**Get available flairs for a subreddit**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/api/link_flair_v2" +``` + +**Submit a post with flair**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "sr=SUBREDDIT&kind=self&title=TITLE&text=BODY&flair_id=FLAIR_ID&flair_text=FLAIR_TEXT" \ + "https://oauth.reddit.com/api/submit" +``` + +**Set flair on an existing post** (requires mod or post author permissions): +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "link=t3_POST_ID&flair_template_id=FLAIR_ID" \ + "https://oauth.reddit.com/r/SUBREDDIT/api/selectflair" +``` + +### Moderation Endpoints + +These require moderator permissions on the target subreddit. + +**Get moderation queue**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about/modqueue?limit=25" +``` + +**Approve a post/comment**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "id=FULLNAME" \ + "https://oauth.reddit.com/api/approve" +``` + +**Remove a post/comment**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "id=FULLNAME&spam=false" \ + "https://oauth.reddit.com/api/remove" +``` + +**Get moderation log**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about/log?limit=25&type=removelink" +``` + +**Distinguish a comment as moderator**: +```bash +curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + -d "id=FULLNAME&how=yes" \ + "https://oauth.reddit.com/api/distinguish" +``` + +### Multi-Subreddit Monitoring + +**Monitor multiple subreddits in a single request**: +```bash +# Combine subreddits with "+" for a merged feed +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/python+rust+golang/new?limit=50" +``` + +**Search across multiple subreddits**: +```bash +# Use the subreddit field in search to restrict +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/search?q=BrandName+subreddit%3Apython+OR+subreddit%3Arust&sort=new&limit=25" +``` + +**Get subreddit metadata for comparison**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about" +``` +Key fields in response: `subscribers`, `active_user_count`, `created_utc`, `public_description`, `submit_text`, `submission_type`. + +### Polling Strategies for Real-Time Awareness + +Reddit has no webhook support. Use polling with these patterns: + +**Efficient polling loop**: +``` +1. Fetch /r/SUBREDDIT/new?limit=10 every 60 seconds +2. Store the fullname of the newest item seen +3. On next poll, use ?before=LAST_SEEN_FULLNAME to get only new items +4. If response is empty, no new posts — sleep and retry +5. If response has items, process them and update LAST_SEEN_FULLNAME +``` + +**Polling frequency by priority**: +| Monitoring Type | Poll Interval | Endpoint | +|----------------|---------------|----------| +| Brand crisis monitoring | 30-60 seconds | /search?q=brand&sort=new | +| Subreddit new posts | 60-120 seconds | /r/SUB/new | +| Comment replies to own posts | 120 seconds | /message/inbox | +| Competitor mentions | 300 seconds | /search?q=competitor&sort=new | +| Weekly trend analysis | Once daily | /r/SUB/top?t=day | + +**Respect rate limits while polling**: +``` +At 30 requests/minute (app-only auth): +- 1 subreddit at 60s interval = 1 req/min → can monitor ~25 subreddits +- 1 search query at 60s interval = 1 req/min +- Reserve 5 req/min for ad-hoc queries +- Total budget: 30 req/min, plan accordingly +``` + +--- + +## Subreddit Analysis Framework + +### Evaluating a Subreddit Before Posting + +Before investing effort in any subreddit, run this assessment: + +**Step 1 — Pull subreddit metadata**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/about" | python3 -c " +import sys, json +d = json.load(sys.stdin)['data'] +print(f'Subscribers: {d[\"subscribers\"]:,}') +print(f'Active now: {d[\"active_user_count\"]:,}') +print(f'Created: {d[\"created_utc\"]}') +print(f'Type: {d[\"submission_type\"]}') +print(f'Description: {d[\"public_description\"][:200]}') +" +``` + +**Step 2 — Measure actual engagement** (not just subscriber count): + +```bash +# Get top 25 hot posts and examine their scores and comment counts +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/hot?limit=25" +``` + +Calculate from the response: +``` +Engagement Score = median(post_scores) * median(num_comments) +Activity Ratio = active_user_count / subscribers +Health Indicator = (posts_per_day > 5) AND (Activity Ratio > 0.001) +``` + +**Step 3 — Subreddit quality scorecard**: + +| Factor | Good Sign | Bad Sign | +|--------|-----------|----------| +| Active/subscriber ratio | > 0.1% | < 0.01% | +| Median hot post score | > 50 | < 10 | +| Median comment count | > 10 | < 3 | +| Posts per day | 5-50 | < 1 or > 500 (noise) | +| Mod activity | Active modqueue, clear rules | No rules, spam in feed | +| Top post age | Within last 24h | Weeks old (dead subreddit) | +| Account age requirements | Reasonable (7 days) | None (spam-prone) or extreme (1 year) | + +### Peak Engagement Hours by Subreddit Type + +Optimal posting times vary by audience. All times in EST: + +| Subreddit Type | Peak Hours | Peak Days | Reasoning | +|---------------|------------|-----------|-----------| +| Tech/Programming | 9-11 AM EST | Tue-Thu | Developers browse during morning coffee | +| Business/Startup | 7-9 AM EST | Mon-Wed | Professionals check before work | +| Gaming | 6-10 PM EST | Fri-Sun | After work/school | +| Science/Academic | 10 AM-12 PM EST | Mon-Wed | Researchers between tasks | +| Lifestyle/Hobby | 12-2 PM EST, 7-9 PM EST | Any | Lunch breaks and evenings | +| News/Politics | 7-9 AM EST | Mon-Fri | Morning news cycle | +| Finance/Crypto | 8-10 AM EST | Mon-Fri | Pre-market and market open | + +To measure a specific subreddit's peak hours: +```bash +# Pull the last 100 posts and extract their timestamps +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/r/SUBREDDIT/new?limit=100" +# Parse created_utc for each post and bucket by hour-of-day +# Cross-reference with score to find high-score hours, not just high-volume hours +``` + +### Competitor Presence Analysis + +**Step 1 — Search for competitor mentions**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/search?q=%22CompetitorName%22&sort=new&t=month&limit=100" +``` + +**Step 2 — Build a competitor activity profile**: +``` +For each competitor, track: +- Which subreddits they are mentioned in (and by whom -- users vs the company) +- Frequency of mentions (per week) +- Sentiment of mentions (positive / neutral / negative) +- Whether they have official accounts engaging in threads +- Common complaints about them (your opportunity) +- Common praise for them (your benchmark) +``` + +**Step 3 — Competitor comparison matrix**: +| Metric | Your Brand | Competitor A | Competitor B | +|--------|-----------|-------------|-------------| +| Weekly mentions | | | | +| Positive sentiment % | | | | +| Subreddits present in | | | | +| Official account activity | | | | +| Top complaint theme | | | | +| Top praise theme | | | | + +### Content Format Preferences by Subreddit Type + +| Subreddit Type | Preferred Format | Avoid | +|---------------|-----------------|-------| +| Technical (r/programming, r/rust) | Long-form text, code blocks, benchmarks | Short posts, images without context | +| Q&A (r/AskReddit, r/askscience) | Concise questions, detailed answers | Link-only posts | +| Showcase (r/sideproject, r/webdev) | Screenshots, demos, before/after | Text-only without visuals | +| News (r/technology, r/science) | Link to source with summary comment | Self-post opinion pieces | +| Discussion (r/startups, r/cscareerquestions) | Personal experience, specific details | Generic advice, platitudes | +| Meme-friendly (r/ProgrammerHumor) | Images, short and punchy | Long text posts | + +--- + +## Growth & Reputation Building + +### Karma Building Strategies (Comment-First Approach) + +New accounts or accounts entering a new subreddit should follow the comment-first approach: + +**Week 1-2: Listen and respond** +``` +1. Sort by "new" in your target subreddits +2. Find questions you can genuinely answer +3. Write substantive, helpful comments (3+ sentences with specifics) +4. Respond to 3-5 threads per day +5. Do NOT mention your product, company, or project at all +``` + +**Week 3-4: Establish presence** +``` +1. Start sharing relevant resources (not yours) that help the community +2. Engage in discussions about trends and opinions in your domain +3. Build recognition by being consistently helpful +4. Your username should start becoming familiar to regulars +``` + +**Week 5+: Contribute original content** +``` +1. Share a technical write-up, tutorial, or analysis (unrelated to your product) +2. If well-received, you have earned the trust to occasionally mention your work +3. Always frame self-promotional content as "I built X" (transparent) not "Check out X" (spammy) +4. Maintain the 10:1 ratio — 10 helpful contributions for every 1 self-promotional post +``` + +Karma accumulation benchmarks: +| Milestone | Unlocks | +|-----------|---------| +| 10 comment karma | Bypass most anti-spam filters | +| 50 comment karma | Reduced posting cooldowns | +| 100+ comment karma in a subreddit | Trusted contributor status in some subreddits | +| 1000+ total karma | Access to r/lounge and some restricted subreddits | + +### Building Authority in Niche Subreddits + +Authority is built through consistency and expertise, not volume: + +1. **Pick 3-5 subreddits maximum** -- spreading across 20 subreddits builds no authority anywhere +2. **Develop a recognizable voice** -- consistent formatting, depth of answers, specific expertise area +3. **Answer the hard questions** -- skip the easy ones that 10 people will answer; tackle the ones that require real expertise +4. **Follow up on your own answers** -- if someone asks a follow-up, respond promptly +5. **Cite sources and show work** -- "I benchmarked this myself, here are the numbers" is worth 100x "I think X is faster" +6. **Accept corrections gracefully** -- being wrong publicly and handling it well builds more trust than never being wrong + +### Cross-Posting Etiquette and Strategy + +Cross-posting (sharing a post from one subreddit to another) has specific norms: + +**Do:** +- Use Reddit's built-in cross-post feature (preserves attribution) +- Cross-post to subreddits where the content genuinely fits +- Add a comment explaining why it is relevant to the new subreddit +- Wait at least a few hours between cross-posts (avoid appearing spammy) + +**Don't:** +- Cross-post to more than 2-3 subreddits +- Cross-post to subreddits that explicitly ban it (check rules) +- Copy-paste the same text as a new post instead of cross-posting (treated as spam) +- Cross-post your own content excessively + +**Strategic cross-posting pattern**: +``` +1. Post original content in the most specific/niche subreddit first +2. If it gains traction (>20 upvotes, positive comments), cross-post to a broader subreddit +3. Customize the title for the new audience +4. Engage in comments on BOTH subreddits +``` + +### Handling Negative Feedback and Criticism + +Negative feedback on Reddit is public and permanent. Handle it strategically: + +**Response framework**: +``` +1. PAUSE — Do not respond within the first 15 minutes. Emotional responses backfire. +2. ASSESS — Is the criticism valid, partially valid, or trolling? +3. RESPOND (or don't): + - Valid criticism: Acknowledge, thank them, explain what you will do about it + - Partially valid: Acknowledge the valid part, clarify the rest with facts + - Trolling/bad faith: Do NOT respond. Silence is the best response. +4. FOLLOW UP — If you promised to fix something, come back and confirm when it is done +``` + +**Response templates by situation**: + +| Situation | Response Pattern | +|-----------|-----------------| +| Bug report | "Thanks for reporting this. Can you share [details]? I've opened [issue link] to track it." | +| Feature complaint | "That's fair feedback. Here's why we made that choice: [reason]. We're considering [alternative]." | +| Unfair comparison | "Good question. Here's a direct comparison: [facts]. [Competitor] is great at X, we focus on Y." | +| Personal attack | Do not respond. Report if it violates rules. | +| "This is trash" | "Sorry it didn't work for you. What specifically went wrong? Happy to help." | + +--- + +## Analytics & Reporting + +### Post Performance Metrics + +Key metrics to track for every post: + +| Metric | Where to Find | What It Means | +|--------|--------------|---------------| +| Score | `data.score` | Net upvotes (upvotes minus downvotes) | +| Upvote ratio | `data.upvote_ratio` | 0.0-1.0, percentage of votes that are upvotes | +| Number of comments | `data.num_comments` | Total comments including replies | +| Awards | `data.all_awardings` | List of awards received | +| Cross-posts | `data.num_crossposts` | How many times others cross-posted it | + +**Fetch post performance**: +```bash +curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \ + -A "LibreFang Reddit Hand/1.0" \ + "https://oauth.reddit.com/by_id/t3_POST_ID" +``` + +**Quality indicators**: +``` +High engagement: upvote_ratio > 0.85 AND num_comments > 20 +Controversial: upvote_ratio 0.40-0.60 (heavily split votes) +Viral potential: score > 100 within first 2 hours +Dead on arrival: score < 5 after 4 hours +Comment quality: avg comment length > 100 chars (real discussion vs memes) +``` + +### Engagement Trend Tracking + +Track performance over time by recording metrics at regular intervals: + +``` +For each post, capture at: +- T+1 hour: score, num_comments, upvote_ratio +- T+4 hours: score, num_comments, upvote_ratio +- T+24 hours: score, num_comments, upvote_ratio (final snapshot) + +For account-level tracking: +- Weekly comment karma change +- Weekly post karma change +- Number of posts/comments per subreddit +- Average score per post by subreddit +``` + +**Growth trajectory assessment**: +| Period | Healthy Growth | Stagnant | Declining | +|--------|---------------|----------|-----------| +| Weekly karma change | > +50 | -10 to +10 | < -10 | +| Avg post score trend | Increasing | Flat | Decreasing | +| Comment reply rate | > 30% of comments get replies | 10-30% | < 10% | +| New subreddit penetration | 1-2 new per month | 0 | Banned from any | + +### ROI Measurement for Business-Related Reddit Activity + +For teams using Reddit for marketing, community building, or support: + +**Trackable outcomes**: +``` +Direct metrics: +- Referral traffic from Reddit (track with UTM parameters in shared links) +- Sign-ups/downloads from Reddit referral +- Support tickets deflected by Reddit answers +- GitHub stars/forks from Reddit posts (track with ?ref=reddit) + +Indirect metrics: +- Brand mention volume over time +- Sentiment ratio trend (positive / total mentions) +- Share of voice vs competitors on Reddit +- Community size if you run your own subreddit +``` + +**Cost calculation**: +``` +Time invested: Hours per week on Reddit * hourly cost +Content cost: Time creating Reddit-specific content +Tool cost: Monitoring tools, analytics +───────────────────────────────────────────── +Total cost/week: Sum of above + +ROI = (Value of outcomes - Total cost) / Total cost +``` + +**Value assignment for outcomes**: +| Outcome | Suggested Valuation Method | +|---------|--------------------------| +| Referral sign-up | Same as other channel CAC | +| Support ticket deflected | Average support ticket cost | +| GitHub star from Reddit | Track conversion to paying user | +| Positive brand mention | Equivalent ad impression value | +| Viral post (>1000 score) | Equivalent paid reach cost | + +### Weekly Reddit Activity Report Template + +``` +## Reddit Activity Report — Week of [Date] + +### Account Health +- Current karma: [post] / [comment] +- Karma change this week: +/- [N] +- Account age: [N] days +- Active subreddits: [list] + +### Content Published +| Date | Subreddit | Type | Title | Score | Comments | Upvote Ratio | +|------|-----------|------|-------|-------|----------|-------------| +| | | | | | | | + +### Comments Made +- Total comments: [N] +- Avg comment score: [N] +- Top comment: [link] (score: [N]) +- Subreddit breakdown: r/sub1 ([N]), r/sub2 ([N]) + +### Brand Mentions (External) +- Total mentions found: [N] +- Sentiment: [N]% positive, [N]% neutral, [N]% negative +- Notable threads: + 1. [Thread title] — [subreddit] — [sentiment] — [link] + 2. ... + +### Engagement Metrics +| Metric | This Week | Last Week | Trend | +|--------|-----------|-----------|-------| +| Posts published | | | | +| Total post score | | | | +| Comments made | | | | +| Replies received | | | | +| Avg response time | | | | + +### Referral Traffic (if tracked) +- Clicks from Reddit: [N] +- Sign-ups from Reddit: [N] +- Top referral post: [link] + +### Next Week Plan +- [ ] Target subreddits: [list] +- [ ] Content planned: [description] +- [ ] Threads to follow up on: [links] +``` diff --git a/hands/researcher/HAND.toml b/hands/researcher/HAND.toml index 8a6cd5b..7e2a0b3 100644 --- a/hands/researcher/HAND.toml +++ b/hands/researcher/HAND.toml @@ -442,6 +442,241 @@ token_consumption = "high" default_active = true activation_warning = "Researcher hand runs continuously and performs deep research, consuming tokens." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "深度研究 Hand" description = "自主深度研究员——全面调研、交叉验证、事实核查和结构化报告" +category = "生产力" + +[i18n.zh.settings.research_depth] +label = "研究深度" +description = "每次调研的详尽程度" + +[i18n.zh.settings.output_style] +label = "输出格式" +description = "研究报告的格式风格" + +[i18n.zh.settings.source_verification] +label = "来源验证" +description = "在引用前通过多个来源交叉验证论述" + +[i18n.zh.settings.max_sources] +label = "最大来源数" +description = "每次调研参考的最大来源数量" + +[i18n.zh.settings.auto_follow_up] +label = "自动追问" +description = "自动研究调查过程中发现的延伸问题" + +[i18n.zh.settings.save_research_log] +label = "保存研究日志" +description = "保存详细的搜索查询和来源评估记录" + +[i18n.zh.settings.citation_style] +label = "引用格式" +description = "报告中引用来源的格式" + +[i18n.zh.settings.language] +label = "语言" +description = "研究和输出的主要语言" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "심층 연구 Hand" +description = "자율 심층 연구원 — 철저한 조사, 교차 검증, 팩트체크 및 구조화된 보고서" +category = "생산성" + +[i18n.ko.settings.research_depth] +label = "연구 깊이" +description = "각 조사의 철저함 정도" + +[i18n.ko.settings.output_style] +label = "출력 스타일" +description = "연구 보고서의 형식 스타일" + +[i18n.ko.settings.source_verification] +label = "출처 검증" +description = "인용 전 여러 출처를 통해 주장을 교차 검증" + +[i18n.ko.settings.max_sources] +label = "최대 출처 수" +description = "조사당 참고할 최대 출처 수" + +[i18n.ko.settings.auto_follow_up] +label = "자동 후속 조사" +description = "조사 과정에서 발견된 후속 질문을 자동으로 연구" + +[i18n.ko.settings.save_research_log] +label = "연구 로그 저장" +description = "상세한 검색 쿼리 및 출처 평가 기록 저장" + +[i18n.ko.settings.citation_style] +label = "인용 형식" +description = "보고서에서 출처를 인용하는 형식" + +[i18n.ko.settings.language] +label = "언어" +description = "연구 및 출력의 주요 언어" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "ディープリサーチ Hand" +description = "自律型深層調査エージェント——徹底的な調査、クロスリファレンス、ファクトチェック、構造化レポート" +category = "生産性" + +[i18n.ja.settings.research_depth] +label = "調査の深さ" +description = "各調査の徹底度" + +[i18n.ja.settings.output_style] +label = "出力スタイル" +description = "調査レポートのフォーマットスタイル" + +[i18n.ja.settings.source_verification] +label = "ソース検証" +description = "引用前に複数のソースでクレームをクロスチェックする" + +[i18n.ja.settings.max_sources] +label = "最大ソース数" +description = "調査ごとに参照するソースの最大数" + +[i18n.ja.settings.auto_follow_up] +label = "自動フォローアップ" +description = "調査中に発見されたフォローアップ質問を自動的に調査する" + +[i18n.ja.settings.save_research_log] +label = "調査ログの保存" +description = "詳細な検索クエリとソース評価の記録を保存する" + +[i18n.ja.settings.citation_style] +label = "引用スタイル" +description = "レポートでのソース引用の形式" + +[i18n.ja.settings.language] +label = "言語" +description = "調査と出力の主要言語" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Investigación" +description = "Investigador autónomo en profundidad — investigación exhaustiva, referencias cruzadas, verificación de hechos e informes estructurados" +category = "Productividad" + +[i18n.es.settings.research_depth] +label = "Profundidad de investigación" +description = "Qué tan exhaustiva debe ser cada investigación" + +[i18n.es.settings.output_style] +label = "Estilo de salida" +description = "Cómo formatear los informes de investigación" + +[i18n.es.settings.source_verification] +label = "Verificación de fuentes" +description = "Verificar afirmaciones cruzando múltiples fuentes antes de incluirlas" + +[i18n.es.settings.max_sources] +label = "Máximo de fuentes" +description = "Número máximo de fuentes a consultar por investigación" + +[i18n.es.settings.auto_follow_up] +label = "Seguimiento automático" +description = "Investigar automáticamente preguntas de seguimiento descubiertas durante la investigación" + +[i18n.es.settings.save_research_log] +label = "Guardar registro de investigación" +description = "Guardar consultas de búsqueda detalladas y notas de evaluación de fuentes" + +[i18n.es.settings.citation_style] +label = "Estilo de citación" +description = "Cómo citar fuentes en los informes" + +[i18n.es.settings.language] +label = "Idioma" +description = "Idioma principal para la investigación y los resultados" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand de Recherche Approfondie" +description = "Chercheur autonome en profondeur — recherche exhaustive, références croisées, vérification des faits et rapports structurés" +category = "Productivité" + +[i18n.fr.settings.research_depth] +label = "Profondeur de recherche" +description = "Niveau de minutie de chaque investigation" + +[i18n.fr.settings.output_style] +label = "Style de sortie" +description = "Style de formatage du rapport de recherche" + +[i18n.fr.settings.source_verification] +label = "Vérification des sources" +description = "Vérifier les affirmations auprès de plusieurs sources avant de citer" + +[i18n.fr.settings.max_sources] +label = "Nombre maximum de sources" +description = "Nombre maximum de sources à consulter par recherche" + +[i18n.fr.settings.auto_follow_up] +label = "Suivi automatique" +description = "Rechercher automatiquement les questions de suivi découvertes pendant l'investigation" + +[i18n.fr.settings.save_research_log] +label = "Sauvegarder le journal de recherche" +description = "Conserver les journaux détaillés des requêtes de recherche et des évaluations de sources" + +[i18n.fr.settings.citation_style] +label = "Style de citation" +description = "Format de citation des sources dans les rapports" + +[i18n.fr.settings.language] +label = "Langue" +description = "Langue principale pour la recherche et les résultats" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Tiefenforschungs-Hand" +description = "Autonomer Tiefenforscher — gründliche Untersuchung, Querverweise, Faktencheck und strukturierte Berichte" +category = "Produktivität" + +[i18n.de.settings.research_depth] +label = "Forschungstiefe" +description = "Gründlichkeit jeder Untersuchung" + +[i18n.de.settings.output_style] +label = "Ausgabestil" +description = "Formatierungsstil des Forschungsberichts" + +[i18n.de.settings.source_verification] +label = "Quellenverifikation" +description = "Behauptungen vor dem Zitieren mit mehreren Quellen gegenkontrollieren" + +[i18n.de.settings.max_sources] +label = "Maximale Quellen" +description = "Maximale Anzahl der pro Untersuchung zu konsultierenden Quellen" + +[i18n.de.settings.auto_follow_up] +label = "Automatisches Nachfassen" +description = "Während der Untersuchung entdeckte Folgefragen automatisch recherchieren" + +[i18n.de.settings.save_research_log] +label = "Forschungsprotokoll speichern" +description = "Detaillierte Protokolle der Suchabfragen und Quellenbewertungen speichern" + +[i18n.de.settings.citation_style] +label = "Zitierstil" +description = "Format für Quellenangaben in Berichten" + +[i18n.de.settings.language] +label = "Sprache" +description = "Hauptsprache für Forschung und Ergebnisse" diff --git a/hands/researcher/SKILL.md b/hands/researcher/SKILL.md index e4a3b6c..caca695 100644 --- a/hands/researcher/SKILL.md +++ b/hands/researcher/SKILL.md @@ -183,6 +183,179 @@ After synthesis, explicitly note: --- +## Worked Examples + +### Example 1: Technology Adoption Decision + +**Question**: "Should our company adopt Rust for backend services?" + +**Phase 1 — Define** + +Decompose into sub-questions: +``` +Main: "Should our company adopt Rust for backend services?" +Sub-questions: + 1. What are Rust's strengths for backend work? (factual) + 2. What are the real-world costs of adoption? (factual + case studies) + 3. How does Rust compare to our current stack (Go) on key metrics? (comparative) + 4. What do teams of our size (15-30 engineers) report? (case studies) + 5. What is the hiring/training landscape? (survey) + 6. What are the migration paths and risks? (how-to + risk analysis) +``` + +Scope constraints: Backend HTTP services, team of 20 engineers currently using Go, latency-sensitive workloads, 18-month planning horizon. + +**Phase 2 — Search (multi-strategy)** +``` +Strategy 1 (Direct): "Rust backend production experience" +Strategy 2 (Authoritative): site:arxiv.org "Rust" "memory safety" performance +Strategy 3 (Practical): "migrating from Go to Rust" blog OR postmortem +Strategy 4 (Contrarian): "Rust backend" problems OR regret OR "not worth" +Strategy 5 (Data): "Rust" "developer survey" adoption 2024 2025 +Strategy 6 (Case studies): site:engineering.*.com Rust adoption +``` + +**Phase 3 — Evaluate (CRAAP scoring)** +``` +Source 1: Rust annual survey (rust-lang.org) → A (primary, current) +Source 2: Discord engineering blog on Rust migration → A (primary, practitioner) +Source 3: Figma "Rust in production" post → A (primary, detailed metrics) +Source 4: Random Medium post "Rust is the future" → D (no credentials, no data) +Source 5: AWS SDK for Rust announcement → B (authoritative, but marketing) +Source 6: "Why we moved back to Go" blog post → B (primary experience, single case) +Source 7: Stack Overflow developer survey → A (large sample, methodology documented) +``` + +Drop Source 4 entirely. Use Source 6 as a counterpoint despite being a single case. + +**Phase 4 — Synthesize** +``` +FINDING 1: Rust delivers measurable performance and reliability gains + Evidence for: Discord reported 50% memory reduction after migration [2]. + Figma measured p99 latency improvements of 3-5x for compute-heavy paths [3]. + Evidence against: Gains may be marginal for I/O-bound CRUD services [6]. + Confidence: High for compute-intensive workloads, medium for I/O-bound. + +FINDING 2: Adoption cost is front-loaded and significant + Evidence for: Average ramp-up time for experienced Go/C++ engineers is + 3-6 months to productive Rust [2][7]. Compile times 2-5x longer than Go [3]. + Evidence against: Teams report that after the learning curve, maintenance + costs drop due to fewer production incidents [2][3]. + Confidence: High + +FINDING 3: Hiring pipeline is narrow but growing + Evidence for: Rust ranks as "most admired" language for 8 consecutive years + in SO survey, but only ~13% of developers use it professionally [7]. + Evidence against: Rust job demand is growing ~40% YoY [7]. + Confidence: Medium — hiring data is self-reported. +``` + +**Phase 5 — Verify and deliver** + +Cross-check: Discord and Figma metrics are confirmed by independent engineering talks. SO survey methodology is published and peer-reviewed. + +Final recommendation structure: +``` +Adopt for: Latency-sensitive, compute-heavy services (strong evidence) +Avoid for: Simple CRUD APIs where Go is already performant (low ROI) +Mitigate hiring risk: Invest in internal training, start with one team +Timeline: 6-month pilot on a non-critical service before broader adoption +Confidence: Medium-high — strong technical evidence, moderate organizational evidence +``` + +### Example 2: Incident Analysis + +**Question**: "What caused the 2024 CrowdStrike outage and what are the implications?" + +**Phase 1 — Define** + +This is a causal question with survey elements. Decompose: +``` +Main: "What caused the 2024 CrowdStrike outage?" +Sub-questions: + 1. What happened? (timeline — factual) + 2. What was the technical root cause? (causal) + 3. What was the scope of impact? (factual, data) + 4. How did CrowdStrike respond? (factual) + 5. What systemic issues does this reveal? (analytical) + 6. What changed in the industry as a result? (survey + predictive) +``` + +**Phase 2 — Search** +``` +Strategy 1 (Primary): site:crowdstrike.com "July 2024" postmortem OR incident +Strategy 2 (Technical): "CrowdStrike" "channel file" root cause analysis +Strategy 3 (Impact data): "CrowdStrike outage" damages OR cost OR impact 2024 +Strategy 4 (Regulatory): site:gov "CrowdStrike" review OR hearing OR testimony +Strategy 5 (Contrarian): "CrowdStrike" "kernel driver" criticism before:2024-07-01 +Strategy 6 (Expert): "CrowdStrike outage" analysis site:*.edu OR site:arxiv.org +``` + +Note Strategy 5: searching for pre-incident criticism establishes whether warnings existed. + +**Phase 3 — Evaluate and build timeline** +``` +Timeline (verified — Level 3): + 2024-07-19 04:09 UTC CrowdStrike deploys Channel File 291 update + 2024-07-19 04:09-05:27 Falcon sensor crashes → Windows BSOD on boot + 2024-07-19 05:27 UTC CrowdStrike reverts the channel file + 2024-07-19 ~06:00 Scope becomes apparent: 8.5M Windows devices affected + 2024-07-19-21 Manual remediation required (boot to Safe Mode, delete file) + 2024-07-20-25 Airlines, hospitals, banks in multi-day recovery + +Sources: CrowdStrike PIR [A], Microsoft blog [A], Reuters reporting [B], + Congressional testimony transcript [A] +``` + +**Phase 4 — Synthesize root cause** +``` +FINDING 1: Technical root cause was an out-of-bounds memory read + A channel file update (type 291) contained malformed data. + The Falcon sensor's Content Interpreter triggered an OOB read, + causing a kernel-level crash (BSOD). The sensor ran as a kernel + driver, so its crash took down the entire OS. + Sources: CrowdStrike PIR [A], independent reverse engineering [B] + Confidence: High (confirmed by vendor + independent analysis) + +FINDING 2: The update bypassed adequate testing + Channel files ("rapid response content") used a different validation + pipeline than sensor code. The Template Type tested had 20 input + fields; the deployed content provided 21. The validator did not + catch the mismatch. + Sources: CrowdStrike PIR [A], Congressional testimony [A] + Confidence: High + +FINDING 3: Impact — $5-10B+ in estimated damages + 8.5M devices affected (Microsoft estimate). Delta Air Lines alone + reported $500M in losses. Parametrix estimated $5.4B in direct + losses for Fortune 500 companies. + Sources: Microsoft [A], Parametrix [B], Delta SEC filing [A] + Confidence: Medium-high (total figure is estimated, individual claims are documented) + +FINDING 4: Systemic issue — monoculture risk in security infrastructure + A single vendor's kernel-level agent was present on ~24% of + enterprise Windows endpoints. Pre-incident criticism of kernel-mode + security agents existed but was not widely acted upon. + Sources: Congressional hearing [A], pre-incident security research [B] + Confidence: High +``` + +**Phase 5 — Verify and present implications** +``` +Verified implications (cross-referenced across 3+ independent sources): + 1. Regulatory pressure on kernel-mode security agents accelerated + 2. Microsoft announced Windows Resiliency Initiative (user-mode alternatives) + 3. Enterprise customers began requiring staged/canary rollout for security updates + 4. Cyber insurance models updated to account for single-vendor concentration + +Remaining uncertainties: + - Full financial impact is still in litigation (Delta v. CrowdStrike) + - Long-term market share impact on CrowdStrike is unclear + - Whether kernel-mode restrictions will actually be enforced +``` + +--- + ## Citation Formats ### Inline URL @@ -325,3 +498,99 @@ Be aware of these biases during research: - Check if findings have been replicated - Preprints have not been peer-reviewed — note this caveat - p-values and effect sizes both matter — not just "statistically significant" + +--- + +## Research Shortcuts + +### When to Stop Researching + +Research has diminishing returns. Recognize these signals: + +**Stop signals — you have enough**: +- Three independent sources converge on the same answer +- New searches return sources you have already seen +- The last 3 searches added no new information or perspectives +- You have found primary source data that directly answers the question +- Remaining disagreements are about edge cases, not the core finding + +**Keep going signals — you do not have enough**: +- Only one source supports a critical claim +- Two credible sources directly contradict each other with no resolution +- The requester's specific context (industry, scale, constraints) is not addressed +- You have secondary reporting but no primary source for a key fact +- Your confidence assessment would be "low" on a central finding + +**Time-boxing rule**: For a standard research question, allocate effort roughly as: +``` +Quick facts: 2-4 searches, 1-2 minutes +Standard question: 6-12 searches, 5-10 minutes +Deep dive: 15-30 searches, 20-40 minutes +``` +If you exceed 2x the expected searches without convergence, stop and report what you have with explicit gaps noted. + +### Quick Assessment vs Deep Dive + +Not every question deserves a full 5-phase research process. Use this decision matrix: + +``` +Quick assessment (skip to synthesis fast): + ✓ Question has a single factual answer + ✓ Authoritative primary source exists and is accessible + ✓ Low stakes — wrong answer has minimal consequences + ✓ Requester wants speed over thoroughness + Example: "What version of Python dropped GIL?" + → Check python.org docs/PEPs, answer in one search. + +Standard research (full 5-phase process): + ✓ Comparative or analytical question + ✓ Multiple valid perspectives exist + ✓ Answer will inform a decision + ✓ Moderate stakes + Example: "React vs Svelte for our new dashboard?" + → Full decomposition, multi-source, synthesis needed. + +Deep dive (extended research with formal deliverable): + ✓ High-stakes decision (architecture, vendor, strategy) + ✓ Conflicting information is likely + ✓ Historical context and trend analysis needed + ✓ Requester expects a report they can share with others + Example: "Should we move from AWS to multi-cloud?" + → Multiple sub-questions, 10+ sources, formal report. +``` + +### Source Reuse Patterns + +Not every question starts from zero. Build efficiency by recognizing reusable sources. + +**Tier 1 — Canonical references (always check first for their domain)**: +``` +Programming languages: Official docs, language spec, release notes +Cloud services: AWS/GCP/Azure docs, status pages, pricing pages +Security: CVE databases, vendor advisories, NIST NVD +Statistics: Official census/survey data, World Bank, OECD +Companies: SEC filings (EDGAR), official IR pages +Open source: GitHub repo, CHANGELOG, issue tracker +``` + +**Tier 2 — High-signal aggregators (good starting points)**: +``` +Technology trends: ThoughtWorks Radar, Stack Overflow survey, TIOBE +Security incidents: CISA advisories, Krebs on Security +Academic papers: Google Scholar, Semantic Scholar, arXiv +Industry analysis: Gartner (with bias caveat), a16z, Sequoia +Developer experience: JetBrains survey, GitHub Octoverse +``` + +**Tier 3 — Practitioner sources (for real-world validation)**: +``` +Engineering blogs: Company engineering blogs (Netflix, Uber, Stripe, Discord) +Conference talks: Recorded talks from Strange Loop, QCon, KubeCon +Community discussion: Hacker News (comments often more valuable than articles), + Reddit (r/programming, r/devops, domain-specific subs) +``` + +**Anti-patterns to avoid**: +- Do not reuse a source across topics just because it scored well once — re-evaluate CRAAP for the new topic +- Do not treat aggregator rankings (Gartner Magic Quadrant, G2 reviews) as primary evidence — they are influenced by vendor spending +- Do not assume a source's authority transfers across domains — a security vendor's blog is authoritative on threats but not on database performance diff --git a/hands/strategist/HAND.toml b/hands/strategist/HAND.toml index a8e4165..c9642ca 100644 --- a/hands/strategist/HAND.toml +++ b/hands/strategist/HAND.toml @@ -378,6 +378,241 @@ token_consumption = "medium" default_active = true activation_warning = "Strategist hand runs continuously and performs strategic analysis, consuming tokens." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "策略分析 Hand" description = "自主策略分析师——市场研究、竞争分析、商业规划和战略建议" +category = "生产力" + +[i18n.zh.settings.focus_area] +label = "聚焦方向" +description = "战略分析的主要方向" + +[i18n.zh.settings.analysis_depth] +label = "分析深度" +description = "每次战略分析的详尽程度" + +[i18n.zh.settings.industry] +label = "行业" +description = "重点分析的行业(例如 SaaS、金融科技、医疗健康)" + +[i18n.zh.settings.competitors] +label = "主要竞争对手" +description = "需要追踪的竞争对手列表(逗号分隔)" + +[i18n.zh.settings.auto_monitor] +label = "自动监控" +description = "自动追踪竞争对手动态和市场变化" + +[i18n.zh.settings.report_format] +label = "报告格式" +description = "战略报告的格式风格" + +[i18n.zh.settings.confidence_threshold] +label = "置信度阈值" +description = "报告中纳入分析结论的最低置信度" + +[i18n.zh.settings.frameworks] +label = "首选分析框架" +description = "优先使用的战略分析框架(逗号分隔,例如 SWOT,Porter,PESTEL)" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Estrategia" +description = "Analista estratégico autónomo — investigación de mercado, análisis competitivo, planificación empresarial y recomendaciones estratégicas" +category = "Productividad" + +[i18n.es.settings.focus_area] +label = "Área de enfoque" +description = "Área principal del análisis estratégico" + +[i18n.es.settings.analysis_depth] +label = "Profundidad del análisis" +description = "Nivel de detalle de cada análisis estratégico" + +[i18n.es.settings.industry] +label = "Industria" +description = "Industria principal en la que enfocar el análisis (ej. SaaS, fintech, salud)" + +[i18n.es.settings.competitors] +label = "Competidores clave" +description = "Lista de competidores a rastrear separados por comas" + +[i18n.es.settings.auto_monitor] +label = "Monitoreo automático" +description = "Rastrear automáticamente movimientos de competidores y cambios del mercado" + +[i18n.es.settings.report_format] +label = "Formato de informe" +description = "Formato de los informes estratégicos" + +[i18n.es.settings.confidence_threshold] +label = "Umbral de confianza" +description = "Nivel mínimo de confianza para incluir hallazgos en los informes" + +[i18n.es.settings.frameworks] +label = "Marcos de análisis preferidos" +description = "Marcos estratégicos a priorizar (separados por comas, ej. SWOT, Porter, PESTEL)" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "戦略分析 Hand" +description = "自律型戦略アナリスト——市場調査、競合分析、事業計画、戦略的提言" +category = "生産性" + +[i18n.ja.settings.focus_area] +label = "フォーカスエリア" +description = "戦略分析の主な対象分野" + +[i18n.ja.settings.analysis_depth] +label = "分析の深さ" +description = "各戦略分析の詳細度" + +[i18n.ja.settings.industry] +label = "業界" +description = "分析の対象となる主要業界(例: SaaS、フィンテック、ヘルスケア)" + +[i18n.ja.settings.competitors] +label = "主要な競合" +description = "追跡する競合のリスト(カンマ区切り)" + +[i18n.ja.settings.auto_monitor] +label = "自動監視" +description = "競合の動向と市場の変化を自動的に追跡する" + +[i18n.ja.settings.report_format] +label = "レポート形式" +description = "戦略レポートのフォーマット" + +[i18n.ja.settings.confidence_threshold] +label = "信頼度しきい値" +description = "レポートに分析結果を含めるための最低信頼度" + +[i18n.ja.settings.frameworks] +label = "優先フレームワーク" +description = "優先的に使用する戦略分析フレームワーク(カンマ区切り、例: SWOT,Porter,PESTEL)" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Stratégique" +description = "Analyste stratégique autonome — étude de marché, analyse concurrentielle, planification d'entreprise et recommandations stratégiques" +category = "Productivité" + +[i18n.fr.settings.focus_area] +label = "Domaine d'intérêt" +description = "Domaine principal de l'analyse stratégique" + +[i18n.fr.settings.analysis_depth] +label = "Profondeur d'analyse" +description = "Niveau de détail de chaque analyse stratégique" + +[i18n.fr.settings.industry] +label = "Secteur" +description = "Secteur principal d'analyse (ex. SaaS, fintech, santé)" + +[i18n.fr.settings.competitors] +label = "Concurrents clés" +description = "Liste de concurrents à suivre séparée par des virgules" + +[i18n.fr.settings.auto_monitor] +label = "Surveillance automatique" +description = "Suivre automatiquement les mouvements des concurrents et les évolutions du marché" + +[i18n.fr.settings.report_format] +label = "Format de rapport" +description = "Format des rapports stratégiques" + +[i18n.fr.settings.confidence_threshold] +label = "Seuil de confiance" +description = "Niveau de confiance minimum pour inclure les résultats dans les rapports" + +[i18n.fr.settings.frameworks] +label = "Cadres d'analyse préférés" +description = "Cadres d'analyse stratégique à privilégier (séparés par des virgules, ex. SWOT, Porter, PESTEL)" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Strategie-Hand" +description = "Autonomer Strategieanalyst — Marktforschung, Wettbewerbsanalyse, Geschäftsplanung und strategische Empfehlungen" +category = "Produktivität" + +[i18n.de.settings.focus_area] +label = "Fokusbereich" +description = "Hauptbereich der strategischen Analyse" + +[i18n.de.settings.analysis_depth] +label = "Analysetiefe" +description = "Detailgrad jeder strategischen Analyse" + +[i18n.de.settings.industry] +label = "Branche" +description = "Hauptbranche für die Analyse (z.B. SaaS, Fintech, Gesundheitswesen)" + +[i18n.de.settings.competitors] +label = "Wichtige Wettbewerber" +description = "Kommagetrennte Liste der zu verfolgenden Wettbewerber" + +[i18n.de.settings.auto_monitor] +label = "Automatische Überwachung" +description = "Wettbewerberbewegungen und Marktveränderungen automatisch verfolgen" + +[i18n.de.settings.report_format] +label = "Berichtsformat" +description = "Format der Strategieberichte" + +[i18n.de.settings.confidence_threshold] +label = "Konfidenzschwelle" +description = "Mindest-Konfidenzniveau für die Aufnahme von Ergebnissen in Berichte" + +[i18n.de.settings.frameworks] +label = "Bevorzugte Analyse-Frameworks" +description = "Bevorzugte strategische Analyse-Frameworks (kommagetrennt, z.B. SWOT, Porter, PESTEL)" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "전략 분석 Hand" +description = "자율 전략 분석가 — 시장 조사, 경쟁 분석, 사업 계획 및 전략적 권고" +category = "생산성" + +[i18n.ko.settings.focus_area] +label = "집중 분야" +description = "전략 분석의 주요 방향" + +[i18n.ko.settings.analysis_depth] +label = "분석 깊이" +description = "각 전략 분석의 철저함 정도" + +[i18n.ko.settings.industry] +label = "산업" +description = "분석의 중점 산업 (예: SaaS, 핀테크, 헬스케어)" + +[i18n.ko.settings.competitors] +label = "주요 경쟁사" +description = "추적할 경쟁사 목록 (쉼표로 구분)" + +[i18n.ko.settings.auto_monitor] +label = "자동 모니터링" +description = "경쟁사 동향 및 시장 변화를 자동으로 추적" + +[i18n.ko.settings.report_format] +label = "보고서 형식" +description = "전략 보고서의 형식 스타일" + +[i18n.ko.settings.confidence_threshold] +label = "신뢰도 임계값" +description = "보고서에 분석 결과를 포함하기 위한 최소 신뢰도" + +[i18n.ko.settings.frameworks] +label = "선호 분석 프레임워크" +description = "우선적으로 사용할 전략 분석 프레임워크 (쉼표로 구분, 예: SWOT,Porter,PESTEL)" diff --git a/hands/strategist/SKILL.md b/hands/strategist/SKILL.md index dd5e8bd..e8e9d98 100644 --- a/hands/strategist/SKILL.md +++ b/hands/strategist/SKILL.md @@ -236,3 +236,725 @@ Employee Count: [Growth indicator] ## Implementation [How to execute the recommendation] ``` + +--- + +## Worked Examples + +### Example 1: B2B SaaS Market Entry into Japan + +**Context**: A US-based B2B SaaS company (project management tool, $15M ARR, 200 employees) evaluating entry into the Japanese market. + +**PESTEL Analysis — Japan B2B SaaS (2025):** + +| Factor | Assessment | Impact | Score (1-5) | +|--------|-----------|--------|-------------| +| **Political** | Stable democracy; strong US-Japan trade relations; Digital Agency pushing government digitization | Positive | 4 | +| **Economic** | GDP $4.2T; weak yen (150 JPY/USD) makes USD-priced SaaS expensive; enterprise IT spend growing 4% YoY | Mixed | 3 | +| **Social** | Aging workforce accelerates automation need; consensus-driven decision making lengthens sales cycles (avg 6-9 months); strong preference for local-language support | Critical constraint | 2 | +| **Technological** | High internet penetration (93%); cloud adoption lagging US by 3-5 years but accelerating; 5G rollout complete in urban areas | Opportunity | 4 | +| **Environmental** | ESG reporting mandated for listed companies from 2023; sustainability-linked procurement gaining traction | Moderate opportunity | 3 | +| **Legal** | APPI (Act on Protection of Personal Information) requires data residency consideration; strict labor laws affect HR SaaS | Compliance cost | 2 | + +**PESTEL Score**: 18/30 — Moderately favorable. Key risk: social/cultural factors demand significant localization investment. + +**Porter's Five Forces — Japan Project Management SaaS:** + +| Force | Rating | Evidence | +|-------|--------|---------| +| New Entrants | 2/5 | High localization cost ($500K-$1M); relationship-driven market favors incumbents | +| Supplier Power | 1/5 | Cloud infrastructure (AWS Tokyo, Azure Japan) is commodity; no supplier concentration | +| Buyer Power | 4/5 | Enterprise buyers demand customization; long procurement cycles give buyers leverage; RFP-driven purchasing | +| Substitutes | 3/5 | Excel/spreadsheet culture deeply entrenched; domestic tools (Backlog, Jooto) have cultural fit advantage | +| Rivalry | 4/5 | Asana, Monday.com, Notion already present; domestic players Backlog (Nulab) and Redmine have loyal bases | + +**Go-to-Market Recommendation:** + +``` +Strategy: Partner-Led Entry (not direct sales) +Timeline: 18 months to first enterprise deal + +Phase 1 (Months 1-6): Foundation + - Hire Country Manager (must be bilingual Japanese national) + - Full UI/UX localization (not just translation — date formats, name order, honorifics) + - Achieve ISMAP certification (required for government/enterprise procurement) + - Data residency: Deploy on AWS Tokyo region + - Budget: $800K + +Phase 2 (Months 4-12): Channel Development + - Sign 2-3 SIer (System Integrator) partners: target NTT Data, Fujitsu, NEC + - Japanese SIers control 60% of enterprise software purchasing decisions + - Co-develop integration with domestic tools (kintone, Sansan, freee) + - Budget: $600K (partner enablement + integration development) + +Phase 3 (Months 8-18): Market Penetration + - Target mid-market first (500-2000 employees) — faster decision cycles than enterprise + - Launch at Japan IT Week (Spring/Autumn) and SaaS Industry Conference + - Content marketing: Japanese-language case studies, webinars with local customers + - Target: 20 paying customers, $500K ARR by month 18 + - Budget: $400K + +Total Investment: $1.8M over 18 months +Break-even: Month 30 (projected) +``` + +**Decision**: Proceed with caution. The $4.2T economy and cloud adoption tailwind justify the investment, but only with proper localization and channel strategy. Direct sales without SIer partnerships has a historically high failure rate (>70% for foreign SaaS in Japan). + +--- + +### Example 2: Competitive Response — Major Player Enters Your Niche + +**Context**: You run a $5M ARR vertical SaaS for veterinary clinics (500 customers, 15% market share). Salesforce just announced "Salesforce for Veterinary" — a vertical solution built on their platform. + +**Threat Assessment:** + +| Dimension | Your Position | Salesforce | Gap | +|-----------|--------------|------------|-----| +| Brand recognition | Niche leader | Global enterprise brand | Large — but irrelevant in vet niche | +| Product depth | Purpose-built (8 years domain expertise) | Horizontal platform with vertical skin | Strong advantage | +| Price point | $200/mo per clinic | $500/mo estimated (Salesforce pricing) | 2.5x cheaper | +| Implementation time | 2 weeks | 3-6 months (typical SF implementation) | Strong advantage | +| Integration depth | Deep PMS/PIMS integration | API-based, requires middleware | Strong advantage | +| Sales motion | Direct + word-of-mouth | Enterprise sales team + SI partners | Different segments | +| Switching cost for your customers | Moderate (data migration + retraining) | High (Salesforce ecosystem lock-in) | Neutral | + +**Strategic Response Framework:** + +``` +IMMEDIATE (Week 1-4): Defend the Base + 1. Customer communication campaign + - CEO letter to all 500 customers: "Our commitment to veterinary" + - Emphasize: purpose-built > horizontal platform + - Announce product roadmap acceleration + + 2. Lock in at-risk accounts + - Identify top 50 accounts by revenue + - Offer annual contract discounts (15-20% for 2-year commitment) + - Schedule QBRs with all enterprise accounts within 30 days + + 3. Competitive battle card + - Create internal sales doc: feature-by-feature comparison + - "Why vets choose us over Salesforce" — 5 key differentiators + - Objection handling for "shouldn't we go with the safe choice?" + +SHORT-TERM (Month 2-6): Deepen the Moat + 4. Accelerate domain-specific features + - AI-powered treatment plan suggestions (Salesforce can't match this) + - Telemedicine integration (vertical-specific) + - Inventory management tied to treatment protocols + + 5. Build switching costs + - Launch data analytics dashboard (clinics depend on historical trends) + - Introduce multi-location management (target growing chains) + - API marketplace for vet-specific integrations (lab equipment, imaging) + + 6. Community defense + - Launch "Vet Tech Community" — user forum + knowledge base + - Annual user conference (even virtual — creates tribal loyalty) + - Customer advisory board (top 10 clinics = co-development partners) + +MEDIUM-TERM (Month 6-18): Counterattack + 7. Move upmarket selectively + - Enterprise tier for 10+ location chains ($500/mo — match SF pricing) + - Offer white-glove migration from legacy systems + - This is the segment Salesforce will target — contest it + + 8. Geographic expansion + - Salesforce announcement creates awareness of the category + - Ride the wave: "Already purpose-built, already proven" + - Target UK, Australia, Canada (English-speaking, similar vet market structure) +``` + +**Pricing Response Decision Matrix:** + +| Option | Revenue Impact | Competitive Effect | Risk | +|--------|---------------|-------------------|------| +| No change | Neutral | Salesforce still 2.5x more expensive | Low — price isn't the battleground | +| Cut prices 20% | -$1M ARR | Signals weakness; Salesforce won't match | High | +| Add premium tier | +$500K potential | Compete at enterprise level; justify R&D | Medium | +| Usage-based addon | +$300K potential | Expand ARPU without base price war | Low | + +**Recommendation**: Add premium tier + usage-based addons. Do NOT cut base prices. Salesforce's entry validates your market — use it to raise your valuation narrative ("Salesforce sees a $2B market opportunity in vet SaaS — we already own 15%"). + +**Confidence**: Medium-High (75%) — Historical pattern: when Salesforce enters verticals, purpose-built incumbents retain 80%+ of existing customers. Risk is in new customer acquisition where brand matters more. + +--- + +### Example 3: Platform Sunset Decision — Migrate or Maintain Legacy Product + +**Context**: A mid-stage startup ($20M ARR) runs two products: a legacy desktop app (60% of revenue, declining 10% YoY) and a modern cloud product (40% of revenue, growing 50% YoY). Should they sunset the desktop app? + +**Decision Matrix:** + +| Criterion (Weight) | Option A: Maintain Both | Option B: Sunset in 12mo | Option C: Sunset in 24mo | +|--------------------|------------------------|--------------------------|--------------------------| +| Revenue protection (30%) | 5 — No disruption | 2 — Lose 40% of legacy revenue | 4 — Gradual migration | +| Engineering efficiency (25%) | 1 — Two codebases drain resources | 5 — Full focus on cloud | 3 — Phased transition | +| Customer satisfaction (20%) | 3 — Legacy stagnates | 2 — Forced migration angers users | 4 — Supported migration path | +| Market positioning (15%) | 2 — Confused narrative | 5 — Clear cloud-first story | 4 — Transitional narrative | +| Financial risk (10%) | 3 — Slow bleed sustainable | 2 — Revenue cliff risk | 4 — Manageable decline | +| **Weighted Score** | **2.95** | **3.35** | **3.75** | + +**Recommendation**: Option C — 24-month sunset with structured migration program. + +``` +Migration Program: + Months 1-6: Feature parity audit; build top 20 missing cloud features + Months 7-12: Migration incentive (20% discount for annual cloud commitment) + Months 13-18: Desktop enters maintenance-only mode; no new features + Months 19-24: End-of-life announcement; dedicated migration support team + Month 24: Desktop product sunsets; legacy support for 6 more months + +Financial Model: + Current state: $12M desktop + $8M cloud = $20M ARR + Month 12 (projected): $9M desktop + $14M cloud = $23M ARR + Month 24 (projected): $2M desktop + $22M cloud = $24M ARR + Month 30 (projected): $0 desktop + $26M cloud = $26M ARR + + Net ARR risk: ~$3M from non-migrating desktop customers + Offset: Engineering savings of $1.5M/yr + faster cloud feature velocity +``` + +--- + +## Financial Analysis Frameworks + +### Unit Economics + +Core metrics every strategy should quantify: + +``` +CAC (Customer Acquisition Cost) + = Total Sales & Marketing Spend / New Customers Acquired + Example: $500K spend / 100 new customers = $5,000 CAC + +LTV (Lifetime Value) + = ARPU x Gross Margin % x (1 / Churn Rate) + Example: $500/mo x 80% x (1 / 0.03) = $13,333 LTV + +LTV:CAC Ratio + Target: > 3:1 for healthy SaaS + Example: $13,333 / $5,000 = 2.67:1 (below target — reduce CAC or increase retention) + +CAC Payback Period + = CAC / (ARPU x Gross Margin %) + Example: $5,000 / ($500 x 0.80) = 12.5 months + Target: < 18 months for SaaS +``` + +**Unit Economics Health Check:** + +| Metric | Danger Zone | Acceptable | Excellent | +|--------|------------|------------|-----------| +| LTV:CAC | < 1:1 | 3:1 | > 5:1 | +| CAC Payback | > 24 months | 12-18 months | < 12 months | +| Gross Margin | < 60% | 70-80% | > 80% | +| Net Revenue Retention | < 90% | 100-110% | > 120% | +| Logo Churn (monthly) | > 5% | 2-3% | < 1% | + +### Revenue Modeling + +**SaaS Revenue Waterfall:** + +``` +Beginning ARR: $10,000,000 + + New Business: +$3,000,000 (new logos) + + Expansion: +$1,500,000 (upsell/cross-sell) + - Contraction: -$500,000 (downgrades) + - Churn: -$1,200,000 (lost customers) + = Ending ARR: $12,800,000 + +Net New ARR: $2,800,000 +Net Revenue Retention: 113% = ($10M + $1.5M - $0.5M - $1.2M) / $10M +Gross Revenue Retention: 88% = ($10M - $0.5M - $1.2M) / $10M +``` + +**MRR Growth Decomposition:** + +``` +MRR Growth Rate = New MRR + Expansion MRR - Churned MRR - Contraction MRR + ───────────────────────────────────────────────────────── + Beginning MRR + +Quick Ratio = (New MRR + Expansion MRR) / (Churned MRR + Contraction MRR) +Target: > 4 for high-growth SaaS +``` + +### Break-Even Analysis + +``` +Break-Even Revenue = Fixed Costs / Gross Margin % + +Example: + Fixed Costs (monthly): $200K (salaries, rent, tools) + Gross Margin: 80% + Break-Even Revenue = $200K / 0.80 = $250K/month = $3M ARR + +Break-Even Customers = Break-Even Revenue / ARPU + = $250K / $500 = 500 customers +``` + +**Scenario Table:** + +| Scenario | Fixed Costs | Gross Margin | Break-Even ARR | Break-Even Customers | +|----------|------------|--------------|-----------------|---------------------| +| Lean | $150K/mo | 85% | $2.1M | 353 | +| Base | $200K/mo | 80% | $3.0M | 500 | +| Growth | $350K/mo | 75% | $5.6M | 933 | + +### Project Evaluation — Simplified DCF + +Use for evaluating strategic investments (new market entry, build vs buy, major feature investment): + +``` +NPV = Σ [Cash Flow_t / (1 + r)^t] - Initial Investment + +Where: + r = discount rate (typically 10-15% for startups, 8-10% for established companies) + t = year (0, 1, 2, ... n) +``` + +**Worked Example — Should we build a mobile app?** + +``` +Initial Investment: $500K (development cost) +Discount Rate: 12% + +Year | Incremental Revenue | Incremental Cost | Net Cash Flow | PV Factor | Present Value +------|--------------------|--------------------|---------------|-----------|------------- + 0 | $0 | $500,000 | -$500,000 | 1.000 | -$500,000 + 1 | $200,000 | $80,000 | $120,000 | 0.893 | $107,143 + 2 | $400,000 | $100,000 | $300,000 | 0.797 | $239,158 + 3 | $600,000 | $120,000 | $480,000 | 0.712 | $341,655 + 4 | $700,000 | $130,000 | $570,000 | 0.636 | $362,204 + +NPV = $550,160 → Positive NPV → Project is financially justified +Payback Period: ~2.3 years (cumulative cash flow turns positive in Year 3) +``` + +**Decision Rule:** +- NPV > 0 → Proceed (project creates value) +- NPV < 0 → Reject (project destroys value) +- Compare NPV across mutually exclusive options; pick highest + +--- + +## Go-to-Market Strategy Patterns + +### Growth Motion Selection + +| Growth Motion | Best For | Sales Cycle | CAC | Key Metric | +|--------------|---------|-------------|-----|------------| +| **Product-Led Growth (PLG)** | Self-serve products; low price point (<$500/mo); individual users | Minutes to days | Low ($50-$500) | Activation rate, PQL conversion | +| **Sales-Led Growth** | Enterprise products; complex deployment; >$50K ACV | Weeks to months | High ($5K-$50K) | Pipeline velocity, win rate | +| **Community-Led Growth** | Developer tools; open-source; platform products | Varies | Very low ($10-$100) | Community size, contribution rate | +| **Partner-Led Growth** | Market entry; regulated industries; ecosystem products | Varies | Medium ($1K-$10K) | Partner-sourced revenue % | + +**PLG Funnel:** +``` +Visitor → Sign-up → Activated User → PQL → Paid Customer → Expanded Account + 100% 10% 40% 25% 15% 30% + +Key levers: + - Sign-up friction: Reduce form fields, add SSO + - Time-to-value: Get user to "aha moment" in < 5 minutes + - PQL definition: User hits usage threshold that correlates with purchase + - Expansion trigger: Team features, usage limits, premium capabilities +``` + +**Sales-Led Funnel:** +``` +Lead → MQL → SQL → Opportunity → Proposal → Closed Won + 100% 20% 50% 60% 70% 30% + +Key levers: + - Lead quality: ICP fit scoring + - MQL→SQL handoff: Alignment between marketing and sales + - Discovery: Deep pain identification + - Champion building: Enable internal advocate + - Procurement: Legal/security review preparation +``` + +### Pricing Strategy Frameworks + +**Value-Based Pricing (recommended for most SaaS):** +``` +1. Quantify customer value created + Example: Your tool saves 10 hours/week per user + Value = 10 hrs x $75/hr x 52 weeks = $39,000/year + +2. Capture 10-20% of value created + Price = $39,000 x 15% = $5,850/year = $487/month + +3. Validate with willingness-to-pay research + Van Westendorp Price Sensitivity Meter: + - "At what price is this too expensive?" → $600/mo + - "At what price is this a bargain?" → $200/mo + - "At what price does it seem expensive but you'd still consider?" → $450/mo + - "At what price does it seem too cheap to trust?" → $100/mo + → Optimal price range: $200-$450/mo +``` + +**Pricing Tier Architecture:** + +``` +Tier Structure (Good-Better-Best): + +| | Starter | Professional | Enterprise | +|---|---------|-------------|------------| +| Target | Individual/SMB | Mid-market team | Large organization | +| Price | $29/mo | $99/mo/user | Custom (>$500/mo) | +| Anchor role | Drive adoption | Revenue driver (~60% of revenue) | Margin driver | +| Features | Core functionality | Full platform | Custom + SLA + support | +| Support | Self-serve/email | Priority email + chat | Dedicated CSM + phone | +| Billing | Monthly/Annual | Annual preferred | Annual contract | + +Design principles: + - Middle tier should be the obvious best value + - Top tier exists to make middle tier look reasonable (anchoring effect) + - Feature gates should align with natural usage growth + - Price metric should scale with value received (per user, per GB, per transaction) +``` + +**Competitive Pricing Analysis:** + +``` +Competitor Price Map: + +Competitor | Entry Price | Mid-Tier | Enterprise | Price Metric +-------------|-------------|----------|------------|------------- +Competitor A | $49/mo | $149/mo | Custom | Per user +Competitor B | $0 (free) | $99/mo | $299/mo | Flat rate +Competitor C | $29/mo | $79/mo | Custom | Per user +Your Product | ??? | ??? | ??? | ??? + +Positioning options: + - Price leader: 20-30% below average → requires cost advantage + - Value leader: At or above average → requires clear differentiation + - Premium: 30%+ above average → requires brand and feature superiority +``` + +### Channel Strategy + +| Channel | Margin | Control | Scale | Best For | +|---------|--------|---------|-------|----------| +| Direct sales | High (85-95%) | Full | Slow | Enterprise, complex products | +| Inside sales | High (80-90%) | Full | Medium | Mid-market, $5K-$50K ACV | +| Self-serve | Highest (95%+) | Full | Fast | PLG, low ACV | +| Reseller/VAR | Low (60-70%) | Medium | Medium | Regional coverage, compliance | +| Marketplace (AWS/Azure) | Low (70-85%) | Low | Fast | Enterprise procurement shortcuts | +| System Integrator | Low (50-70%) | Low | Medium | Complex implementations | +| Affiliate/Referral | High (80-90%) | Low | Fast | Consumer, SMB | + +### Launch Playbook Template + +``` +LAUNCH PLAYBOOK: [Product/Feature Name] +Launch Date: YYYY-MM-DD +Launch Type: [Major / Minor / Feature / Beta] + +PRE-LAUNCH (T-8 weeks to T-0) + Week -8: Finalize positioning and messaging + Week -6: Create sales enablement materials (battle cards, one-pagers, demo script) + Week -4: Brief analyst relations (Gartner, Forrester) if applicable + Week -3: Seed beta customers (5-10 design partners); collect testimonials + Week -2: Pre-brief press/media under embargo + Week -1: Internal all-hands; sales team training; support team training + +LAUNCH DAY (T-0) + - Blog post (SEO-optimized) + - Email to customer base + - Social media campaign (LinkedIn, Twitter/X) + - Press release (if major launch) + - Product Hunt submission (if applicable) + - In-app announcement for existing users + - Founder/CEO LinkedIn post (highest engagement channel) + +POST-LAUNCH (T+1 to T+8 weeks) + Week +1: Monitor activation metrics; respond to all feedback + Week +2: Publish customer case study + Week +4: Webinar / live demo for pipeline + Week +6: Analyze launch metrics vs targets + Week +8: Retrospective and iteration plan + +METRICS TO TRACK: + - Awareness: Blog views, social impressions, press mentions + - Activation: Sign-ups, trial starts, feature adoption rate + - Revenue: Pipeline generated, deals influenced, new ARR + - Sentiment: NPS from beta users, social sentiment, support ticket volume +``` + +--- + +## Scenario Planning + +### Best / Base / Worst Case Framework + +Structure every major strategic decision with three scenarios: + +``` +SCENARIO PLANNING: [Decision or Initiative] + + | Worst Case | Base Case | Best Case +--------------------|-----------------|-----------------|------------------ +Revenue impact | [quantify] | [quantify] | [quantify] +Timeline | [duration] | [duration] | [duration] +Key assumption | [what goes wrong]| [most likely] | [what goes right] +Probability | [15-25%] | [50-60%] | [15-25%] +Trigger indicators | [early signals] | [tracking metrics]| [early signals] +Response plan | [pivot/exit] | [continue/adjust]| [accelerate/expand] +``` + +**Worked Example — Launching a New Product Line:** + +``` +SCENARIO PLANNING: Launch enterprise analytics add-on ($200/mo) + + | Worst Case (20%) | Base Case (55%) | Best Case (25%) +--------------------|-------------------|-------------------|------------------- +Adoption rate | 5% of customers | 15% of customers | 30% of customers +Year 1 revenue | $120K | $360K | $720K +Development cost | $400K | $400K | $400K +Year 1 ROI | -70% | -10% | +80% +Break-even | Never (kill it) | Month 18 | Month 8 +Key assumption | Customers don't | Moderate demand; | Strong demand; + | see value; churn | gradual adoption | pulls forward + | increases 2% | | enterprise deals + +Trigger Indicators: + Worst: < 3% adoption after 3 months; NPS < 20 for add-on + Base: 8-12% adoption after 3 months; positive but slow pipeline + Best: > 20% adoption after 3 months; inbound enterprise interest + +Response Plans: + Worst: Pivot to bundling analytics into existing plan (retention play) + Base: Continue; invest in onboarding and customer education + Best: Hire dedicated analytics PM; accelerate roadmap; raise prices 20% +``` + +**Expected Value Calculation:** + +``` +Expected Revenue = (Worst Revenue x Worst Prob) + (Base Revenue x Base Prob) + (Best Revenue x Best Prob) + = ($120K x 0.20) + ($360K x 0.55) + ($720K x 0.25) + = $24K + $198K + $180K + = $402K + +Expected ROI = ($402K - $400K) / $400K = 0.5% +→ Marginal on expected value alone — proceed only if strategic upside justifies the bet +``` + +### Sensitivity Analysis + +Identify which variables have the highest impact on outcomes: + +``` +SENSITIVITY ANALYSIS: New Market Entry + +Base Case NPV: $550K + +Variable | -20% Change | Base | +20% Change | Sensitivity +--------------------|---------------|----------|----------------|------------ +Customer price | $280K (-49%) | $550K | $820K (+49%) | HIGH +Customer volume | $310K (-44%) | $550K | $790K (+44%) | HIGH +Churn rate | $720K (+31%) | $550K | $380K (-31%) | HIGH +Development cost | $650K (+18%) | $550K | $450K (-18%) | MEDIUM +CAC | $610K (+11%) | $550K | $490K (-11%) | MEDIUM +Discount rate | $590K (+7%) | $550K | $510K (-7%) | LOW +``` + +**Interpretation**: Price and volume are the highest-leverage variables. Strategy should prioritize pricing power and demand generation over cost optimization. + +**Tornado Chart Format (text representation):** + +``` +Variable Impact on NPV (base = $550K): + +Customer price |████████████████████| -49% to +49% +Customer volume |███████████████████ | -44% to +44% +Churn rate |██████████████ | -31% to +31% +Development cost |█████████ | -18% to +18% +CAC |██████ | -11% to +11% +Discount rate |████ | -7% to +7% +``` + +### Risk-Adjusted Decision Making + +**Risk Register Template:** + +| Risk | Probability (1-5) | Impact (1-5) | Risk Score | Mitigation | Residual Risk | +|------|-------------------|-------------|------------|------------|---------------| +| Key hire doesn't work out | 3 | 4 | 12 | Pipeline of 2 backup candidates | 6 | +| Competitor launches first | 4 | 3 | 12 | Focus on differentiation not speed | 8 | +| Technical architecture fails to scale | 2 | 5 | 10 | Prototype load test at 10x before commit | 4 | +| Regulatory change blocks approach | 1 | 5 | 5 | Legal review + pivot plan documented | 3 | +| Customer demand lower than projected | 3 | 4 | 12 | Pre-sell to 10 design partners before building | 6 | + +**Risk-Adjusted NPV:** +``` +Risk-Adjusted NPV = Base NPV x (1 - Risk Discount) + +Where Risk Discount = Σ (Probability x Impact x Weight) for all material risks + +Example: + Base NPV: $550K + Combined risk score: 0.15 (derived from risk register) + Risk-Adjusted NPV: $550K x (1 - 0.15) = $467.5K +``` + +--- + +## Industry Analysis Templates + +### Market Landscape Map + +Plot all players in a market on two strategic dimensions: + +``` +MARKET LANDSCAPE: [Industry/Category] + + Enterprise-Grade + | + Quadrant 2| Quadrant 1 + Niche | Market Leaders + Enterprise| + Narrow ──────────────┼────────────── Broad + Solution | Platform + Quadrant 3| Quadrant 4 + Point | Mass-Market + Solutions | Platforms + | + SMB-Focused + +Example — Project Management SaaS (2025): + +Quadrant 1 (Leaders): Asana, Monday.com, Smartsheet +Quadrant 2 (Niche): Targetprocess (SAFe), Planview (PPM), Kantata (services) +Quadrant 3 (Point): Todoist, Basecamp, Trello +Quadrant 4 (Platforms): Notion, ClickUp, Microsoft Planner + +Your Position: [X] +Desired Position: [→ direction of strategic movement] +``` + +**Building a Landscape Map:** + +1. Select two dimensions that represent the most important strategic trade-offs in the market +2. Commonly used axes: + - Price / Complexity + - Breadth of platform / Depth of solution + - Enterprise / SMB focus + - Horizontal / Vertical specialization + - Self-serve / High-touch +3. Plot all known competitors (minimum 8-10 for useful map) +4. Identify white space — under-served quadrant combinations +5. Draw your strategic vector — where are you moving and why? + +### Technology Adoption Lifecycle Positioning + +``` +THE ADOPTION CURVE: + + Innovators Early Early Late Laggards + (2.5%) Adopters Majority Majority (16%) + (13.5%) (34%) (34%) + ___ + / \ + / \____ + / \________ + / \_________ +/ \___ + + ↑ ↑ + THE CHASM MAINSTREAM + (biggest (revenue + risk point) acceleration) +``` + +**Positioning by Stage:** + +| Stage | Customer Profile | Sales Approach | Pricing Strategy | Key Risk | +|-------|-----------------|----------------|------------------|----------| +| Innovators | Tech enthusiasts; will tolerate bugs | Community; direct outreach | Free/very low; usage-based | Building for wrong use case | +| Early Adopters | Visionaries; want competitive advantage | Consultative selling; pilots | Value-based; ROI-justified | Chasm — can't cross to mainstream | +| Early Majority | Pragmatists; want proven solutions | References; case studies; demos | Competitive; published pricing | Scaling sales and support | +| Late Majority | Conservatives; want complete solutions | Standard procurement; RFPs | Bundled; enterprise agreements | Margin compression | +| Laggards | Skeptics; forced by circumstance | Compliance-driven; mandates | Legacy pricing; long contracts | Market is commoditizing | + +**Chasm-Crossing Checklist:** +``` +□ Whole product: Does the product solve the complete use case without workarounds? +□ References: Do you have 3-5 referenceable customers in the target segment? +□ Repeatability: Can you sell and implement without founder involvement? +□ Support: Can you support customers at scale (not just white-glove)? +□ Positioning: Is the messaging pragmatist-friendly (ROI, risk reduction) not visionary? +□ Competition: Have you defined the competitive set for pragmatist comparison? +□ Pricing: Is pricing simple, transparent, and aligned with buyer expectations? +``` + +### Value Chain Analysis + +Decompose industry activities to find competitive advantage: + +``` +VALUE CHAIN: [Industry] + +PRIMARY ACTIVITIES: +┌─────────────┬──────────────┬──────────────┬──────────────┬──────────────┐ +│ Inbound │ Operations │ Outbound │ Marketing │ Service │ +│ Logistics │ │ Logistics │ & Sales │ │ +├─────────────┼──────────────┼──────────────┼──────────────┼──────────────┤ +│ Sourcing │ Production │ Distribution │ Branding │ Support │ +│ Inventory │ Quality │ Delivery │ Pricing │ Maintenance │ +│ Supplier │ Assembly │ Warehousing │ Channel mgmt │ Returns │ +│ management │ Testing │ Order mgmt │ Positioning │ Training │ +└─────────────┴──────────────┴──────────────┴──────────────┴──────────────┘ + +SUPPORT ACTIVITIES: +┌──────────────────────────────────────────────────────────────────────────┐ +│ Infrastructure: Finance, Legal, Management, Planning │ +│ Human Resources: Recruiting, Training, Compensation, Culture │ +│ Technology: R&D, IT systems, Automation, Data analytics │ +│ Procurement: Vendor selection, Negotiation, Contract management │ +└──────────────────────────────────────────────────────────────────────────┘ +``` + +**Analysis Process:** + +``` +For each activity: + 1. Cost: What % of total cost does this activity represent? + 2. Value: How much does this activity contribute to customer willingness-to-pay? + 3. Capability: Rate your performance vs competitors (1-5) + 4. Strategic importance: Is this a source of differentiation? (Yes/No) + +Activity | Cost % | Value Contribution | Capability | Differentiator? +---------------------|--------|-------------------|------------|---------------- +Inbound logistics | 15% | Low | 3/5 | No +Operations | 25% | High | 4/5 | Yes +Outbound logistics | 10% | Medium | 3/5 | No +Marketing & Sales | 30% | High | 2/5 | Needs improvement +Service | 20% | High | 5/5 | Yes + +Strategic Implications: + - Invest: Operations (current strength + high value) and Service (strength to protect) + - Improve: Marketing & Sales (high cost + low capability = drag on growth) + - Optimize: Logistics (non-differentiating — minimize cost) +``` + +**SaaS-Specific Value Chain:** + +``` +┌────────────┬───────────────┬──────────────┬────────────────┬─────────────┐ +│ Product │ Customer │ Customer │ Customer │ Expansion │ +│ Development│ Acquisition │ Onboarding │ Success │ & Retention │ +├────────────┼───────────────┼──────────────┼────────────────┼─────────────┤ +│ R&D │ Marketing │ Implementation│ Support │ Upsell │ +│ Design │ Sales │ Training │ Account mgmt │ Cross-sell │ +│ QA │ Partnerships │ Migration │ Health scoring │ Renewals │ +│ Platform │ Growth/PLG │ Integration │ Community │ Advocacy │ +└────────────┴───────────────┴──────────────┴────────────────┴─────────────┘ + +Key insight for SaaS: The majority of LTV is created AFTER the initial sale. +Disproportionate investment should go to Onboarding → Success → Expansion. +``` diff --git a/hands/trader/HAND.toml b/hands/trader/HAND.toml index ba458a4..233263f 100644 --- a/hands/trader/HAND.toml +++ b/hands/trader/HAND.toml @@ -781,6 +781,337 @@ default_active = false # Warning shown when user tries to activate activation_warning = "Trading hand runs continuously and consumes tokens. Deactivate when not trading." +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "交易 Hand" description = "自主市场情报与交易引擎——多信号分析、对抗性多空推理、校准置信度评分、严格风控和投资组合分析" +category = "数据" + +[i18n.zh.settings.trading_mode] +label = "交易模式" +description = "交易 Hand 的运行方式——仅分析、模拟交易或实盘交易" + +[i18n.zh.settings.market_focus] +label = "市场关注" +description = "监控和交易的目标市场" + +[i18n.zh.settings.strategy_style] +label = "策略风格" +description = "交易时间框架和策略类型" + +[i18n.zh.settings.risk_per_trade] +label = "单笔风险" +description = "单笔交易允许承受的最大仓位占比" + +[i18n.zh.settings.max_daily_loss] +label = "单日最大亏损" +description = "触发熔断机制的每日最大允许亏损比例" + +[i18n.zh.settings.analysis_depth] +label = "分析深度" +description = "每个标的收集和交叉验证的信号数量" + +[i18n.zh.settings.scan_schedule] +label = "扫描频率" +description = "扫描市场和更新分析的频率" + +[i18n.zh.settings.watchlist] +label = "关注列表" +description = "要监控的标的代码列表(逗号分隔,股票: AAPL,加密货币: BTC,ETF: SPY)" + +[i18n.zh.settings.initial_capital] +label = "初始资金" +description = "模拟交易或追踪的起始投资组合金额(美元)" + +[i18n.zh.settings.alpaca_api_key] +label = "Alpaca API 密钥" +description = "用于实盘/模拟交易的 Alpaca API 密钥(可在 alpaca.markets 免费获取)" + +[i18n.zh.settings.alpaca_secret_key] +label = "Alpaca Secret 密钥" +description = "Alpaca API 的 Secret 密钥" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "执行实盘交易前需要用户明确审批——强烈建议开启" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Trading" +description = "Motor autónomo de inteligencia de mercado y trading — análisis multi-señal, razonamiento adversarial alcista/bajista, puntuación de confianza calibrada, gestión de riesgo estricta y analítica de cartera" +category = "Datos" + +[i18n.es.settings.trading_mode] +label = "Modo de trading" +description = "Cómo opera el Hand de Trading — solo análisis, trading simulado o trading real" + +[i18n.es.settings.market_focus] +label = "Enfoque de mercado" +description = "Qué mercados monitorear y operar" + +[i18n.es.settings.strategy_style] +label = "Estilo de estrategia" +description = "Marco temporal y enfoque de la estrategia de trading" + +[i18n.es.settings.risk_per_trade] +label = "Riesgo por operación" +description = "Porcentaje máximo de la cartera en riesgo en una sola operación" + +[i18n.es.settings.max_daily_loss] +label = "Pérdida diaria máxima" +description = "Porcentaje máximo de pérdida diaria de la cartera antes de activar el disyuntor" + +[i18n.es.settings.analysis_depth] +label = "Profundidad del análisis" +description = "Cuántas señales recopilar y cruzar por activo" + +[i18n.es.settings.scan_schedule] +label = "Frecuencia de escaneo" +description = "Con qué frecuencia escanear los mercados y actualizar el análisis" + +[i18n.es.settings.watchlist] +label = "Lista de seguimiento" +description = "Lista de tickers a monitorear separados por comas (acciones: AAPL, cripto: BTC, ETFs: SPY)" + +[i18n.es.settings.initial_capital] +label = "Capital inicial" +description = "Valor inicial de la cartera para trading simulado o seguimiento (en USD)" + +[i18n.es.settings.alpaca_api_key] +label = "Clave API de Alpaca" +description = "Clave API de Alpaca para trading real/simulado (obtener gratis en alpaca.markets)" + +[i18n.es.settings.alpaca_secret_key] +label = "Clave secreta de Alpaca" +description = "Clave secreta de la API de Alpaca" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Requerir aprobación explícita del usuario antes de ejecutar cualquier operación real — altamente recomendado" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "トレーディング Hand" +description = "自律型マーケットインテリジェンス&トレーディングエンジン——マルチシグナル分析、対立的ブル/ベア推論、キャリブレーション済み信頼度スコアリング、厳格なリスク管理、ポートフォリオ分析" +category = "データ" + +[i18n.ja.settings.trading_mode] +label = "トレーディングモード" +description = "トレーディングHandの動作方式——分析のみ、ペーパートレード、またはライブトレード" + +[i18n.ja.settings.market_focus] +label = "マーケットフォーカス" +description = "監視・取引する対象市場" + +[i18n.ja.settings.strategy_style] +label = "戦略スタイル" +description = "取引の時間軸と戦略アプローチ" + +[i18n.ja.settings.risk_per_trade] +label = "1トレードあたりのリスク" +description = "1回の取引でリスクにさらすポートフォリオの最大割合" + +[i18n.ja.settings.max_daily_loss] +label = "1日の最大損失" +description = "サーキットブレーカーが作動するまでの1日あたりの最大損失割合" + +[i18n.ja.settings.analysis_depth] +label = "分析の深さ" +description = "銘柄ごとに収集・クロスリファレンスするシグナルの数" + +[i18n.ja.settings.scan_schedule] +label = "スキャンスケジュール" +description = "市場スキャンと分析更新の頻度" + +[i18n.ja.settings.watchlist] +label = "ウォッチリスト" +description = "監視するティッカーのリスト(カンマ区切り、株式: AAPL、暗号通貨: BTC、ETF: SPY)" + +[i18n.ja.settings.initial_capital] +label = "初期資金" +description = "ペーパートレードまたはトラッキングの開始ポートフォリオ額(USD)" + +[i18n.ja.settings.alpaca_api_key] +label = "Alpaca APIキー" +description = "ライブ/ペーパートレード用のAlpaca APIキー(alpaca.marketsで無料取得可能)" + +[i18n.ja.settings.alpaca_secret_key] +label = "Alpaca Secretキー" +description = "Alpaca APIのSecretキー" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "ライブトレード実行前にユーザーの明示的な承認を必要とする——強く推奨" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand de Trading" +description = "Moteur autonome d'intelligence de marché et de trading — analyse multi-signaux, raisonnement adversarial haussier/baissier, score de confiance calibré, gestion stricte des risques et analytique de portefeuille" +category = "Données" + +[i18n.fr.settings.trading_mode] +label = "Mode de trading" +description = "Mode de fonctionnement du Hand de Trading — analyse seule, trading simulé ou trading réel" + +[i18n.fr.settings.market_focus] +label = "Focus marché" +description = "Quels marchés surveiller et sur lesquels opérer" + +[i18n.fr.settings.strategy_style] +label = "Style de stratégie" +description = "Horizon temporel et approche de la stratégie de trading" + +[i18n.fr.settings.risk_per_trade] +label = "Risque par opération" +description = "Pourcentage maximum du portefeuille en risque sur une seule opération" + +[i18n.fr.settings.max_daily_loss] +label = "Perte quotidienne maximale" +description = "Pourcentage maximum de perte quotidienne du portefeuille avant déclenchement du coupe-circuit" + +[i18n.fr.settings.analysis_depth] +label = "Profondeur d'analyse" +description = "Nombre de signaux à collecter et recouper par actif" + +[i18n.fr.settings.scan_schedule] +label = "Fréquence de scan" +description = "Fréquence de scan des marchés et de mise à jour de l'analyse" + +[i18n.fr.settings.watchlist] +label = "Liste de surveillance" +description = "Liste de tickers à surveiller séparés par des virgules (actions : AAPL, crypto : BTC, ETF : SPY)" + +[i18n.fr.settings.initial_capital] +label = "Capital initial" +description = "Valeur initiale du portefeuille pour le trading simulé ou le suivi (en USD)" + +[i18n.fr.settings.alpaca_api_key] +label = "Clé API Alpaca" +description = "Clé API Alpaca pour le trading réel/simulé (obtenir gratuitement sur alpaca.markets)" + +[i18n.fr.settings.alpaca_secret_key] +label = "Clé secrète Alpaca" +description = "Clé secrète de l'API Alpaca" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Exiger l'approbation explicite de l'utilisateur avant d'exécuter toute opération réelle — fortement recommandé" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Trading-Hand" +description = "Autonomer Marktintelligenz- und Trading-Motor — Multi-Signal-Analyse, adversariales Bull/Bear-Reasoning, kalibriertes Konfidenz-Scoring, striktes Risikomanagement und Portfolio-Analytik" +category = "Daten" + +[i18n.de.settings.trading_mode] +label = "Trading-Modus" +description = "Betriebsmodus des Trading-Hand — nur Analyse, simuliertes Trading oder Live-Trading" + +[i18n.de.settings.market_focus] +label = "Marktfokus" +description = "Welche Märkte überwacht und gehandelt werden" + +[i18n.de.settings.strategy_style] +label = "Strategiestil" +description = "Zeithorizont und Ansatz der Handelsstrategie" + +[i18n.de.settings.risk_per_trade] +label = "Risiko pro Trade" +description = "Maximaler Prozentsatz des Portfolios, der bei einem einzelnen Trade riskiert wird" + +[i18n.de.settings.max_daily_loss] +label = "Maximaler Tagesverlust" +description = "Maximaler täglicher Portfolioverlust in Prozent, bevor der Circuit Breaker auslöst" + +[i18n.de.settings.analysis_depth] +label = "Analysetiefe" +description = "Anzahl der pro Asset zu sammelnden und gegenzuprüfenden Signale" + +[i18n.de.settings.scan_schedule] +label = "Scan-Zeitplan" +description = "Wie oft Märkte gescannt und Analysen aktualisiert werden" + +[i18n.de.settings.watchlist] +label = "Watchlist" +description = "Kommagetrennte Liste der zu überwachenden Ticker (Aktien: AAPL, Krypto: BTC, ETFs: SPY)" + +[i18n.de.settings.initial_capital] +label = "Anfangskapital" +description = "Anfänglicher Portfoliowert für simuliertes Trading oder Tracking (in USD)" + +[i18n.de.settings.alpaca_api_key] +label = "Alpaca API-Schlüssel" +description = "Alpaca API-Schlüssel für Live-/Papierhandel (kostenlos auf alpaca.markets erhältlich)" + +[i18n.de.settings.alpaca_secret_key] +label = "Alpaca Secret-Schlüssel" +description = "Secret-Schlüssel der Alpaca API" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Ausdrückliche Benutzergenehmigung vor der Ausführung von Live-Trades erforderlich — dringend empfohlen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "트레이딩 Hand" +description = "자율 시장 인텔리전스 및 트레이딩 엔진 — 다중 신호 분석, 대립적 매수/매도 추론, 보정된 신뢰도 평가, 엄격한 리스크 관리 및 포트폴리오 분석" +category = "데이터" + +[i18n.ko.settings.trading_mode] +label = "트레이딩 모드" +description = "트레이딩 Hand의 운영 방식 — 분석 전용, 모의 거래 또는 실거래" + +[i18n.ko.settings.market_focus] +label = "시장 관심" +description = "모니터링 및 거래할 대상 시장" + +[i18n.ko.settings.strategy_style] +label = "전략 스타일" +description = "거래 시간 프레임 및 전략 유형" + +[i18n.ko.settings.risk_per_trade] +label = "거래당 리스크" +description = "단일 거래에서 허용되는 최대 포트폴리오 비율" + +[i18n.ko.settings.max_daily_loss] +label = "일일 최대 손실" +description = "서킷 브레이커 발동 전 허용되는 일일 최대 손실 비율" + +[i18n.ko.settings.analysis_depth] +label = "분석 깊이" +description = "자산별 수집 및 교차 검증할 신호 수" + +[i18n.ko.settings.scan_schedule] +label = "스캔 일정" +description = "시장 스캔 및 분석 업데이트 주기" + +[i18n.ko.settings.watchlist] +label = "관심 목록" +description = "모니터링할 종목 코드 목록 (쉼표로 구분, 주식: AAPL, 암호화폐: BTC, ETF: SPY)" + +[i18n.ko.settings.initial_capital] +label = "초기 자본" +description = "모의 거래 또는 추적을 위한 시작 포트폴리오 금액 (USD)" + +[i18n.ko.settings.alpaca_api_key] +label = "Alpaca API 키" +description = "실거래/모의 거래용 Alpaca API 키 (alpaca.markets에서 무료 발급)" + +[i18n.ko.settings.alpaca_secret_key] +label = "Alpaca 시크릿 키" +description = "Alpaca API 시크릿 키" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "실거래 실행 전 사용자의 명시적 승인 필요 — 강력히 권장" diff --git a/hands/twitter/HAND.toml b/hands/twitter/HAND.toml index fc6f4dc..e0f11c0 100644 --- a/hands/twitter/HAND.toml +++ b/hands/twitter/HAND.toml @@ -526,6 +526,313 @@ frequency = "hourly" token_consumption = "medium" default_active = false +# ─── Internationalization (optional) ───────────────────────────────────────── +# All i18n sections are optional. Without them, the English values above are used. +# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de). +# Settings translations are also optional — omit to keep English labels. + +# ─── Chinese (简体中文) ──────────────────────────────────────────────────── + [i18n.zh] name = "Twitter Hand" description = "自主 Twitter/X 管理——内容创作、定时发布、互动管理和效果追踪" +category = "通信" + +[i18n.zh.settings.twitter_bearer_token] +label = "Twitter Bearer Token" +description = "Twitter/X 开发者平台的 Bearer Token,所有 Twitter API 操作均需此凭证。" + +[i18n.zh.settings.twitter_style] +label = "内容风格" +description = "推文的语气和风格" + +[i18n.zh.settings.post_frequency] +label = "发布频率" +description = "创建和发布内容的频率" + +[i18n.zh.settings.auto_reply] +label = "自动回复" +description = "自动回复提及和相关对话" + +[i18n.zh.settings.auto_like] +label = "自动点赞" +description = "自动为人脉网络中的推文和相关内容点赞" + +[i18n.zh.settings.content_topics] +label = "内容主题" +description = "要创作内容的主题(逗号分隔,例如 AI、创业、效率提升)" + +[i18n.zh.settings.brand_voice] +label = "品牌调性" +description = "描述你的独特风格(例如"用幽默简化复杂技术的创业者")" + +[i18n.zh.settings.thread_mode] +label = "推文串模式" +description = "在内容组合中加入推文串(多条推文组成的故事)" + +[i18n.zh.settings.content_queue_size] +label = "内容队列大小" +description = "待发队列中保持的推文数量" + +[i18n.zh.settings.engagement_hours] +label = "互动时段" +description = "检查提及和互动的时间段" + +[i18n.zh.settings.approval_mode] +label = "审批模式" +description = "将推文写入队列等待审核,而非直接发布" + +# ─── Spanish (Español) ──────────────────────────────────────────────────── + +[i18n.es] +name = "Hand de Twitter" +description = "Gestor autónomo de Twitter/X — creación de contenido, publicación programada, interacciones y seguimiento de rendimiento" +category = "Comunicación" + +[i18n.es.settings.twitter_bearer_token] +label = "Token Bearer de Twitter" +description = "Token Bearer del Portal de Desarrolladores de Twitter/X. Requerido para todas las operaciones de la API de Twitter." + +[i18n.es.settings.twitter_style] +label = "Estilo de contenido" +description = "Voz y tono para tus tweets" + +[i18n.es.settings.post_frequency] +label = "Frecuencia de publicación" +description = "Con qué frecuencia crear y publicar contenido" + +[i18n.es.settings.auto_reply] +label = "Respuesta automática" +description = "Responder automáticamente a menciones y conversaciones relevantes" + +[i18n.es.settings.auto_like] +label = "Me gusta automático" +description = "Dar me gusta automáticamente a tweets de tu red y contenido relevante" + +[i18n.es.settings.content_topics] +label = "Temas de contenido" +description = "Temas sobre los que crear contenido (separados por comas, ej. IA, startups, productividad)" + +[i18n.es.settings.brand_voice] +label = "Voz de marca" +description = "Describe tu voz única (ej. 'fundador sarcástico que simplifica la tecnología compleja')" + +[i18n.es.settings.thread_mode] +label = "Modo de hilos" +description = "Incluir hilos de tweets (historias de múltiples tweets) en la mezcla de contenido" + +[i18n.es.settings.content_queue_size] +label = "Tamaño de la cola de contenido" +description = "Número de tweets a mantener en la cola preparada" + +[i18n.es.settings.engagement_hours] +label = "Horario de interacción" +description = "Cuándo verificar menciones e interactuar" + +[i18n.es.settings.approval_mode] +label = "Modo de aprobación" +description = "Escribir los tweets en un archivo de cola para revisión en lugar de publicarlos directamente" + +# ─── Japanese (日本語) ──────────────────────────────────────────────────── + +[i18n.ja] +name = "Twitter Hand" +description = "自律型Twitter/Xマネージャー——コンテンツ作成、スケジュール投稿、エンゲージメント管理、パフォーマンス追跡" +category = "コミュニケーション" + +[i18n.ja.settings.twitter_bearer_token] +label = "Twitter Bearerトークン" +description = "Twitter/X開発者ポータルのBearerトークン。すべてのTwitter API操作に必要です。" + +[i18n.ja.settings.twitter_style] +label = "コンテンツスタイル" +description = "ツイートの語調とスタイル" + +[i18n.ja.settings.post_frequency] +label = "投稿頻度" +description = "コンテンツの作成・投稿の頻度" + +[i18n.ja.settings.auto_reply] +label = "自動返信" +description = "メンションや関連する会話に自動で返信する" + +[i18n.ja.settings.auto_like] +label = "自動いいね" +description = "ネットワーク内のツイートや関連コンテンツに自動でいいねする" + +[i18n.ja.settings.content_topics] +label = "コンテンツトピック" +description = "作成するコンテンツのトピック(カンマ区切り、例: AI、スタートアップ、生産性)" + +[i18n.ja.settings.brand_voice] +label = "ブランドボイス" +description = "あなた独自の語り口を記述(例:「複雑なテクノロジーをわかりやすく伝える皮肉屋の起業家」)" + +[i18n.ja.settings.thread_mode] +label = "スレッドモード" +description = "コンテンツミックスにツイートスレッド(複数ツイートで構成するストーリー)を含める" + +[i18n.ja.settings.content_queue_size] +label = "コンテンツキューサイズ" +description = "準備キューに保持するツイートの数" + +[i18n.ja.settings.engagement_hours] +label = "エンゲージメント時間帯" +description = "メンションの確認とエンゲージメントを行う時間帯" + +[i18n.ja.settings.approval_mode] +label = "承認モード" +description = "ツイートを直接投稿せず、レビュー用のキューファイルに書き出す" + +# ─── French (Français) ──────────────────────────────────────────────────── + +[i18n.fr] +name = "Hand Twitter" +description = "Gestionnaire Twitter/X autonome — création de contenu, publication programmée, interactions et suivi des performances" +category = "Communication" + +[i18n.fr.settings.twitter_bearer_token] +label = "Jeton Bearer Twitter" +description = "Jeton Bearer du Portail Développeurs Twitter/X. Requis pour toutes les opérations de l'API Twitter." + +[i18n.fr.settings.twitter_style] +label = "Style de contenu" +description = "Ton et style pour vos tweets" + +[i18n.fr.settings.post_frequency] +label = "Fréquence de publication" +description = "Fréquence de création et de publication de contenu" + +[i18n.fr.settings.auto_reply] +label = "Réponse automatique" +description = "Répondre automatiquement aux mentions et conversations pertinentes" + +[i18n.fr.settings.auto_like] +label = "Like automatique" +description = "Aimer automatiquement les tweets de votre réseau et le contenu pertinent" + +[i18n.fr.settings.content_topics] +label = "Sujets de contenu" +description = "Sujets sur lesquels créer du contenu (séparés par des virgules, ex. IA, startups, productivité)" + +[i18n.fr.settings.brand_voice] +label = "Voix de marque" +description = "Décrivez votre voix unique (ex. 'fondateur sarcastique qui simplifie la technologie complexe')" + +[i18n.fr.settings.thread_mode] +label = "Mode fil de discussion" +description = "Inclure des fils de tweets (histoires à plusieurs tweets) dans le mix de contenu" + +[i18n.fr.settings.content_queue_size] +label = "Taille de la file de contenu" +description = "Nombre de tweets à maintenir dans la file d'attente préparée" + +[i18n.fr.settings.engagement_hours] +label = "Heures d'engagement" +description = "Quand vérifier les mentions et interagir" + +[i18n.fr.settings.approval_mode] +label = "Mode d'approbation" +description = "Écrire les tweets dans un fichier d'attente pour révision au lieu de les publier directement" + +# ─── German (Deutsch) ──────────────────────────────────────────────────── + +[i18n.de] +name = "Twitter-Hand" +description = "Autonomer Twitter/X-Manager — Content-Erstellung, geplante Veröffentlichung, Engagement-Management und Performance-Tracking" +category = "Kommunikation" + +[i18n.de.settings.twitter_bearer_token] +label = "Twitter Bearer-Token" +description = "Bearer-Token vom Twitter/X-Entwicklerportal. Erforderlich für alle Twitter-API-Operationen." + +[i18n.de.settings.twitter_style] +label = "Inhaltsstil" +description = "Ton und Stil für Ihre Tweets" + +[i18n.de.settings.post_frequency] +label = "Veröffentlichungshäufigkeit" +description = "Wie oft Inhalte erstellt und veröffentlicht werden" + +[i18n.de.settings.auto_reply] +label = "Automatische Antwort" +description = "Automatisch auf Erwähnungen und relevante Gespräche antworten" + +[i18n.de.settings.auto_like] +label = "Automatisches Like" +description = "Tweets im Netzwerk und relevante Inhalte automatisch liken" + +[i18n.de.settings.content_topics] +label = "Inhaltsthemen" +description = "Themen für die Content-Erstellung (kommagetrennt, z.B. KI, Startups, Produktivität)" + +[i18n.de.settings.brand_voice] +label = "Markenstimme" +description = "Beschreiben Sie Ihre einzigartige Stimme (z.B. 'sarkastischer Gründer, der komplexe Technologie vereinfacht')" + +[i18n.de.settings.thread_mode] +label = "Thread-Modus" +description = "Tweet-Threads (mehrteilige Tweet-Geschichten) in den Content-Mix aufnehmen" + +[i18n.de.settings.content_queue_size] +label = "Größe der Content-Warteschlange" +description = "Anzahl der Tweets in der vorbereiteten Warteschlange" + +[i18n.de.settings.engagement_hours] +label = "Engagement-Zeiten" +description = "Wann Erwähnungen geprüft und interagiert werden soll" + +[i18n.de.settings.approval_mode] +label = "Genehmigungsmodus" +description = "Tweets in eine Warteschlangendatei zur Überprüfung schreiben, anstatt sie direkt zu veröffentlichen" + +# ─── Korean (한국어) ──────────────────────────────────────────────────── + +[i18n.ko] +name = "Twitter Hand" +description = "자율 Twitter/X 관리 — 콘텐츠 제작, 예약 게시, 소통 관리 및 성과 추적" +category = "커뮤니케이션" + +[i18n.ko.settings.twitter_bearer_token] +label = "Twitter Bearer 토큰" +description = "Twitter/X 개발자 포털의 Bearer 토큰. 모든 Twitter API 작업에 필수." + +[i18n.ko.settings.twitter_style] +label = "콘텐츠 스타일" +description = "트윗의 어조와 스타일" + +[i18n.ko.settings.post_frequency] +label = "게시 빈도" +description = "콘텐츠를 작성하고 게시하는 주기" + +[i18n.ko.settings.auto_reply] +label = "자동 답글" +description = "멘션 및 관련 대화에 자동으로 답글 작성" + +[i18n.ko.settings.auto_like] +label = "자동 좋아요" +description = "네트워크 내 트윗 및 관련 콘텐츠에 자동으로 좋아요" + +[i18n.ko.settings.content_topics] +label = "콘텐츠 주제" +description = "콘텐츠를 작성할 주제 (쉼표로 구분, 예: AI, 스타트업, 생산성)" + +[i18n.ko.settings.brand_voice] +label = "브랜드 보이스" +description = "고유한 스타일을 설명 (예: '복잡한 기술을 쉽게 풀어내는 유머러스한 창업자')" + +[i18n.ko.settings.thread_mode] +label = "스레드 모드" +description = "콘텐츠 구성에 트윗 스레드 (다중 트윗 스토리) 포함" + +[i18n.ko.settings.content_queue_size] +label = "콘텐츠 대기열 크기" +description = "준비 대기열에 유지할 트윗 수" + +[i18n.ko.settings.engagement_hours] +label = "소통 시간대" +description = "멘션 확인 및 소통 활동을 수행하는 시간대" + +[i18n.ko.settings.approval_mode] +label = "승인 모드" +description = "트윗을 직접 게시하지 않고 대기열 파일에 기록하여 검토" diff --git a/hands/twitter/SKILL.md b/hands/twitter/SKILL.md index b949f79..9278bae 100644 --- a/hands/twitter/SKILL.md +++ b/hands/twitter/SKILL.md @@ -226,6 +226,72 @@ Do NOT auto-like: --- +## Advanced Engagement Patterns + +### Quote Tweet vs Reply vs Retweet + +Choosing the right interaction type determines whether you gain visibility or waste it. + +**Use a Quote Tweet when**: +- You have a distinct take or added context (not just "this!") +- The original tweet has high impressions and you want to draft off its reach +- You are crediting someone while adding your own insight for your audience +- The original author has a similar or larger following (exposes you to their audience) + +**Use a Reply when**: +- You want to build a direct relationship with the author +- Your comment only makes sense in context of the original +- The original author has a much larger following (replies show on their thread, giving you visibility without looking self-promotional) +- You are answering a question or adding a correction + +**Use a plain Retweet when**: +- The original says everything perfectly and you have nothing to add +- You want to signal-boost a community member, customer, or partner +- The content is time-sensitive (breaking news, event announcements) + +**Avoid**: +- Quote tweeting with only emojis or "this" -- adds no value, looks lazy +- Quote tweeting someone with fewer followers just to dunk -- punching down +- Retweeting more than 3-4 times per day -- dilutes your original content ratio + +### Thread Repurposing + +A thread that performed well contains 5-7 standalone content pieces. Extract them over the following week to maximize ROI. + +**Process**: +1. Day 0 (original): Post the full thread +2. Day 2: Pull the single most quotable tweet from the thread. Post it standalone with slightly different wording. No link back to the thread +3. Day 4: Turn a data point or example from the thread into a graphic or screenshot tweet +4. Day 6: Post the thread's core thesis as a hot take (one tweet, punchy) +5. Day 8+: If engagement stayed strong, post a "Part 2" thread that goes deeper on whichever tweet in the original got the most replies + +**Rules**: +- Change the wording each time -- copy-pasting feels like spam to followers who saw the original +- Space extractions at least 48 hours apart +- Stop if any extraction underperforms significantly -- the topic is tapped out +- Never repurpose a thread that got low engagement; the content did not resonate + +### Trending Topic Participation + +**When to participate**: +- The trend directly intersects one of your content pillars +- You have a genuine, informed perspective (not a generic reaction) +- The trend is still rising (check the "Trending" tab; if it has been trending for >12 hours, you are late) +- The tone of the trend matches your brand voice + +**When to avoid**: +- Tragedy, disaster, or crisis events -- opportunistic posting destroys trust +- Highly polarized political or social debates outside your expertise +- Trends driven by outrage mobs -- associating your brand is high-risk, low-reward +- You would need to force-fit your product or message into the trend + +**Execution**: +- Lead with your actual insight, not the hashtag. The hashtag goes at the end or is omitted entirely if the topic keyword is in your text +- Be early or be different. If 50 people have already made the same joke, skip it +- Tie back to your pillar: "Trend X is exactly why [your pillar topic] matters more than ever" + +--- + ## Content Calendar Template ``` @@ -254,6 +320,169 @@ Friday: --- +## Worked Examples + +### Example 1: Product Launch Twitter Campaign (1-Week Plan) + +**Context**: A dev tools startup is launching "FastDB," an open-source embedded database. The account has 2,400 followers, mostly backend engineers. + +**Pre-launch (3 days before)**: +- Seed curiosity without revealing the product name +- Engage heavily in database-related threads to increase profile visits before launch + +**Day 1 (Monday) -- Teaser**: +``` +We've been heads-down for 8 months building something +we think embedded databases have been missing. + +Shipping it open-source this Thursday. + +More soon. +``` +Purpose: Create anticipation. No hashtags, no links. Let curiosity drive profile visits. + +**Day 2 (Tuesday) -- Problem framing**: +``` +SQLite is incredible for what it does. + +But if you need concurrent writes, ACID transactions, +AND sub-millisecond reads in the same embedded DB... +your options get thin fast. + +We've been living in that gap. Fix incoming Thursday. +``` +Purpose: Define the problem space. People who feel this pain will follow for the reveal. + +**Day 3 (Wednesday) -- Social proof / build-up**: +``` +Shipped our embedded DB to 12 beta testers last month. + +Results so far: +- 4.2x faster concurrent writes vs SQLite WAL mode +- Zero-config replication +- Single static binary, 3.8 MB + +One more day. +``` +Purpose: Concrete numbers build credibility. "One more day" maintains tension. + +**Day 4 (Thursday) -- Launch day thread** (6-tweet thread): +``` +1/6 [HOOK]: Introducing FastDB -- embedded DB for concurrent-write-heavy + workloads. Open source. Single binary. Here's why we built it: +2/6 [PROBLEM]: SQLite = single-writer. Fine for reads, hits a wall on + write-heavy apps (event logging, IoT, realtime sync). FastDB uses + MVCC -- writers never block readers, readers never block writers. +3/6 [PROOF]: Benchmarks (M2 Mac, 8 threads): concurrent writes 51K ops/s + vs SQLite WAL 12K ops/s. Point reads on par at ~900K ops/s. +4/6 [ONBOARD]: Getting started: `cargo add fastdb` then 3 lines of code. + Full SQLite-compatible query layer coming in v0.2. +5/6 [ROADMAP]: v0.1 ships ACID transactions, built-in replication, crash + recovery, zero deps beyond libc. v0.2: SQL layer, S3 cold storage. +6/6 [CTA]: Star the repo: github.com/example/fastdb -- open issues, roast + the benchmarks, tell us what's missing. +``` +Key structural choices: tweet 1 is a standalone hook, tweet 3 has hard numbers, tweet 6 ends with a specific ask (not just "check it out"). + +**Day 4 afternoon** -- Post a standalone tweet answering the most common reply question publicly (drives docs traffic). **Day 5 (Friday)** -- Reply to every substantive comment. Templates for common reactions: +- "How is this different from X?" -> Concrete comparison, link to docs +- "Benchmarks look suspicious" -> Link the reproduction steps, invite them to run it +- "Will you support [feature]?" -> Link the tracking issue + +**Day 6-7 (Weekend)** -- Repurpose: extract the benchmark tweet as a standalone with a chart image; post a "5 things I learned launching an open-source DB" reflection thread. + +### Example 2: Building Thought Leadership from Scratch (Month 1) + +**Context**: An individual ML engineer with 180 followers wants to become a recognized voice in applied machine learning. No existing audience. No viral content history. + +**Core principle for month 1**: Do not broadcast. Contribute. Your first 500 followers come from being consistently useful in other people's threads, not from your own tweets. + +**Week 1 -- Comment-first growth**: +- Post 0 original tweets +- Find 10 accounts in your niche with 5K-50K followers who post regularly +- Reply to 5-8 of their tweets per day with substantive comments (not "great post!") +- Goal: Get 3-5 of those authors to like or reply to your comments by end of week + +**What a good reply looks like**: +``` +Original tweet: "Fine-tuning LLMs is overrated. Most use cases +are better served by good prompting + RAG." + +Bad reply: "Agreed!" + +Good reply: "Mostly agree, but there's a middle ground -- +LoRA fine-tuning on 500 domain-specific examples +consistently beats RAG for structured extraction tasks. + +We saw 23% higher F1 on invoice parsing after a 2-hour +fine-tune vs our best RAG setup. + +RAG still wins for open-domain QA though." +``` +This reply adds data, shows experience, and invites further discussion. People reading the thread see your expertise and check your profile. + +**Week 2 -- First original content**: +- Continue the reply strategy (5/day minimum) +- Post 2-3 original tweets. Keep them observational, not promotional: +``` +Something I've noticed after fine-tuning 30+ models +this year: + +The quality of your eval set matters 10x more than +the size of your training set. + +50 carefully labeled examples with clear edge cases +beats 5000 noisy scraped examples every time. +``` +- Post 1 "ask the audience" tweet to start conversations: +``` +ML engineers: what's the most counterintuitive lesson +you've learned about deploying models to production? + +I'll start: the model is almost never the bottleneck. +Data pipelines are. +``` + +**Week 3 -- First thread** (5-tweet authority thread): +``` +1/5 [HOOK]: I've deployed 12 ML models to production this year. The ones + that worked all had one thing in common. It wasn't the architecture. +2/5 [THESIS]: Every success had a tight feedback loop -- predictions + validated by a human within 24 hours, not "we'll evaluate next quarter." +3/5 [EVIDENCE]: Model A (invoice classifier): accountants flagged errors + same-day, retrained weekly, 84% -> 97% in 6 weeks. Model B (churn + predictor): sales ignored outputs, no feedback 3 months, drifted to + coin-flip accuracy. +4/5 [FRAMEWORK]: The pattern: (1) deploy with human-in-the-loop review, + (2) log every correction, (3) retrain on corrections every 1-2 weeks, + (4) remove human review once accuracy stabilizes. +5/5 [CTA]: If you're skipping the feedback loop, you're building on sand. + What's your experience? +``` +Notice the structure: personal credibility in tweet 1, a clear thesis in tweet 2, contrasting real examples in tweet 3, an actionable takeaway in tweet 4, and a discussion prompt in tweet 5. + +**Week 4 -- Establish rhythm**: +- Settle into a sustainable cadence: 1 thread/week, 1-2 standalone tweets/day, 5+ replies/day +- Review metrics from week 2-3 content to identify which topics resonated +- Double down on the topic that got the most replies (not likes -- replies indicate deeper engagement) + +**Month 1 milestones**: +| Metric | Target | Why it matters | +|--------|--------|----------------| +| Followers | 350-500 | 2-3x growth signals the approach is working | +| Avg impressions per tweet | 800-2000 | Shows the algorithm is distributing your content | +| Replies received per original tweet | 3-5 | People are engaging, not just scrolling past | +| Mutual follows from target accounts | 5-10 | Your niche peers are noticing you | +| Profile visits / week | 200+ | Your replies are driving curiosity | + +**What to avoid in month 1**: +- Posting 10 tweets/day hoping something sticks -- looks desperate, exhausts your ideas +- Buying followers or using engagement pods -- Twitter's algorithm detects and penalizes this +- Talking about yourself or your product -- earn attention through insight first +- Getting discouraged by low numbers -- 180 to 400 followers in a month is strong growth + +--- + ## Performance Metrics ### Key Metrics