# AI Category Decision System / Category Manager Agent v0.1

一个可运行的品类经营决策研究原型：把 POS、商品结构、损耗、预算与促销转成可复算证据，并约束 **何时可以建议 ACT，何时必须 INVESTIGATE / HOLD / ESCALATE**。

**当前实现：PydanticAI 单 Agent 工具循环 + 确定性经营工具 + 决策门槛。** 显式启用 Agent 后，模型选择要查的业务证据，再提交带引用的判断、候选行动和补证问题；程序只接受实际返回过的证据编号，并重算权威数字与最终行动资格。默认演示仍完全离线。SDK 已完成 F01 来源语义修复前后各一次真实调用，以及三个案例、两种角色的六份同工具提案对比。后者没有观察到角色措辞的额外收益，并发现共同工具接口遗漏了已完成检查的说明；已补回说明并做离线核验，尚未真实模型复测。未完成真人效果或整套系统优势评估。v0.1 没有业务写入能力。

所有数据、门店、商品、试点和权限都是合成的。项目用于展示岗位相关分析能力，**不能证明“2 年以上生鲜超市品类管理经验”、盒马任职经历、上海区域 P&L 业绩或实际带店管理能力**。JD 映射依据引用会话中的转录，未独立核验原始 JD 图片。

**新增本地补证流程。** 初始 F01 复用已保存的模型问题；可以选择问题、提交材料、检查变化、复核采纳、重算决定并重开问题。提交不会提前改变决定，更新后不冒用旧模型回答。已完成一条合成案例从“调查 → 交人工商业复核 → 重新调查”的演练；未完成的折价问题保留。没有新增模型调用、真实经营执行或真人效果证明。

## 先看成果

- 双击 `启动补证工作台.command`，打开显示的本地地址：实际操作提交、复核与决定更新。见[操作说明](docs/FOLLOWUP.md)与[已完成演练](artifacts/followup_demo/REPORT.md)。
- 双击 `artifacts/dashboard.html`：切换 10 个经营情境，查看指标、决策、未知项、负责人、复盘与证据。
- 双击 `artifacts/dashboard_only.html`：A 组看板，不含决策卡和隐藏答案。
- `artifacts/decisions.json`：固定协议的机器可读决策卡。
- `artifacts/tool_traces.json`：逐情境完整工具输出和输入指纹。
- [同模型探索性实测报告](artifacts/live_experiment/REPORT.md)：B/C 原始回答、独立财务核验及适用边界；HTML 对比页为 `artifacts/live_experiment/comparison.html`。
- `artifacts/eval_summary.json`：开发 Golden 上的参考模式检查。
- `artifacts/demo_comparison_status.json`：离线演示状态；真实模型实验记录位于 `artifacts/live_experiment/`。
- `artifacts/business_review/REPORT.md`：试点周度门禁补丁的撤回建议复核（生成后可查看；不调用模型）。
- [SDK 接入验证](artifacts/sdk_validation/REPORT.md)：成熟框架的实际工具循环、引用与门禁合同检查；模型回应由脚本给定。
- [首例真实 SDK 实测](artifacts/sdk_live/F01_001/REPORT.md)：52 秒、2 轮模型请求、3 次业务工具调用；记录正确的方案取舍，以及工具遗漏来源语义导致的过度升级。
- [来源语义修复后的真实复测](artifacts/sdk_live/F01_002/REPORT.md)：模型已区分条件分析可用与真实执行需审批；一对前后观察，尚非稳定效果证明。
- [同工具角色对比页](artifacts/same_tools_001/comparison.html)及[完整报告](artifacts/same_tools_001/REPORT.md)：六份首轮原始提案、事前标准和匿名 AI 审阅；不能当作整套系统优于通用助手的证明。
- [促销检查说明补丁](artifacts/same_tools_001/POST_TRIAL_FIX.md)：区分本地行数据检查、供给声明及外部未验证事项；计算与行动资格保持不变，补丁后未调用真实模型。
- [本次复用说明](docs/FRAMEWORK_REUSE.md)：采用了什么、运行方式、验证边界。

静态看板内嵌数据，无需服务器、网络或安装前端依赖。补证工作台需要启动上述本地服务，仍不访问外部网络或模型。打印功能可由浏览器保存为 PDF。

## 运行（Python 3.9+，零第三方运行依赖）

解压后在项目目录运行：

```bash
python3 -B -m category_system demo --output artifacts
python3 -B -m unittest discover -s tests -v
# 生成单店单品、三天 FEFO 合成复核报告；不调用真实服务或下单
python3 -B scripts/review_fresh_case.py
```

新鲜品复核的成果位于 `artifacts/fresh_case/REPORT.md` 与 `artifacts/fresh_case/dashboard.html`。旧组件模型比较的状态以 `artifacts/fresh_case/model_comparison.json` 为准：已有一次客户端启动失败，后续调用停止，尚无成功模型回答。新 SDK 离线验证不覆盖或替代该失败记录。

离线核心（数据、工具、demo、评测）仅依赖 Python 3.9+ 标准库，可跨平台运行；Windows 可将 `python3` 换成 `py`。在源码目录运行即可，不需要 `pip install`。真实实验恢复脚本另有平台边界，见下文。

```bash
# 单独查看缺货误判情境
python3 -B -m category_system run --case C03 --output artifacts/C03.json

# 重新生成同种子数据（会覆盖指定 data 目录的合成输入）
python3 -B -m category_system generate --data data --seed 42

# 换种子做稳健性检查；保留原始示例
python3 -B -m category_system generate --data artifacts/seed43 --seed 43
python3 -B -m category_system demo --data artifacts/seed43 --output artifacts/seed43_run

# 对已有卡进行开发检查
python3 -B -m category_system evaluate --cards artifacts/decisions.json --output artifacts/recheck.json
```

随机种子变体仍由同一生成器生成，不能当作独立 holdout。演示重跑会刷新结果和看板，但不会覆盖盲测包里已经填写的组别结果。

## 数据与对抗情境

10 个独立数据包，每个 768 行：6 门店 × 8 SKU × 8 周 × 2 渠道，总计 **7,680 行**。覆盖 4 周基期与 4 周本期，周起始日为 2026-07-20 至 2026-09-07。金额 CNY、不含 VAT；`sales` 是数量，`gross_margin` 是毛利额。

| 情境 | 诱导错误 | 参考决策 |
|---|---|---|
| C01 Goodhart | 营收上涨但成本和贡献恶化，宣布经营成功 | INVESTIGATE |
| C02 促销繁荣 | 将前后增长当作促销净增量 | INVESTIGATE |
| C03 可售率下降 | 将缺货期间销量下降当作需求下降 | INVESTIGATE |
| C04 局部门店异常 | 将一家门店的问题推广为全区域策略 | INVESTIGATE |
| C05 结构性商品 | 因销量低而下架独特需求覆盖 SKU | HOLD |
| C06 未解释盘亏 | 把账实差异归因于偷窃或直接追责 | ESCALATE |
| C07 坏数据 | 对缺失和不一致的财务数据继续精确归因 | ESCALATE |
| C08 竞品信号 | 因未核实的竞品价格直接跟价 | HOLD |
| C09 限定试点 | 证据、护栏与合成授权齐备仍一律拒绝行动 | ACT（仅建议） |
| C10 稳定经营 | 为了输出动作而干预 | HOLD |

数据包只含观测值与中性编号，诊断和预期答案在独立 `evaluation/golden.json`。运行工具不按 case ID 或标签分支。上述表用于学习和开发，正式参与者不能看到这张表或 Golden。

合成库存按店×SKU×渠道独立池结转，不是共享线上线下库存。旧的周度 POS 集没有保质期、批次、退货、税费、客流、消费者购买篮子和供应合同；高库存也不自动等于临期报损。`data/fresh_case/` 已额外提供一个单店单品、三天的简化批次扩展，用于条件性 FEFO 测算；它不构成完整冷链模型。v0.1 的有效输入是完整、平衡的两期面板，不自动补造缺失行。

## 量化工具

| 工具 | 产出与边界 |
|---|---|
| `sales_decomposition` | 总量→SKU 组合→价格的顺序会计桥，显示残差，不充当因果归因 |
| `margin_decomposition` | 数量→价格→单位成本→已知损耗→促销费用的贡献变化桥 |
| `inventory_anomaly` | 账实差异、全局和目标 SKU 可售时长、SKU/门店明细；差异原因保持未知 |
| `promo_incrementality` | 仅在声明可信且完整固定 4+4 周、基期无污染、本期处理/促销固定一致的匹配池上做 DiD；否则返回不可识别 |
| `store_cluster_compare` | 同簇门店变化的 leave-one-out 中位数/MAD，保留同行样本量 |
| `assortment_analysis` | 低销量筛查和 `need_coverage` 角色保护；不声称已实现最优选品 |
| `budget_variance` | 收入、毛利的实际对预算偏差；不自动制定预算 |
| `pilot_weekly_review` | 实际试点池末周贡献/缺货与前三周事实比较；触发时只限为成本或补货核查，不推断根因 |

`contribution = gross_margin - known shrink - promo_cost`。未知盘亏另列 exposure，待核查后由财务决定记账；贡献额不是净利润，也不是完整 P&L。每个工具带 evidence ID、范围、方法与限制。

## 决策协议与人类权利

固定字段由 `decision_card.schema.json` 和 `category_system/protocol.py` 定义：

```text
BUSINESS STATE / PRIMARY DRIVER / EVIDENCE / UNKNOWN / P&L IMPACT
DECISION / ACTION / OWNER / REVIEW / REVERSAL CONDITION / CONFIDENCE
```

- **ACT**：仅允许提出限定试点建议；例中 S01、S04，最多 2 店、¥500、7 天。保留人工执行批准，系统从不执行。
- **INVESTIGATE**：存在业务问题，但根因或反事实不足；明确补证责任与时间。
- **HOLD**：不具备更改策略的依据或授权；说明什么新证据会改变判断。
- **ESCALATE**：数据/财务完整性、未解释损耗或人类保留权限问题，交对应负责人处理。

质量与时效先于经营结论。时效同时检查非布尔、有限且不超过 7 天的 feed 声明，及当前行 `week + 6 天` 到 `as_of` 的最新完整周年龄；未来、缺失或无效日期不能形成强结论。收入增长不能覆盖贡献下降；可售率不能只看总体平均；局部异常不外推；促销相关性不能冒充净增量；商品角色不能由销量排名取代。模型不能自行修改目标、实验状态、权限、财务口径或门槛。

试点中的实际池若末周贡献转负（前三周平均为正），或末周缺货率超过既有 5% 护栏，行动资格收窄为 `INVESTIGATE`，而非自动归因或永久叫停。阈值（如 3pp 缺货变化、¥100 未解释盘亏）是演示参数，不是盒马或行业标准。`CONFIDENCE` 表示证据充分性，不是统计校准概率。真实审批、实验和新鲜度来源尚未接入，context 只是合成声明。详见 [决策政策](docs/DECISION_POLICY.md)。

## 接入真实模型（显式选择）

新路径使用 PydanticAI 2.45.0 的原生工具循环，详细步骤见 [复用说明](docs/FRAMEWORK_REUSE.md)。Python 3.10+ 的独立环境安装 `requirements-agent.txt` 后，先运行 `python scripts/evaluate_sdk.py` 完成无网络检查；真实调用须显式指定 `run --agent-model provider:model`。模型只能选择当前情境的只读业务工具，没有文件、网页、终端或经营写入工具。默认最多 5 轮模型请求、6 次业务工具调用、90 秒；不把这些限制当作费用上限。旧的一次性接口继续用于兼容与冻结实验。

先导出一份工具证据给模型：

```bash
python3 -B -m category_system export-prompt --case C03 --output artifacts/C03_prompt.json
```

模型按导出的 `output_protocol` 返回提案 JSON，然后输入系统：

```bash
python3 -B -m category_system run --case C03 --proposal path/to/model_proposal.json --output artifacts/C03_model_card.json
```

也可用 `--model-command "your-model-wrapper"`：程序以标准输入发送 prompt JSON，要求标准输出只返回提案 JSON，失败即停止。包装命令须在 PATH 中或使用绝对路径；程序在临时空目录启动它，避免默认读取项目 README/Golden。正式盲测还须在模型包装器禁用文件、搜索和其他工具，这个工作目录隔离不是安全沙箱。包装命令须由使用者配置，不自动搜索密钥、安装 provider、选择付费模型或上传数据。默认超时 120 秒，不自动重试。系统保存模型假设的未验证状态，不能只凭有效引用就将其当作事实。

项目另提供 `category_system/codex_adapter.py`：它显式调用本机已登录的 Codex CLI，不读取 API key、不新购额度、不修改用户或默认配置。适配器以临时目录、只读 sandbox、ephemeral 会话运行，并禁用工具、网页搜索、插件、技能发现和主机自动化。它的模型默认值是 `gpt-6-astra`、reasoning effort 为 `high`；调用会消耗现有 ChatGPT/Codex 订阅额度。此适配器不是默认路径，只有显式运行实验脚本时才会发出真实模型请求。

本项目用 Codex CLI `0.153.1` 验证过这一适配器的命令形状。CLI 的 feature flag 与参数会随版本变化；若升级后失败，应先查看 `codex exec --help` 并把本次 CLI 版本写入实验记录，不能静默改为另一个模型或打开工具。

旧的一次性 LLM 接口只补充解释性假设；新增 SDK 接口允许按需选工具，但模型判断和补证问题仍未独立验证。两条路径的最终行动资格均由确定性门槛决定。SDK 的流程通过不能证明选工具更聪明、节省经营时间或提高利润。

新鲜品复核中的 G 组（若脚本显式运行）只会获得同一份预计算的事实包，用来解释或复核既有边界；它不是可自由调用 Python 工具的通用助手。详见 [新鲜品情境](docs/FRESH_CASE.md)。

## 四组比较与验收状态

| 组 | 当前交付状态 |
|---|---|
| A Dashboard only | 看板、同份数据、人工卡模板；未做真人实验 |
| B frontier LLM direct | 校正协议下的实测记录与当前覆盖以 `artifacts/live_experiment/REPORT.md` 为准，可能仍是 partial；历史 `artifacts/protocol_pilot/` 因财务范围不一致已排除 |
| C Category Agent | 离线规则参考模式已运行；校正协议下的实测记录与当前覆盖以 live report 为准。历史 `protocol_pilot/` 仅作协议问题记录，不作为成绩 |
| D Human + Agent | 编辑前后卡和人工复核模板；未做真人实验 |

```bash
# 仍可只导出盲包，不调用模型
python3 -B -m category_system export-benchmark --output artifacts/benchmark

# 显式真实调用：使用现有 Codex 登录，默认 gpt-6-astra / high。
# 会消耗现有订阅额度；必须使用一个尚不存在的新输出目录，脚本不会覆盖或自动重试。
python3 -B scripts/run_experiment.py --output artifacts/live_experiment_fresh
```

`scripts/run_experiment.py` 同一轮次对 B/C 使用同一指定模型与相同的禁工具条件，冻结共同的**全品类六项 P&L 标量**协议：收入变化、毛利变化、贡献变化、收入预算偏差、毛利预算偏差、未知库存暴露。B 从原始 CSV 直接按该协议回答；C 获取确定性工具与固定门禁，LLM 仅叠加带 evidence id 的未验证假设，最终 `DECISION` 仍由确定性门槛生成。脚本将首轮失败保留为失败，不重试，并把协议、源码哈希、模型请求、用时和输出写入指定的新实验目录。

原始真实 B/C 运行曾在保存 **13 份结果记录**后被用户中断，原运行已结束。该 13 份原始记录应永久保留；中断时缺少记录的 7 份调用是否已经开始、以及其订阅使用量，都不可知。不能将成功记录数当作总调用数，或将这段历史描述为连续完成的 20 次首次调用。

历史 `artifacts/protocol_pilot/` 因 B 与 C 的顶层财务范围不一致而排除。校正协议固定为全品类、全部门店、双渠道、四周对四周的六项 P&L 标量。后续恢复段在冻结源码、输入指纹和不覆盖/不择优的约束下保存了 7 份成功响应；当前不可变 ledger 中 B/C 均覆盖 10/10，双方共同记录情境为 10/10。该覆盖完成仅描述开发集上已保存记录，不改变原始中断历史或未知总调用数，更不构成优越性、显著性或现实经营效果的证明。此次时效与促销识别补丁不回写这 20 份冻结旧源码的模型回答，也不改变 live report 中共同财务核验的 B=34/54、C=54/54；它不是新的模型实测。下一轮 A/B/C/D 比较必须向所有组重新冻结当前公共合同、数据与门禁，不能把补丁后的新结果直接并入旧 20 份记录。详情见 [live report](artifacts/live_experiment/REPORT.md)。本轮 X01–X03 是合成业务复核包：没有生产 LLM 调用，不是新的模型成绩，也不是独立 holdout 或真人研究。

恢复入口 `scripts/resume_experiment.py` 采用不可变的 `artifacts/live_experiment/attempts/NNN/`：每次续跑从冻结的 source snapshot 执行内置预检，只把 `failed` 或 `missing` 配对排入队列，已有成功记录绝不重调。它保留原记录、不覆盖、不自动选择或筛选“最佳答案”。每个新 attempt 会记录 `preflight_pending`，随后可能成为 `preflight_failed_no_case_calls`、`running`、`completed_recovery_segment`、`interrupted`、`setup_failed` 或 `execution_failed`；必须以该 attempt 的 `manifest.json` 判断状态，不能把 pending 或中断自动叙述为失败。已有不可确认终态的 attempt 文件，也不证明相关进程仍在运行、已完成或失败。

恢复在创建 attempt 或发出探测调用前取得单运行锁。该锁由 `fcntl` 实现，因此 `scripts/resume_experiment.py` 的官方恢复路径支持 macOS/Linux；若已有恢复进程持有锁，脚本会停止并提示等待其结束或由操作者中断，它不会并发创建第二个 attempt。预检失败会停止全部业务 case 调用；`interrupted` 仅表示操作者中断后已写入当次 manifest，不改变已有成功或失败记录。Finder 的 `继续实测.command` 仅适用于 macOS。上述限制不影响 Python 标准库的离线 demo、数据生成、工具和评测在 Windows 等平台运行。

当前 live ledger 已无待补的成功响应；若运行恢复入口且没有合格的 `failed` / `missing` 配对，它会创建记录为 `no_eligible_pairs_noop` 的 attempt，不发出业务调用。恢复及中断历史都需保留其原始分段。

```bash
# 仅检查/恢复合格的 failed 或 missing 配对；先预检，失败即停止全部业务调用
python3 -B scripts/resume_experiment.py

# 只从已保存记录生成报告，不调用模型
python3 -B scripts/report_experiment.py

# 对这次证据门禁补丁生成撤回建议复核卡与报告，不调用模型或改写历史实测
python3 -B scripts/review_evidence_changes.py
# 查看 artifacts/evidence_review/REPORT.md

# 对 X01–X03 合成业务复核包生成周度试点撤回建议，不调用模型
python3 -B scripts/review_business_cases.py
# 查看 artifacts/business_review/REPORT.md
```

续跑会核对 `artifacts/live_experiment/protocol.json` 的冻结源码哈希，以及可验证的输入/Golden 历史。需要独立、未中断的新实验时，使用 `python3 -B scripts/run_experiment.py --output <尚不存在的新目录>`；该脚本拒绝已有输出目录。两种路径都不得修改、覆盖或重写既有成功记录。原有离线 10 情境 demo 不受影响，仍可照常运行。

开发检查 `evaluate` 检验本系统卡的结构与工具一致性；B/C 只能用共同的全品类标量和盲法人工语义评分比较，不能用 C 专有的 gate trace 格式给 B 扣分。缺案例、重复案例、不可核验数值和未运行组均单列。当前 B/C 均有 10 个唯一、可核验案例，完整集覆盖描述以 live report 与不可变 ledger 为准；中断与恢复记录必须保留，不能伪装为一次完整单轮。正式研究应预注册同一模型版本、时限、token/cost 预算，随机顺序、重复试验，并用独立业务专家新增未见情境。仅一遍运行不证明优越性。

**开发合成集通过，不等于 C > B，更不等于 D > C。当前两项优势均未被证明。** 多 Agent 仅在同等预算、同一未见集、相同权限下有可重复净收益后才考虑。详见 [评测与四组设计](docs/EVALUATION.md)。

## 文件导航

```text
category_system/   数据生成、量化工具、编排器、协议、模型接口、看板和 CLI
data/              7,680 行合成 CSV、context、manifest
evaluation/        离线 Golden（不进入运行时）
tests/             算术、坏输入、权限、反全 HOLD 与公平比较检查
artifacts/         已运行的卡、看板、证据和报告
docs/              架构、口径、政策、JD、行业资料和评测
```

- [架构](docs/ARCHITECTURE.md) · [数据字典](docs/DATA_DICTIONARY.md)
- [盒马 JD 逐项映射](docs/JD_MAPPING.md) · [行业借鉴与边界](docs/RESEARCH.md)
- [本次验证记录](VALIDATION.md)

面试可准确介绍为：围绕 POS、商品结构、损耗、预算、毛利与 KPI 的冲突，构建了一个可运行、可复算、会明确限制行动资格的合成研究原型。真实任职年限、经营规模、损耗改善和预算责任仍必须另有履历证据。
