Просмотр исходного кода

docs(claude): commit message 格式去除 Co-Authored-By 和 Generated 行,精简长度

刘立冬 2 недель назад
Родитель
Сommit
fd92407bfe
1 измененных файлов с 727 добавлено и 0 удалено
  1. 727 0
      CLAUDE.md

+ 727 - 0
CLAUDE.md

@@ -0,0 +1,727 @@
+# Claude 开发指南
+
+## 项目概述
+
+这是一个基于 Reson Agent 框架的业务开发项目。项目包含:
+- **Agent 框架源码**(只读,不可修改)
+- **业务开发区域**(可自由开发)
+- **基础设施服务**(按需使用)
+
+## 🚨 重要约束
+
+### Git 操作规范
+
+**🚨 硬性规则:没有用户明确指令,绝对不执行 git commit / git push。**
+
+**默认行为:**
+- ❌ **不自动提交(commit)** — 必须等待用户明确说"提交"或"commit"才能执行
+- ❌ **不自动推送(push)** — 必须等待用户明确说"推送"或"push"才能执行
+- ❌ **不主动提议提交** — 完成代码修改后,汇报改动内容即可,不要主动问"要不要提交"
+- ❌ **禁止以任何形式暗示/诱导提交** — 以下句式全部禁用:
+  - "要不要我帮你提交/推送?"
+  - "需要我现在提交推送吗?"
+  - "是否需要提交这些修改?"
+  - "改完后要不要一起提交?"
+  - "现在可以推送了吗?"
+  - 任何结尾带"提交/推送"问号的句子都是违规
+- ✅ 改完代码只做两件事:(1) 汇报改了什么;(2) 停下,等用户指令
+- ✅ 可以创建分支、查看状态、查看 diff
+- ✅ 提交前必须向用户展示改动内容并等待确认
+
+**正确流程:**
+1. 完成代码修改
+2. 展示改动摘要给用户
+3. **等待用户主动说"提交"或"commit"**(不要主动询问)
+4. 执行 `git add` + `git commit`
+5. **等待用户主动说"推送"或"push"**(不要主动询问)
+6. 执行 `git push`
+
+**Commit message 格式规范(2026-06-08 用户确认):**
+- ❌ **不加** `Co-Authored-By: Claude ...` 行
+- ❌ **不加** `🤖 Generated with [Claude Code](...)` 行
+- ✅ 标题一行,模仿项目历史风格(`feat(xxx): ...` / `fix(xxx): ...`)
+- ✅ 正文最多 3-5 行,只写"为什么/做了什么"的本质,不堆改动清单
+- ✅ 信息越短越好,能一行说清就一行
+
+### 禁止修改的目录(框架源码)
+
+以下目录是 Agent 框架的核心源码,**在任何情况下都不得修改**:
+
+```
+agent/                  # Agent 框架核心代码
+├── core/              # 核心运行逻辑
+├── tools/             # 内置工具系统
+├── llm/               # LLM 调用封装
+├── trace/             # 轨迹追踪
+├── skill/             # Skill 系统
+├── cli/               # 命令行工具
+├── utils/             # 工具函数
+└── docs/              # 框架文档
+```
+
+**如果需要扩展功能,应该:**
+- ✅ 在 `examples/[your_project]/tools/` 创建自定义工具
+- ✅ 在 `examples/[your_project]/skills/` 创建自定义 Skill
+- ✅ 通过配置文件调整框架行为
+- ❌ 不要修改 `agent/` 目录下的任何文件
+
+### 可以修改的目录(业务开发区域)
+
+```
+examples/              # 业务开发主目录
+├── my_business/       # 你的业务项目
+│   ├── config.py      # 业务配置
+│   ├── run.py         # 运行入口
+│   ├── task.prompt    # 任务描述
+│   ├── tools/         # 自定义工具(可选)
+│   ├── skills/        # 自定义 Skill(可选)
+│   └── outputs/       # 输出目录
+└── [other_examples]/  # 其他业务项目
+```
+
+### 基础设施目录(按需使用)
+
+```
+frontend/              # 前端可视化界面
+gateway/               # API 网关
+im-server/             # IM 服务器
+im-client/             # IM 客户端
+knowhub/               # 知识库服务
+config/                # 全局配置
+```
+
+这些目录提供基础设施支持,通常不需要修改。如需调整配置,优先在业务项目的 `config.py` 中覆盖。
+
+## 当前修改说明
+
+### 已修改文件
+
+1. **frontend/react-template/package-lock.json**
+   - 升级 Semi UI 组件库:`2.56.0` → `2.92.2`
+   - 目的:使用最新的 UI 组件特性
+   - 影响范围:前端可视化界面
+
+2. **examples/my_business/** (新增)
+   - 业务开发示例项目
+   - 包含:配置、运行脚本、任务描述
+   - 当前任务:分析 `agent/core` 目录结构
+
+3. **examples/auto_ad_placement/** (新增)
+   - 腾讯广告自动化投放 Agent 系统
+   - 基于腾讯广告 Marketing API v3.0
+   - 包含:7个 Agent(main/audience/creative/budget/system_ops/monitor/data_analyst)
+   - 工具:ad_api.py(API封装)、data_query.py(数据查询)、budget_calc.py(预算计算)等
+   - Skills:ad_domain、budget_strategy、audience_strategy、creative_strategy、monitor_rules
+
+4. **examples/auto_put_ad_mini/** (新增 — 当前活跃开发)
+   - 小程序投流场景 — 面向 ROI 的广告调控 Agent
+   - 定位:自动化系统的**最小业务单元**,专注"数据驱动的广告粒度决策"
+   - 后续将作为模块接入 `auto_put_ad` 完整体系(无人工干预 → 自主决策 → 自学习反馈)
+
+## 🎯 auto_put_ad_mini:当前阶段目标与领域知识
+
+> **工作目录**: `examples/auto_put_ad_mini/`
+> **业务场景**: 微信小程序投流(`MARKETING_CARRIER_TYPE_MINI_PROGRAM_WECHAT`)
+> **核心目标**: 基于 ROI + 跑量(消耗)双维度,自动给出广告粒度的操作决策
+
+### 阶段定位
+
+本项目是整个自动化投放系统的**第一个业务单元**:
+
+```
+终极形态(auto_put_ad)          当前阶段(auto_put_ad_mini)
+┌──────────────────────┐        ┌───────────────────────┐
+│ 受众策略 Agent        │        │                       │
+│ 创意策略 Agent        │        │  数据拉取 → ROI 计算  │
+│ 预算策略 Agent        │        │       ↓               │
+│ ★ 监控调控 Agent ◄───┼────────│  决策引擎(规则+策略) │
+│ 数据分析 Agent        │        │       ↓               │
+│ 系统运维 Agent        │        │  操作执行(API 调用)  │
+│ 自学习/反馈环        │        │                       │
+└──────────────────────┘        └───────────────────────┘
+```
+
+### 当前阶段决策范围(仅限以下操作)
+
+| 决策类型 | 操作 | API 端点 | 触发条件 |
+|---------|------|---------|---------|
+| **调整出价** | 修改广告 bid_amount | `/v3.0/adgroups/update` | ROI 偏离目标、跑量不足/过快 |
+| **暂停广告** | 修改 configured_status → DELETED/SUSPEND | `/v3.0/adgroups/update` | ROI 过低、长期无消耗、当日预算耗尽 |
+
+> ⚠️ 当前阶段**不包含**:创建广告、修改定向、修改创意、调整预算分配。这些属于后续扩展。
+
+### 数据维度与决策依据
+
+Agent 需要拉取并分析以下三个时间粒度的数据:
+
+| 时间粒度 | 用途 | 关键指标 |
+|---------|------|---------|
+| **小时级** | 实时监控,快速止损 | 最近 1-3 小时消耗速率、转化成本突变 |
+| **日级** | 当天表现评估,出价微调 | 当日 ROI、当日消耗进度、当日转化量 |
+| **周级** | 趋势判断,策略调整 | 7 日 ROI 均值、消耗趋势、转化成本波动 |
+
+### 核心决策双维度
+
+```
+                    ROI 高
+                      │
+         ┌────────────┼────────────┐
+         │  高ROI低量  │  高ROI高量  │
+         │  → 提价放量  │  → 维持/微调 │
+消耗少 ──┼────────────┼────────────┤── 消耗多
+         │  低ROI低量  │  低ROI高量  │
+         │  → 暂停观察  │  → 降价/暂停 │
+         └────────────┼────────────┘
+                      │
+                    ROI 低
+```
+
+**决策逻辑(7 种 action,详见 config.py 和 skills/)**:
+1. **pause** — 规则标记 roi_low + LLM综合判断(裂变/历史/tier组合/数据质量)→ 暂停
+2. **bid_down** — 规则标记 bid_down_candidate + LLM权衡 → 降价 3%-5%
+3. **bid_up** — 规则标记 bid_up_candidate(仅4-7天冷启动期)→ 提价 5%-10%
+4. **scale_up** — 成熟+稳定+高消耗+ROI达标 → 建议扩量
+5. **creative_adjust** — ROI达标但素材吸引力不足 → 建议换素材
+6. **observe** — 数据不充分 / 刚调整过 → 观察等待
+7. **hold** — 无异常信号 → 保持不变
+
+### 先验策略规则
+
+- **ROI 目标**:业务配置,通常 >= 1.0(每投入 1 元至少回收 1 元)
+- **阈值基准**:ROI 基于渠道P50(全体 `channel_roi_p50`,即"动态ROI 7日均值"的中位数),裂变率基于同类人群包均值
+- **出价调整步长**:提价 5%-10%,降价 3%-5%(提降分离,降价更保守)
+- **冷启动保护**:<=3天极度保护,4-7天仅允许提价
+- **最低消耗门槛**:日消耗 < 100 元的广告数据不具统计意义;降价需>=500元/天
+- **出价边界**:下限 0.05 元,上限 1.00 元
+- **关停线**:`ROI_LOW_FACTOR=0.75`,**提价线**:`BID_UP_ROI_FACTOR=1.05`,**降价线**:`BID_DOWN_ROI_FACTOR=0.90`
+- **暂停后复活**:本阶段不处理,留给后续扩展
+
+### ROI 计算公式
+
+#### 简单 ROI(直接收益率)
+```
+ROI = 收入(GMV / 转化价值) ÷ 广告消耗(cost)
+
+# 分时间粒度
+hourly_roi = sum(hourly_revenue) / sum(hourly_cost)
+daily_roi  = daily_revenue / daily_cost
+weekly_roi = sum(7d_revenue) / sum(7d_cost)
+```
+
+#### 动态 ROI (7日均值)(考虑裂变效率稳定性的动态 ROI)
+
+**⚠️ 重要:决策参考使用 动态 ROI (7日均值) 均值,而非单日值**
+
+**公式定义**:
+```
+对每一天(需日消耗 ≥ 100 元才参与计算):
+  T0裂变系数 = T0裂变数(fission0_count) / 首层打开数(open_count)
+  arpu       = 总收入 / 总回流人数
+
+  当日裂变收益率 = T0裂变数 × arpu / cost
+  当日回流倍数   = 总回流人数 / 首层打开数
+
+7日滚动均值(min_periods=3,至少3天合格数据即可计算):
+  回流倍数_7日均值     = mean(当日回流倍数) over 7天
+  T0裂变系数_7日均值   = mean(T0裂变系数) over 7天
+  裂变效率稳定因子     = 回流倍数_7日均值 / T0裂变系数_7日均值
+
+动态 ROI (7日均值) = 当日裂变收益率 × 裂变效率稳定因子
+```
+
+**变量含义说明**:
+- **当日裂变收益率**:当天每投入 1 元,通过 T0 层裂变带来的直接收益
+- **当日回流倍数**:当天每个首层用户平均带来多少总回流用户(含裂变)
+- **裂变效率稳定因子**:7 日裂变效率的稳定性调整系数,反映长期裂变能力
+- **动态 ROI (7日均值)**:综合考虑当日收益和 7 日裂变稳定性的动态 ROI
+
+**两个关键指标**:
+1. **动态 ROI (7日均值)**(单日值):某一天的 动态 ROI (7日均值),如 20260412 = 1.2071
+2. **动态 ROI (7日均值) 均值**(多日均值):最近 N 天每天的 动态 ROI (7日均值) 求平均,如 7 天均值 = 1.7295
+
+**决策使用规则**:
+- **广告级决策**:使用单个广告的 动态 ROI (7日均值)(需连续 7 天日消耗 ≥ 100 元)
+- **人群包评估**:使用人群包整体的 动态 ROI (7日均值) 均值(用于整体质量评估)
+- **关停阈值**:动态 ROI (7日均值) < 渠道P50 × ROI_LOW_FACTOR(详见 config.py)→ 关停
+
+**计算层级差异**:
+- **广告级 ROI**:先按广告聚合,再计算 ROI(用于单个广告决策)
+- **人群包级 ROI**:先汇总所有广告数据,再计算 ROI(用于整体评估)
+- 两者数值可能不同,用途不同,不能直接对比
+
+### 关键数据字段映射(腾讯广告 Reporting API)
+
+| 业务含义 | API 字段 | 说明 |
+|---------|---------|------|
+| 广告消耗 | `cost` | 单位:分 |
+| 曝光量 | `view_count` | |
+| 点击量 | `valid_click_count` | |
+| 转化量 | `conversions_count` | 取决于 optimization_goal |
+| 转化成本 | `cost_per_conversion` | cost / conversions_count |
+| 千次曝光成本 | `thousand_display_price` | |
+| 点击率 | `ctr` | |
+| 当前出价 | `bid_amount`(广告属性) | 单位:分 |
+| 广告状态 | `configured_status` / `system_status` | |
+
+### 项目结构规划
+
+```
+examples/auto_put_ad_mini/
+├── run.py                    # 运行入口
+├── config.py                 # 业务配置(ROI 阈值、出价边界等)
+├── presets.json              # 预设参数
+├── prompts/
+│   └── system.prompt         # Agent 系统 Prompt
+├── tools/
+│   ├── ad_api.py             # 腾讯广告 API 封装(拉数据 + 操作)
+│   └── roi_calculator.py     # ROI 计算与决策建议生成
+├── skills/
+│   ├── ad_domain.md          # 业务模型:裂变模型、R值、ROI公式
+│   ├── platform_rules.md     # 平台硬约束:oCPM学习期、调价上限
+│   ├── decision_framework.md # 决策框架:角色 + 候选标记 + 年龄策略
+│   ├── action_playbook.md    # 动作手册:7种action + 权衡原则
+│   └── posterior_wisdom.md   # 后验经验:学习中断/置信度分级
+└── outputs/                  # 运行输出
+```
+
+### 与 auto_put_ad 的关系
+
+- `auto_put_ad_mini` 是 `auto_put_ad` 终极体系中 **Monitor/调控 Agent** 的前身
+- 当前阶段独立运行,只做"数据→决策→执行"单向链路
+- 后续接入完整体系后,将增加:反馈环(执行结果回馈策略)、跨 Agent 协作、自学习机制
+- 工具层(`tools/ad_api.py`)设计时应考虑复用性,便于后续迁移
+
+## 腾讯广告 3.0 关键 API 知识
+
+**⚠️ 重要:本项目使用腾讯广告 Marketing API v3.0,与旧版(2.0)有根本性区别!**
+
+### 层级结构(3.0 简化为 2 层)
+
+| 旧版(2.0,已废弃) | 新版(3.0,当前使用) |
+|---------------------|----------------------|
+| 推广计划(Campaign) | ❌ 已移除 |
+| 广告组(AdGroup) | ❌ 业务概念已被"广告"取代 |
+| 广告(Ad)| ✅ **广告** — 3.0 顶层单位 |
+| 广告创意 | ✅ **动态创意(Dynamic Creative)** |
+
+### API 端点与业务概念的映射(避免混淆)
+
+| 业务概念 | API 端点 | 返回字段 | 说明 |
+|---------|---------|---------|------|
+| **广告**(3.0 顶层) | `/v3.0/adgroups/add` | `adgroup_id` | 技术保留旧名,但业务是"广告" |
+| **创意** | `/v3.0/dynamic_creatives/add` | `dynamic_creative_id` | 组件化创意 |
+
+### 广告创建关键参数(`/v3.0/adgroups/add`)
+
+本业务固定参数:
+- `marketing_goal = MARKETING_GOAL_USER_GROWTH`(用户增长)
+- `marketing_carrier_type`:`MARKETING_CARRIER_TYPE_MINI_PROGRAM_WECHAT` 或 `MARKETING_CARRIER_TYPE_WECHAT_OFFICIAL_ACCOUNT`
+- `bid_mode = BID_MODE_OCPM`(oCPM 出价,固定)
+- `optimization_goal`:`OPTIMIZATIONGOAL_PAGE_VIEW` 或 `OPTIMIZATIONGOAL_CLICK`
+- `targeting.custom_audience`:自有人群包 ID 数组
+- `targeting.age`:年龄区间数组,如 `[{"min": 25, "max": 35}]`
+- `time_series`:336 位字符串(48段×7天,每段30分钟,"1"=投放)
+
+### 3.0 核心策略变化
+
+- 旧策略:堆砌大量"广告+创意"组合(拼基建)
+- 新策略:**少广告、多素材**,同一广告下创建多个创意,系统自动优选(拼素材)
+- 数据聚合在同一营销目标下,缩短冷启动周期
+
+### API 限制
+
+- 单账户 QPS 限制 10
+- 批量操作单次最多 50 条
+- 出价和预算单位:分(1元 = 100分)
+- 审核时间:普通素材 2-4 小时,节假日可能延长至 24 小时
+- 数据延迟:实时数据 15-30 分钟,转化数据 1-2 小时
+
+## 开发规范
+
+### 0. Python 环境规范
+
+**每次执行 Python 脚本前,必须确保使用虚拟环境:**
+
+```bash
+# 检查虚拟环境是否存在
+if [ ! -d ".venv" ]; then
+    python3 -m venv .venv
+fi
+
+# 激活虚拟环境
+source .venv/bin/activate
+
+# 安装依赖(如需要)
+pip3 install -r requirements.txt
+```
+
+- 使用 `pip3` 而非 `pip` 安装依赖
+- 虚拟环境路径:`.venv/`
+- 执行脚本统一使用:`.venv/bin/python3`
+
+### 1. 创建新业务项目
+
+```bash
+# 在 examples/ 下创建新项目
+mkdir -p examples/your_project/{tools,skills,outputs}
+cd examples/your_project
+
+# 复制模板文件
+cp ../my_business/config.py .
+cp ../my_business/run.py .
+cp ../my_business/task.prompt .
+```
+
+### 2. 自定义工具开发
+
+在业务项目下创建 `tools/` 目录:
+
+```python
+# examples/your_project/tools/my_tool.py
+from agent.tools import tool, ToolResult
+
+@tool(description="我的自定义工具")
+async def my_custom_tool(param: str) -> ToolResult:
+    """工具功能描述
+
+    Args:
+        param: 参数说明
+    """
+    # 实现逻辑
+    return ToolResult(output="结果")
+```
+
+在 `run.py` 中导入:
+
+```python
+from tools.my_tool import my_custom_tool
+```
+
+### 3. 自定义 Skill 开发
+
+在业务项目下创建 `skills/` 目录:
+
+```markdown
+<!-- examples/your_project/skills/my_skill.md -->
+---
+name: my-skill
+description: 我的领域知识
+category: custom
+---
+
+## 使用场景
+- 场景描述
+
+## 指导原则
+- 原则说明
+```
+
+### 4. 配置管理
+
+业务配置集中在 `config.py`:
+
+```python
+from agent.core.runner import RunConfig, KnowledgeConfig
+
+RUN_CONFIG = RunConfig(
+    model="qwen/qwen3.5-plus-02-15",
+    temperature=0.3,
+    max_iterations=50,
+    tools=["read_file", "write_file", "your_custom_tool"],  # 工具白名单
+    knowledge=KnowledgeConfig(
+        enable_injection=False,
+        enable_completion_extraction=False,
+    )
+)
+```
+
+## 协作约定
+
+### Claude 助手行为准则
+
+当协助开发时,Claude 应该:
+
+1. **严格遵守目录约束**
+   - 永远不修改 `agent/` 目录下的文件
+   - 所有业务代码放在 `examples/[project]/` 下
+   - 如需扩展功能,通过自定义工具/Skill 实现
+
+2. **优先使用框架能力**
+   - 查阅 `agent/README.md` 了解框架功能
+   - 使用内置工具而非重复实现
+   - 通过配置调整行为而非修改源码
+
+3. **保持项目结构清晰**
+   - 每个业务项目独立目录
+   - 配置、代码、输出分离
+   - 遵循框架推荐的目录结构
+
+4. **提供清晰的说明**
+   - 修改文件时说明原因和影响范围
+   - 新增功能时提供使用示例
+   - 配置变更时解释参数含义
+
+### 开发者行为准则
+
+1. **不要直接修改框架源码**
+   - 如发现框架 bug,记录并反馈给框架维护者
+   - 通过扩展机制实现自定义功能
+
+2. **保持业务代码独立**
+   - 每个业务项目独立目录
+   - 避免跨项目依赖
+   - 共享代码可提取到独立模块
+
+3. **合理使用版本控制**
+   - 框架源码变更通过 git submodule 或上游同步
+   - 业务代码正常提交
+   - 配置文件注意敏感信息
+
+## 常见问题
+
+### Q: 如何扩展框架功能?
+
+A: 通过以下方式扩展,而不是修改源码:
+- 自定义工具:`examples/[project]/tools/`
+- 自定义 Skill:`examples/[project]/skills/`
+- 配置覆盖:`config.py` 中的 `RunConfig`
+
+### Q: 如何调试框架行为?
+
+A: 使用框架提供的调试功能:
+- 日志级别:`setup_logging(level="DEBUG")`
+- 轨迹追踪:查看 `.trace/` 目录
+- 前端可视化:启动 `frontend/react-template`
+
+### Q: 如何更新框架版本?
+
+A:
+```bash
+# 如果是 git submodule
+git submodule update --remote agent
+
+# 如果是直接克隆
+cd agent && git pull origin main
+```
+
+## 🚨 开发注意事项和常见陷阱(auto_put_ad_mini)
+
+### ⚠️ 关键问题1:决策CSV缺失字段(已反复出现多次!)
+
+**问题描述**:
+生成的决策报告(Excel/飞书表格)只显示7列基本字段(ad_id、action、dimension、reason、recommended_change_pct、current_bid、recommended_bid),缺少关键业务字段如:
+- ad_name(广告名称)
+- ad_age_days(投放天数)
+- cost_7d_avg(7日均消耗)
+- audience_tier(人群包)
+- 动态ROI
+- 等约13个字段
+
+**根本原因**:
+在 `tools/ad_decision.py` 的 `apply_decisions()` 函数中,决策DataFrame是直接从LLM输出字典构建的:
+```python
+df_out = pd.DataFrame(all_decisions)  # 只包含决策字段
+```
+LLM输出的字典只包含决策相关字段(action、reason等),不包含metrics CSV中的业务字段。如果不合并metrics CSV,输出的Excel/飞书表格就会缺失这些关键信息。
+
+**历史记录**:
+- 从初始commit(10b0b28)就存在这个bug,从未有合并逻辑
+- 在开发过程中反复出现此问题多次
+- 每次修改其他功能后,这个问题会再次显现
+
+**正确解决方案**:
+在 `apply_decisions()` 函数中,DataFrame创建后**立即合并**metrics CSV字段:
+
+```python
+# ===== 关键修复:合并 metrics CSV 中的字段 =====
+try:
+    df_metrics_full = pd.read_csv(metrics_csv)
+
+    # 定义需要合并的字段
+    merge_cols = [
+        "ad_id", "account_id", "ad_name", "audience_tier", "create_time", "ad_age_days",
+        "bid_amount", "yesterday_cost", "yesterday_revenue", "yesterday_roi",
+        "cost_7d_total", "cost_7d_avg", "revenue_7d_total",
+        "动态ROI", "动态ROI_7日均值", "cost_30d_total", "cost_30d_avg",
+        "stable_spend_days_30d", "creative_count", "roi_valid_days"
+    ]
+
+    # 仅保留实际存在的列
+    merge_cols = [c for c in merge_cols if c in df_metrics_full.columns]
+    df_metrics_merge = df_metrics_full[merge_cols]
+
+    # 左连接:保留所有决策,添加metrics字段
+    df_out = df_out.merge(df_metrics_merge, on="ad_id", how="left", suffixes=("", "_metrics"))
+
+    logger.info(f"已从 metrics CSV 合并 {len(merge_cols)} 个字段")
+except Exception as e:
+    logger.warning(f"合并 metrics 字段失败: {e}")
+```
+
+**关键位置**:
+- 文件:`examples/auto_put_ad_mini/tools/ad_decision.py`
+- 函数:`apply_decisions()`(约1324-1345行)
+- 必须在 `df_out = pd.DataFrame(all_decisions)` **之后立即执行**
+
+**预防措施**:
+1. **在测试时验证列完整性**:每次测试后检查生成的Excel文件,确认所有OUTPUT_COLUMNS都存在
+2. **不要删除关键字段**:避免使用 `df_out.drop(columns=["cost_7d_avg"])` 等操作删除业务字段
+3. **代码审查检查点**:任何修改 `apply_decisions` 函数的变更,都必须验证字段合并逻辑是否完整
+4. **端到端测试**:修改决策逻辑后,必须执行完整流程并检查飞书表格的列是否正确
+
+---
+
+### ⚠️ 关键问题2:年龄保护逻辑不完整
+
+**问题描述**:
+早期成长期(4-7天)的广告收到了LLM的降价(bid_down)或关停(pause)建议,触发兜底检查告警。这些广告应该只允许提价(bid_up)决策。
+
+**根本原因**:
+在 `get_ads_for_review()` 函数的年龄保护逻辑中,只检查了"是否有提价候选",但没有检查"是否有其他类型的候选":
+
+```python
+# ❌ 错误逻辑(不完整)
+if not (bid_up_candidate or scale_up_candidate):
+    # 没有提价候选就跳过,但没检查是否有其他候选
+    normal_ads_count += 1
+    continue
+```
+
+这导致如果广告同时满足 `roi_low=True` 和 `bid_up_candidate=False`,就会进入LLM评估,LLM可能建议降价或关停。
+
+**正确解决方案**:
+检查是否存在**任何非提价类型的候选**,如果有则排除:
+
+```python
+# ✅ 完整逻辑
+elif ad_age <= EARLY_GROWTH_DAYS:  # 4-7天
+    if not (bid_up_candidate or scale_up_candidate):
+        # 检查是否有其他候选标记
+        has_any_candidate = roi_low or decay_signal or bid_down_candidate
+        if has_any_candidate:
+            normal_ads_count += 1
+            logger.debug(
+                f"广告 {row['ad_id']} 处于早期成长期({ad_age}天),"
+                f"年龄保护:仅允许提价/扩量,其他候选已排除"
+                f"(roi_low={roi_low}, decay={decay_signal}, bid_down={bid_down_candidate})"
+            )
+            age_protected_skip = True
+```
+
+**关键位置**:
+- 文件:`examples/auto_put_ad_mini/tools/ad_decision.py`
+- 函数:`get_ads_for_review()`(约996-1020行)
+- 在候选标记判断之后,LLM评估之前
+
+**设计原则**:
+- **三层架构**:年龄保护(硬约束) → 业务逻辑(LLM评估) → 兜底检查
+- **5种候选标记**:roi_low、decay_signal、bid_up_candidate、bid_down_candidate、scale_up_candidate
+- **规则+LLM协作**:规则确定**是否**评估,LLM确定**如何**操作
+
+**验证方法**:
+```bash
+# 运行后检查兜底检查触发次数
+grep "兜底检查触发" outputs/decision_log_*.log | wc -l
+# 应该输出 0
+```
+
+---
+
+### ⚠️ 关键问题3:硬编码日期问题
+
+**问题描述**:
+代码或测试中使用硬编码的日期参数(如 `--date 20260415`),导致无法使用最新数据。
+
+**解决方案**:
+1. 默认使用"昨天"日期:
+```python
+from datetime import datetime, timedelta
+default_date = (datetime.now() - timedelta(days=1)).strftime("%Y%m%d")
+```
+
+2. 移除测试代码中的硬编码日期
+3. 在CLAUDE记忆中清除特定日期的上下文
+
+**预防措施**:
+- 在代码审查时搜索硬编码日期:`grep -r "20260[0-9]" --include="*.py"`
+- 配置文件中使用相对日期表达式
+
+---
+
+### 💡 调试技巧
+
+**验证决策流程完整性**:
+```bash
+# 1. 检查metrics CSV列
+head -1 outputs/metrics_*.csv | tr ',' '\n' | nl
+
+# 2. 检查决策CSV列(应包含所有metrics字段)
+head -1 outputs/reports/decisions_*.csv | tr ',' '\n' | nl
+
+# 3. 对比OUTPUT_COLUMNS定义
+grep "OUTPUT_COLUMNS = " tools/report_generator.py -A 20
+
+# 4. 检查Excel文件实际列数
+python3 -c "import pandas as pd; print(pd.read_excel('outputs/reports/approval_table_*.xlsx').columns.tolist())"
+```
+
+**验证年龄保护逻辑**:
+```bash
+# 检查兜底检查触发情况
+grep "兜底检查触发" outputs/decision_log_*.log
+
+# 应该输出空(0个触发)
+```
+
+---
+
+### 📋 修改清单模板
+
+每次修改决策相关代码后,执行以下检查:
+
+- [ ] 运行完整流程:`cd examples/auto_put_ad_mini && .venv/bin/python3 execute_once.py`
+- [ ] 验证metrics CSV包含所有字段:`head -1 outputs/metrics_*.csv`
+- [ ] 验证决策CSV包含所有字段:`head -1 outputs/reports/decisions_*.csv`
+- [ ] 打开Excel文件检查列是否完整(至少20列)
+- [ ] 检查飞书消息格式是否正确(包含统计信息和表格)
+- [ ] 验证年龄保护:`grep "兜底检查触发" outputs/decision_log_*.log` 应为空
+- [ ] 检查无硬编码日期:`grep -r "20260[0-9]" --include="*.py" | grep -v ".venv"`
+
+---
+
+**文档更新**:2026-04-20
+**记录原因**:这些问题已反复出现多次,必须明确文档化以防止再次发生
+
+## 项目依赖
+
+### 环境要求
+
+- Python 3.10+
+- Node.js 16+ (前端可视化)
+- 必需的 API Key:
+  - `QWEN_API_KEY` (通义千问)
+  - `OPEN_ROUTER_API_KEY` (OpenRouter,可选)
+  - `GEMINI_API_KEY` (Gemini,可选)
+
+### 安装依赖
+
+```bash
+# Python 依赖
+pip install -r requirements.txt
+
+# 前端依赖(可选)
+cd frontend/react-template
+npm install
+```
+
+## 参考资源
+
+- 框架文档:`agent/README.md`
+- 示例项目:`examples/*/`
+- API 文档:`agent/docs/`
+- 前端界面:http://localhost:3000 (启动后)
+
+---
+
+**最后更新**: 2026-04-09
+**维护者**: liulidong