---
name: ads
description: |
  Managed multi-channel ads. Only load when user explicitly asks to run paid ads
  (e.g. "帮我投广告", "launch a campaign", "推广这款商品", "加广告预算", "查看广告效果",
  "ads launch", "优化广告", "生成广告报告"). Do NOT load for general marketing
  questions or organic growth — those go to the `growth` skill.
---

# Ads 托管广告投放

AI 广告官:通过 `~/ads/` 工作目录持续运营用户的付费广告投放。

## 核心:`~/ads/` 工作目录

所有操作基于用户 workspace 的 `~/ads/`,两层结构:

- **用户级根目录**: 跨 campaign 的整体策略和经验
- **`campaigns/<slug>/` 子目录**: 每个 campaign 的专属文件

```
~/ads/
├── ADS.md              用户级整体策略
├── LEARNINGS.md        跨 campaign 经验沉淀
├── PROGRESS.md         全局工作日志 (每段标 campaign tag)
├── REPORTS/            用户级周报/月报
├── assets/             跨 campaign 共享素材 (.gitignore)
├── campaigns/
│   └── <slug>/
│       ├── STRATEGY.md     campaign 专属策略
│       ├── CREATIVES.md    campaign 变体表
│       └── NOTES.md        campaign 运行观察
└── .git/
```

## 启动 SOP(每次会话)

1. `ls ~/ads/ADS.md` — 不存在 → 进入"初始化流程"(见下方)
2. `cat ~/ads/PROGRESS.md | head -30` — 上次做了什么、异常、下次待办
3. `git -C ~/ads log --oneline -5` — 最近变更
4. `ls ~/ads/campaigns/` — 列出本地登记的 campaign
5. `ads status` — 从后端拉事实（默认 JSON 输出，加 `--pretty` 可读格式）: 在跑的 campaign 列表 + 7 天花费 + 钱包 + 月度 cap
   - 钱包分为付费余额(`balanceUsd`)和赠送余额(`grantedBalanceUsd`),**赠送余额不能用于广告投放**
   - 如果付费余额 < 阈值,第一时间告诉用户
   - 如果月度 cap 使用率 > 80%,同样提示
   - 如果后端 campaign 和本地目录对不齐,视为需要修复
6. → 决定本次要做的**一个**动作
   - 聚焦单 campaign 的 session 优先 `cat ~/ads/campaigns/<name>/*.md` 载入专属上下文

## 初始化流程(第一次会话)

1. Copy the template from this skill's directory: `cp -r $(dirname "$SKILL_PATH")/template/user/ ~/ads/`
   (The template directory is at the same path as this SKILL.md file, under `template/user/`.)
2. `cd ~/ads && git init && git add -A && git commit -m "init workspace"`
3. **对话式引导填 ADS.md**(一次问一个,不要塞 10 个表单):
   - "我们要推广什么?"（商品、店铺、网站、活动等均可。如果是商品,加载 `product` skill 查询商品信息）
   - "默认目标受众是谁?(地域 / 年龄 / 设备 / 时段)"
   - "月度总预算上限多少美元?"
   - "有什么品牌禁忌或必须避开的词吗?"
   每问完一段就写进 ADS.md,`git commit -m "fill ADS.md: <段落>"`
4. `ads init --total-monthly-budget <X>` — 后端创建 user_ads 记录 + 确保 Google Ads label 存在 + 查 USD wallet
5. 把后端返回的 ID 自动填进 ADS.md 的"后端登记"段,`git commit -m "register backend"`
6. 提示用户:
   - 注意区分 `wallet_balance_usd`(付费余额)和 `wallet_granted_usd`(赠送余额)。**赠送余额不能用于广告投放**,只有付费余额可以。
   - 付费余额为 0 → "需要先充值. 说 'ads budget topup --amount 100' 可充 $100"
   - 有付费余额 → "可以现在 launch 第一个 campaign,或者下次会话再开始"

**不会自动 launch 任何 campaign.** 第一次 launch 必须由用户明确要求。

## 单会话单任务

每次会话只执行一种动作(launch / optimize / collect / report / budget / pause / diagnose / creative 的其中一个),完成后 commit 并更新 `PROGRESS.md`。出错时可以精准 `git revert`。

**例外**: `collect` 在每个其它动作开头隐式跑(让 LLM 基于新鲜数据推理),不算独立 session 动作。

## 8 个动作

### 1. launch — 启动新 campaign

**触发**: 用户说"推广 XX"、或 PROGRESS 里标记了下次 launch。

**流程**:
1. 读 ADS.md 拿整体策略,确认推什么产品、受众、预算
2. 加载 `gen` skill 生成多个素材变体到 `~/ads/assets/`
3. 构造 CampaignSpec JSON(参考下方"CampaignSpec 结构"),写到 `/tmp/spec.json`
4. `ads launch create --spec /tmp/spec.json --reason "..."` — 默认 PAUSED
5. **必做**: 创建 `~/ads/campaigns/<slug>/` 子目录:
   ```bash
   slug=<campaign-slug>
   mkdir -p ~/ads/campaigns/$slug
   cp -r $(dirname "$SKILL_PATH")/template/campaign/. ~/ads/campaigns/$slug/
   ```
6. 填 `campaigns/<slug>/STRATEGY.md`(从 spec.json 拷贝产品、受众、关键词、日预算、差异化角度,加后端关联 ID)
7. 填 `campaigns/<slug>/CREATIVES.md`(5 个变体的表格,CTR/CVR 留空)
8. 检查 compliance_check 通过后 → `ads launch enable <id> --reason "compliance passed"`
9. 追加到 `PROGRESS.md`(tag: `launch, campaign=<slug>`)
10. `git -C ~/ads add -A && git -C ~/ads commit -m "launch: <slug>"`

### 2. optimize — 优化一个 campaign

**触发**: sentinel 定时或用户说"优化一下"。

**流程**:
1. `ads collect` 先拉最新数据(SOP 前置)
2. 读 `~/ads/campaigns/<slug>/CREATIVES.md` 看变体表现
3. 读 `~/ads/LEARNINGS.md` 看历史经验
4. 决定要改什么(一个或多个):
   - 淘汰低 CTR 素材: `ads optimize pause-variant --campaign <id> --variant <id> --reason "..."`
   - 恢复素材: `ads optimize resume-variant --campaign <id> --variant <id> --reason "..."`
   - 加新关键词: `ads optimize add-keywords --campaign <id> --keywords "word1" "word2" --reason "..."`
   - 移除关键词: `ads optimize remove-keywords --campaign <id> --keywords "word1" --reason "..."`
   - 加否定词: `ads optimize add-negatives --campaign <id> --keywords "word1" "word2" --reason "..."`
   - 调出价修正: `ads optimize change-bid-mod --campaign <id> --modifier 1.2 --reason "..."`
   - 替换素材: `ads optimize replace-variant --campaign <id> --old-variant <id> --spec /tmp/v.json --reason "..."`
   - 调预算: `ads budget set --campaign <id> --daily <micros> --reason "..."`
5. 更新 `campaigns/<slug>/CREATIVES.md`(把被淘汰的变体移到"已淘汰"段)
6. 追加一段到 `campaigns/<slug>/NOTES.md`(观察 + 推理 + 下次验证点)
7. 如果这个洞察是可泛化的,也追加到 `~/ads/LEARNINGS.md`
8. 追加到 `PROGRESS.md`
9. commit

### 3. collect — 拉最新数据

**触发**: 定时(每天)或作为其它动作的前置。

**流程**:
1. `ads collect --days 7` → 后端从 Google Ads 拉 per-campaign 和 per-variant 的最新数据,返回 JSON
2. 对返回的每个 snapshot 中的 `variantPerf` 项,找到对应 `campaigns/<slug>/CREATIVES.md`(通过 `campaign_id` 匹配——每个 `campaigns/<slug>/STRATEGY.md` 的"后端关联"段记录了 `campaign_id`),用新 CTR/CVR/花费重写"在投变体"表
3. 如果是纯 collect session(不是被其它动作调用),追加一段到 PROGRESS.md 和 commit。
   如果是嵌入在其它动作里,则跟那个动作的 commit 合并。

### 4. report — 生成周/月报告

**触发**: sentinel 定时或用户问"最近怎么样"。

**流程**:
1. `ads report --period week`(或 `--period month`)→ 后端返回结构化数据
2. LLM 结合 `LEARNINGS.md` 和 `ADS.md` 的业务目标,组合出人话 markdown 报告
3. 写到 `~/ads/REPORTS/2026-W14.md`(周报)或 `~/ads/REPORTS/2026-04.md`(月报)
4. PROGRESS.md tag 一段 "generated report"
5. commit

### 5. budget — 调预算 / 钱包

**触发**: 用户说"加预算"、"充钱"。

**场景**:
- "加到 $20/天" → `ads budget set --campaign <id> --daily 20000000 --reason "..."`
- "月度上限改 $500" → `ads budget set --total-monthly 500000000 --reason "..."`
- "充 $100" → `ads budget topup --amount 100` → 把返回的 `checkout_url` 作为 markdown 链接输出给用户（topup 用 USD）
- "看下预算" → `ads budget show`（注意区分付费余额和赠送余额,赠送余额不可用于广告）

改完之后相应更新 `ADS.md`(月度 cap 变化)或 `campaigns/<slug>/STRATEGY.md`(campaign 日预算变化),commit。

### 6. pause — 紧急停投

**触发**: 用户说"停掉"、"全停"。

**流程**:
- "停掉 XX campaign" → `ads pause campaign <id> --reason "..."`
- "全停" → `ads pause all --reason "..."`
- "停某个素材" → `ads pause variant <variant_id> --reason "..."`
- "恢复" → `ads resume ...`(但钱包低余额或月度 cap 超出时会被后端拒)

停掉之后在对应 `campaigns/<slug>/NOTES.md` 记一笔,commit。

### 7. diagnose — 问题排查

**触发**: 用户说"为啥没展示"、"怎么烧钱没单"。

**流程**:
1. `ads diagnose --scope all`(或 `--campaign <id>` 聚焦某个)
2. 后端返回 issues 列表,每个带 `cli_hint`
3. LLM 把问题翻译成人话解释给用户,并建议下一步
4. 如果用户同意某个建议,执行对应的 `cli_hint`(这变成一个新的 optimize / pause / budget session,原则上 diagnose session 本身不改任何东西)
5. 更新 `campaigns/<slug>/NOTES.md` 或 `PROGRESS.md`(记录诊断发现和建议,不改其它状态文件)
6. commit(仅包含文档更新)

### 8. creative — 素材迭代

**触发**: 独立会话,聚焦素材质量。

**流程**:
1. `ads status --include-variants` 看现状
2. 读 `~/ads/campaigns/<slug>/CREATIVES.md` 和 `~/ads/LEARNINGS.md`
3. 决定要生成什么新变体(几个 prompt、什么风格)
4. 加载 `gen` skill 生成素材到 `~/ads/assets/`
5. 写进对应 `campaigns/<slug>/CREATIVES.md`
6. 如果要把新变体上线到现有 campaign: `ads optimize replace-variant --campaign <campaign_id> --old-variant <id> --spec /tmp/v.json --reason "..."`
7. 如果只是建素材库待用,不上线,也 OK
8. commit

## CampaignSpec 结构(构造 spec.json 用)

```json
{
  "userId": "<CLI 自动从 ~/.optima/token.json 的 JWT 提取, 不需要手动填>",
  "name": "<slug-name-without-u-prefix>",
  "objective": "conversions",
  "productIds": ["12345"],
  "audience": {
    "geos": ["US", "CA"],
    "ageRanges": ["AGE_RANGE_25_34", "AGE_RANGE_35_44"],
    "genders": ["FEMALE"],
    "devices": ["MOBILE", "DESKTOP"],
    "intentSignals": ["夏季连衣裙", "summer dress"],
    "excludeSignals": ["免费", "free"]
  },
  "budget": { "dailyLimitMicros": 10000000, "totalLimitMicros": 300000000 },
  "variants": [
    {
      "variantId": "v_abc123",
      "headlines": ["标题1 最多 30 字", "标题2", "标题3", "标题4", "标题5"],
      "descriptions": ["描述1 最多 90 字", "描述2"],
      "imageAssets": ["/home/user/ads/assets/image_abc.png"],
      "finalUrl": "https://shop.example.com/p/12345"
    }
  ]
}
```

**Google Ads RSA 要求**: 至少 3 个 headlines(各 ≤30 字符),至少 2 个 descriptions(各 ≤90 字符)。后端会强制校验,违规会 fail compliance 预审。

## 提交约定

- 每次会话结束必有**一个** commit
- message: `<action>: <一句话>` 例: `launch: summer-promo`、`optimize: drop low-CTR creative`、`budget: topup $100`
- PROGRESS.md 更新和动作产物**合并在同一个 commit**
- 失败时,只更新 PROGRESS.md 记失败原因(其它状态文件不动)
- `~/ads/.git/` 是本地 only,不推远程

## 归档

某 campaign 被删除或生命周期结束时:`mv ~/ads/campaigns/<slug> ~/ads/archive/<slug>`,不要直接删(保留历史给 LEARNINGS 参考)。`ls ~/ads/campaigns/` 永远只反映当前活跃/暂停的 campaign。

## Skill 之间的协作

按需加载其它 skill:
- **`gen`** — image 生成
- **`video-gen`** — video 生成
- **`scout`** / **`shein`** / **`tiktok`** 等 — 竞品研究、关键词发现(在 launch 或 optimize 的策略阶段)
- **`sentinel`** — 定时调度 collect / optimize / report
- **`browser`** — API 不支持时的兜底

