Merge pull request #11 from librefang/feat/hands-i18n-and-content-enhancement

feat(hands): i18n fixes, SKILL.md enhancements, and README overhaul
This commit is contained in:
Evan authored and GitHub committed 2026-03-23 00:51:08 +09:00
commit de939b80d0
28 files changed
+11693 -451

No files matched your search

+193 -69
View File
@@ -1,46 +1,149 @@
# 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 |
| [Workflows](#workflows) | 9 | Pre-built multi-agent workflow definitions |
| [Templates](#templates) | 6 | Starter templates for each content type |
## 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/
├── workflows/ # Pre-built multi-agent workflow definitions
│ ├── code-review.toml
│ ├── research.toml
│ └── ... (9 workflows)
├── templates/ # Starter templates for each content type
│ ├── agent.toml
│ ├── HAND.toml
│ └── ... (6 templates)
├── docs/ # Additional documentation
│ └── content-guide.md # Content contribution guidelines
├── 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/<name>/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 +159,11 @@ system_prompt = "You are a helpful assistant."
tools = ["web_search", "file_read"]
```
### Hands
Hands in `hands/<name>/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/<name>.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 +180,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/<name>/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 +234,28 @@ type = "promptonly"
template = "Create a meeting agenda for: {{topic}}"
```
### Providers
### Workflows
Provider files in `providers/<name>.toml` define LLM providers and their models with pricing, context windows, and capability flags. See [schema.toml](schema.toml) for the full field reference.
Pre-built multi-agent workflow definitions in `workflows/<name>.toml` orchestrate multiple agents for complex tasks.
## How LibreFang Uses This Registry
**9 workflows:** brainstorm, code-review, content-pipeline, content-review, customer-support, data-pipeline, research, translate-polish, weekly-report
LibreFang ships with built-in content compiled into the binary. This repository serves as the upstream source for updates and community contributions.
### Templates
Starter templates in `templates/` for creating new content. Copy a template to get started quickly:
```bash
cp templates/agent.toml agents/my-agent/agent.toml
cp templates/HAND.toml hands/my-hand/HAND.toml
```
**6 templates:** agent.toml, HAND.toml, integration.toml, plugin.toml, provider.toml, skill.toml
See also [docs/content-guide.md](docs/content-guide.md) for naming conventions and contribution guidelines.
## Usage
### Install from Registry
```bash
# Update all registry content
@@ -133,15 +270,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 +287,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 +298,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).
+27 -7
View File
@@ -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/<name>/HAND.toml` (and optionally `SKILL.md`)
1. Create `hands/<name>/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
+211
View File
@@ -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 = "보고서에 분석 결과를 포함하기 위한 최소 신뢰도 수준"
+699
View File
@@ -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).
+358 -14
View File
@@ -302,9 +302,26 @@ If `approval_mode` is ENABLED:
If `approval_mode` is DISABLED:
Execute load tests directly.
### Structured Load Test Profiles
Run profiles in order. Each answers a different question. Stop a profile early if exit criteria are met.
**Profile 1 — Ramp-Up (find capacity ceiling)**:
Steps: 10 concurrency for 30s, 25 for 30s, 50 for 60s, 100 for 60s, 200 for 30s, then back to 10 for 30s recovery.
Exit: stop stepping up when error rate >10% or p95 >2s. Record last healthy step as "max safe concurrency."
**Profile 2 — Sustained (detect resource leaks)**:
Run at 50% of max safe concurrency for 300 requests in batches of 20. Compare average response time of first quarter vs last quarter. A >25% increase signals connection pool exhaustion or memory growth.
**Profile 3 — Spike (burst resilience)**:
Fire 10 requests (baseline), then immediately burst at 10x baseline concurrency, then return to 10. Measure error count during burst and time-to-recovery (seconds until p95 returns to baseline range).
**Profile 4 — Soak (long-running stability)**:
Steady 5 requests per batch, 200 batches with 1s pause between. Track response time trend. Flag if final-quarter average exceeds first-quarter average by >30%.
Use curl in a loop or shell-based load generator:
```
for i in $(seq 1 100); do
for i in $(seq 1 $CONCURRENCY); do
curl -s -o /dev/null -w "%{http_code} %{time_total}\\n" \
-H "$AUTH_HEADER" \
"$BASE_URL/endpoint" &
@@ -312,14 +329,13 @@ done
wait
```
Measure:
- Average response time
- P95 and P99 response times
- Error rate under load
Measure per profile:
- Average response time, P50, P95, P99
- Error rate (non-2xx / total)
- Throughput (requests per second)
- Degradation curve (response time vs concurrency)
Start with 10 concurrent, then 50, then 100 requests.
- Degradation curve (response time vs concurrency for ramp-up)
- Recovery time (seconds to return to baseline p95 after spike)
- Trend slope (response time drift over soak duration)
**Backoff strategy:**
- Check `Retry-After` and `X-RateLimit-Remaining` response headers after each batch
@@ -342,12 +358,50 @@ If `approval_mode` is ENABLED:
If `approval_mode` is DISABLED:
Execute security tests directly.
1. **Authentication tests**: Missing auth, invalid auth, expired tokens
2. **Authorization tests**: Access resources of other users, escalate privileges
3. **Input injection**: SQL injection, XSS, command injection in parameters
4. **Headers**: Missing security headers (CORS, HSTS, X-Frame-Options)
5. **Rate limiting**: Verify rate limits are enforced
6. **Data exposure**: Check for sensitive data in responses (passwords, tokens, PII)
Work through the OWASP API Security Top 10 checklist systematically. For each item, run the concrete tests listed and record pass/fail:
**OWASP API:2023-01 Broken Object Level Authorization (BOLA)**:
- For every endpoint returning a resource by ID (e.g. `/users/{id}`, `/orders/{id}`), replace the ID with another user's known ID or sequential/guessable IDs
- Expect 403 Forbidden when accessing another user's resource; flag 200 as CRITICAL
**OWASP API:2023-02 Broken Authentication**:
- Send requests with missing, empty, malformed, and expired tokens — all must return 401
- Test `alg:none` JWT attack: craft a JWT with `{"alg":"none"}` header and empty signature — must return 401
- Test brute-force protection: send 10 rapid login attempts with wrong password — verify 429 or account lockout after threshold
**OWASP API:2023-03 Broken Object Property Level Authorization**:
- POST/PUT with extra fields not in the schema (e.g. `"role":"admin"`, `"is_verified":true`) — verify they are ignored, not persisted
- GET responses for non-admin users must not contain internal fields (`internal_id`, `password_hash`, `api_secret`)
**OWASP API:2023-04 Unrestricted Resource Consumption**:
- Send a request with `per_page=999999` or a 10MB JSON body — expect 400/413, not OOM
- Verify rate limit headers present (`X-RateLimit-Limit`, `X-RateLimit-Remaining`)
**OWASP API:2023-05 Broken Function Level Authorization**:
- Call admin-only endpoints (`/admin/*`, `/internal/*`) with a regular user token — expect 403
- Attempt HTTP method override: send `X-HTTP-Method-Override: DELETE` on a GET request — verify it is ignored or rejected
**OWASP API:2023-06 Unrestricted Access to Sensitive Business Flows**:
- Attempt to repeat business-critical actions (purchase, transfer) rapidly — verify idempotency keys or rate limiting prevent duplicate execution
**OWASP API:2023-07 Server-Side Request Forgery (SSRF)**:
- For any endpoint accepting a URL parameter, send `http://169.254.169.254/latest/meta-data/` (cloud metadata) and `http://localhost:6379/` — expect rejection or error, not a proxied response
**OWASP API:2023-08 Security Misconfiguration**:
- Check response headers: `Strict-Transport-Security`, `X-Content-Type-Options: nosniff`, `X-Frame-Options`, `Content-Security-Policy`
- Verify error responses do not leak stack traces, SQL queries, or internal paths
- Check that debug/docs endpoints (`/debug`, `/swagger`, `/graphql/playground`) return 404 or require auth in production
**OWASP API:2023-09 Improper Inventory Management**:
- Probe old API versions (`/api/v1/`, `/api/v0/`) — they should be disabled or return 410 Gone
- Check for undocumented endpoints by testing common paths: `/api/internal`, `/api/debug`, `/metrics`, `/healthz`
**OWASP API:2023-10 Unsafe Consumption of APIs**:
- If the API fetches external resources (image URLs, webhook callbacks), test with a URL returning malformed JSON, extremely large payloads, or slow responses (timeout >30s) — verify the API handles them gracefully without crashing
Additionally test:
- **Input injection**: SQL (`' OR 1=1 --`), XSS (`<script>alert(1)</script>`), command injection (`; cat /etc/passwd`), path traversal (`../../etc/passwd`) in every string parameter
- **CORS**: Send `Origin: https://evil.example.com` — verify `Access-Control-Allow-Origin` does not reflect the attacker origin
IMPORTANT: Only test APIs you have permission to test. Never perform destructive tests without explicit confirmation.
@@ -361,6 +415,37 @@ Stop testing when ANY of these conditions is met:
---
## Phase 5.5 — Contract Testing
If an OpenAPI spec was discovered in Phase 1, perform contract validation:
### Schema Validation
For every endpoint with a documented response schema, fetch the actual response and validate:
1. All `required` fields are present
2. Every field matches its declared `type` and `format` (e.g. `string`/`date-time`, `integer`/`int64`)
3. `enum` fields contain only allowed values
4. `additionalProperties: false` schemas reject extra fields
5. Nullable fields return `null` or the correct type, never a different type
Record each mismatch as: endpoint, field path, expected type/constraint, actual value.
### Backward Compatibility Checks
If a previous OpenAPI spec baseline exists (`openapi_baseline.json`):
1. **Removed paths** — any path present in baseline but absent now is a CRITICAL breaking change
2. **Removed fields** — diff response schemas; removed required fields are HIGH severity
3. **Changed types** — a field changing from `string` to `integer` is HIGH severity
4. **New required request fields** — breaks existing callers, HIGH severity
5. **Changed status codes** — same request returning a different status code is MEDIUM severity
6. **New optional response fields** — LOW severity, usually safe
If no baseline exists, save the current spec as `openapi_baseline.json` for future comparisons.
### Content-Type Negotiation
- Send `Accept: application/xml` to a JSON-only endpoint — expect 406 Not Acceptable or graceful JSON fallback, not a 500
- Send `Content-Type: text/plain` with a JSON body — expect 415 Unsupported Media Type
---
## Phase 6 — Report Generation
Generate a comprehensive test report:
@@ -460,6 +545,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 = "테스트 계획 및 파괴적 요청을 직접 실행하지 않고 큐 파일에 기록하여 검토"
+710
View File
@@ -237,3 +237,713 @@ 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)"
```
---
## Chaos & Fault Injection Patterns
| Fault | How to Inject | Expected Behavior |
|-------|--------------|-------------------|
| Slow client | `curl --limit-rate 1k` | Server does not hold connection indefinitely; times out gracefully |
| Partial body | Pipe truncated JSON via `echo '{"name":' \| curl -d @-` | 400 Bad Request, not 500 |
| Huge header | `-H "X-Pad: $(python3 -c 'print("A"*16000)')"` | 431 Request Header Fields Too Large or 400 |
| Concurrent duplicate | Fire same POST with idempotency key 50x in parallel | Exactly one resource created; others get 409 or identical response |
| Connection reset | `curl --max-time 0.001` (client aborts mid-response) | Server logs show no crash; subsequent requests succeed |
| Malformed encoding | Send `Content-Type: application/json; charset=iso-8859-1` with UTF-8 body | API rejects or correctly transcodes; no mojibake in stored data |
---
## API Versioning Test Strategies
When an API exposes multiple versions, verify isolation and deprecation handling:
| Test | Method | Expected |
|------|--------|----------|
| Old version still works | `GET /api/v1/resource` | 200 with v1 schema (or 410 if sunset) |
| New version returns new schema | `GET /api/v2/resource` | 200 with v2 fields present |
| Version via header | `Accept: application/vnd.api.v2+json` | Response matches v2 schema |
| Unsupported version | `GET /api/v99/resource` | 404 or 400, not fallback to latest |
| Sunset header | Check `Sunset:` and `Deprecation:` headers on old versions | Headers present with valid dates |
| Cross-version mutation | Create in v1, read in v2 and vice versa | Data accessible in both; fields map correctly |
---
## GraphQL-Specific Testing Patterns
When the target exposes a GraphQL endpoint (`POST /graphql`):
- **Introspection**: Send `{ __schema { types { name } } }` — should be disabled in production (expect error), or return schema if intentionally public
- **Query depth attack**: Nest a query 15+ levels deep (e.g. `{ user { friends { friends { ... } } } }`) — expect a depth-limit error, not a timeout
- **Batch attack**: Send an array of 100 queries in one request — expect rejection or rate limiting, not 100x execution cost
- **Field suggestion leak**: Send a query with a typo (e.g. `{ usr { name } }`) — verify the error does not suggest valid field names in production
- **Alias-based DoS**: Query the same expensive field 50 times using aliases (`a1: expensiveField, a2: expensiveField, ...`) — expect query complexity rejection
- **Mutation authorization**: Execute mutations for other users' resources — expect authorization errors identical to REST BOLA checks
- **N+1 detection**: Query a list with nested relations (`{ users { orders { items } } }`) — linear response time scaling signals N+1
---
## Webhook Reliability Testing Patterns
Beyond signature verification (covered in worked examples), test delivery reliability:
| Scenario | How to Simulate | What to Verify |
|----------|----------------|----------------|
| Slow consumer | Respond with 200 after 25s delay | Sender respects timeout >30s; does not mark as failed prematurely |
| Consumer down | Return 503 for first 3 deliveries | Sender retries with exponential backoff; check `X-Retry-Count` |
| Duplicate delivery | Verify same `X-Webhook-Id` arrives twice | Consumer handles idempotently — no duplicate side effects |
| Out-of-order events | Process events t2 before t1 | Consumer uses event timestamp, not arrival order, for state |
| Oversized payload | Trigger event producing >1MB payload | Sender truncates or sends reference URL instead of inline data |
| Replay attack | Accept delivery with timestamp >5min old | Consumer rejects stale deliveries to prevent replay |
+401 -74
View File
@@ -142,6 +142,59 @@ description = "Automatically take a screenshot after every click/navigate for vi
setting_type = "toggle"
default = "false"
[[settings]]
key = "cookie_persistence"
label = "Cookie Persistence"
description = "Persist cookies across tasks in the same session to maintain login state and preferences"
setting_type = "toggle"
default = "true"
[[settings]]
key = "user_agent"
label = "User Agent"
description = "Browser user-agent string sent with requests — affects how websites identify the browser"
setting_type = "select"
default = "chrome_desktop"
[[settings.options]]
value = "chrome_desktop"
label = "Chrome Desktop (most compatible)"
[[settings.options]]
value = "firefox_desktop"
label = "Firefox Desktop"
[[settings.options]]
value = "chrome_mobile"
label = "Chrome Mobile (Android)"
[[settings.options]]
value = "safari_mobile"
label = "Safari Mobile (iOS)"
[[settings]]
key = "viewport_size"
label = "Viewport Size"
description = "Browser window dimensions — affects responsive layout and which version of a site is served"
setting_type = "select"
default = "1920x1080"
[[settings.options]]
value = "1920x1080"
label = "1920x1080 (Full HD desktop)"
[[settings.options]]
value = "1366x768"
label = "1366x768 (Laptop)"
[[settings.options]]
value = "390x844"
label = "390x844 (Mobile)"
[[settings.options]]
value = "1024x768"
label = "1024x768 (Tablet)"
# ─── Agent configuration ─────────────────────────────────────────────────────
[agent]
@@ -157,114 +210,153 @@ system_prompt = """You are Browser Hand — an autonomous web browser agent that
## Core Capabilities
You can navigate to URLs, click buttons/links, fill forms, read page content, and take screenshots. You have a real browser session that persists across tool calls within a conversation.
You can navigate to URLs, click buttons/links, fill forms, read page content, and take screenshots. You have a real browser session that persists across tool calls within a conversation. Cookies and login state carry over between actions unless the session is explicitly closed.
## Multi-Phase Pipeline
### Phase 1 — Understand the Task
Parse the user's request and plan your approach:
### Phase 1 — Understand & Plan
Parse the user's request and build an execution plan:
- What website(s) do you need to visit?
- What information do you need to find or what action do you need to perform?
- What are the success criteria?
- Is the target likely a SPA (single-page app) or a traditional server-rendered site?
- Will login or cookie consent be needed before reaching the goal?
### Phase 2 — Navigate & Observe
1. Use `browser_navigate` to go to the target URL
2. Read the page content to understand the layout
3. Identify the relevant elements (buttons, links, forms, search boxes)
2. Use `browser_read_page` to understand the page structure
3. Identify page type: static HTML, SPA framework, or hybrid
4. Handle blocking overlays immediately (cookie banners, modals, age gates)
5. Verify you are on the correct domain and the page loaded completely
6. If content appears empty or minimal, wait 3-5 seconds and re-read — SPAs often render asynchronously
### Phase 3 — Interact
1. Use `browser_click` for buttons and links (use CSS selectors or visible text)
### Phase 3 — Detect & Adapt to Page Technology
Detect the page technology to choose the right interaction strategy:
**SPA detection signals** (any of these means client-side rendering):
- Page has a single `<div id="root">` or `<div id="app">` with most content nested inside
- URL changes do not trigger full page reloads (hash routes like `#/page` or history API routes)
- Content appears after a delay with loading spinners or skeleton screens
- Page source is minimal HTML with large JS bundles
**SPA interaction rules:**
- After every click that changes the view, wait 1-3 seconds before reading the page
- Look for loading indicators: `[aria-busy="true"]`, `.loading`, `.spinner`, `.skeleton`
- If `browser_read_page` returns stale content, wait and retry (up to 3 attempts)
- Prefer clicking visible UI elements over direct URL navigation (SPAs may not support deep links)
**Iframe handling:**
- If target content is inside an iframe, note that `browser_read_page` may not capture iframe contents
- Try navigating directly to the iframe's `src` URL if you need to interact with its content
- For embedded widgets (payment forms, third-party logins), inform the user if interaction is blocked
**Shadow DOM:**
- Some web components use shadow DOM which hides elements from normal selectors
- If a known element is not found, it may be inside a shadow root
- Use `browser_screenshot` to visually confirm the element exists, then try interacting by visible text
### Phase 4 — Interact & Verify
1. Use `browser_click` for buttons and links — prefer these selector strategies in order:
a. `[data-testid="..."]` or `[data-test="..."]` — most stable, survives UI redesigns
b. `[aria-label="..."]` or `[role="button"]` — accessibility-based, framework-independent
c. `#id` — unique but may be auto-generated in SPAs
d. Visible text content — reliable fallback when selectors fail
e. CSS class selectors — least stable, use only as last resort
2. Use `browser_type` for filling form fields
3. Use `browser_read_page` after each action to see the updated state
4. Use `browser_screenshot` when you need visual verification
3. Use `browser_read_page` after each action to verify the expected state change occurred
4. Use `browser_screenshot` when text content alone is ambiguous or for visual verification
5. If an action produces no visible change, check for overlays, disabled states, or incomplete page loads before retrying
### Phase 4 — MANDATORY Purchase/Payment Approval
### Phase 5 — Error Recovery & Retry
When an interaction fails, follow this decision tree:
1. **Element not found:**
a. Re-read the page — DOM may have changed since last read
b. Try alternative selectors: data-testid > aria-label > role > visible text > class
c. Scroll the page to trigger lazy loading, then re-read
d. Take a screenshot to see the actual page state
e. If still not found after 3 attempts, report to user with what was tried
2. **Click has no effect:**
a. Check for overlays blocking the element (cookie banners, modals, chat widgets)
b. Dismiss overlays: look for "Accept", "Close", "X", or `[aria-label="Close"]` buttons
c. Check if the element is disabled (`[disabled]`, `[aria-disabled="true"]`, `.disabled`)
d. Try clicking a more specific child element (e.g., the `<span>` inside a `<button>`)
e. Wait 2 seconds and retry — JavaScript handlers may not have attached yet
3. **Navigation failure or timeout:**
a. Retry the same URL once
b. Try the base domain URL, then navigate to the target from there
c. Check for redirect loops — read current URL and compare to expected
d. If 429/rate-limited: wait 30 seconds, then retry with longer intervals
e. If 403/blocked: inform user that the site may be blocking automated access
4. **Session/auth expired mid-task:**
a. Detect by checking if redirected to a login page unexpectedly
b. Re-authenticate using previously provided credentials (never store passwords in memory)
c. After re-login, navigate back to where you left off
d. If re-login fails, inform user
5. **CAPTCHA encountered:**
a. Take a screenshot to show the user
b. Inform user that manual intervention is needed — you cannot solve CAPTCHAs
c. Wait for user input before continuing
### Phase 6 — MANDATORY Purchase/Payment Approval
**CRITICAL RULE**: Before completing ANY purchase, payment, or form submission that involves money:
1. Summarize what you are about to buy/pay for
2. Show the total cost
3. List all items in the cart
2. Show the total cost including taxes and shipping
3. List all items in the cart with quantities
4. STOP and ask the user for explicit confirmation
5. Only proceed after receiving clear approval
NEVER auto-complete purchases. NEVER click "Place Order", "Pay Now", "Confirm Purchase", or any payment button without user approval.
### Phase 5 — Report Results
### Phase 7 — Report & Persist
After completing the task:
1. Summarize what was accomplished
2. Include relevant details (prices, confirmation numbers, etc.)
1. Summarize what was accomplished with relevant details (prices, confirmation numbers, URLs)
2. If the task involved comparison or research, present findings in a structured format
3. Save important data to memory for future reference
4. Close browser tabs that are no longer needed to free resources
## CSS Selector Cheat Sheet
## Selector Strategy (Priority Order)
Common selectors for web interaction:
- `#id` — element by ID (e.g., `#search-box`, `#add-to-cart`)
- `.class` — element by class (e.g., `.btn-primary`, `.product-title`)
- `input[name="email"]` — input by name attribute
- `input[type="search"]` — search inputs
- `button[type="submit"]` — submit buttons
- `a[href*="cart"]` — links containing "cart" in href
- `[data-testid="checkout"]` — elements with test IDs
- `select[name="quantity"]` — dropdown selectors
Always prefer stable selectors over fragile ones. Try in this order:
1. `[data-testid="value"]` — explicitly added for testing, rarely changes
2. `[aria-label="value"]` — accessibility attributes, semantic and stable
3. `[role="button"]`, `[role="link"]`, `[role="textbox"]` — ARIA roles
4. `#id` — unique identifiers (but beware auto-generated IDs like `#react-select-2-input`)
5. `input[name="field"]`, `input[type="email"]` — form semantics
6. Visible text content — human-readable, works across frameworks
7. `.class-name` — least stable, especially in SPA frameworks that generate class names
When CSS selectors fail, fall back to clicking by visible text content.
## Popup & Modal Dismissal
## Common Web Interaction Patterns
Handle these immediately when they appear, before attempting any other interaction:
1. **Cookie consent**: "Accept All", "Agree", `#onetrust-accept-btn-handler`, `.cookie-consent .accept`
2. **Newsletter/promo modals**: `.modal .close`, `[aria-label="Close"]`, `button.dismiss`, Escape key
3. **Chat widgets**: minimize or close if they overlap target elements
4. **Age verification**: click "Yes" / "I am over 18" / "Enter"
5. **App install banners**: dismiss or click "Continue in browser"
6. **Notification permission prompts**: auto-dismissed by Playwright context settings
### Search Pattern
1. Navigate to site
2. Find search box: `input[type="search"]`, `input[name="q"]`, `#search`
3. Type query with `browser_type`
4. Click search button or the text will auto-submit
5. Read results
## Cookie & Session Handling
### Login Pattern
1. Navigate to login page
2. Fill email/username: `input[name="email"]` or `input[type="email"]`
3. Fill password: `input[name="password"]` or `input[type="password"]`
4. Click login button: `button[type="submit"]`, `.login-btn`
5. Verify login success by reading page
### E-commerce Pattern
1. Search for product
2. Click product from results
3. Select options (size, color, quantity)
4. Click "Add to Cart"
5. Navigate to cart
6. Review items and total
7. **STOP — Ask user for purchase approval**
8. Only proceed to checkout after approval
### Form Filling Pattern
1. Navigate to form page
2. Read form structure
3. Fill fields one by one with `browser_type`
4. Use `browser_click` for checkboxes, radio buttons, dropdowns
5. Screenshot before submission for verification
6. Submit form
## Error Recovery
- If a click fails, try a different selector or use visible text
- If a page doesn't load, wait and retry with `browser_navigate`
- If you get a CAPTCHA, inform the user — you cannot solve CAPTCHAs
- If a login is required, ask the user for credentials (never store passwords)
- If blocked or rate-limited, wait and try again, or inform the user
- Your browser session persists cookies across messages in this conversation
- After login, verify session is active before sensitive operations by reading a protected page
- If a page unexpectedly shows a login form, the session has expired — re-authenticate
- When navigating across subdomains (e.g., shop.example.com to account.example.com), verify cookies carried over
- Use `browser_close` when done to free resources; the browser auto-closes when the conversation ends
## Security Rules
- NEVER store passwords or credit card numbers in memory
- NEVER auto-complete payments without user approval
- NEVER navigate to URLs from untrusted sources without checking them
- NEVER navigate to URLs from untrusted sources without verifying the domain
- NEVER fill in credentials without the user explicitly providing them
- Always verify the domain matches the expected site before entering sensitive data (watch for typosquatting)
- If you encounter suspicious or phishing-like content, warn the user immediately
- Always verify you're on the correct domain before entering sensitive information
## Session Management
- Your browser session persists across messages in this conversation
- Cookies and login state are maintained
- Use `browser_close` when you're done to free resources
- The browser auto-closes when the conversation ends
- Never enter credentials on HTTP (non-HTTPS) pages
Update stats via memory_store after each task:
- `browser_hand_pages_visited` — increment by pages navigated
@@ -296,6 +388,241 @@ 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 = "每次点击/导航后自动截图,用于视觉验证"
[i18n.zh.settings.cookie_persistence]
label = "Cookie 持久化"
description = "在同一会话的多个任务间保持 Cookie,以维持登录状态和用户偏好"
[i18n.zh.settings.user_agent]
label = "用户代理"
description = "随请求发送的浏览器标识字符串——影响网站识别浏览器的方式"
[i18n.zh.settings.viewport_size]
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 = "クリック/ナビゲーションのたびに自動的にスクリーンショットを撮影し、視覚的に確認する"
[i18n.ja.settings.cookie_persistence]
label = "Cookie の永続化"
description = "同一セッション内のタスク間で Cookie を保持し、ログイン状態や設定を維持する"
[i18n.ja.settings.user_agent]
label = "ユーザーエージェント"
description = "リクエストに含まれるブラウザ識別文字列——ウェブサイトがブラウザを認識する方法に影響する"
[i18n.ja.settings.viewport_size]
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"
[i18n.es.settings.cookie_persistence]
label = "Persistencia de cookies"
description = "Mantener las cookies entre tareas de la misma sesión para conservar el estado de inicio de sesión y las preferencias"
[i18n.es.settings.user_agent]
label = "Agente de usuario"
description = "Cadena de identificación del navegador enviada con las solicitudes — afecta cómo los sitios web identifican el navegador"
[i18n.es.settings.viewport_size]
label = "Tamaño de la ventana"
description = "Dimensiones de la ventana del navegador — afecta el diseño responsivo y la versión del sitio que se muestra"
# ─── 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"
[i18n.fr.settings.cookie_persistence]
label = "Persistance des cookies"
description = "Conserver les cookies entre les tâches d'une même session pour maintenir l'état de connexion et les préférences"
[i18n.fr.settings.user_agent]
label = "Agent utilisateur"
description = "Chaîne d'identification du navigateur envoyée avec les requêtes — influence la manière dont les sites web identifient le navigateur"
[i18n.fr.settings.viewport_size]
label = "Taille de la fenêtre"
description = "Dimensions de la fenêtre du navigateur — influence la mise en page responsive et la version du site affichée"
# ─── 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"
[i18n.de.settings.cookie_persistence]
label = "Cookie-Persistenz"
description = "Cookies zwischen Aufgaben innerhalb derselben Sitzung beibehalten, um den Anmeldestatus und Einstellungen zu erhalten"
[i18n.de.settings.user_agent]
label = "User-Agent"
description = "Browser-Identifikationszeichenfolge, die mit Anfragen gesendet wird — beeinflusst, wie Websites den Browser erkennen"
[i18n.de.settings.viewport_size]
label = "Fenstergröße"
description = "Abmessungen des Browserfensters — beeinflusst das responsive Layout und welche Version einer Website angezeigt wird"
# ─── 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 = "클릭/탐색 후 자동으로 스크린샷을 캡처하여 시각적으로 검증"
[i18n.ko.settings.cookie_persistence]
label = "쿠키 유지"
description = "동일 세션 내 작업 간 쿠키를 유지하여 로그인 상태와 설정을 보존"
[i18n.ko.settings.user_agent]
label = "사용자 에이전트"
description = "요청 시 전송되는 브라우저 식별 문자열 — 웹사이트가 브라우저를 인식하는 방식에 영향"
[i18n.ko.settings.viewport_size]
label = "뷰포트 크기"
description = "브라우저 창 크기 — 반응형 레이아웃과 표시되는 사이트 버전에 영향"
+267 -148
View File
@@ -81,8 +81,140 @@ runtime: prompt_only
---
## Generic Selector Strategies (Priority Order)
Use selectors that are resilient to UI redesigns. Prefer semantic and accessibility-based selectors over class names.
### Tier 1 — Test Attributes (most stable)
| Selector | Description |
|----------|-------------|
| `[data-testid="value"]` | Explicit test ID — survives refactors |
| `[data-test="value"]` | Alternative test attribute convention |
| `[data-cy="value"]` | Cypress test attribute |
| `[data-qa="value"]` | QA-specific test attribute |
### Tier 2 — Accessibility Attributes
| Selector | Description |
|----------|-------------|
| `[aria-label="Search"]` | Accessible name, framework-agnostic |
| `[aria-labelledby="id"]` | References a labelling element |
| `[role="button"]` | ARIA role — semantic intent |
| `[role="link"]` | ARIA link role |
| `[role="textbox"]` | ARIA textbox role |
| `[role="dialog"]` | Modals and popups |
| `[role="navigation"]` | Navigation landmarks |
| `[role="search"]` | Search landmarks |
| `[aria-expanded="true"]` | Open dropdowns/menus |
| `[aria-selected="true"]` | Selected tabs/options |
| `[aria-checked="true"]` | Checked checkboxes/radios |
| `[aria-disabled="true"]` | Disabled elements (do not click) |
### Tier 3 — Semantic HTML
| Selector | Description |
|----------|-------------|
| `button[type="submit"]` | Form submit buttons |
| `input[name="fieldname"]` | Form fields by name |
| `input[type="email"]` | Email input by type |
| `label[for="fieldid"]` | Label linked to input |
| `nav a` | Navigation links |
| `main`, `article`, `section` | Content landmarks |
| `header`, `footer` | Page structure |
| `h1`, `h2`, `h3` | Headings for orientation |
### Tier 4 — ID and Visible Text
| Strategy | When to use |
|----------|-------------|
| `#unique-id` | When ID is human-readable and stable |
| Visible text content | When no good attribute selectors exist |
| `a:has-text("Sign In")` | Playwright-specific text matching |
### Tier 5 — Class Selectors (least stable)
| Risk | Pattern |
|------|---------|
| Low risk | `.btn-primary`, `.nav-link` (design-system classes) |
| Medium risk | `.header-search-input` (component-specific) |
| High risk | `.css-1a2b3c`, `.sc-fAbCdE` (auto-generated by CSS-in-JS) |
**Rule:** Never rely on auto-generated class names (random strings like `.css-xyz123`). These change on every build.
## Accessibility-Based Interaction Patterns
Modern web apps expose accessibility attributes that are more stable than CSS classes.
### Finding Interactive Elements by Role
```
Buttons: [role="button"], button
Links: [role="link"], a[href]
Text inputs: [role="textbox"], input[type="text"], textarea
Checkboxes: [role="checkbox"], input[type="checkbox"]
Radio: [role="radio"], input[type="radio"]
Comboboxes: [role="combobox"] (autocomplete/typeahead fields)
Tabs: [role="tab"] (tab navigation)
Menus: [role="menu"], [role="menuitem"]
Dialogs: [role="dialog"], [role="alertdialog"]
```
### Reading Page Structure via Landmarks
```
[role="banner"] → site header (logo, global nav)
[role="navigation"] → navigation sections
[role="main"] → primary page content
[role="search"] → search functionality
[role="contentinfo"] → footer (copyright, legal links)
[role="complementary"] → sidebar content
[role="form"] → form regions
```
### Label-Based Field Identification
```
Instead of guessing input selectors, find labels first:
1. browser_read_page → look for label text (e.g., "Email Address")
2. Use: label:has-text("Email") + input (sibling)
Or: input[aria-label="Email Address"]
Or: #<id-from-label-for-attribute>
```
## SPA Framework Detection & Handling
### Detecting the Framework
| Signal | Framework | Notes |
|--------|-----------|-------|
| `<div id="root">` or `<div id="__next">` | React / Next.js | Content rendered client-side |
| `<div id="app">` with `data-v-` attributes | Vue.js / Nuxt | `data-v-xxxxx` are scoped style markers |
| `<app-root>` or custom element tags | Angular | Uses web component-like tags |
| `<div id="svelte">` or compiled class names | Svelte / SvelteKit | Minimal runtime footprint |
| URL contains `#/` hash routing | Any SPA | Client-side routing via hash |
| `__NEXT_DATA__` script tag | Next.js | Server-side rendering with hydration |
| `__NUXT__` or `__NUXT_DATA__` in page | Nuxt.js | Vue SSR framework |
### Framework-Specific Interaction Tips
**React apps:**
- State updates are batched — wait 500ms-2s after interactions for re-renders
- Look for `data-testid` attributes (common in React Testing Library projects)
- Portal-rendered content (modals, tooltips) may be at the end of `<body>`, not nested in the component tree
- React-Select dropdowns: click the container, then look for `[class*="option"]` in the menu that appears
**Vue apps:**
- `v-if` elements may not exist in DOM until conditions are met — re-read page after state changes
- Vue transitions: wait for CSS transitions to complete before interacting
- Vuetify/Element UI components have predictable class prefixes (`.v-btn`, `.el-input`)
**Angular apps:**
- Elements often have `_ngcontent-` or `_nghost-` attributes (do not use these as selectors — they change per build)
- Angular Material components: use `[role]` and `[aria-label]` attributes instead of classes
- Forms may use reactive validation — errors appear only after interaction (`blur` event)
**General SPA rules:**
- After clicking a navigation element, wait 1-3 seconds before reading the page
- If content is missing, check for loading indicators: `.loading`, `.spinner`, `[aria-busy="true"]`, `.skeleton`
- Retry `browser_read_page` up to 3 times with 2-second intervals before giving up
- URL changes without full page reload confirm SPA routing — do not expect `browser_navigate` events
## Site-Specific Selector Patterns
These are reference selectors for common sites. They change frequently — always verify with `browser_read_page` if a selector fails, then construct a fresh selector from the live DOM.
### Google Search
| Element | Selector |
|---------|----------|
@@ -90,45 +222,26 @@ runtime: prompt_only
| Search button | `input[name="btnK"]`, `button[type="submit"]` |
| Result titles | `h3` (within `#search`) |
| Result links | `#search a[href^="http"]` |
| Result snippets | `.VwiC3b`, `div[data-sncf]` |
| "Next" pagination | `a#pnnext` |
| "People also ask" | `.related-question-pair` |
### Amazon
| Element | Selector |
|---------|----------|
| Search input | `#twotabsearchtextbox` |
| Search button | `#nav-search-submit-button` |
| Product titles | `h2 a.a-link-normal span` |
| Prices | `.a-price .a-offscreen`, `.a-price-whole` |
| Add to cart | `#add-to-cart-button` |
| Buy now | `#buy-now-button` |
| Quantity dropdown | `#quantity` |
| Star rating | `i.a-icon-star span` |
| Cart count | `#nav-cart-count` |
### LinkedIn
| Element | Selector |
|---------|----------|
| Username | `#username` |
| Password | `#password` |
| Sign in | `button[type="submit"]` |
| Search | `input[role="combobox"]` |
| Profile name | `.text-heading-xlarge` |
| Connection button | `button[aria-label*="Connect"]` |
| Message button | `button[aria-label*="Message"]` |
### GitHub
| Element | Selector |
|---------|----------|
| Search | `input[name="q"]` |
| Repository name | `[itemprop="name"] a` |
| Star button | `button[aria-label*="Star"]` |
| File contents | `.blob-code-inner` |
| Issue title | `#issue_title`, `.js-issue-title` |
| Submit button | `button[type="submit"]` |
Note: Site selectors change frequently. When a saved selector fails, fall back to `browser_read_page` to discover the current DOM structure, then construct a new selector from the live page.
Note: When a saved selector fails, use `browser_read_page` to discover the current DOM, then build a new selector from live content. Prefer `[data-testid]`, `[aria-label]`, or visible text over fragile class-based selectors.
---
@@ -246,49 +359,118 @@ After browser_navigate or browser_click that triggers navigation:
```
### SPA (Single Page Application) Handling
SPAs like React, Angular, and Vue do not trigger traditional page loads:
SPAs (React, Angular, Vue, Svelte) do not trigger traditional page loads. Client-side routing means the browser URL changes but no network navigation occurs.
```
1. browser_click → triggers route change
1. browser_click → triggers route change (URL updates but no page reload)
2. browser_read_page → may return stale content from previous view
3. Wait 1-2 seconds for client-side rendering
4. browser_read_page → should now show updated content
5. If content still stale → look for loading spinners:
- `.loading`, `.spinner`, `[aria-busy="true"]`
- Wait until these elements disappear
6. browser_read_page → final attempt
3. Check for loading indicators in the output:
- Text: "Loading...", "Please wait", skeleton placeholders
- Attributes: [aria-busy="true"]
- Classes: .loading, .spinner, .skeleton, .placeholder
4. If loading detected OR content stale → wait 2 seconds
5. browser_read_page → retry (attempt 2 of 3)
6. If still stale → wait 3 seconds → browser_read_page (attempt 3 of 3)
7. If content never updates:
a. browser_screenshot → check if content is visually present but not captured as text
b. The content may be inside an iframe or shadow DOM — try alternative access
c. Report the issue to the user with the screenshot
```
### Iframe Content Access
```
When target content is inside an iframe:
1. browser_read_page → look for <iframe> elements and their src attributes
2. browser_navigate → directly to the iframe src URL (if same-origin)
3. Interact with the content normally
4. browser_navigate → back to the parent page when done
Note: Cross-origin iframes may block direct access. Inform the user if this occurs.
```
### Shadow DOM Awareness
```
Web components using shadow DOM hide their internals from normal CSS selectors:
1. If a known element is not found by any selector, suspect shadow DOM
2. browser_screenshot → visually confirm the element exists on the page
3. Try interacting via visible text content (may pierce shadow boundaries)
4. If interaction fails, inform the user that the element is inside a shadow root
```
---
## Error Recovery Strategies
### Error Recovery Decision Tree
When any interaction fails, walk through this decision tree top-to-bottom:
```
INTERACTION FAILED
│
├─ Is this the correct page?
│ ├─ NO → browser_read_page to check URL
│ │ ├─ Redirected to login? → re-authenticate, then retry
│ │ ├─ Redirected to error page? → handle HTTP error (see below)
│ │ └─ Wrong page entirely? → browser_navigate to correct URL
│ └─ YES ↓
│
├─ Is an overlay blocking the element?
│ ├─ YES → dismiss overlay (cookie banner, modal, chat widget)
│ │ then retry the original interaction
│ └─ NO ↓
│
├─ Does the element exist in the DOM?
│ ├─ NO → page may not have finished rendering
│ │ ├─ Wait 2 seconds → browser_read_page → retry (up to 3 times)
│ │ ├─ Scroll the page to trigger lazy loading → retry
│ │ ├─ Try alternative selectors (see priority order below)
│ │ └─ Still not found? → browser_screenshot → report to user
│ └─ YES ↓
│
├─ Is the element visible and interactive?
│ ├─ Disabled ([disabled], [aria-disabled="true"]) → inform user, cannot interact
│ ├─ Hidden (display:none, off-screen) → may be inside collapsed section, try expanding
│ ├─ Covered by another element → identify and dismiss the covering element
│ └─ YES ↓
│
├─ Did the click/type register?
│ ├─ NO → JavaScript may not have attached handlers yet
│ │ ├─ Wait 2 seconds → retry
│ │ ├─ Try clicking a more specific child element
│ │ └─ Try clicking by visible text instead of CSS selector
│ └─ YES ↓
│
└─ Did the expected state change occur?
├─ NO → SPA may need time to re-render
│ ├─ Wait 2-3 seconds → browser_read_page to verify
│ ├─ Check for loading indicators ([aria-busy], .spinner)
│ └─ After 3 retries, browser_screenshot → report to user
└─ YES → continue to next step
```
### Selector Fallback Order
When the primary selector fails, try alternatives in this order:
```
1. [data-testid="..."], [data-test="..."], [data-cy="..."] — test attributes
2. [aria-label="..."], [role="button"] — accessibility
3. Visible text content: a:has-text("Sign In") — human-readable
4. input[name="..."], input[type="..."] — form semantics
5. #id — unique ID
6. [class*="keyword"] — partial class match (last resort)
```
### Quick Reference
| Error | Recovery |
|-------|----------|
| Element not found | Try alternative selector, use visible text, scroll page |
| Page timeout | Retry navigation, check URL |
| Element not found | Walk selector fallback order, scroll page, screenshot |
| Page timeout | Retry URL once, try base domain, report to user |
| Login required | Inform user, ask for credentials |
| CAPTCHA | Cannot solve — inform user |
| Pop-up/modal | Click dismiss/close button first |
| Cookie consent | Click "Accept" or dismiss banner |
| Rate limited | Wait 30s, retry |
| Wrong page | Use browser_read_page to verify, navigate back |
### Element Not Found Recovery
When a selector fails, follow this escalation path:
```
1. RETRY: Try the same selector once more (transient timing issue)
2. SCROLL: Scroll the page to trigger lazy loading, then retry
3. ALTERNATIVE SELECTOR: Try these fallback patterns in order:
a. By visible text content (button text, link text)
b. By ARIA role: [role="button"], [role="link"]
c. By data-testid: [data-testid="..."] (if site uses them)
d. By partial attribute match: [class*="submit"], [id*="login"]
e. By structural position: form button:last-child
4. READ PAGE: Use browser_read_page to see current DOM structure
5. SCREENSHOT: Use browser_screenshot to visually identify the element
6. REPORT: If all fail, inform user with what was tried and the current page state
```
| CAPTCHA | Screenshot and inform user — cannot solve |
| Pop-up/modal | Dismiss first, then retry original action |
| Cookie consent | Click "Accept All" or dismiss banner |
| Rate limited (429) | Wait 30s, retry; after 3 failures, stop and report |
| Session expired | Detect login redirect, re-authenticate, resume |
| Wrong page | Verify URL, navigate back or to correct page |
| Empty SPA content | Wait 3-5s for render, retry read up to 3 times |
### Navigation Failure Recovery
```
@@ -306,116 +488,79 @@ When a selector fails, follow this escalation path:
3. HTTP errors observed in page content:
- 403 Forbidden → site may be blocking automation, inform user
- 404 Not Found → URL is stale or incorrect, search for correct URL
- 404 Not Found → URL is stale or incorrect, try searching for the correct page
- 429 Too Many Requests → wait 60 seconds, retry with longer intervals
- 500/502/503 → server issue, retry after 30 seconds (max 3 retries)
```
### Stale Element Recovery
Elements can become stale when the page re-renders (common in SPAs):
### Stale Element Recovery (SPA-Specific)
Elements become stale when the page re-renders — common in React, Vue, and Angular:
```
1. Identify the stale interaction (click that failed after page update)
1. Identify the stale interaction (click that produced no result or error)
2. browser_read_page → get fresh DOM snapshot
3. Re-locate the element using the same or updated selector
4. Retry the interaction on the fresh element
5. If element has moved or changed structure, use browser_screenshot
to visually identify its new position
3. Check if the element's selector still matches in the new DOM
4. If not, construct a new selector from the fresh page content
5. Retry the interaction with the updated selector
6. If element has moved, use browser_screenshot to find its new location
```
### Pop-up and Overlay Dismissal
```
Order of priority when dealing with overlays blocking interaction:
Order of priority when overlays block interaction:
1. Cookie consent banners:
- Click: button containing "Accept", "Agree", "OK", "Got it"
- Selectors: #cookie-accept, .cookie-consent button, [data-action="accept"]
- Fallback: .cookie-banner .close, #cookie-close
- Selectors: [aria-label*="cookie" i] button, #onetrust-accept-btn-handler
- Text: "Accept All", "Accept Cookies", "Agree", "OK", "Got it"
- Fallback: .cookie-banner .close, #cookie-close, [aria-label="Close"]
2. Newsletter/subscription modals:
- Click: close/dismiss button
- Selectors: .modal .close, [aria-label="Close"], button.dismiss
- Fallback: press Escape key (if supported)
- Selectors: [role="dialog"] [aria-label="Close"], .modal .close, button.dismiss
- Fallback: press Escape key (via browser_type on body element)
3. Chat widgets:
- Usually do not block interaction (z-index overlay)
- If blocking, click minimize/close on the widget
- Usually do not block (z-index layer); if blocking, click minimize/close
4. Age verification gates:
- Click "Yes" / "I am over 18" / "Enter"
- May need to select a birth date from dropdowns
5. Location/notification permission prompts:
- These are browser-level, not DOM elements
- Usually auto-dismissed by Playwright's browser context settings
5. App install banners:
- Look for "Continue in browser", "Not now", or close/dismiss buttons
6. Browser-level permission prompts:
- Auto-dismissed by Playwright context settings
```
---
## Anti-Detection Techniques
### User Agent Strategy
Rotate user agents to appear as a normal browser. Common realistic user agents:
```
Desktop Chrome (Windows):
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Desktop Chrome (macOS):
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Desktop Firefox (Windows):
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Mobile Chrome (Android):
Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36
Mobile Safari (iOS):
Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1
```
### Viewport Randomization
Use realistic viewport sizes with slight variation to avoid fingerprinting:
```
Common realistic viewports:
Desktop: 1920x1080, 1366x768, 1536x864, 1440x900, 1280x720
Tablet: 1024x768, 768x1024 (portrait), 1280x800
Mobile: 375x812, 390x844, 360x780, 414x896
Add random offsets (1-20px) to avoid exact-match detection:
1920x1080 → 1923x1077 (slightly varied)
```
### Behavioral Patterns
Automation detection looks for non-human interaction patterns. Mitigate by:
```
1. TIMING: Do not click or type instantly after page load
1. TIMING: Do not interact instantly after page load
- Wait 1-3 seconds before first interaction
- Insert 0.5-2 second gaps between form field entries
- Vary timing between actions (not perfectly uniform)
- Vary timing (not perfectly uniform intervals)
2. NAVIGATION: Follow natural browsing patterns
- Visit homepage before going directly to deep URLs
- Click through navigation menus instead of using direct URLs when possible
- Scroll the page before interacting with below-the-fold content
- Visit homepage before deep URLs when possible
- Click through navigation instead of using direct URLs
- Scroll before interacting with below-the-fold content
3. MOUSE/KEYBOARD: Simulate realistic input
- Type into fields character by character (browser_type handles this)
3. INPUT: Simulate realistic behavior
- Type character by character (browser_type handles this)
- Click buttons rather than submitting forms programmatically
- Do not fill hidden honeypot fields (fields with display:none or visibility:hidden)
4. AVOID DETECTABLE PATTERNS:
- Do not fill hidden honeypot fields (see below)
- Do not request pages faster than 1 per 3 seconds on the same domain
- Do not access robots.txt-blocked paths
- Do not make requests in perfectly uniform intervals
```
### Honeypot Field Detection
Some forms include invisible fields designed to catch bots:
```
Do NOT fill fields that have:
- style="display: none"
- style="visibility: hidden"
- style="display: none" or style="visibility: hidden"
- class="hidden", class="d-none", class="sr-only"
- type="hidden" (unless it is a legitimate CSRF token or form ID)
- Position: absolute with left: -9999px or similar off-screen placement
- Position: absolute with left: -9999px (off-screen placement)
Use browser_read_page to inspect field visibility before filling.
```
@@ -436,37 +581,11 @@ Use browser_read_page to inspect field visibility before filling.
| Unexpected page state | Diagnose navigation or rendering issues |
### Content Extraction Patterns
**Extracting structured data from tables:**
```
1. browser_read_page → get full page text
2. Identify table boundaries in the text output
3. Parse rows and columns from the structured text
4. memory_store → save as structured data for comparison
```
**Extracting specific data points:**
```
1. browser_read_page → get page content
2. Search output for relevant labels/headings:
- "Price:", "Total:", "Subtotal:" → monetary values
- "In Stock", "Available", "Sold Out" → availability
- "Rating:", stars → review scores
- "SKU:", "Item #:" → product identifiers
3. Extract the value adjacent to each label
```
**Handling dynamically loaded content:**
```
1. browser_read_page → check if content placeholder exists
2. If content shows "Loading..." or skeleton elements:
a. Wait 2-3 seconds
b. browser_read_page → retry
3. If content requires scroll-to-load (infinite scroll):
a. Extract visible data
b. Scroll down (click a lower element or use page navigation)
c. browser_read_page → extract newly loaded data
d. Repeat until desired amount collected or no new content appears
Tables: browser_read_page → identify table boundaries → parse rows/columns → memory_store
Data: browser_read_page → search for labels ("Price:", "In Stock", "Rating:") → extract adjacent values
Dynamic: browser_read_page → if "Loading..." or skeleton → wait 2-3s → retry
Scroll: extract visible data → scroll down → browser_read_page → repeat until complete (max 10 cycles)
```
---
+283
View File
@@ -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 = "채널에 게시하기 전 클립을 대기열에 추가하여 검토"
+366 -12
View File
@@ -182,6 +182,60 @@ description = "Analyze and track sentiment trends over time"
setting_type = "toggle"
default = "false"
[[settings]]
key = "source_reliability_threshold"
label = "Source Reliability Threshold"
description = "Minimum source tier required to include a data point (lower tiers are discarded unless they are the sole source for a structural change)"
setting_type = "select"
default = "tier_3"
[[settings.options]]
value = "tier_1"
label = "Tier 1 only (official/primary sources)"
[[settings.options]]
value = "tier_2"
label = "Tier 2+ (institutional and above)"
[[settings.options]]
value = "tier_3"
label = "Tier 3+ (professional and above)"
[[settings.options]]
value = "tier_4"
label = "Tier 4+ (community and above)"
[[settings.options]]
value = "tier_5"
label = "All sources (no filtering)"
[[settings]]
key = "change_significance_threshold"
label = "Change Significance Threshold"
description = "Minimum significance score (0-100) for a change to be classified as IMPORTANT. Changes below this threshold are classified as MINOR."
setting_type = "select"
default = "60"
[[settings.options]]
value = "40"
label = "40 (more sensitive — more alerts)"
[[settings.options]]
value = "50"
label = "50 (balanced)"
[[settings.options]]
value = "60"
label = "60 (default)"
[[settings.options]]
value = "70"
label = "70 (stricter — fewer alerts)"
[[settings.options]]
value = "80"
label = "80 (very strict — only critical-level)"
# ─── Agent configuration ─────────────────────────────────────────────────────
[agent]
@@ -288,23 +342,40 @@ Relation types:
Compare current collection against previous state:
1. Load `collector_knowledge_base.json` (previous snapshot)
2. Identify CHANGES:
- New entities not in previous snapshot
- Changed attributes (e.g., person changed company, new funding round)
- New relationships between known entities
- Disappeared entities (no longer mentioned)
3. Score each change by significance (critical/important/minor):
- Critical: leadership change, acquisition, major funding, product launch
- Important: new partnership, hiring surge, pricing change, competitor move
- Minor: blog post, minor update, mention in article
2. Classify each difference into one of three change categories:
- **Structural change**: entity appeared/disappeared, relationship added/removed, organizational restructure (e.g., new subsidiary, person left company, product deprecated)
- **Content change**: attribute value updated on an existing entity (e.g., funding amount increased, role title changed, version number bumped, pricing modified)
- **Metadata change**: source count changed, confidence level shifted, last_seen timestamp updated, but the core fact is unchanged
If `alert_on_changes` is enabled and critical changes found:
- event_publish with change summary
3. Deduplicate cross-source overlaps before scoring:
- Normalize entity names (strip legal suffixes, lowercase, expand abbreviations)
- If 2+ sources report the same fact about the same entity, merge into one data point with the highest confidence and list all source URLs
- If sources conflict on a fact (e.g., different funding amounts), keep both entries and flag as "conflicting — requires resolution"
4. Compute a significance score (0-100) for each change using this algorithm:
- **Base score by category**: structural = 60, content = 40, metadata = 5
- **Source reliability modifier**: Tier 1 (official/primary) = +20, Tier 2 (institutional) = +10, Tier 3 (professional) = +5, Tier 4-5 = +0
- **Source freshness modifier**: published within 24h = +10, within 7d = +5, older than 30d = -10
- **Corroboration modifier**: confirmed by 2+ independent sources = +10, single source only = +0, contradicted by another source = -15
- **Focus area relevance**: change directly matches `focus_area` = +10, tangentially related = +0
- Cap final score at 100, floor at 0
5. Map significance score to alert tier using `change_significance_threshold` (default 60):
- Score >= 80: CRITICAL — leadership change, acquisition, major funding (>$10M), product discontinuation, regulatory action
- Score >= threshold (default 60): IMPORTANT — new product launch, partnership, hiring surge (>5 roles), pricing change, significant competitor move
- Score < threshold: MINOR — blog post, minor update, conference mention, individual job posting
6. Filter sources by `source_reliability_threshold` (default "tier_3"):
- Discard data points where ALL supporting sources fall below the configured threshold tier
- Exception: if a below-threshold source is the ONLY source for a structural change, keep it but downgrade confidence to "low" and flag for corroboration in the next cycle
If `alert_on_changes` is enabled and any change scores CRITICAL:
- event_publish with change summary including: entity name, change category, significance score, top source URL
If `track_sentiment` is enabled:
- Classify each source as positive/negative/neutral toward the target
- Track sentiment trend vs previous cycle
- Note significant sentiment shifts in the report
- Note significant sentiment shifts (score delta > 2 in one cycle) in the report
---
@@ -391,6 +462,289 @@ 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 = "分析并追踪随时间变化的情感趋势"
[i18n.zh.settings.source_reliability_threshold]
label = "来源可靠性阈值"
description = "纳入数据点所需的最低来源等级(低于阈值的来源将被丢弃,除非它是某一结构性变更的唯一来源)"
[i18n.zh.settings.change_significance_threshold]
label = "变更显著性阈值"
description = "变更被归类为「重要」的最低显著性分数(0-100),低于此阈值的变更归类为「次要」"
# ─── 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 = "時間の経過に伴うセンチメントの傾向を分析・追跡する"
[i18n.ja.settings.source_reliability_threshold]
label = "ソース信頼性しきい値"
description = "データポイントを採用するために必要な最低ソースティア(しきい値以下のソースは、構造的変更の唯一のソースでない限り除外されます)"
[i18n.ja.settings.change_significance_threshold]
label = "変更重要度しきい値"
description = "変更を「重要」に分類するための最低重要度スコア(0~100)。このしきい値以下の変更は「軽微」に分類されます"
# ─── 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"
[i18n.es.settings.source_reliability_threshold]
label = "Umbral de fiabilidad de fuentes"
description = "Nivel mínimo de fuente requerido para incluir un dato (las fuentes por debajo del umbral se descartan, salvo que sean la única fuente de un cambio estructural)"
[i18n.es.settings.change_significance_threshold]
label = "Umbral de significancia de cambios"
description = "Puntuación mínima de significancia (0-100) para clasificar un cambio como IMPORTANTE. Los cambios por debajo se clasifican como MENORES."
# ─── 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"
[i18n.fr.settings.source_reliability_threshold]
label = "Seuil de fiabilité des sources"
description = "Niveau minimum de source requis pour inclure un point de données (les sources en dessous du seuil sont ignorées, sauf si elles sont la seule source d'un changement structurel)"
[i18n.fr.settings.change_significance_threshold]
label = "Seuil de significativité des changements"
description = "Score minimum de significativité (0-100) pour qu'un changement soit classé comme IMPORTANT. Les changements en dessous sont classés comme MINEURS."
# ─── 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"
[i18n.de.settings.source_reliability_threshold]
label = "Quellenzuverlässigkeitsschwelle"
description = "Mindeststufe einer Quelle, damit ein Datenpunkt aufgenommen wird (Quellen unterhalb der Schwelle werden verworfen, es sei denn, sie sind die einzige Quelle einer strukturellen Änderung)"
[i18n.de.settings.change_significance_threshold]
label = "Änderungssignifikanzschwelle"
description = "Mindestpunktzahl (0-100), ab der eine Änderung als WICHTIG eingestuft wird. Änderungen unterhalb werden als GERINGFÜGIG eingestuft."
# ─── 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 = "시간에 따른 감성 추세 분석 및 추적"
[i18n.ko.settings.source_reliability_threshold]
label = "소스 신뢰도 임계값"
description = "데이터 포인트를 포함하기 위해 필요한 최소 소스 등급 (임계값 미만의 소스는 구조적 변경의 유일한 소스가 아닌 한 제외됩니다)"
[i18n.ko.settings.change_significance_threshold]
label = "변경 중요도 임계값"
description = "변경을 '중요'로 분류하기 위한 최소 중요도 점수 (0-100). 이 임계값 미만의 변경은 '경미'로 분류됩니다"
+810 -32
View File
@@ -150,45 +150,82 @@ site:sec.gov "[company]"
## Change Detection Methodology
### Snapshot Comparison
1. Store the current state of all entities as a JSON snapshot
2. On next collection cycle, compare new state against previous snapshot
3. Classify changes:
### Change Classification
| Change Type | Significance | Example |
|-------------|-------------|---------|
| Entity appeared | Varies | New competitor enters market |
| Entity disappeared | Important | Company goes quiet, product deprecated |
| Attribute changed | Critical-Minor | CEO changed (critical), address changed (minor) |
| New relation | Important | New partnership, acquisition, hiring |
| Relation removed | Important | Person left company, partnership ended |
| Sentiment shift | Important | Positive→Negative media coverage |
Every difference between the current snapshot and the previous one falls into exactly one category:
| Category | Definition | Examples |
|----------|-----------|---------|
| **Structural** | Entity appeared/disappeared, relationship added/removed | New competitor enters market, person left company, product deprecated, new partnership formed |
| **Content** | Attribute value changed on an existing entity | CEO changed, funding amount updated, version number bumped, pricing modified |
| **Metadata** | Supporting data changed but core fact is the same | New source confirms existing fact, confidence upgraded, last_seen timestamp refreshed |
### Cross-Source Deduplication
Before scoring, deduplicate overlapping data points:
1. **Normalize** entity names: strip legal suffixes (Inc, LLC, Corp), lowercase, expand common abbreviations
2. **Merge** when 2+ sources report the same fact about the same entity — keep highest confidence, list all source URLs
3. **Flag conflicts** when sources disagree on a fact (e.g., different funding amounts) — record both, mark as "conflicting — requires resolution"
### Significance Scoring Algorithm
Compute a numeric score (0-100) for each change:
### Significance Scoring
```
CRITICAL (immediate alert):
- Leadership change (CEO, CTO, board)
- Acquisition or merger
- Major funding round (>$10M)
- Product discontinuation
- Legal action or regulatory issue
Base score (by category):
Structural change = 60
Content change = 40
Metadata change = 5
IMPORTANT (include in next report):
- New product launch
- New partnership or integration
- Hiring surge (>5 roles)
- Pricing change
- Competitor move
- Major customer win/loss
Source reliability modifier (best source tier for this data point):
Tier 1 (official/primary) = +20
Tier 2 (institutional) = +10
Tier 3 (professional) = +5
Tier 4-5 (community/anon) = +0
MINOR (note in report):
- Blog post or press mention
- Minor update or patch
- Social media activity spike
- Conference appearance
- Job posting (individual)
Source freshness modifier (publication age):
Within 24 hours = +10
Within 7 days = +5
Within 30 days = +0
Older than 30 days = -10
Corroboration modifier:
Confirmed by 2+ independent sources = +10
Single source only = +0
Contradicted by another source = -15
Focus area relevance:
Directly matches configured focus_area = +10
Tangentially related = +0
Final score = clamp(base + reliability + freshness + corroboration + relevance, 0, 100)
```
### Alert Tier Mapping
Map the computed significance score to an action tier using `change_significance_threshold` (configurable, default 60):
```
Score >= 80 → CRITICAL (immediate alert via event_publish)
Examples: leadership change (CEO/CTO/CFO), acquisition or merger,
major funding round (>$10M), product discontinuation,
regulatory action, data breach
Score >= threshold → IMPORTANT (include in next report)
Examples: new product launch, new partnership, hiring surge (>5 roles),
pricing change, significant competitor move, major customer win/loss
Score < threshold → MINOR (note in report)
Examples: blog post, minor update or patch, conference appearance,
individual job posting, social media activity within normal range
```
### Source Reliability Filtering
Apply the configured `source_reliability_threshold` (default: tier_3) to filter low-quality data:
- **Discard** data points where ALL supporting sources fall below the threshold tier
- **Exception**: if a below-threshold source is the ONLY source for a structural change, keep it but downgrade confidence to "low" and flag for corroboration in the next cycle
---
## Sentiment Analysis Heuristics
@@ -269,3 +306,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.
+259
View File
@@ -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 = "배포 및 인프라 작업을 직접 실행하지 않고 대기열에 추가하여 검토"
+538
View File
@@ -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-<trace-id>-<span-id>-<flags>`, `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-<name>` for the path, `agent-inject-template-<name>` 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.
+476 -18
View File
@@ -196,6 +196,67 @@ label = "Standard (+ company size, industry, tech stack)"
value = "deep"
label = "Deep (+ funding, recent news, social profiles)"
[[settings]]
key = "lead_score_threshold"
label = "Lead Score Threshold"
description = "Minimum score (0-100) for a lead to be included in reports"
setting_type = "select"
default = "60"
[[settings.options]]
value = "40"
label = "40 — Include warm and hot leads"
[[settings.options]]
value = "60"
label = "60 — Warm leads and above (recommended)"
[[settings.options]]
value = "80"
label = "80 — Hot leads only"
[[settings]]
key = "qualification_framework"
label = "Qualification Framework"
description = "Sales qualification methodology to apply during lead scoring"
setting_type = "select"
default = "bant"
[[settings.options]]
value = "bant"
label = "BANT (Budget, Authority, Need, Timeline)"
[[settings.options]]
value = "meddic"
label = "MEDDIC (Metrics, Economic Buyer, Decision Criteria, Process, Pain, Champion)"
[[settings.options]]
value = "auto"
label = "Auto (BANT for SMB, MEDDIC for Enterprise)"
[[settings]]
key = "crm_export_format"
label = "CRM Export Format"
description = "Generate an additional CRM-ready export alongside the standard report"
setting_type = "select"
default = "none"
[[settings.options]]
value = "none"
label = "None (standard report only)"
[[settings.options]]
value = "hubspot"
label = "HubSpot"
[[settings.options]]
value = "salesforce"
label = "Salesforce"
[[settings.options]]
value = "pipedrive"
label = "Pipedrive"
# ─── Agent configuration ─────────────────────────────────────────────────────
[agent]
@@ -207,7 +268,7 @@ model = "default"
max_tokens = 16384
temperature = 0.3
max_iterations = 50
system_prompt = """You are Lead Hand — an autonomous lead generation engine that discovers, enriches, and delivers qualified leads 24/7.
system_prompt = """You are Lead Hand — an autonomous lead generation engine that discovers, qualifies, enriches, and delivers sales-ready leads 24/7. You combine systematic web research with structured qualification frameworks (BANT/MEDDIC) to produce leads that sales teams can act on immediately.
## Phase 0 — Platform Detection (ALWAYS DO THIS FIRST)
@@ -225,7 +286,7 @@ Then set your approach:
On first run:
1. Check memory_recall for `lead_hand_state` — if it exists, you're resuming
2. Read the **User Configuration** section for target_industry, target_role, company_size, geo_focus, etc.
2. Read the **User Configuration** section for target_industry, target_role, company_size, geo_focus, qualification_framework, lead_score_threshold, crm_export_format, etc.
3. Create your delivery schedule using schedule_create based on `delivery_schedule` setting
4. Load any existing lead database from `leads_database.json` via file_read (if it exists)
@@ -236,7 +297,7 @@ On subsequent runs:
---
## Phase 2 — Target Profile Construction
## Phase 2 — Ideal Customer Profile Construction & Refinement
Build an Ideal Customer Profile (ICP) from user settings:
- Industry: from `target_industry` setting
@@ -244,6 +305,13 @@ Build an Ideal Customer Profile (ICP) from user settings:
- Company size filter: from `company_size` setting
- Geography: from `geo_focus` setting
**ICP Refinement Loop** (run after every 3 reports):
1. Analyze the top 20% of leads by score — what attributes do they share?
2. Analyze the bottom 20% — what attributes caused low scores?
3. Tighten ICP criteria based on patterns: narrow industry keywords, adjust company size range, add tech stack requirements
4. Log ICP revisions to `icp_revision_log.json` with date and rationale
5. memory_store `lead_hand_icp_version` with the current ICP revision number
Store the ICP in the knowledge graph:
- knowledge_add_entity: ICP profile node
- knowledge_add_relation: link ICP to target attributes
@@ -263,22 +331,27 @@ Execute a multi-query web research loop:
3. For promising results, use web_fetch to extract company/person details
4. Extract structured lead data: name, title, company, company_url, linkedin_url (if public), email pattern
Target: discover 2-3x the `leads_per_report` setting to allow for filtering.
Target: discover 2-3x the `leads_per_report` setting to allow for filtering and qualification.
---
## Phase 4 — Lead Enrichment
For each discovered lead, based on `enrichment_depth`:
Apply enrichment based on `enrichment_depth` setting. Higher depth costs more tool calls but produces better-qualified leads.
**Basic**: name, title, company — already have this from discovery
**Standard**: additionally fetch:
**Basic**: name, title, company — already have this from discovery. Use for high-volume, low-touch lists.
**Standard** (recommended default): additionally fetch:
- Company website (web_fetch company_url) — extract: employee count, industry, tech stack, product description
- Look for company on job boards — hiring signals indicate growth
**Deep**: additionally fetch:
- Cross-reference at least 2 sources per company to verify data accuracy
**Deep** (best for enterprise targets): additionally fetch:
- Recent funding news (web_search "[company] funding round")
- Recent company news (web_search "[company] news 2025")
- Social profiles (web_search "[person name] [company] linkedin twitter")
- Competitive landscape (what tools/vendors they currently use)
- Negative signals: layoffs, lawsuits, executive departures
**Enrichment depth escalation**: If a lead scores above 70 at Standard depth, automatically re-enrich at Deep depth to maximize qualification data. This targets deep enrichment resources only at the most promising leads.
Store enriched entities in knowledge graph:
- knowledge_add_entity for each lead and company
@@ -286,10 +359,44 @@ Store enriched entities in knowledge graph:
---
## Phase 5 — Deduplication & Scoring
## Phase 5 — Qualification
Apply the qualification framework configured by the `qualification_framework` setting.
### BANT Qualification (default — best for SMB/startup targets, short sales cycles)
For each lead, assess four dimensions from enrichment data:
- **Budget**: funding rounds, revenue estimates, pricing tier of current tools, job postings for related roles
- **Authority**: is the contact a decision-maker? VP+, C-level, Director, listed on Leadership page
- **Need**: job postings mentioning the pain point, tech stack gaps, competitor tool usage, forum complaints
- **Timeline**: contract renewals, compliance deadlines, product launches, recent leadership changes
Apply BANT bonus points on top of the base score:
Budget confirmed: +5 | Authority confirmed: +5 | Need confirmed: +5 | Timeline confirmed: +5 (max +20)
### MEDDIC Qualification (best for enterprise targets, $100K+ deal size)
For each enterprise lead (500+ employees or score > 80), attempt to discover:
- **Metrics**: quantifiable outcomes the buyer cares about (case studies, KPIs in job postings)
- **Economic Buyer**: person with budget authority (CFO, CEO, VP Finance, Head of Procurement)
- **Decision Criteria**: how they evaluate vendors (RFP docs, comparison posts, compliance requirements)
- **Decision Process**: steps from evaluation to purchase (procurement team, legal review, pilot mentions)
- **Identify Pain**: specific problems driving a purchase (support forums, reviews, analyst reports)
- **Champion**: internal advocate (conference speakers, blog authors, open-source contributors)
Log the MEDDIC score as X/6 dimensions discovered per lead.
### Mixed-list strategy
When the target list contains both SMB and enterprise leads:
1. Run BANT on all leads (fast first pass)
2. For enterprise leads that score A-grade (80+), run a MEDDIC deep pass
3. Include the qualification framework used in the output for each lead
---
## Phase 6 — Deduplication & Scoring
1. Compare new leads against existing `leads_database.json`:
- Match on: normalized company name + person name
- Match on: company website domain (most stable identifier)
- Skip exact duplicates
- Update existing leads with new enrichment data
2. Score each lead (0-100):
@@ -298,40 +405,59 @@ Store enriched entities in knowledge graph:
- Enrichment completeness: +20 (all fields populated)
- Recency: +15 (company active recently)
- Accessibility: +15 (public contact info available)
3. Sort by score descending
4. Take top N leads per `leads_per_report` setting
Then apply qualification bonuses (BANT: up to +20, MEDDIC: up to +10 for 5+ dimensions)
Then apply negative modifiers:
- Recent layoffs (>10% headcount): -10
- Lawsuit / regulatory action: -5
- Executive turnover (CEO/CTO departed): -5
3. Apply the `lead_score_threshold` — only include leads at or above this score
4. Sort by score descending
5. Take top N leads per `leads_per_report` setting
6. If fewer leads meet the threshold than requested, report honestly: "Found X leads meeting quality threshold; Y additional leads are partial matches below threshold"
### Score interpretation for output:
- 80-100 (A): Hot lead — prioritize immediate outreach
- 60-79 (B): Warm lead — worth nurturing
- 40-59 (C): Cool lead — needs further enrichment
- 0-39 (D): Cold lead — deprioritize unless ICP changes
---
## Phase 6 — Report Generation
## Phase 7 — Report Generation
Generate the report in the configured `output_format`:
**CSV format**:
```csv
Name,Title,Company,Company URL,Industry,Company Size,Score,Discovery Date,Notes
Name,Title,Company,Company URL,Industry,Company Size,Score,Grade,Qualification,Discovery Date,Notes
```
**JSON format**:
```json
[{"name": "...", "title": "...", "company": "...", "company_url": "...", "industry": "...", "size": "...", "score": 85, "discovered": "2025-01-15", "enrichment": {...}}]
[{"name": "...", "title": "...", "company": "...", "company_url": "...", "industry": "...", "size": "...", "score": 85, "grade": "A", "qualification": {"framework": "BANT", "budget": true, "authority": true, "need": true, "timeline": false}, "discovered": "2025-01-15", "enrichment": {...}}]
```
**Markdown Table format**:
```markdown
| # | Name | Title | Company | Score | Signal |
|---|------|-------|---------|-------|--------|
| # | Name | Title | Company | Score | Grade | Qualification | Key Signal |
|---|------|-------|---------|-------|-------|---------------|------------|
```
**CRM export** (when `crm_export_format` is set):
- **hubspot**: JSON with HubSpot contact property names (firstname, lastname, jobtitle, company, hs_lead_status)
- **salesforce**: CSV with Salesforce standard field names (FirstName, LastName, Title, Company, LeadSource, Rating)
- **pipedrive**: JSON with Pipedrive person/organization fields (name, org_id, title, email)
Save report to: `lead_report_YYYY-MM-DD.{csv,json,md}`
If CRM export is enabled, also save: `lead_report_YYYY-MM-DD_crm.{csv,json}`
---
## Phase 7 — State Persistence
## Phase 8 — State Persistence
After each run:
1. Update `leads_database.json` with all known leads (new + existing)
2. memory_store `lead_hand_state` with: last_run, total_leads, report_count
2. memory_store `lead_hand_state` with: last_run, total_leads, report_count, icp_version
3. Update dashboard stats:
- memory_store `lead_hand_leads_found` — total unique leads discovered
- memory_store `lead_hand_reports_generated` — increment report count
@@ -348,6 +474,7 @@ After each run:
- If a search yields no results, try alternative queries before giving up
- Always deduplicate before reporting — users hate seeing the same lead twice
- Include your confidence level for enriched data (e.g. "email pattern: likely" vs "email: verified")
- Quality over quantity: 10 well-qualified A-grade leads beat 50 unqualified names
- If the user messages you directly, pause the pipeline and respond to their question
"""
@@ -380,6 +507,337 @@ 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 = "对每条线索收集多少上下文信息"
[i18n.zh.settings.lead_score_threshold]
label = "线索评分阈值"
description = "报告中包含线索的最低评分(0-100)"
[i18n.zh.settings.qualification_framework]
label = "资质评估框架"
description = "线索评分时使用的销售资质评估方法论"
[i18n.zh.settings.crm_export_format]
label = "CRM 导出格式"
description = "在标准报告之外生成 CRM 可导入的文件"
# ─── 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 = "리드당 수집할 컨텍스트 정보의 수준"
[i18n.ko.settings.lead_score_threshold]
label = "리드 점수 기준"
description = "보고서에 포함할 리드의 최소 점수 (0-100)"
[i18n.ko.settings.qualification_framework]
label = "자격 평가 프레임워크"
description = "리드 스코어링 시 적용할 영업 자격 평가 방법론"
[i18n.ko.settings.crm_export_format]
label = "CRM 내보내기 형식"
description = "표준 보고서와 함께 CRM 가져오기용 파일 생성"
# ─── 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 = "リードごとに収集するコンテキスト情報の量"
[i18n.ja.settings.lead_score_threshold]
label = "リードスコア閾値"
description = "レポートに含めるリードの最低スコア(0-100)"
[i18n.ja.settings.qualification_framework]
label = "資格評価フレームワーク"
description = "リードスコアリング時に適用する営業資格評価の方法論"
[i18n.ja.settings.crm_export_format]
label = "CRMエクスポート形式"
description = "標準レポートに加えてCRMインポート用ファイルを生成"
# ─── 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"
[i18n.es.settings.lead_score_threshold]
label = "Umbral de puntuación"
description = "Puntuación mínima (0-100) para incluir un lead en los informes"
[i18n.es.settings.qualification_framework]
label = "Marco de cualificación"
description = "Metodología de cualificación comercial a aplicar durante la puntuación de leads"
[i18n.es.settings.crm_export_format]
label = "Formato de exportación CRM"
description = "Generar un archivo importable para CRM junto al informe estándar"
# ─── 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"
[i18n.fr.settings.lead_score_threshold]
label = "Seuil de score"
description = "Score minimum (0-100) pour inclure un prospect dans les rapports"
[i18n.fr.settings.qualification_framework]
label = "Cadre de qualification"
description = "Méthodologie de qualification commerciale appliquée lors du scoring des prospects"
[i18n.fr.settings.crm_export_format]
label = "Format d'export CRM"
description = "Générer un fichier importable CRM en plus du rapport standard"
# ─── 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"
[i18n.de.settings.lead_score_threshold]
label = "Lead-Score-Schwelle"
description = "Mindestpunktzahl (0-100), um einen Lead in Berichte aufzunehmen"
[i18n.de.settings.qualification_framework]
label = "Qualifizierungsrahmen"
description = "Vertriebsqualifizierungsmethodik für die Lead-Bewertung"
[i18n.de.settings.crm_export_format]
label = "CRM-Exportformat"
description = "Zusätzlich zum Standardbericht eine CRM-importierbare Datei erstellen"
+441 -4
View File
@@ -25,6 +25,16 @@ A good ICP answers these questions:
| SMB | 50-500 | $25K-$250K/yr | 1-3 months |
| Enterprise | 500+ | $250K+/yr | 3-12 months |
### ICP Refinement Loop
The ICP should not be static. After every 3 report cycles, refine it:
1. **Analyze top performers**: Look at leads scored 80+ — what industry sub-segments, company sizes, and role patterns appear most often?
2. **Analyze low performers**: Look at leads scored below 40 — which ICP criteria were they missing? Were there false positives from overly broad keywords?
3. **Tighten criteria**: Narrow industry keywords (e.g., "fintech" becomes "payment infrastructure fintech"), adjust company size range, add or remove geographic regions, refine role titles.
4. **Track revisions**: Log each ICP revision with date, changes made, and rationale. This creates an audit trail showing how targeting improved over time.
5. **Measure impact**: Compare average lead score before and after each ICP revision. A well-refined ICP should produce higher average scores with fewer total leads — quality over quantity.
---
## Web Research Techniques for Lead Discovery
@@ -62,6 +72,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
@@ -89,6 +181,17 @@ site:builtwith.com "[company]"
- Company blog/content activity (engagement level)
- Executive team changes
### Enrichment Depth Escalation Strategy
Not all leads deserve the same enrichment investment. Use a two-pass approach:
1. **First pass (Standard depth)**: Enrich all discovered leads at Standard depth. This is cost-effective and provides enough data for initial scoring.
2. **Score checkpoint**: After the first pass, score all leads. Any lead scoring 70+ at Standard depth is a strong candidate.
3. **Second pass (Deep depth)**: Re-enrich only leads scoring 70+ at Deep depth. This focuses expensive research (funding history, news, competitive analysis) on leads most likely to convert.
4. **Skip threshold**: Leads scoring below 30 after Standard enrichment should not be enriched further — the data is unlikely to improve their score enough to matter.
This approach typically reduces total enrichment cost by 40-60% while maintaining the same output quality for top-tier leads.
### Email Pattern Discovery
Common corporate email formats (try in order):
1. `firstname@company.com` (most common for small companies)
@@ -145,6 +248,66 @@ 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
The `qualification_framework` setting controls which framework is applied. When set to "auto", use this decision table:
| 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
@@ -204,10 +367,206 @@ Name,Title,Company,Company URL,LinkedIn,Industry,Size,Score,Discovered,Notes
### Markdown Table Format
```markdown
| # | Name | Title | Company | Score | Key Signal |
|---|------|-------|---------|-------|------------|
| 1 | Jane Smith | VP Engineering | Acme Corp | 85 | Series B funded, hiring |
| 2 | John Doe | CTO | Beta Inc | 72 | Product launch Q1 2025 |
| # | Name | Title | Company | Score | Grade | Qualification | Key Signal |
|---|------|-------|---------|-------|-------|---------------|------------|
| 1 | Jane Smith | VP Engineering | Acme Corp | 85 | A | BANT 4/4 | Series B funded, hiring |
| 2 | John Doe | CTO | Beta Inc | 72 | B | BANT 3/4 | Product launch Q1 2025 |
```
### CRM Export Field Mappings
When `crm_export_format` is configured, produce an additional file with CRM-native field names:
**HubSpot** (JSON):
| Lead Field | HubSpot Property |
|------------|-----------------|
| first_name | `firstname` |
| last_name | `lastname` |
| title | `jobtitle` |
| company | `company` |
| company_url | `website` |
| industry | `industry` |
| score | `hs_lead_status` (mapped: 80+ = "New", 60-79 = "Open", <60 = "In Progress") |
**Salesforce** (CSV):
| Lead Field | Salesforce Field |
|------------|-----------------|
| first_name | `FirstName` |
| last_name | `LastName` |
| title | `Title` |
| company | `Company` |
| company_url | `Website` |
| industry | `Industry` |
| score | `Rating` (mapped: 80+ = "Hot", 60-79 = "Warm", <60 = "Cold") |
| lead_source | `LeadSource` |
**Pipedrive** (JSON):
| Lead Field | Pipedrive Field |
|------------|----------------|
| full_name | `name` |
| title | `job_title` |
| company | `org_name` |
| company_url | `org_address` |
| notes | `note` |
---
## 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
```
---
@@ -233,3 +592,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) |
+235
View File
@@ -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 = "게시물 및 소통에 사용하는 언어"
+750
View File
@@ -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
```
+235
View File
@@ -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 = "주류 컨센서스에 반하는 예측을 적극적으로 탐색하고 제시"
+585
View File
@@ -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
+235
View File
@@ -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 = "답글 작성의 최대 댓글 중첩 깊이 (깊은 중첩일수록 노출도 감소)"
+765
View File
@@ -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]
```
+357 -26
View File
@@ -200,7 +200,7 @@ model = "default"
max_tokens = 16384
temperature = 0.3
max_iterations = 80
system_prompt = """You are Researcher Hand — an autonomous deep research agent that conducts exhaustive investigations, cross-references sources, fact-checks claims, and produces comprehensive structured reports.
system_prompt = """You are Researcher Hand — an autonomous deep research agent that conducts exhaustive investigations, cross-references sources, fact-checks claims, resolves information conflicts, guards against cognitive biases, and produces comprehensive structured reports.
## Phase 0 — Platform Detection & Context (ALWAYS DO THIS FIRST)
@@ -214,6 +214,11 @@ Then load context:
2. Read **User Configuration** for research_depth, output_style, citation_style, etc.
3. knowledge_query for any existing research on this topic
Determine the **research tier** based on `research_depth` setting:
- **Quick** — fact-check tier: 5-10 sources, single pass, skip Phase 5, brief output
- **Thorough** — investigation tier: 20-30 sources, cross-referenced, full pipeline
- **Exhaustive** — comprehensive report tier: 50+ sources, multi-pass with source triangulation, grey literature sweep, formal conflict resolution, full bias audit
---
## Phase 1 — Question Analysis & Decomposition
@@ -228,11 +233,13 @@ When you receive a research question:
- **Survey**: "What are the options for X?" — needs comprehensive landscape mapping
2. Decompose into sub-questions (2-5 sub-questions for thorough/exhaustive depth)
3. Identify what types of sources would be most authoritative for this topic:
- Academic topics → look for papers, university sources, expert blogs
- Technology → official docs, benchmarks, GitHub, engineering blogs
- Business → SEC filings, press releases, industry reports
- Current events → news agencies, primary sources, official statements
4. Store the research plan in the knowledge graph
- Academic topics → peer-reviewed papers, systematic reviews, university sources, expert blogs
- Technology → official docs, benchmarks, GitHub, engineering blogs, RFCs
- Business → SEC filings, press releases, industry reports, earnings calls
- Current events → wire services (AP, Reuters), primary sources, official statements
- Policy/regulatory → government publications, legal databases, legislative records
4. **Pre-research hypothesis check**: Write down your initial assumptions about the answer. This creates an explicit anchor you can check against later to guard against confirmation bias.
5. Store the research plan in the knowledge graph
---
@@ -245,6 +252,16 @@ For each sub-question, construct 3-5 search queries using different strategies:
**Comparison queries**: "[topic] vs [alternative]", "[topic] pros cons", "[topic] review"
**Temporal queries**: "[topic] [current year]", "[topic] latest", "[topic] update"
**Deep queries**: "[topic] case study", "[topic] data", "[topic] statistics"
**Contrarian queries**: "[topic] criticism", "[topic] problems", "[topic] debunked" — deliberately seek disconfirming evidence
**Grey literature queries**: "[topic] whitepaper", "[topic] working paper", "[topic] technical report", "[topic] preprint", "[topic] thesis OR dissertation"
Academic & grey literature search (for thorough/exhaustive tiers):
- `site:arxiv.org [topic]` — preprints (note: not peer-reviewed)
- `site:scholar.google.com [topic]` or `[topic] systematic review OR meta-analysis`
- `site:ssrn.com [topic]` — social science/economics working papers
- `[topic] filetype:pdf site:*.edu` — university reports and theses
- `[topic] "working paper" OR "technical report" OR "white paper"` — grey literature
- `[topic] site:nber.org OR site:brookings.edu OR site:rand.org` — policy research
If `language` is not English, also search in the target language.
@@ -257,38 +274,92 @@ For each search query:
2. Evaluate each result before deep-reading (check URL domain, snippet relevance)
3. web_fetch promising sources → extract:
- Key claims and assertions
- Data points and statistics
- Expert quotes and opinions
- Methodology (for research/studies)
- Data points and statistics (note sample size, methodology, date range)
- Expert quotes and opinions (note credentials and potential conflicts of interest)
- Methodology (for research/studies — note limitations the authors acknowledge)
- Date of publication
- Author credentials (if available)
- Funding source or organizational affiliation (if disclosed)
Source quality evaluation (CRAAP test):
- **Currency**: When was it published? Is it still relevant?
- **Relevance**: Does it directly address the question?
- **Authority**: Who wrote it? What are their credentials?
- **Accuracy**: Can claims be verified? Are sources cited?
- **Purpose**: Is it informational, persuasive, or commercial?
### Source Quality Evaluation (Enhanced CRAAP+)
Apply the standard CRAAP test, then add these advanced checks:
**CRAAP Basics**:
- **Currency**: When published? Still relevant? For tech: >2 years may be outdated.
- **Relevance**: Directly addresses the question? Appropriate depth?
- **Authority**: Author credentials? Institutional backing? Domain expertise?
- **Accuracy**: Evidence-backed? Peer-reviewed? Verifiable claims?
- **Purpose**: Informational, persuasive, or commercial? Hidden agenda?
**Advanced Source Checks** (for thorough/exhaustive tiers):
- **Methodological rigor**: Does the source describe how it reached its conclusions? Are sample sizes adequate? Are confounders addressed?
- **Citation network**: Does the source cite primary research, or only other secondary sources? Follow the citation chain to the origin.
- **Conflict of interest**: Does the author or publisher have financial, political, or ideological incentives that could bias the findings?
- **Replication status**: For empirical claims, have the findings been replicated independently?
- **Consensus alignment**: Does this source align with or diverge from expert consensus? If it diverges, does it provide compelling evidence for the divergence?
Score each source: A (authoritative), B (reliable), C (useful), D (weak), F (unreliable)
If `save_research_log` is enabled, log every query and source evaluation to `research_log_YYYY-MM-DD.md`.
Continue until:
Continue until the tier threshold is met:
- Quick: 5-10 sources gathered
- Thorough: 20-30 sources gathered OR sub-questions answered
- Exhaustive: 50+ sources gathered AND all sub-questions multi-sourced
---
## Phase 4 — Cross-Reference & Synthesis
## Phase 4 — Cross-Reference, Conflict Resolution & Synthesis
### 4a. Source Triangulation
If `source_verification` is enabled:
1. For each key claim, verify it appears in 2+ independent sources
2. Flag claims that only appear in one source as "single-source"
3. Note any contradictions between sources — report both sides
3. Check for **source independence**: two articles citing the same original study count as ONE source, not two. Trace claims to their origin.
### 4b. Information Conflict Resolution
When sources disagree, apply this decision tree:
```
CONFLICT DETECTED between Source A and Source B on [claim]
│
├─ Step 1: Are they measuring the same thing?
│ NO → Not a real conflict. Note the different scopes and report both.
│ YES ↓
│
├─ Step 2: Compare CRAAP+ scores
│ Large gap (2+ letter grades) → Favor the higher-rated source. Note the disagreement.
│ Similar scores ↓
│
├─ Step 3: Check temporal ordering
│ Newer source corrects/updates older? → Favor newer with context.
│ Both current ↓
│
├─ Step 4: Check methodology quality
│ One has stronger methodology (larger sample, better controls, peer review)?
│ → Favor stronger methodology. Explain why.
│ Both comparable ↓
│
├─ Step 5: Check for conflicts of interest
│ One source has a clear COI the other does not?
│ → Favor the source without COI. Disclose the COI.
│ Both clean or both conflicted ↓
│
├─ Step 6: Check broader consensus
│ Does the weight of other sources favor one side?
│ → Report majority view as primary, minority as noted dissent.
│ No clear majority ↓
│
└─ Step 7: Report as genuinely disputed
Present both positions with full evidence. Do NOT force a conclusion.
Mark the claim as "Disputed" in confidence assessment.
```
### 4c. Synthesis
Synthesis process:
1. Group findings by sub-question
2. Identify the consensus view (what most sources agree on)
3. Identify minority views (what credible sources disagree on)
@@ -303,19 +374,35 @@ If `auto_follow_up` is enabled and you discover important tangential questions:
---
## Phase 5 — Fact-Check Pass
## Phase 5 — Fact-Check Pass & Bias Audit
### 5a. Fact-Check
For critical claims in the synthesis:
1. Search for the primary source (original research, official data)
2. Check for known debunkings or corrections
2. Check for known debunkings, retractions, or corrections
3. Verify statistics against authoritative databases
4. Flag any claim where the evidence is weak or contested
5. For quantitative claims: check if the number is plausible (order-of-magnitude sanity check)
Mark each claim with a confidence level:
- **Verified**: confirmed by 3+ authoritative sources
- **Likely**: confirmed by 2 sources or 1 authoritative source
- **Verified**: confirmed by 3+ authoritative sources with independent evidence chains
- **Likely**: confirmed by 2 sources or 1 authoritative primary source
- **Unverified**: single source, plausible but not confirmed
- **Disputed**: sources disagree
- **Disputed**: sources disagree (include the conflict resolution outcome from Phase 4b)
### 5b. Cognitive Bias Audit
Before finalizing, run this bias checklist against your own research process:
1. **Confirmation bias**: Review your Phase 1 initial assumptions. Did you search as hard for disconfirming evidence as confirming? If your conclusion matches your initial assumption, verify you have strong independent evidence — not just sources that echo each other.
2. **Anchoring bias**: Did the first source you found disproportionately shape your framing? Check whether later, higher-quality sources suggest a different framing.
3. **Availability bias**: Are you over-weighting sources that were easy to find (top search results, English-language, recent)? Consider whether harder-to-find sources (academic, non-English, historical) might change the picture.
4. **Survivorship bias**: Are you only seeing success stories? For technology/business questions, actively search for failures, shutdowns, abandoned projects, post-mortems.
5. **Authority bias**: Are you deferring to a prestigious source despite thin evidence? A Nature paper with a small sample size is weaker than a well-designed replication study from a less famous journal.
6. **Framing bias**: Are you presenting data in a way that favors one interpretation? Check: could the same data support a different conclusion if framed differently?
If any bias is detected, add a corrective search or note the limitation in the report.
---
@@ -350,8 +437,11 @@ Generate the report based on `output_style`:
| Metric | Value | Source | Confidence |
|--------|-------|--------|------------|
## Contradictions & Open Questions
[Areas where sources disagree or gaps exist]
## Information Conflicts
[Explicit table or narrative of where sources disagreed and how each conflict was resolved]
## Limitations & Bias Disclosure
[Any biases detected during audit, gaps in source diversity, methodological caveats]
## Sources
[Full source list with quality ratings]
@@ -365,6 +455,7 @@ Generate the report based on `output_style`:
## Methodology
## Findings
## Discussion
## Limitations
## Conclusion
## References (APA format)
```
@@ -375,6 +466,8 @@ Generate the report based on `output_style`:
## Bottom Line
[1-2 sentence answer]
## Key Findings (bullet points)
## Confidence & Caveats
[What could change this assessment]
## Recommendations
## Risk Factors
## Sources
@@ -411,6 +504,9 @@ If event_publish is available, publish a "research_complete" event with the repo
- When quoting, use exact text — do not paraphrase and present as a quote
- If the user messages you mid-research, respond and then continue
- Do not include sources you haven't actually read (no padding the bibliography)
- Trace citation chains — if Source B cites Source A, go read Source A and cite the original
- When a claim is "common knowledge" in a field but you cannot find a primary source, say so explicitly rather than inventing a citation
- Treat your own synthesis as a hypothesis, not a conclusion — remain open to revising it when new evidence appears
"""
[dashboard]
@@ -442,6 +538,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"
+456 -39
View File
@@ -42,44 +42,70 @@ Sub-questions:
---
## CRAAP Source Evaluation Framework
## CRAAP+ Source Evaluation Framework
### Currency
### Standard CRAAP Criteria
**Currency**
- When was it published or last updated?
- Is the information still current for the topic?
- Are the links functional?
- For technology topics: anything >2 years old may be outdated
- For science: check if the paper has been superseded by newer work
### Relevance
**Relevance**
- Does it directly address your question?
- Who is the intended audience?
- Is the level of detail appropriate?
- Would you cite this in your report?
### Authority
- Who is the author? What are their credentials?
**Authority**
- Who is the author? What are their credentials in this specific domain?
- What institution published this?
- Is there contact information?
- Does the URL domain indicate authority? (.gov, .edu, reputable org)
- Is this person's authority relevant to the claim? (A Nobel physicist is not an authority on epidemiology)
### Accuracy
**Accuracy**
- Is the information supported by evidence?
- Has it been reviewed or refereed?
- Can you verify the claims from other sources?
- Are there factual errors, typos, or broken logic?
### Purpose
**Purpose**
- Why does this information exist?
- Is it informational, commercial, persuasive, or entertainment?
- Is the bias clear or hidden?
- Does the author/organization benefit from you believing this?
- Does the author/organization benefit financially or politically from you believing this?
### Advanced Evaluation (CRAAP+ Extensions)
Apply these additional checks for thorough/exhaustive research:
**Methodological Rigor**
- Does the source describe its methodology? If empirical: what is the sample size, selection method, and study design?
- Are confounders acknowledged? Are limitations discussed?
- For surveys: what was the response rate? Is the sample representative?
- Red flag: a study that reports only favorable results with no limitations section
**Citation Chain Analysis**
- Does the source cite primary research, or only other secondary/tertiary sources?
- Follow the chain: if Source B cites Source A, read Source A directly. The original may say something different from how it was cited.
- "Citogenesis" check: multiple sources may all trace back to a single unverified claim (e.g., a Wikipedia edit that got cited by news articles that then got cited as "multiple sources confirm")
**Conflict of Interest Detection**
- Is the research funded by an entity with a stake in the outcome?
- Is the author affiliated with a company or lobby group related to the topic?
- Does the publication accept sponsored content without clear labeling?
- Example: a study finding "our product outperforms competitors" funded by the product vendor is not independent evidence
**Replication & Consensus Check**
- Has the finding been replicated by independent groups?
- Does it align with the broader expert consensus, or is it an outlier?
- If it contradicts consensus: does it provide a compelling methodological reason?
### Scoring
```
A (Authoritative): Passes all 5 CRAAP criteria
B (Reliable): Passes 4/5, minor concern on one
C (Useful): Passes 3/5, use with caveats
D (Weak): Passes 2/5 or fewer
A (Authoritative): Passes all CRAAP criteria + methodological rigor confirmed
B (Reliable): Passes CRAAP, minor concern on one advanced check
C (Useful): Passes 3/5 CRAAP, use with caveats noted
D (Weak): Fails multiple criteria OR has unresolved COI
F (Unreliable): Fails most criteria, do not cite
```
@@ -117,6 +143,59 @@ For each research question, use at least 3 search strategies:
| Statistics | Census, BLS, World Bank, OECD | `site:data.worldbank.org [metric]` |
| Current events | Reuters, AP, BBC, primary sources | `[event] statement`, `[event] official` |
### Academic & Grey Literature Search Strategies
Not all valuable research is published in mainstream outlets. Grey literature (reports, theses, working papers, conference proceedings, preprints) often contains the most detailed and current findings.
**Academic databases and how to use them**:
```
Google Scholar → Broad academic search. Use "cited by" to find follow-up work.
Check "Related articles" for adjacent findings.
arXiv.org → CS, physics, math preprints. Free. NOT peer-reviewed — note this.
PubMed → Biomedical/health. Use MeSH terms for precise queries.
SSRN → Social science, economics, law working papers.
Semantic Scholar → AI-enhanced academic search with citation graphs.
IEEE Xplore → Engineering and CS papers (often paywalled — check for preprints).
```
**Grey literature sources by domain**:
```
Policy/government: Government reports, GAO studies, parliamentary inquiries
→ site:gao.gov, site:*.gov/reports, site:oecd.org
Think tanks: Brookings, RAND, Chatham House, NBER
→ "[topic] site:rand.org OR site:brookings.edu"
Industry reports: Vendor-neutral analyst reports, trade association data
→ "[topic] industry report filetype:pdf"
Theses: University repositories (often the most detailed single-topic work)
→ "[topic] thesis OR dissertation filetype:pdf site:*.edu"
Standards bodies: NIST, ISO, W3C, IETF RFCs
→ "[topic] site:nist.gov OR site:w3.org OR site:rfc-editor.org"
Conference proc.: Slides and papers from domain-specific conferences
→ "[topic] [conference name] proceedings OR slides"
```
**Citation chain technique**: When you find one highly relevant paper:
1. Read its references for foundational work (backward search)
2. Search "cited by" to find newer work that builds on it (forward search)
3. Check the authors' other publications for related work
4. This often uncovers sources that keyword searches miss
### Systematic Review Methodology (Lite)
For exhaustive-tier research, apply a lightweight systematic review approach:
1. **Define inclusion/exclusion criteria** before searching:
- Date range, language, source types, geographic scope
- What counts as "relevant" — define upfront, not after seeing results
2. **Document your search strategy**: record every query, database, and date searched
3. **Screen results in two passes**:
- Pass 1: title and snippet — exclude obviously irrelevant results
- Pass 2: read the full source — evaluate against inclusion criteria
4. **Extract data consistently**: use the same extraction template for every source
5. **Report the numbers**: "Searched N databases, retrieved M results, N1 passed screening, N2 included in final synthesis"
This is not a full academic systematic review, but it adds rigor and transparency that distinguishes exhaustive research from ad hoc searching.
---
## Cross-Referencing Techniques
@@ -136,20 +215,75 @@ Level 4: Expert consensus (well-established)
→ Mark as "widely accepted" or "scientific consensus"
```
### Contradiction Resolution
When sources disagree:
1. Check which source is more authoritative (CRAAP scores)
2. Check which is more recent (newer may have updated info)
3. Check if they're measuring different things (apples vs oranges)
4. Check for known biases or conflicts of interest
5. Present both views with evidence for each
6. State which view the evidence better supports (if clear)
7. If genuinely uncertain, say so — don't force a conclusion
### Contradiction Resolution Decision Tree
When sources disagree, work through this structured process:
```
CONFLICT: Source A says X, Source B says Y
│
├─ 1. Scope check: Are they measuring the same thing?
│ Example: "React is faster" vs "Vue is faster" — one measures
│ initial render, the other measures re-render. Not a real conflict.
│ → If different scope: report both with context, not as a conflict.
│
├─ 2. Quality gap: Compare CRAAP+ scores
│ → If 2+ letter grades apart: favor higher-rated source, note the
│ disagreement. Example: peer-reviewed study (A) vs blog post (C)
│ on the same empirical question — favor the study.
│
├─ 3. Temporal ordering: Is one an update/correction of the other?
│ → If newer source explicitly addresses and corrects older data:
│ favor newer. Example: "Our 2024 study corrects the methodology
│ flaw in the 2022 paper" — favor 2024.
│
├─ 4. Methodology comparison: Which has stronger evidence?
│ Consider: sample size, study design (RCT > observational > anecdote),
│ peer review status, replication.
│ → Favor stronger methodology. Explain the methodological difference.
│
├─ 5. Conflict of interest: Does one source have a COI?
│ → Favor the source without COI. Disclose the COI explicitly.
│ Example: vendor benchmark vs independent benchmark — favor independent.
│
├─ 6. Consensus weight: What do other sources say?
│ → If 5 sources say X and 1 credible source says Y: report X as
│ the majority view, Y as a noted dissenting position.
│
└─ 7. Genuinely disputed: No resolution possible
→ Present both positions with full evidence. Mark as "Disputed."
Do NOT force a conclusion. State what additional evidence would
resolve the conflict.
```
### Source Independence Verification
Two articles citing the same original study are ONE source, not two:
- Trace every claim to its origin before counting source agreement
- News articles often rewrite the same press release — that is one source
- "Multiple outlets report" is not corroboration if they share a single upstream source
- Independent means: different data collection, different research team, different methodology
---
## Synthesis Patterns
### Source Triangulation
Before synthesizing, verify key claims through triangulation — confirming a finding via multiple independent evidence types:
```
Triangulation types:
Data triangulation: Same question examined with different datasets
Method triangulation: Same question studied with different methods
(e.g., survey + case study + statistical analysis)
Source triangulation: Same claim confirmed by sources with different
perspectives (e.g., vendor + customer + analyst)
Temporal triangulation: Finding holds across different time periods
```
A claim supported by multiple triangulation types is much stronger than one confirmed by multiple sources of the same type. "Three blog posts agree" is weaker than "a blog post, a peer-reviewed study, and an SEC filing agree."
### Narrative Synthesis
```
The evidence suggests [main finding].
@@ -167,6 +301,7 @@ A key limitation is [gap or uncertainty].
FINDING 1: [Claim]
Evidence for: [Source A], [Source B] — [details]
Evidence against: [Source C] — [details]
Triangulation: [data/method/source types used]
Confidence: [high/medium/low]
Reasoning: [why the evidence supports this finding]
@@ -180,6 +315,180 @@ After synthesis, explicitly note:
- What data would strengthen the conclusions?
- What are the limitations of the available sources?
- What follow-up research would be valuable?
- What types of triangulation are missing? (e.g., "All sources are practitioner blogs — no academic validation exists")
---
## 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
```
---
@@ -280,27 +589,39 @@ According to recent research [1], the finding was confirmed by independent analy
---
## Cognitive Bias in Research
## Cognitive Bias Detection & Countermeasures
Be aware of these biases during research:
These biases are not hypothetical — they actively distort research outcomes. For each bias below, apply the countermeasure as a concrete step in your process.
1. **Confirmation bias**: Favoring information that confirms your initial hypothesis
- Mitigation: Explicitly search for disconfirming evidence
### 1. Confirmation Bias
**What it is**: Favoring information that confirms your initial hypothesis while unconsciously discounting contradictory evidence.
**How it manifests in research**: You find 3 sources supporting your initial hunch and stop searching. You dismiss a contradicting source as "low quality" without rigorous evaluation.
**Countermeasure**: In Phase 1, write down your initial assumption explicitly. In Phase 2, construct at least one "contrarian query" specifically designed to find disconfirming evidence. In Phase 4, count your sources: if >80% support one side, force a targeted search for the opposing view.
**Example**: Researching "Is TypeScript worth adopting?" — if your first 5 sources all say yes, search specifically for "TypeScript problems", "TypeScript not worth it", "TypeScript migration regret".
2. **Authority bias**: Over-trusting sources from prestigious institutions
- Mitigation: Evaluate evidence quality, not just source prestige
### 2. Anchoring Bias
**What it is**: The first piece of information you encounter disproportionately shapes your entire analysis.
**How it manifests in research**: The first article frames the topic in a specific way, and subsequent research unconsciously filters through that frame.
**Countermeasure**: After gathering all sources, re-read your synthesis. Ask: "Would I have written this the same way if I had encountered Source N first instead of Source 1?" If the first source you read is still dominating the framing, consciously rewrite the synthesis from a different source's perspective and compare.
3. **Anchoring**: Fixating on the first piece of information found
- Mitigation: Gather multiple sources before forming conclusions
### 3. Availability Bias
**What it is**: Over-weighting information that is easy to find (top search results, English-language, well-promoted content).
**Countermeasure**: After initial searches, ask: "What voices are missing?" Consider: non-English sources, academic papers behind paywalls (check preprint servers), practitioner experience that does not get blog posts (failure stories are under-reported). For exhaustive research, explicitly search grey literature and non-English sources.
4. **Selection bias**: Only finding sources that are easy to access
- Mitigation: Vary search strategies, check non-English sources
### 4. Survivorship Bias
**What it is**: Only seeing successes because failures are invisible — they do not publish blog posts or get media coverage.
**How it manifests in research**: Technology X looks universally successful because companies that failed with it quietly moved on without writing about it.
**Countermeasure**: For any "should we adopt X?" question, explicitly search for: "[X] failure", "[X] abandoned", "[X] migration away from", "[X] post-mortem". Check GitHub for projects that started with X and switched away (look at archived repos, migration PRs).
**Example**: Researching microservices adoption — searching only for success stories will miss the many companies that reverted to monoliths but did not publicize it.
5. **Recency bias**: Over-weighting recent publications
- Mitigation: Include foundational/historical sources when relevant
### 5. Authority Bias
**What it is**: Deferring to prestigious sources even when their evidence is thin.
**Countermeasure**: Evaluate the evidence, not the letterhead. A well-designed study from an unknown university with n=10,000 outweighs an opinion piece in a famous journal. Check: does the prestigious source provide data, or just assertions? Would you accept this evidence if it came from an unknown author?
6. **Framing effect**: Being influenced by how information is presented
- Mitigation: Look at raw data, not just interpretations
### 6. Framing Bias
**What it is**: Being influenced by how data is presented rather than what the data shows.
**How it manifests in research**: "90% success rate" vs "10% failure rate" — same data, different impression. Relative vs absolute risk: "doubles the risk" could mean 0.001% to 0.002%.
**Countermeasure**: When a source presents a statistic, mentally reframe it: convert relative to absolute numbers, invert percentages, check base rates. If a claim sounds dramatic, check the absolute magnitude.
---
@@ -325,3 +646,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
+307 -8
View File
@@ -198,9 +198,19 @@ When you receive a strategic question or analysis request:
- **Opportunity**: "Should we enter market X?"
- **Planning**: "What's our strategy for X?"
- **Risk**: "What are the risks of X?"
2. Define the analysis scope and frameworks to apply
3. Identify key data sources and research needs
4. Create a research plan with milestones
- **Trade-off resolution**: "Should we prioritize X or Y?"
- **Stakeholder alignment**: "How do we get buy-in for X?"
2. **Stakeholder Mapping** — Before any analysis, identify:
- Who are the decision-makers, influencers, and affected parties?
- What does each stakeholder optimize for (revenue, risk, speed, quality)?
- Where do stakeholder interests conflict? Map tensions explicitly.
- Who has veto power and what would trigger it?
3. Define the analysis scope and select frameworks deliberately:
- Pick 2-3 complementary frameworks (not just the obvious one)
- Plan how frameworks will feed into each other (e.g., PESTEL findings inform Porter's forces, which inform SWOT's external factors)
4. Identify key data sources and research needs
5. Create a research plan with milestones
6. **Assess execution constraints upfront**: timeline pressure, budget limits, team capacity, technical debt, organizational readiness
---
@@ -258,10 +268,36 @@ Strategic insight: Netflix's technology advantage + Blockbuster's inability to p
**Other frameworks**: PESTEL, Value Chain Analysis, Blue Ocean Strategy, BCG Matrix, Jobs-to-be-Done — apply when the question calls for it.
### Multi-Framework Synthesis (CRITICAL — never present frameworks in isolation)
After completing individual frameworks, ALWAYS produce a unified synthesis:
1. **Cross-framework validation**: Do SWOT threats align with Porter's high forces? Do PESTEL factors explain Porter's dynamics? Flag any contradictions between frameworks — contradictions often reveal the most important strategic insight.
2. **Convergence map**: Identify themes that appear across 2+ frameworks. These are high-confidence strategic factors.
3. **Divergence analysis**: Where frameworks disagree, investigate why. One framework's blind spot is often another's strength.
4. **Unified strategic narrative**: Synthesize into a 3-5 sentence summary that explains the strategic situation holistically, not as a list of framework outputs.
### Competitive Response Modeling
For any strategy that affects competitors, model their likely responses:
1. **Competitor capability assessment**: Can they match this move? How fast? At what cost?
2. **Competitor incentive analysis**: Is responding in their interest, or does it cannibalize their existing business?
3. **Response timeline**: Immediate (weeks), tactical (months), or strategic (years)?
4. **Second-order moves**: If they respond with X, what is our counter-move? Play out 2-3 rounds.
5. **Non-response scenario**: What if competitors ignore this move? What does that signal?
### Execution Feasibility Assessment
Every strategic option must be assessed for executability, not just desirability:
- **Organizational readiness**: Does the team have the skills? Is the culture aligned? What changes are needed?
- **Resource gap analysis**: What resources (people, capital, tech, partnerships) are missing? How long to acquire?
- **Dependency mapping**: What must happen first? What can be parallelized? What are the critical path items?
- **Change management load**: How much organizational change does this require? Rate: Low (process tweak) / Medium (new capability) / High (structural change) / Extreme (cultural transformation)
**Confidence scoring** — Tag every conclusion:
- **High** (≥80%): Multiple independent sources confirm; quantitative data available
- **Medium** (50-80%): 1-2 credible sources; some assumptions required
- **Low** (<50%): Limited data; significant assumptions; flag as exploratory
- For each confidence score, state the **key assumption** that, if wrong, would change the rating
For each framework:
1. Gather evidence from Phase 2 research
@@ -280,13 +316,41 @@ Generate actionable recommendations:
4. Map risks and mitigation strategies
5. Define success metrics and KPIs
### Scenario Planning (MANDATORY for any significant recommendation)
Structure every major recommendation with three scenarios:
- **Best case** (15-25% probability): What if key assumptions break in our favor? Quantify the upside. Define acceleration triggers.
- **Base case** (50-60% probability): Most likely outcome given current evidence. This is the planning target.
- **Worst case** (15-25% probability): What if key assumptions fail? Quantify the downside. Define exit criteria and pivot triggers.
For each scenario, calculate expected value: EV = Sum(outcome x probability). If expected value is negative, the recommendation needs revision.
### Stakeholder Impact Mapping
For each recommendation, assess impact on every identified stakeholder:
| Stakeholder | Impact (+/-/neutral) | Their likely reaction | Risk of blocking | Alignment action needed |
This mapping often reveals why "obviously correct" strategies fail — they ignore stakeholder dynamics.
### Trade-Off Articulation (NEVER present a recommendation without stating what you give up)
Every strategic choice has costs. For each recommendation, explicitly state:
- **What you gain** and the confidence level of that gain
- **What you sacrifice** (speed, cost, optionality, simplicity, focus)
- **What you foreclose** (future options this decision eliminates)
- **Reversibility**: Can this be unwound if wrong? At what cost? In what timeframe?
### Devil's Advocate Check
Before finalizing recommendations, actively challenge each one:
1. **Pre-mortem**: "Assume this strategy failed in 12 months. What went wrong?"
2. **Contrarian view**: "What would a skeptic say about this recommendation?"
3. **Second-order effects**: "What unintended consequences could this trigger?"
4. **Alternative framing**: "Is there a simpler/cheaper approach we're overlooking?"
If the devil's advocate reveals a fatal flaw, revise the recommendation. If it holds up, note the key risks and mitigations.
1. **Pre-mortem**: "Assume this strategy failed in 12 months. What went wrong?" — List the top 3 failure modes with probability estimates.
2. **Contrarian view**: "What would a skeptic say about this recommendation?" — Steelman the opposing position.
3. **Second-order effects**: "What unintended consequences could this trigger?" — Consider effects on customers, competitors, team morale, brand, and partnerships.
4. **Alternative framing**: "Is there a simpler/cheaper approach we're overlooking?" — The best strategy is often the one with the fewest moving parts.
5. **Survivorship bias check**: "Are we only looking at success stories? What about companies that tried this and failed?"
6. **Timing critique**: "Is now the right time? What changes in 6 months that might make this easier/harder/unnecessary?"
If the devil's advocate reveals a fatal flaw, revise the recommendation. If it holds up, note the key risks and mitigations explicitly in the final output.
### Implementation Risk Assessment
For each recommendation, produce a risk-adjusted implementation plan:
- **Critical dependencies**: What must be true for this to work? (Market conditions, team capabilities, partner cooperation, regulatory environment)
- **Early warning indicators**: What signals in weeks 2-4 would tell you this is off track?
- **Decision gates**: At what milestones will you evaluate continue/pivot/kill?
- **Minimum viable test**: What is the smallest experiment to validate the core assumption before full commitment?
Use a decision matrix to rank options:
- Strategic fit (1-5)
@@ -378,6 +442,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)"
+862
View File
@@ -23,6 +23,16 @@ Best practices:
- Prioritize: Rank items by impact
- Cross-reference: Look for SO (strength-opportunity) and WT (weakness-threat) combinations
- Action-oriented: Every SWOT item should suggest a strategic response
- Time-bound: Note whether each factor is stable, strengthening, or weakening
**SWOT Cross-Impact Matrix** — The real value of SWOT is in the intersections:
| | Opportunities | Threats |
|---|---|---|
| **Strengths** | SO strategies: Use strengths to capture opportunities (offensive) | ST strategies: Use strengths to neutralize threats (defensive) |
| **Weaknesses** | WO strategies: Fix weaknesses to unlock opportunities (investment) | WT strategies: Minimize weaknesses exposed by threats (survival) |
Prioritize: SO strategies first (highest ROI), then ST (protect position), then WO (selective investment), last WT (only if existential).
### Porter's Five Forces
@@ -36,6 +46,8 @@ Analyze industry attractiveness:
Rate each force: Low / Medium / High with supporting evidence.
**Dynamic Five Forces**: Forces change over time. For each force, note the **trend direction** (strengthening/stable/weakening) and the **trigger event** that could shift it. A force rated "Low" today with a strengthening trend deserves more attention than a stable "Medium" force.
### PESTEL Analysis
Macro-environmental scanning:
@@ -49,6 +61,45 @@ Macro-environmental scanning:
| **Environmental** | Climate regulations? Sustainability demands? Resource scarcity? |
| **Legal** | Employment law? IP protection? Competition law? Data privacy? |
### Framework Integration Methodology
Individual frameworks are lenses. Strategic insight comes from combining them. Here is how to synthesize multiple frameworks into a unified analysis:
**The Integration Cascade** — Use frameworks in dependency order:
```
Step 1: PESTEL (macro context)
→ Identifies external forces shaping the industry
→ Output: Which macro factors matter most? What is changing?
Step 2: Porter's Five Forces (industry structure)
→ PESTEL outputs feed directly into Porter's forces
→ Example: "AI adoption accelerating" (PESTEL-Tech) → "Threat of new entrants rising" (Porter)
→ Output: How attractive is this industry? Where is structural power?
Step 3: SWOT (company positioning within industry)
→ Porter's outputs define the external O/T quadrants
→ Internal assessment (S/W) is company-specific
→ Output: Where does this company sit relative to industry forces?
Step 4: Strategic Options Generation
→ SWOT cross-impact matrix generates candidate strategies
→ Porter's forces identify which strategies are structurally viable
→ PESTEL trends determine timing and urgency
```
**Cross-Framework Contradiction Resolution:**
When frameworks disagree, do not average or ignore — investigate:
- PESTEL says favorable + Porter says unattractive → Macro tailwind but bad industry structure (e.g., restaurant industry: everyone eats, but margins are terrible)
- SWOT says strong + Porter says high rivalry → Company advantage may erode faster than expected
- Resolution: State both findings, explain the tension, and let the tension inform the recommendation (e.g., "Enter but with a differentiation strategy that exploits the macro trend while avoiding head-on competition")
**Synthesis Quality Checklist:**
- Does the conclusion follow logically from framework outputs, or did you skip to a preferred answer?
- Did you weight frameworks by relevance (PESTEL matters more for market entry; Porter matters more for competitive strategy)?
- Are the frameworks consistent? If not, is the inconsistency explained?
- Could someone reconstruct your reasoning by reading the framework outputs alone?
### Market Sizing (TAM-SAM-SOM)
**TAM** (Total Addressable Market): Total market demand for a product/service.
@@ -236,3 +287,814 @@ 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.
```
---
## Strategic Analysis Anti-Patterns
Common cognitive traps that produce bad strategy. Actively check for these in every analysis:
| Anti-Pattern | Detection Question | Countermeasure |
|---|---|---|
| **Confirmation Bias** — Seeking data that supports pre-existing beliefs; ignoring contradictory evidence | "Did I search for disconfirming evidence with equal effort?" | For every key conclusion, explicitly search for the strongest counterargument |
| **Anchoring** — First number encountered dominates all later estimates (first source says "$10B market" and final estimate drifts toward $10B) | "Is my final estimate suspiciously close to the first number I found?" | Collect 3+ independent estimates; use both bottom-up and top-down methods; investigate any 2x+ divergence |
| **Strategy-by-Analogy** — "Uber did X, so we should do X in healthcare" without testing structural similarity | "What are the 3 most important differences between this situation and the analogy?" | Use analogies to generate hypotheses, never to validate conclusions |
| **Missing Causal Chain** — Clear start and desirable end, but no credible mechanism connecting them (Step 1 → ??? → Profit) | "What specifically happens between 'launch' and 'achieve outcome'?" | Every recommendation needs a testable causal chain: A → B → C → D |
| **Denominator Neglect** — Citing impressive absolutes while ignoring base rates ("10,000 users!" out of 2M impressions = 0.5%) | "Relative to what?" | Always present metrics as ratios/rates; compare to benchmarks |
| **Survivorship Bias** — Deriving strategy from winners only; ignoring that failed companies tried the same thing | "How many companies tried this and failed?" | Seek failure case studies; note success AND failure rates |
| **Planning Fallacy** — Timelines assuming everything goes right | "Does this plan require performing better than we ever have?" | Use reference class forecasting; add 30-50% buffer; present best/base/worst timelines |
---
## Uncertainty Quantification
### Expressing Uncertainty
**For quantitative estimates (market size, revenue, costs):**
- Never give a single number. Always give a range: "Market size: $8-12B (base estimate $10B)"
- State the confidence interval: "80% confident the market is between $8B and $12B"
- Identify the key variable driving the range: "Range is driven primarily by uncertainty in adoption rate (15-25%)"
**For qualitative assessments:**
- Use the calibrated confidence scale consistently:
- **Very High (>90%)**: Would be genuinely surprised if wrong. Multiple high-quality sources agree.
- **High (70-90%)**: Strong evidence, but plausible alternative interpretations exist.
- **Medium (50-70%)**: Balanced evidence. Reasonable people could disagree.
- **Low (30-50%)**: More uncertain than certain. Treat as hypothesis, not finding.
- **Very Low (<30%)**: Speculative. Useful for scenario planning but not for action.
### Assumption Tracking
Every analysis rests on assumptions. Make them explicit:
```
ASSUMPTION REGISTER:
| # | Assumption | Confidence | Impact if Wrong | Validation Method |
|---|-----------|------------|-----------------|-------------------|
| 1 | Market grows 15% YoY | High | Changes TAM by +/- 30% | Track quarterly industry reports |
| 2 | No new regulation in 12mo | Medium | Could block market entry | Monitor regulatory pipeline |
| 3 | Key hire joins by Q2 | Medium | Delays launch 3-6 months | Pipeline status check monthly |
| 4 | Competitor does not cut price | Low | Margin compression 10-15% | Track competitor pricing weekly |
```
Flag any assumption rated "Low" that has "High" impact — these are the **strategic landmines** that deserve contingency plans.
### When to Say "We Don't Know"
It is better to say "insufficient data to assess" than to fabricate a confident-sounding answer. Specifically:
- If fewer than 2 independent sources support a data point, flag it as unverified
- If the key variable has a range wider than 3x (e.g., market could be $5B or $15B), call out that the analysis is highly sensitive to this input
- If you are extrapolating a trend beyond the data range, state the extrapolation explicitly
---
## Industry-Specific Strategic Patterns
Certain strategic dynamics recur within industry categories. Recognizing these patterns accelerates analysis:
### Platform / Marketplace Businesses
- **Winner-take-most dynamics**: Network effects create power-law outcomes. Market share of #1 player often exceeds #2 + #3 combined.
- **Chicken-and-egg problem**: Must solve supply and demand simultaneously. Common solutions: single-player mode, subsidize one side, constrain geography first.
- **Multi-homing risk**: If users can easily use multiple platforms, network effects weaken. Strategy must increase switching costs or exclusive value.
- **Key metric**: Liquidity (match rate between supply and demand). Revenue follows liquidity, not the reverse.
### B2B SaaS
- **Land-and-expand**: Initial deal size matters less than expansion potential. Net revenue retention >120% can drive growth even at 0 new logos.
- **Switching cost lifecycle**: Switching costs increase with integration depth, data accumulation, and workflow embedding. Year 1 churn is always highest.
- **Category creation vs. category entry**: Creating a new category requires 3-5x more marketing spend but yields pricing power. Entering an existing category is cheaper but forces competitive positioning.
- **Key metric**: Net Revenue Retention (NRR). Above 130% = exceptional. Below 100% = leaky bucket that marketing cannot fill.
### Consumer / D2C
- **Acquisition cost spiral**: As easy-to-reach audiences saturate, CAC rises. Growth requires channel diversification or organic/viral mechanics.
- **Brand as moat**: In commoditized categories, brand is the primary differentiation. Brand building requires consistency over years, not campaigns over months.
- **Retention curve shape**: If the retention curve flattens (users who stay past day 30 tend to stay indefinitely), invest in onboarding. If it keeps declining, the product has a retention problem, not an acquisition problem.
- **Key metric**: Cohort retention at day 30/60/90. Payback period on CAC.
### Regulated Industries (Healthcare, Finance, Insurance)
- **Compliance as moat**: Regulatory requirements (HIPAA, SOC2, PCI-DSS) are expensive to achieve but create durable barriers to entry.
- **Sales cycle reality**: Enterprise sales cycles of 6-18 months are normal. Budget accordingly. Premature scaling of sales teams is the #1 killer.
- **Build vs. partner**: In heavily regulated industries, partnering with incumbents (who have regulatory relationships) often beats trying to disrupt them directly.
- **Key metric**: Sales cycle length, regulatory approval timeline, compliance cost as % of revenue.
+331
View File
@@ -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 = "실거래 실행 전 사용자의 명시적 승인 필요 — 강력히 권장"
+307
View File
@@ -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 = "트윗을 직접 게시하지 않고 대기열 파일에 기록하여 검토"
+229
View File
@@ -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