# CHANGELOG: FDE 外贸获客交付系统

本文件记录系统所有版本迭代、结构变更与功能演进。遵循硬规则：每次改动先说明计划，再修改，改完写入本文件。

---

## [v1.0.0] - 2026-10-07

### 架构整合与目录规范化
- **目录扁平化重组**：将原先分散在 `fde-launch-pack/`、`fde-agent-system/`、`fde-mgmt-system/` 中的资产统一整合归并为根目录下的标准规范架构：
  - `docs/`：存放 PRD、架构技术文档、实施计划与 CHANGELOG
  - `knowledge/`：存放客户档案模版、项目档案（事实源）、品牌语气规范
  - `skills/`：收录 S0 客户建档、S1 买家名单、S2 开发信、S3 内容获客、S4 询盘处理、S5 客户周报、S6 获客诊断等统一模版技能
  - `pilot/`：存放面料工厂 30 天试点方案书与宝宝写真 2 周实验方案
  - `agents/`：收录四大日常运营 Agent 岗位定义（选题、内容、素材、线索）
  - `app/`：Web 控制台前端界面
  - `server/`：轻量 Node.js 本地后端与 SQLite 数据持久化
  - `scripts/`：自动运行器与编排脚本
  - `data/`：持久化 SQLite 数据库文件
- **修复乱码**：修复了历史解压产生的 `03_实施计划.md` 等文件名乱码问题。

---

## [v1.1.0] - 2026-10-07

### 本地持久化系统与外贸交付闭环达成
- **数据库与后端落地 (`server/`)**：
  - 基于 Node.js 22 内置 `node:sqlite`（零二进制编译依赖）建立 `data/fde_system.db` 持久化引擎；
  - 设计并部署 10 张核心数据表：`clients`、`buyers`、`outreaches`、`inquiries`、`weekly_reports`、`skill_logs`、`diagnostics`、`c_topics`、`c_packs`、`c_leads`；
  - 自动注入面料工厂真实试点数据（绍兴柯桥恒信针纺实业），杜绝虚构。
- **Web 控制台全面升级 (`app/index.html`)**：
  - 完整沿用高质感暗黑视觉体系（Manrope + Noto Sans SC + JetBrains Mono，暖金色调）；
  - 全新接入 6 大外贸交付核心视图：
    - S0 客户建档事实源全文查看与下载；
    - S1 买家名单分级看板与 CSV 批量导入；
    - S2 开发信人工审核中心（严格强制退订说明与字数质检拦截，支持在线微调与通过放行）；
    - S4 外贸询盘看板（24h 响应 SLA 倒计时，A级标红，老板确认流转）；
    - S5 客户一页纸周报自动汇算生成器（带三句核心结论，支持一键复制 Markdown 发微信）；
    - S6 免费获客诊断敲门砖生成工具；
  - 完整保留自媒体与 C 端写真流水线（选题、内容包、宝宝写真 14 天止损线看板）；
  - 前端全链路与 SQLite REST API 实时联通。
- **Skill 独立运行器 (`scripts/skill_runner.mjs`)**：
  - 支持命令行执行 `npm run run-skill S1`、`npm run run-skill S2` 等；
  - 解析技能 Markdown 质量门与人工审核点，自动在关键节点暂停并落入待审队列。
- **一键启动标准化**：
  - 配置 `npm start`，一条命令秒级启动本地服务（默认端口 3000）。

---

## [v1.2.0] - 2026-10-07

### 融合 Obsidian 资产：业务员展商拓客中枢与拓客军师 Agent 落地
- **通讯录数据清洗入库**：
  - 将 `外贸独立站客户/` 下两批共 100 家纺织面料展商（参展且无官网企业）完成 GBK 解码与数据清洗，写入 `data/fde_system.db` 的 `prospect_factories` 表；
  - 自动根据参保人数、注册资本、进出口资质评定 14 家 A 级重点大厂。
- **融合 Obsidian 知识库精髓**：
  - 提取 `E:\myObsidian\myObsidian` 中关于“海宁九鼎纺织有限公司 (jdtexcn.com)”的完整 B2B 工业级建站架构、技术护城河（Cloudflare CDN、Turnstile 防护、买家寄样系统）；
  - 提炼业务员向工厂老板介绍案例的 3 大王牌说辞与“外贸询盘增长服务商”定位。
- **系统前端与 Agent 深度升级**：
  - 默认工作台升级为 **【🔥 展商拓客工作台 (sales_copilot)】**，展示 100 家展商通讯录与 4 步走拿单横幅；
  - 部署 **【⚡ 拓客军师 Agent】**：为每家工厂实时针对性生成：
    1. 微信申请词（3条备选，秒过）；
    2. 电话 60 秒破冰黄金话术（直指面料品类，打消电销顾虑）；
    3. 微信私聊三步破冰法（抛九鼎案例与海外买家查样痛点）；
    4. 专属 S6 获客诊断报告；
    5. 临门一脚 30 天试点逼单话术；
  - 新增 **【🏆 海宁九鼎标杆案例】** 专属展示与说辞看板；
  - 提供单段话术一键复制与展商跟进状态实时流转。

---

## [v1.3.0] - 2026-10-07

### L4 商业交付级多租户隔离与角色权限 (RBAC) 升级
- **多工厂项目工作空间（Multi-Factory Workspaces）**：
  - 顶栏引入全局工厂切换器，支持九鼎纺织 (C02)、恒信针纺 (C01) 与全大盘总览；
  - 实现了买家池、开发信审核、询盘看板、客户周报、工作台 KPI 的 100% 工厂维度严格物理隔离，彻底杜绝串客户；
  - 正式将海宁九鼎纺织有限公司 (C02) 纳为标杆交付项目，并配套官方档案、买家池与真实询盘。
- **多角色权限控制 (RBAC) 与老板战报监控**：
  - 支持 Admin（老板/交付总管）与 Sales（业务员小张/小李）双重视角；
  - 业务员端聚焦拓客工作台，隐藏复杂交付与底层配置；
  - 老板端实时展示【业务员拓客拿单排行榜】，监控全员加微数、送诊断数、签单数与转化率。
- **海宁九鼎纺织全息出海架构看板升级**：
  - 完整呈现国家维度多语言 i18n、GEO /llms.txt AI优化、询盘三表去重、WhatsApp直连、Facebook/LinkedIn 社媒矩阵。
- **业务纯度净化**：
  - 剥离 C 端宝宝写真对工业外贸主线的干扰，保留纯粹的工业 B2B 出海交付定位。

---

## [v1.4.0] - 2026-10-07

### L4 商业交付级全链路闭环与高对比度 UI 重构 (百万元交付标准)
- **UI/UX 细节深度重构（根除暗黑模式下拉框白底看不清缺陷）**：
  - 全局根容器引入 `color-scheme: dark` 规范，彻底消除 Chromium / Windows 原生 `<select>` 在深色背景下菜单发白或文字对比度不足的体验缺陷；
  - 顶栏控件重构为 `.topbar-control` 专属高对比碳晶底座（`#12161f` + 香槟金柔光描边 `1px solid rgba(212,162,78,.45)` + 饱满内边距与字体高亮），无论是工厂切换还是身份切换均清晰锐利；
  - 顶栏下拉框动态联动：实时从 `/api/clients` 拉取最新工厂清单，实时从 `/api/users` 拉取最新人员名单，杜绝前端死代码。
- **业务员与团队全权管治体系 (Boss 专享)**：
  - 左侧导航与主视图上线 **【👥 业务员与团队管理 (Boss)】** 独立模块；
  - 支持老板对业务员进行全生命周期 CRUD（创建业务员、编辑资料、修改手机号、重置密码、停用/删除）；
  - **资产安全网机制**：删除业务员时，名下负责的未签约潜客自动安全退回“公海池(未分配)”，杜绝客户资产流失，且禁止删除系统主管理员 admin；
  - 老板可直观查阅全团队 4 项综合指标：团队人数、公海池存量、已签约工厂数、累计启动费金额。
- **真实账号密码鉴权与登录态保持**：
  - 接入 `POST /api/auth/login` 真实密码鉴权；
  - 增加右上角用户身份徽章药丸（支持展示头像、真实姓名、当前角色）与一键“切换账号/登录”模态框；
  - 本地 `localStorage` 持久化保持登录态。
- **展商一键签约转入交付项目库完整闭环**：
  - 展商列表每一行新增金色主操作 **【🤝 签约入库】** 按钮；
  - 弹出 `modalSignContract` 模态框，支持 3 种商业交付方案（A方案 ¥5,000 启动成本 / B方案 结果付费 / C方案 ¥38,000 年度全托管）、自定义金额周期、选择签约业务员；
  - 点击确认后，后端自动在 `knowledge/客户档案/[工厂名].md` 生成符合 S0 事实规范的初始客户档案 Markdown 文件，并在 `clients` 数据库表自动建档建立专属项目空间；
  - 签约成功后实时刷新战报排行榜、更新服务工厂下拉列表，并自动切入新工厂的 S0~S6 履约流程。
- **TDD 自动化测试全覆盖**：
  - 部署并执行 `scripts/test_l4_core.mjs`（9 项后端核心测试，包含登录鉴权、物理隔离、战报、九鼎白皮书、业务员 CRUD、签约入库，100% 通过）；
  - 部署并执行 `scripts/test_l4_frontend_flows.mjs`（5 项前端数据流闭环测试，100% 通过）。

---

## [v1.5.0] - 2026-10-07

### 全量 5,100 家外贸客户深度清洗、交叉补全、去重入库与秒级分页
- **全量数据源深度挖掘与融合**：
  - 突破原先仅提取 100 家样本的限制，全量解析 `外贸独立站客户/` 目录下的所有金矿数据：
    1. `“纺织”20260625.xlsx`：深入解析 5,000 家企业底表，提取法人、成立日期、省市区、有效手机号、更多电话及邮箱；
    2. `纺织面料业务商名单.pdf`：解析 65 页展会官方名录，提取 2,832 家中国参展商中英文名称、展馆号、展位号、主营面料品类（Wool、Knitted、Silk等）及官网网址；
    3. `2 个 CSV 文件`：融合 100 家经过深入工商穿透核查的无独立站重点展商。
- **智能交叉补全与严格质量过滤 (Zero-Noise)**：
  - **智能交叉补全**：将展会 PDF 中的展商与 XLSX 企查查企业知识库进行名称与核心词交叉匹配，成功为参展商自动填入真实负责人手机、固话与邮箱；
  - **严格去重机制**：采用中文规范化名称与全局 `seen_names` 查重，**0 重复公司（去重率 100%）**；
  - **剔除失联与脏数据**：完全去除无联系方式的失联企业以及包含“测试/注销/吊销/非企业”的噪音数据，**入库有效企业真实联系方式覆盖率 100%（手机覆盖率 99.4%，邮箱覆盖率 100%）**；
  - **分级打标**：评定 **A 级重点攻坚大厂 3,654 家 (71.6%)**，其余为 B 级常规潜客。
- **前端海量数据毫秒级秒开与切片分页**：
  - 在 `app/index.html` 引入极速前端切片分页引擎（每页 50 条），展示“显示第 1 ~ 50 家 · 符合筛选共 5,100 家客户 (第 1 / 102 页)”；
  - 搜索、分类筛选与翻页毫秒级响应，彻底杜绝数千条 DOM 导致浏览器卡顿的性能瓶颈。
- **全量承载力 TDD 极限测试**：
  - 部署并执行 `scripts/test_prospect_scale.mjs`：
    - API 响应速度 <250ms；
    - 0 重复公司检验 100% 通过；
    - 0 失联企业检验 100% 通过；
    - 随机中位企业军师 Agent 话术包生成 100% 成功。

---

## [v1.6.0] - 2026-10-07

### 认证门禁、多号码穿透、全屏自适应与精细化管治流转
- **问题 0：品牌定位与多渠道外贸客户重构**：
  - 将原先局限于“柯桥面料工厂试点 / 展商”的表述升级为 **“FDE 交付中枢 · 外贸独立站获客 · 全产业链出海管治”** 与 **“外贸客户拓客工作台”**；
  - 明确系统 5,100 家线索库来源为全渠道金矿：全国重点面料产业带制造厂家（柯桥、海宁、吴江盛泽、常熟、广东等）、行业大型展会名录及多渠道独立站客户名录。
- **问题 1：全屏强制登录门禁 (Auth Lock Guard)**：
  - 彻底封堵免密直通入口，引入高质感暗黑毛玻璃门禁遮罩 `#authLockScreen`；
  - 未登录访客或首次访问强阻断，必须输入账号密码并经后端 `/api/auth/login` 真实鉴权后方可进入；
  - 顶栏右侧新增标红 `⎋ 退出` 按钮，支持随时注销并重新锁定系统。
- **问题 2：当前服务工厂多租户 RBAC 隔离与快速搜索**：
  - 顶栏“当前工厂”下拉框支持基于登录人身份严格过滤：
    - **业务员身份**：仅显示其名下签约/负责的工厂，辅以标杆案例厂（海宁九鼎），杜绝跨业务员撞单；
    - **总顾问 / 老板身份**：具备全局视角，可见全部工厂及“🌐 全大盘总览 (聚合所有工厂)”；
  - 在工厂下拉框旁新增 `#factorySearchInput`（`🔍 快速过滤...`），毫秒级实时模糊搜索工厂名称与编号。
- **问题 3：全息多号码弹窗、邮箱/网站透明化与全屏自适应宽屏**：
  - **宽屏自适应**：取消 `.content` 容器的 1300px 最大宽度限制，改为 100% 满屏自适应，充分释放大屏显示空间；
  - **全息联络通讯录模态框 (`#modalAllContacts`)**：表格电话列若有多个号码自动呈现 `📱 查看全部 N 个号码` 按钮，点击弹窗聚合展示该企业的所有手机、固话，并提供一键呼叫与一键复制；
  - **新增跟进邮箱与独立站列**：拓展为 10 列宽屏表格，明确展示负责人邮箱（带复制）与企业独立站现状（未建站企业高亮 `🎯 无独立站(核心痛点)`，极度利于业务员抓痛点开单）。
- **问题 4：销售跟进精细化流转选项与公海回退**：
  - 全新升级 `#modalProspectStatus`，按三级业务阶段精细化分组：
    1. **🔥 积极推进阶段**：待联系、已加微信、已发诊断报告、意向跟进中、已签单；
    2. **⚠️ 终止 / 无效剔除 (不浪费精力)**：空号/错号/信息有误、明确拒绝/无需求、同行/服务商过滤；
    3. **🌱 培育与公海流转**：深度联系无果/暂时搁置（进入 60 天培育池）、退回公海池（自动重置负责业务员为 `公海池(未分配)`，供团队认领）；
  - 配套常用快捷标签（“空号停机”、“明确无需求”、“已发案例考虑中”等）一键填入沟通纪要。
- **高密度紧凑大盘重构 (5 核心黄金大列，彻底消除按钮折行)**：
  - **根本痛点**：原本 10 个分散列导致水平空间被严重瓜分，右侧“销售推进操作”中的三个按钮（军师支招、流转、签约入库）文本被挤压成 2 行折行（`军师支/招`、`流/转`、`签约入/库`），且电话号码与邮箱也发生异常换行；
  - **重构方案 (10 列聚合为 5 大高密度黄金列)**：
    1. **🏢 客户企业画像与资质**：合并企业全称、A/B 评级标签、省市区地域标签、法定代表、注册资本与业务备注；
    2. **🧵 主营面料与独立站**：合并面料品类/工艺展示与独立站状态标签（“🎯 尚未建站”或“🌐 已建站/访问”），痛点一目了然；
    3. **📞 全息联络通讯录**：主叫电话（等宽绿字+呼叫+复制）与邮箱（发信+复制）垂直对齐，底部提供多号码穿透入口，100% 单行不换行；
    4. **📊 跟进流转**：高对比状态药丸 + 业务员归属；
    5. **⚡ 拿单推进操作**：留足至少 240px 专属操作区，为 `.btn` 与 `.tag` 全局注入 `white-space: nowrap; flex-shrink: 0;`，确保“⚡ 军师支招”、“📌 流转”、“🤝 签约入库”三个高亮按钮绝对单行完整呈现！
- **军师支招 Agent 话术中心弹窗防溢出与子标签重构 (Pitch Modal UX 升级)**：
  - **溢出原因排查**：
    1. 弹窗内的 `<pre>` 代码块未定义 CSS 换行属性，保留了浏览器的默认 `white-space: pre;`，导致长句与长报告文本直接横向冲出弹窗边界；
    2. 5 大板块全部纵向平铺，内容体量极大，弹窗表头没有固定粘性，导致滚动后关闭按钮与工厂信息不可见。
  - **深度优化方案**：
    1. **CSS 强行自动折行**：定义 `.code-view { white-space: pre-wrap !important; word-break: break-word !important; overflow-wrap: break-word !important; }`，文本在边界自然折行，彻底消除横向溢出；
    2. **弹性视口与粘性表头**：模态框升级为 `display: flex; flex-direction: column; overflow: hidden;`，表头固定、关闭按钮常驻，仅内部内容区带防溢出自适应纵向滚动；
    3. **五大板块顶部子标签分段查看**：新增快捷切页选项卡（`📜 全部板块`、`💬 ① 微信申请词`、`📞 ② 电话60s破冰`、`🤝 ③ 微信三步私聊`、`📑 ④ S6诊断报告`、`💰 ⑤ 30天试点逼单`），业务员打电话或加微信时可一键精准聚焦单一环节，免除无效长距离滚动；
    4. **一键复制全部话术包**：顶部新增“📋 一键复制全部话术包”按钮，点击即可整包复制格式化文本。

---

## [v1.7.0] - 2026-10-07

### 深层代码审查：RBAC 权限提权阻断、路由守卫与交互安全闭环
- **安全审计与事实定位（针对“业务员账号登录后能否在顶栏切总顾问”等隐患）**：
  - **严重安全漏洞定性**：业务员在顶栏通过下拉框直接越权切换为“总顾问/老板”是绝对不合理且极其危险的严重漏洞。经深层代码审计，该下拉框是早期前端原型阶段的免密调试遗留（`userRoleSelect`），导致任何普通销售人员都能瞬时获得老板全部机密权限（包括查看全盘数据、增删修改业务员账号、审核放行等）。
- **7 项核心缺陷深度修复与闭环实施**：
  1. **彻底拔除顶栏非法越权下拉框**：
     - 完全移除 `app/index.html` 顶栏中的 `userRoleSelect` 元素；
     - 业务员登录后仅显示其真实姓名与“业务员 (只读所辖工厂/提报线索)”身份徽章，杜绝任何提权可能；
     - 新增受控的老板视角模拟（Boss Preview）：老板可在管理员面板（`team_sales`）中点击“👁️ 模拟业务员视角”，顶部展示醒目的琥珀金模拟横幅 `#bossPreviewBanner`，并可随时点击退出恢复总顾问身份。
  2. **navTo 客户端路由白名单拦截守卫**：
     - 在全局路由跳转引擎 `navTo(v)` 头部注入 `ADMIN_ONLY_VIEWS` 拦截阵列（包含 `team_sales`、`diagnostics`、`sys_rules` 等）；
     - 若当前用户为业务员且试图跳转管理员视图，系统强制拦截、弹出高对比安全警示 Toast 并安全回退至拓客工作台 `sales_copilot`。
  3. **展商签约入库业务流分流修复**：
     - 修复 `submitSignContract` 签约成功后硬编码调用 `navTo('clients')` 的逻辑；
     - 改造为基于角色的安全分流：业务员签约成功后安全停留在拓客大盘，实时刷新战报排行榜并弹出签约祝贺；总顾问签约后方跳转至正式客户档案视图。
  4. **工厂多租户隔离状态防泄露保护**：
     - 修复切换账号后因全局变量残留 `activeFactoryId = 'all'` 导致业务员越权浏览全局大盘买家与询盘的漏洞；
     - 业务员登录时强制抹除 `'all'` 状态，自动重置并锁定为其名下首个负责工厂（如 `C02`）。
  5. **线索流转归属权保护（防止误抢单）**：
     - 在 `#modalProspectStatus` 弹窗中引入负责业务员归属下拉框 `#editProspectSalesRepSelect`；
     - 业务员流转时仅可保留自己或回退至公海池；老板批注时提供“保持原归属业务员”选项，杜绝因保存时将 `currentUser.real_name` 强制写入而导致老板意外“霸占”业务员线索的业务逻辑缺陷。
  6. **军师支招长文本安全复制（彻底消除引号解析中断报错）**：
     - 废除原先将长文本直接拼接入 HTML `onclick="copyText('...')"` 的脆弱机制（避免双引号、换行与特殊字符导致 HTML 属性截断与 JS语法报错）；
     - 重构为安全内存查找机制 `copyPitchSnippet(type, idx)`，由内存直读 `currentPitchPackageData` 并安全写入系统剪贴板。
  7. **清理脱节登录模态框，统一安全门禁**：
     - 彻底清除早期未关联事件的 `#modalLogin` 遗留 DOM 节点，全系统鉴权完全收敛至高质感暗黑毛玻璃安全门禁 `#authLockScreen`；
     - 保证登录、注销、锁屏状态在单一流中严格一致。
  8. **Skill 自动化脚本多工厂参数支持**：
     - 增强 `scripts/skill_runner.mjs`，解除 `LIMIT 1` 客户写死限制，支持命令行传参指定工厂编号执行（如 `node scripts/skill_runner.mjs S2 C02`）。
  9. **买家名单库与自媒体流水线业务指引与交互流增强**：
     - 在 `buyers`、`topics`、`content` 页面顶部注入高质感业务指引横幅，明确业务员使用定位（买家库作为谈判实力物证、自媒体内容作为朋友圈出海专家 IP 背书）；
     - 优化 `quickGenOutreach` 角色逻辑：业务员生成开发信后友好提示“已生成草稿并推入审核队列”，避免触发管理员路由拦截。
- **TDD 自动化测试验证**：
  - 新增 `scripts/test_security_and_rbac_fixes.mjs`，涵盖 7 大安全与交互用例，7/7 全部通过（0 缺陷）；
  - 全套 6 组自动化测试套件（36 个测试用例）持续 100% 保持通过。

---

## [v1.8.0] - 2026-10-07

### 工业自媒体出海获客与一稿四发全矩阵全息内容包重构落地
- **痛点回应与深层重构**：
  - 针对用户提出的“外贸出海选题不硬核、不知道如何增加”、“一稿四发只有审核标签看不出价值、看不到全文”、以及“开发信生成机制与发送机制究竟如何执行”等核心疑问进行全面架构升级。
- **1. 工业级硬核 B2B 选题引擎与自动化生成**：
  - 清理偏离 B2B 的 C 端轻型选题，注入九鼎纺织独立站获客实录、海外买家索样防白嫖标准、欧盟 GRS 环保溢价新规等高价值工业出海选题；
  - 新增 `POST /api/topics/generate`（结合当前选中面料工厂与行业热点一键 AI 智能产出高分选题）与 `POST /api/topics`（手动录入选题）；
  - 前端顶部新增“⚡ AI 智能生成工业品选题”与“+ 录入新选题”操作。
- **2. 一稿四发全息文案中心（废除死标签，提供全量真实内容与一键复制）**：
  - 数据表 `c_packs` 升级为承载四合一全矩阵结构化资产：
    1. 📜 **微信公众号深度行业长文**（2,800+ 字实操长文，带行业痛点、解法、数据复盘与金句）；
    2. 🎬 **80s 短视频分镜出镜脚本**（分镜表格：时间、镜头提示、出镜口播词、贴纸字幕，带前 3 秒黄金钩子）；
    3. 📕 **小红书高赞图文笔记**（带爆款标题、Emoji 视觉排版、痛点标签）；
    4. ✉️ **外贸实战开发信模板**（带高回复率英文主题、正文、字数统计与退订声明）。
  - 前端新增全屏高质感模态框 `#modalPackDetail`，支持子选项卡无缝切换阅读全文，并支持“📋 一键复制当前板块全文”秒级取用。
  - 选题通过后，支持点击“⚡ 裂变一稿四发”一键生成全息内容包。
- **3. 开发信生成与发送机制透明化**：
  - 明确系统当前阶段采用本地确定性 Skill 规则引擎（按工厂档案和买家痛点结构化生成），无需外部第三方付费 API；
  - 明确系统当前的“审核通过/确认发送”属于合规审批流状态机（Approval State Machine），当前未直连 SMTP 服务器，由业务员复制外发并在系统协同；同时为后续直连企业邮 SMTP 预留扩展。
- **4. 自动化测试验证**：
  - 新增 `scripts/test_hardcore_content.mjs`，6/6 项测试全部通过；累计 7 组套件 42 项测试 100% 通过。

---

## [v1.8.1] - 2026-10-07

### 告别假把戏：部署 Agent 方法论引擎 (`server/agent_engine.js`)
- **根除 Mock 假把戏，引入真实方法论与事实源绑定**：
  - 针对用户对“写死模板假把戏”的深刻质疑，正式剔除硬编码 candidate 字符串，构建核心 Agent 生成引擎 `server/agent_engine.js`；
  - 引擎在执行时物理读取：
    - `knowledge/客户档案/` 与 SQLite `clients`（工厂机台数、GRS/OEKO-TEX/SGS真实认证、MOQ、交期）；
    - `skills/附_自媒体获客SOP.md`（严格执行 1. 过程记录、2. 方法拆解、3. 结果展示、4. 认知颠覆 四大支柱策略）；
    - `agents/01_选题官.md` 与 `agents/02_内容官.md`（执行打分门槛、前3秒反差钩子、时间分镜表与提词卡规范）；
    - `knowledge/品牌语气规范.md`（执行冷静锋利人设，强制短段落与真实数字，过滤夸大禁用词）。
- **生成产物附带元数据追溯**：
  - 每一套裂变的一稿四发内容包均带有 `metadata`（包含工厂 ID、引用的 Skill 规范文件、引用的事实源、质量门自检合规结果），确保可追踪、可审计、不偏离业务目标。

---

## [v1.8.2] - 2026-10-07

### 裂变异常根治、人设修正、选题状态流转与分页治理
- **1. 修复裂变报错与数据流闭环**：
  - 排查并修复 `server/agent_engine.js` 中 SQLite 查询双引号辨析异常（修复 `"C02"` 为 `'C02'` 参数化匹配），根除前端点击“⚡ 裂变一稿四发”时出现的 `裂变失败: undefined` 报错；
  - 前端错误捕获增强，确保服务端异常信息 100% 透传至界面。
- **2. 品牌人设历史包袱彻底清理**：
  - 更新 `knowledge/品牌语气规范.md`，将历史遗留的“七分大师”人设正式升级为 **“FDE 外贸出海独立顾问 / 工业出海增长工程师”**；
  - 明确“不以纯字数和时长为唯一标尺，以 30 秒看懂核心价值与转化为终极导向”的内容衡量准则。
- **3. 选题工单精细化流转、分页与删除**：
  - 选题库新增状态选项卡（`全部 / ⏳ 待人工审核 / ✅ 已通过可裂变 / ❌ 已驳回/淘汰`）与角标实时统计；
  - 引入 6 条/页的紧凑分页器，杜绝快速点击生成导致的长列表无限拉伸；
  - 增加 `DELETE /api/topics/:id` 接口与前端“🗑️ 物理删除”功能，允许清理驳回淘汰的无效选题；

---

## [v1.8.3] - 2026-10-08

### Agent体系全面纯净化：剔除历史包袱，100%聚焦工业外贸出海获客
- **1. 根治历史遗留人设与项目混杂问题**：
  - 排查溯源“七分大师”源于早期旧项目档案 `knowledge/项目档案.md`（C端节气AI写真小程序历史底料）；
  - 全面更新 `knowledge/项目档案.md`：剔除“七分大师”与 C 端 1 元情绪卡/9.9 元写真混杂内容，定位 100% 收敛于 **FDE 工业出海独立顾问 / 纺织面料获客交付系统**，明确以高价值工业独立站、自媒体矩阵与欧美买家定向触达为核心业务模型；
  - 全面纯净化 `agents/` 四大核心岗位：
    - `agents/01_选题官.md`：聚焦工厂物理档案、海外买家采购痛点与四大支柱（过程记录/方法拆解/结果复盘/认知颠覆），剔除 C 端混杂；
    - `agents/02_内容官.md`：定位出海全矩阵一稿四发（公众号长文、80s出镜视频分镜、小红书工业避坑、S2合规开发信），确立“以短时间看懂核心价值与促成询盘为唯一衡量准则”；
    - `agents/03_素材官.md`：生成车间实拍、大圆机阵列、GRS/OEKO-TEX证书吊牌、面料样卡实物图与视频提词卡，彻底剔除旧写真对比图逻辑；
    - `agents/04_线索官.md`：建立海外品牌采购商询盘与国内工厂老板自媒体线索双线分级SOP（A/B/C级），对接 SQLite `inquiries` 队列；
  - 净化 `scripts/orchestrator.mjs`：更新每日编排器代码注释与提示词上下文，预留云端大模型 API（DeepSeek/Qwen/Claude）与本地确定性规则引擎的双模适配层。
- **2. 架构测试与全链路回归**：
  - 运行并通过所有自动化测试套件（`test_hardcore_content.mjs`, `test_security_and_rbac_fixes.mjs`），无任何异常。

---

## [v1.8.4] - 2026-10-08

### 选题库扩容至10条与十维方法论选题池扩展
- **1. 选题列表分页调整为 10 条**：
  - 响应用户需求，将前端 `TOPIC_PAGE_SIZE` 常量从 6 条调整为 10 条，每页展示 10 条完整选题信息，提升审阅效率。
- **2. 方法论生成引擎池扩展为 10 维工业出海选题**：
  - 在 `server/agent_engine.js` 中将四大支柱出海选题池丰富扩展为 10 条覆盖全维度的工业品硬核选题（包含 ISPO 展会清洗、国际开发信防垃圾拦截、经编车间实录、独立站索样防白嫖门禁、3天色卡快反、可持续认证溢价、欧美大买家采购路径揭秘等）；
  - 选题生成时动态绑定目标工厂物理档案（机台、品类、证书、MOQ、交期），保证真实感与穿透力。
---

## [v1.8.5] - 2026-10-08

---

## [v1.8.6] - 2026-10-08

### 客户档案（S0）左右 Master-Detail 工作台与三模态 Tab 编辑重构
- **1. 布局重构为左右工作台架构 (Master-Detail)**：
  - 彻底根除原先卡片在上方堆叠过长、编辑器在最底部难以找寻的操作痛点；
  - **左侧栏 (300px)**：工厂导航名录，支持拼音/品类快速检索，卡片带当前选中高亮金边与核心认证/MOQ胶囊；
  - **右侧工作区 (自适应全屏)**：当前工厂档案工作台，包含顶部标题、模式 Tab、保存与下载快捷动作。
- **2. 三模态 Tab 查看与编辑交互**：
  - **📖 结构化预览**：内置零依赖轻量原生 Markdown 渲染器，将标题、大圆机参数、OEKO-TEX证书徽章、表格与引用块以 Notion 式高质感排版呈现；
  - **✏️ Markdown 源码编辑**：提供 100% 宽度的沉浸式等宽代码编辑器，适合快速粘贴老板面谈记录；
  - **⚡ 左右分屏对照 (Split View)**：左边编辑 Markdown 源码，右边实时同步渲染，输入即所见；
---

## [v1.8.8] - 2026-10-08

### 签约客户真实性彻底校准：移除非签约工厂，纯净化知识库
- **1. 恢复未沟通工厂为潜客大盘“待联系”状态**：
  - 针对此前批量演练中误将 13 家潜客流转为“已签约”的历史状态，全面执行数据恢复：
    - `prospect_factories` 潜客大盘中将这 13 家企业（如前进牛仔布、天念材料等）重置为“待联系”，回归正常拓客公海跟进流转；
    - 从 `clients` 签约表中完全剔除这 13 条记录，仅保留**海宁九鼎纺织有限公司 (C02，真实签约客户)** 与 **绍兴柯桥恒信针纺实业 (C01，系统演示样板)**；
- **2. 物理清理 `knowledge/客户档案/` 未签约占位文件**：
  - 物理删除 13 份测试占位 `.md` 文件，磁盘上仅保留真实的 2 份核心档案：
    - `knowledge/客户档案/海宁九鼎纺织有限公司.md`
    - `knowledge/客户档案/绍兴恒信针纺实业.md`
- **3. Web 控制台呈现**：
  - 【客户获客档案 (S0)】视图左侧仅展示 **2 家真正已签约的工厂**，彻底杜绝虚假客户混淆，恪守 AGENTS.md“不得编造客户数据、案例、认证”的最高硬规则。

---

## [v1.9.0] - 2026-10-08

### 深度代码审查发现定位、UX交互闭环修复与文档事实全量同步
- **1. 深度代码审查具体发现与问题定位**：
  - **发现 1 (S0 档案选中失步)**：`app/index.html` 的 `renderClients(clients)` 中曾硬编码 `selectClientProfile(cachedClientsList[0].id)`，导致顶栏选择海宁九鼎 (`C02`) 或页面刷新时，档案查看强制错位覆盖为首项 `C01`。现已修复为优先对齐 `activeFactoryId`，实现状态严格同步。
  - **发现 2 (S5 客户周报模版与请求硬编码)**：`generateReportFast()` 曾写死请求体 `body: JSON.stringify({ client_id: 'C01' })`，且 `viewReportDetail()` 标题写死 `客户：绍兴恒信针纺实业`。导致服务海宁九鼎时周报错乱。现已修复为动态绑定当前激活/查看的工厂，抬头与汇算数据 100% 动态对齐。
  - **发现 3 (S0 缺失前端新签约建档入口)**：后端已具备 `POST /api/clients` 接口，但前端 `v-clients` 头部无新建入口，顾问线下签约新工厂后无法在界面完成标准建档。现已在界面新增 `➕ 签约新工厂建档 (S0)` 按钮及模态框 `#modalNewClient`，输入企业全称、品类、联系人、MOQ、认证等要素后，自动在 `knowledge/客户档案/` 生成规范 `.md` 并入库。
  - **发现 4 (系统设置缺失九鼎标杆客户档案直链)**：`v-settings` 中曾仅有恒信针纺档案链接，现已补充海宁九鼎标杆客户档案（真实签约）的直达链接。
  - **发现 5 (历史文档与代码事实严重脱节)**：`docs/01_PRD.md`、`docs/03_实施计划.md` 与 `docs/04_README.md` 充斥旧项目遗留词汇（“七分大师”、“牧码人”、“PostgreSQL 16”、“localStorage 演示”），且缺失 `docs/02_技术文档.md`。
- **2. 文档体系全量重构与事实对齐**：
  - 重写 `docs/04_README.md`：完整呈现 Node.js 22 + 原生 SQLite、S0-S6 全链路、九鼎标杆、5,100 家面料拓客大盘及单命令快速上手指南；
  - 重写 `docs/01_PRD.md`：建立以出海面料工厂为核心的 B2B 工业 FDE 交付体系 PRD；
  - 创建 `docs/02_技术文档.md`：详尽阐述 10 张核心数据表模型、RESTful API 契约、Agent 确定性规则引擎与前端单页应用架构；
  - 重写 `docs/03_实施计划.md`：制定对齐 `pilot/面料工厂30天试点方案书.md` 的 30 天 4 阶段交付排期与关键风险应对方案。
- **3. 全面验证与测试**：
  - 通过自动化测试脚本验证 `POST /api/clients`、`POST /api/reports/generate (C02)`、`test_hardcore_content.mjs` 以及 `test_security_and_rbac_fixes.mjs`，所有 TDD 测试 100% 通过。

---

## [v1.9.1] - 2026-10-08

### “外贸独立站客户”新增多批次客户表格清洗、跨源融合、去重录入与画像补全
- **1. 多源客户数据全面解析与清洗**：
  - 全量扫描并解析 `外贸独立站客户/` 目录下 15 个最新 CSV 表格（含总线索表 v2 系列、无线上面料厂批次、Top50 黄金名单等共计 2,550 条记录）；
  - 自动适配 `utf-8-sig`、`gb18030`、`gbk`、`utf-8` 编码，提取统一社会信用代码、法定代表人、注册资本、主营品类、联系电话、邮箱、官网及出海信号。
- **2. 严格去重与跨表信息融合**：
  - 规范化企业全称，合并同一企业在多个批次表格中的分散线索（聚合清洗手机、固话、有效企业邮箱）；
  - 与本地 SQLite `prospect_factories` 现有 5,100 家潜客库执行严格交叉比对：
    - **现有客户丰富补全 (100 家)**：成功为库中已有的 100 家展商更新补全更多最新电话、邮箱、官网及工商批注，强化线索全息度；
    - **全新优质客户入库 (+500 家)**：去重确认 500 家此前库中不存在的全新实体面料工厂，顺序自增编号为 `PF05101` ~ `PF05600`，全量持久化写入 SQLite。
- **3. 数据规模与画像升级**：
  - 潜客总库从 **5,100 家扩容至 5,600 家**（完全去重唯一）；
  - A 级重点大厂扩充至 **3,690 家**（结合 ≥1000万大资金、P1/S级出海信号智能评定）；
  - 有效电话覆盖率高达 **99.2%** (5,554 家)，有效企业邮箱覆盖率达 **98.6%** (5,521 家)；
  - 针对新增工厂主营品类自动合成专属 60 秒军师破冰锦囊（`custom_pitch`），赋能业务员高效拿单。
- **4. 前端与文档同步**：
  - 前端控制台角标、筛选按钮及分页器自动动态对齐为 5,600 家（112 页）；
  - 同步更新 `docs/04_README.md`、`docs/01_PRD.md` 与 `docs/02_技术文档.md`。

---

## [v1.9.2] - 2026-10-08

### 签约状态与历史备注校准：清理演练测试残留批注，强化签约状态双向校准
- **1. 问题定位与排查溯源**：
  - 用户反馈：“全部客户中有公司显示‘签约成功’，但右边签约入库按钮显示还没有签约”；
  - **根本原因定位**：
    - 此前在系统功能演练中模拟测试了 13 家展商（PF00002~PF00015）的“签约入库”业务流，签约接口自动在备注字段 `notes` 前追加了 `【签约成功】于 2026-10-07 签约升级为正式交付项目(编号: ...)...`；
    - 在后续响应用户“恢复未沟通工厂为未签约状态”要求时，系统将 `status` 恢复重置为 `'待联系'`，并将虚拟客户从正式 `clients` 表剔除；
    - 但 `prospect_factories` 备注字段 `notes` 中的测试前缀文字当时未被同步剔除；
    - 导致前端第 1 列展示企业备注时显示了 `【签约成功】...`，而第 4 列流转状态为真实状态 `待联系`，第 5 列按钮因 `status !== '已签单'` 显示为 `🤝 签约入库`，形成视觉认知矛盾。
- **2. 数据库历史残留批注清理**：
  - 对 13 家相关展商的 `notes` 字段执行数据清洗，移除历史演练残留的 `【签约成功】...` 前缀，完整保留源数据中的真实工商与出海信号；
  - 库中所有 5,600 家潜客的备注与真实跟进状态保持 100% 纯净与对齐。
- **3. 前端与服务端签约状态双向校准增强**：
  - **前端渲染层 (`app/index.html`)**：升级 `isSigned` 判定逻辑，不仅比对 `status === '已签单'`，同时支持比对 `cachedClientsList`（正式签约客户表），若已在签约客户名录中，右侧一律统一高亮展示 `✓ 已签约`，彻底消除歧义；
  - **后端签约逻辑 (`server/index.js`)**：在签约入库接口中将单纯覆盖备注优化为追加保留现有工商备注，避免后续信息断层。

---

## [v1.9.3] - 2026-10-08

### 售前拓客大盘与交付客户档案全链路闭环：彻底打通数据孤岛
- **1. 问题本质定性（概念分工 vs 交互数据孤岛）**：
  - 用户反馈：“业务员拿单排行榜签约试点显示 0 家、已签单筛选为空，但客户档案有 2 家；拓客工作台搜索海宁九鼎显示‘未匹配到客户’，交互逻辑是 bug 还是正常？”；
  - **客观分析**：系统架构原先将“售前线索公海 (`prospect_factories`)”与“售后交付空间 (`clients`)”进行了分工隔离。海宁九鼎与恒信针纺作为标杆客户直接初始化在交付库，未作为售前线索录入拓客大盘；
  - **UX/业务定性**：这属于严重的**数据孤岛与交互割裂缺陷（体验 Bug）**——核心签约标杆在大盘搜不到易引发撞单与认知混乱，销售看板无法反映真实交付战果。
- **2. 双向镜像与全链路闭环实施**：
  - **标杆客户入盘 (`scripts/sync_signed_clients_to_prospects.js`)**：
    - 将真实签约核心标杆 `海宁九鼎纺织有限公司` (PF05602) 与系统样板 `绍兴柯桥恒信针纺实业` (PF05601) 规范写入 `prospect_factories` 拓客大盘；
    - 状态设置为 `已签单`，归属人标定为 `总顾问 / 老板`，录入真实官网（`jdtexcn.com`）与差异化优势锦囊；
  - **销售战报与漏斗实时联动**：
    - 排行榜“全队累计已签约试点”真实显示为 `2 家`，“总顾问 / 老板”名下清晰呈现签约战绩；
    - 拓客大盘点击“已签单”标签，即刻列出海宁九鼎与恒信针纺；
    - 搜索“海宁九鼎”，秒级召回并高亮展示 `✓ 已签约 · 查S0` 徽章；
  - **前端快捷直达跳转 (`app/index.html`)**：
    - 点击拓客大盘中的 `✓ 已签约 · 查S0`，直接无缝平滑跳转至对应工厂的 S0 客户建档与履约空间；
  - **后端双向建档同步 (`server/index.js`)**：
    - 在 `POST /api/clients` 中增加拓客大盘自动镜像同步逻辑，后续在线录入任何新签约工厂，均自动在售前大盘同步更新或写入 `status = '已签单'` 记录，彻底杜绝售前与售后脱节。

---

## [v2.0.0] - 2026-10-08

### L4 商业落地交付：深度代码审查发现修复 + TDD 有序实施（13 项 / 3 个 Sprint / 89 条断言）

本轮为「先审查定位 → 再定计划 → TDD 红灯 → 实现绿灯 → 回归全绿」的完整闭环。
新增 3 套 TDD 套件（`scripts/test_s1_hemostasis.mjs` / `test_s2_compliance.mjs` / `test_s3_platform.mjs`），
并与既有 7 套存量套件一并纳入 `npm run test:all`。

#### Sprint 1 · 止血（41 条断言，41/41 通过）

- **T1 根治「全库 5,602 家一律误标无独立站」**
  - 根因：前端读 `p.website`，而 `prospect_factories` 根本没有该列（真实列为 `qcc_site`），
    导致连拥有 `jdtexcn.com` 的海宁九鼎本人都被标成「🎯 无独立站（核心痛点）」。
  - 新增 `server/fde_utils.js`，提供 `parseWebsite()`：剥离 `(官网)` 标注、`https://` 协议与路径，
    并**严格区分「品牌独立站」与「第三方平台店铺」**（阿里巴巴/1688/淘宝/慧聪/中国制造网一律不计为独立站），
    过滤 `baidu.com` 等占位域名与「实为占位」批注；`/api/prospects` 每行下发 `website` + `website_kind`（own/platform/none）。
  - 实测：271 家有站点信息的企业中，真正的独立站被正确识别，平台店铺不再被误判。

- **T2 修复签约状态双向校准从未生效**
  - 根因：`cachedClientsList` 是顶层 `let` 声明（不挂载到 `window`），而消费方写的是 `window.cachedClientsList`，
    恒为 `undefined` → v1.9.2 声称的「已在签约客户名录中即高亮 ✓ 已签约」实际从未工作，
    「✓ 已签约 · 查S0」点击后也永远落到兜底分支（不选中任何客户）。
  - 改为直接使用词法作用域变量。

- **T3 周报周次与数据真实性**
  - 根因：`2026-W${Math.ceil(new Date().getDate()/7)}` 把「当月日期÷7」当周次且年份写死 2026
    → 10 月 8 日生成 `2026-W2`（真值 `2026-W41`）；且 `open_count = sent×0.55`、`reply_count = max(1, 询盘数)`
    属凭空编造，却被周报模板标为「真实回复数」，违反 `AGENTS.md` 硬规则 2。
  - 新增 `isoWeekLabel()`（标准 ISO-8601，含跨年正确归周）；未采集指标一律落 `NULL`，
    前端新增 `fmtCount()` 渲染为「未采集」；新增 `DELETE /api/reports/:id`。
  - 数据修复：存量 `REP-231322` 周次由 `2026-W2` 修正为 `2026-W41` 并清除编造值
    （另两条带人工标注的周报 `2026-W40 (第1周)` / `2026-W40 (九鼎纺织)` 属人工录入，保持原样未动）。

- **T4 修复「一条命令可启动」被破坏**
  - 根因：`users` 与 `prospect_factories` 两张表历史上分别由 `scripts/upgrade_l4.mjs`、`scripts/import_prospects.mjs`
    单独创建，从未收敛进 `server/db.js` 的 `initSchema()`。一旦删库或执行 `npm run init-db`，
    `/api/auth/login` 即抛 `no such table: users` → 500，而前端只提示「登录网络异常」→ 用户彻底被锁在门外且无从自救。
  - 两张表建表语句收拢进 `initSchema()`；新增 `seedUsers()` 自动播种 admin/sales1/sales2；
    新增 `FDE_DB_PATH` 环境变量支持（TDD 可在临时库验证 schema 完整性，不污染线上库）。
  - 登录失败提示改为可操作排查指引（服务未起 / 数据库不可写 / 可执行 `npm run init-db`）。

- **T5 Skill 运行器诚实化 + 参数透传**
  - 未实现的 Skill（S0/S3/S4/S5/S6）不再返回 `success:"执行完毕，数据已核验"` 的假成功，
    改为 **HTTP 501 + `SKILL_NOT_IMPLEMENTED` + 明确 hint**，前端如实提示而非静默吞掉。
  - `runSkillFast()` 透传 `client_id`（修复前恒落 C01，在九鼎空间点「采集新名单」像什么都没发生）；
    `quickGenOutreach(buyerId)` 真正按 `buyer_id` 生成（修复前该形参从未被使用，点 A 买家的按钮给 B 买家生成信件，
    却弹出「已为该买家生成专属开发信」的假确认）。

- **T6 补齐 CSS 缺失语义类**：新增 `.tag.warn` / `.tag.danger` / `.tag.faint` / `.empty` 与 `--info` 变量
  （此前这些类只在 JS 里被拼进 class，CSS 从未定义，导致潜客流转状态全部退化为灰色、「🎯 无独立站」失去警示色）。

#### Sprint 2 · 合规与架构（25 条断言，25/25 通过）

- **T7 一稿四发内容包接入人工审核门**（对齐 `AGENTS.md` 硬规则 1）
  - 生成的内容包一律落 `pending`（修复前直接落 `ok`，导致前端「通过放行/退回」按钮永远不显示，
    对外公众号长文、小红书笔记与开发信模板实际无人审核即流出）。
  - 拒绝为未通过（`pending`/`rejected`）选题裂变内容包，返回 400 + 明确原因。
  - 新增 `DELETE /api/packs/:id`。

- **T8 服务端鉴权（关闭严重越权）**
  - 根因：`/api/clients` 直接采信 query 里的 `user_role` / `user_name`（完全由客户端自称），
    业务员只要不传参数即可拿到全量工厂，所谓 RBAC 只是前端把菜单藏起来。
  - 新增 `server/auth.js`：登录签发 HMAC-SHA256 令牌（`X-FDE-Token`），密钥持久化于 `data/.auth_secret`；
    `/api/*` 全量强制校验（仅放行 `/api/status`、`/api/auth/login`、`/api/auth/verify`）；
    新增 `visibleClientIds()` 由服务端按令牌身份强制裁剪工厂可见范围。
  - 前端在唯一入口统一注入令牌（避免遗漏 30+ 处 fetch），并对 401 做全局兜底（回到登录门禁而非无提示失败）。
  - 新增 `scripts/_test_http.mjs` 公共测试客户端，5 套存量 HTTP 测试完成鉴权接入。

- **T9 大盘分页 + 分模块容错**
  - `/api/prospects` 支持可选 `page` / `page_size` 并下发 `pagination` 元信息（不传参数时保持全量，行为向后兼容）。
  - `loadAllData()` 由「12 个接口塞进单个 `Promise.all`」改为逐模块 `loadModule()` 各自兜底：
    修复前任一接口失败即走进 catch，整页一个区块都不渲染；现在坏掉的模块自己报错并顶部提示，其余照常显示。

#### Sprint 3 · 平台化（23 条断言，23/23 通过）

- **T10 宝宝写真实验看板接线**（此前为 100% 不可达的死视图）
  - 补左侧导航入口；新增 `pilot_metrics` 表与基线种子；`/api/pilot/photo` 由硬编码改为读库，
    新增 `PUT /api/pilot/photo` 可录入真实进展；前端新增 `renderPilotBoard()` / `loadPilotData()` / `savePilotMetrics()`
    与录入表单，止损判定按实际单数动态着色。
  - 同步将 `photo_pilot` 纳入 `ADMIN_ONLY_VIEWS` 与业务员隐藏列表（两处口径此前不一致）。

- **T11 Skill 规范质量门元数据化**
  - 新增 `server/skill_spec.js`，解析 `skills/*.md` 的「质量门 / 人工审核点 / 目标 / 输入 / 输出 / 指标」，
    `/api/skills` 下发结构化 `quality_gate[]` 与 `review_point`
    （修复前只解析第一行标题与「目标:」一行，规范里最值钱的质量门从未被解析更未被任何代码执行）。

- **T12 双模生成适配层**
  - 新增 `server/generation_adapter.js`：默认走确定性规则引擎（离线、可复现）；
    配置 `FDE_LLM_API_KEY`（可选 `FDE_LLM_BASE_URL` / `FDE_LLM_MODEL`）后自动切大模型模式，
    任何异常自动回落确定性引擎，绝不把生成流程打断成 500。`/api/topics/generate` 已接入。

- **T13 仓库减脂**：16 个一次性补丁脚本（`patch_*` / `update_*` / `upgrade_*` / `apply_*` / `build_full_*` 等）
  归档至 `scripts/_archive/`，`scripts/` 主目录只保留可复用的数据导入、编排、运行器与 TDD 套件。

#### 验证

- `npm run test:all` → Sprint1 41/41、Sprint2 25/25、Sprint3 23/23、存量 7 套全绿（共 89+ 条断言）。
- 前端内联脚本语法校验通过（1 个 script 块 / 2563 行），CSS 花括号配平 140/140。
- DOM 一致性校验：JS 引用的 168 个 id 全部存在，新增功能必需 id 无缺失。
- 演练数据已清理复位：`clients` 2 家、`prospect_factories` 5,602 家（已签单 2 / 待联系 5,600）、
  归属分布与基线逐项对齐（公海池 1521 / 总顾问 1362 / 小张 1360 / 小李 1359）、
  内容包 20 个、开发信 6 封、周报 3 份、技能日志 3 条。

#### 待办（需决策，未擅自实施）

1. 遗留重复目录 `fde-launch-pack/`、`fde-agent-system/`、`fde-mgmt-system/` 与根目录 `skills/`、`agents/`、`knowledge/`
   内容重复，且 `fde-mgmt-system/docs/03_瀛炴柦璁″垝.md` 仍为乱码文件名 —— 删除属破坏性操作，待确认后处理。（已于 v2.1.0 处理）
2. 大模型通道（`generation_adapter.js` 的 `llmGenerateTopics`）尚未接入具体厂商，配置密钥后需补全实现。（v2.1.0 已提供后台配置入口）
3. S2 规范的「+3/+7/+14 天三封跟进序列」、S4 的「24h 超时告警 / A级报价老板确认」仍未实现（本轮仅完成引擎诚实化，未新增业务规则）。（已于 v2.1.0 实现）

---

## [v2.1.0] - 2026-10-08

### L4 交付：目录瘦身、大模型后台可配、业务规则完善与测试 fixture 化（Sprint 4，37 条断言）

#### 1. 仓库瘦身（按可回溯性分级处理）

- **移除 3 个重复目录** `fde-agent-system/`、`fde-launch-pack/`、`fde-mgmt-system/`
  （与根目录 `skills/`、`agents/`、`knowledge/`、`docs/` 内容重复，且 `fde-mgmt-system/docs/03_瀛炴柦璁″垝.md` 仍是乱码文件名）。
  三者均在 git HEAD 中，**如需回溯执行 `git checkout HEAD -- <目录>` 即可**，不属于不可恢复删除。
- **`yipai/`（25MB，非本项目，被 .gitignore 排除，git 无法回溯）不删除**，改为**移出工作区保留**至 `E:/_archived_yipai/yipai`。
- **`外贸独立站客户/`（3.76MB 原始线索表格）**：安全删除机制拦截了删除操作，按纪律未重试等价删除，目录保留。
  依赖它的 `scripts/import_prospects.mjs` 已还原为可用状态。如需移除请手动执行，内容同样在 git HEAD 中可回溯。

#### 2. 大模型通道改为后台可配置（T14）

- 新增 `app_settings` 表持久化运行配置；新增 `GET/PUT /api/admin/settings` 与 `POST /api/admin/settings/llm/test`。
- **仅老板可读写**（业务员 403）；API Key 回读时脱敏为「已配置 · 尾号xxxx」，空串表示不修改密钥避免误清空。
- `generation_adapter.js` 新增 `configureFromDb()`：后台配置优先于环境变量，保存后立即生效。
- 系统设置页新增「🤖 大模型通道配置」卡片：启用开关、Base URL、模型名、密钥、保存 / 连通性自检 / 重新读取，
  并实时显示当前处于「确定性引擎」还是「大模型模式」。
- 设计前提不变：**默认确定性引擎，大模型不可用时自动回落，绝不把生成流程打断成 500。**

#### 3. 业务规则完善（T15~T19，严格对齐 skills/ 规范）

- **T15 S2 跟进序列**：新增 `outreaches.planned_send_at` / `followup_of` 字段（只加法迁移）；
  新增 `POST /api/outreaches/:id/generate-followups`，按 `skills/S2` 的 **+3 / +7 / +14 天**节奏生成三封跟进信（跟进1/跟进2/最后跟进），
  均落 `pending_review` 待人工审核；**同一买家幂等，不重复生成**（防重复触达）；前端卡片提供「🔁 生成跟进序列」与计划发送日标签。
- **T16 S2 质量门硬拦截**：`≤120 词` 由「打标签提示」升级为**硬性 400 拦截**（`MAX_OUTREACH_WORDS`），与退订说明同为放行前置条件。
- **T17 S4 24h SLA 与老板确认门**：新增 `inquiries.boss_confirmed` 字段；
  询盘列表下发 `is_overdue`（仅未闭环且超 `follow_up_deadline` 才标记），前端标红「⚠️ 已超 24h SLA」；
  **A 级询盘或回复中含报价/交期承诺时，未勾选「老板已确认」不允许置为「已回复」**（返回 400 + 明确原因），
  弹窗实时提示是否需要老板把关。显式传 `false` 可撤回确认（草稿重写后重新把关）。
- **T18 军师话术消费 `custom_pitch`**：库里已为 **502 家**工厂预生成专属锦囊，此前 `agent-pitch` 完全不读、一律用通用模板；
  现在有锦囊时优先用锦囊开场，穿透力显著提升。
- **T19 买家去重**：单条录入与批量导入均按「工厂 + 公司名」查重，重复返回 409 / 自动跳过并回报跳过条数；新增 `DELETE /api/buyers/:id`。
- **修复真实缺陷**：`PUT /api/prospects/:id/status` 在不传 `notes` 时会因 `node:sqlite` 无法绑定 `undefined` 而 **500**；
  现已统一归一为 `null`（T21 回归用例覆盖）。另统一了 `photo_pilot` 在 `ADMIN_ONLY_VIEWS` 与业务员隐藏列表两处的口径。

#### 4. 测试 fixture 化（T20）——彻底解决「测试写脏生产数据」

- 新增 `POST /api/prospects/fixture`（强制名称含 `TDD演练`）、`DELETE /api/prospects/fixture/:id`、
  `DELETE /api/clients/fixture/:id`（**只认 TDD演练 标识，杜绝误删真实客户**）。
- `_test_http.mjs` 新增 `ensureFixtureProspect()` / `deleteFixtureClient()` / `deleteFixtureProspect()`。
- `test_l4_core`、`test_l4_frontend_flows`、`test_l4_enhancements` 三套的**签约入库 / 流转**用例全部改打 fixture，
  并在结尾自动清理演练客户 + 复位 fixture 状态；`test_hardcore_content` 也会清理自己裂变出的内容包。
- 修复 fixture 声明顺序导致的 TDZ 报错（`Cannot access 'TOKEN' before initialization`）。

#### 验证

- `npm run test:all` → Sprint1 41/41、Sprint2 25/25、Sprint3 23/23、**Sprint4 37/37**、存量 7 套全绿（共 126+ 条断言）。
- Sprint4 连续跑两次均为 37/37（幂等，可重复运行）。
- **真实数据不变性实证**：全量回归前后快照逐项一致 —— `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 内容包 20 / 周报 3 / 技能日志 3`。
- 前端内联脚本语法通过，CSS 花括号 140/140 配平，JS 引用的 175 个 DOM id 无缺失，新增控件齐备。

#### 待办

1. 大模型通道尚未接入具体厂商（`generation_adapter.llmGenerateTopics`），后台配好密钥后需补全实现。
2. `外贸独立站客户/` 原始表格目录因安全策略未删除，如需清理请手动执行（git 可回溯）。

---

## [v2.2.0] - 2026-10-08

### L4 商业实施计划 · Sprint 5：补齐三大商业闭环（P0，37 条断言）

本轮依据「系统目前是交付台账而非商业智能体」的定位判断，优先补齐**让系统能替你赚钱**的三段闭环，
而非继续堆功能。新增 `scripts/test_s5_growth.mjs`。

#### T22 成交漏斗 `deal_flow`（让交付可举证、续约有凭）

- **商业理由**：交付链路原先止于「询盘已回复」，报价 / 寄样 / 试样 / 下单 / 回款全在微信与邮件里，
  系统内无任何痕迹 → **无法向老板举证这单是你带来的，续约只能靠嘴说**。
- 新增 `deal_flow` 表（`询盘→报价→寄样→试样反馈→下单→回款→流失`，含金额 / 米数 / 推进时间）。
- 新增 `GET/POST /api/deals`、`PUT/DELETE /api/deals/:id`、`GET /api/deals/stats`
  （各阶段计数 + 已回款总额 + 在谈管道金额 + 成交/流失单数）。**仅老板可见**（业务员 403）。
- 前端新增「💰 成交漏斗看板」视图与导航入口：四张 KPI（回款总额 / 在谈管道 / 已成交 / 流失）、
  各阶段分布条形图、明细表、一键「推进至下一阶段」。

#### T23 今日待办排序层（把 5,602 家潜客池变成每日产能）

- **商业理由**：人均名下 1,300+ 家潜客，但系统只能按「优先级 + 状态 + 关键词」筛选，
  **没有"今天该打谁"的依据**，人类不可能跟完。
- 潜客表新增 `next_contact_at` / `contact_count`（只加法迁移）。
- **流转即自动排期**：`待联系 +1天 / 已加微信 +2天 / 已发诊断 +3天 / 意向跟进 +5天 / 已签单 +30天`；
  无效与搁置状态不排期；每次流转自动累加联系次数。
- 新增 `GET /api/prospects/today?limit=20`（已到期优先 → A 级优先 → 排期早者优先，排除已签单与无效）。
- 拓客工作台顶部新增「📅 今日待办跟进」面板，直达军师支招。

#### T24 开发信效果回写（让 S2 复盘真正可执行）

- **商业理由**：`skills/S2` 明写「指标：打开率、回复率、有效询盘数（按话术版本分组统计）」与
  「每周把回复率最高的开场句式沉淀进话术库」——**此前一个指标都采集不到，系统跑一年也不知道哪种开场句更有效**。
- 开发信表新增 `opened_at` / `replied_at` / `reply_snippet` / `variant`（只加法迁移）。
- 新增 `POST /api/outreaches/:id/track`（open / reply；登记回复会同步买家状态为「已回复」）、
  `DELETE /api/outreaches/:id/track`（误登记可撤销）、`GET /api/outreaches/stats`
  （发送/打开/回复数、打开率、回复率、**按话术版本分组**）。
- 前端：已发送卡片增加「👀 登记已打开」「💬 登记回复」，开发信视图顶部新增「📈 触达效果复盘」面板。

#### 顺带修复

- **T2 守卫抓到回归**：新写的 `renderDeals` 误用了 `window.cachedClientsList`（顶层 `let` 不挂载 window），
  被 Sprint1 的 T2.1 断言拦截，已改回词法作用域引用。
- **测试基建缺陷**：`_test_http.mjs` 中 `createClient.request` 因多行写法未被批量替换到 `agent: false`，
  仍在复用 Node 默认 keep-alive socket，导致连续请求随机 `ECONNRESET`（表现为"偶发失败"）。
  已在公共客户端统一禁用 socket 复用，Sprint5 连续两次运行均 37/37。
- Sprint5 增加**自清理用例**（撤销回写、删除演练成交记录），确保不把演练数据留在真实业务数据里。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 23 / Sprint4 37 / **Sprint5 37** / 存量 7 套全绿（共 163+ 条断言）。
- Sprint5 连续两次运行均 37/37（稳定，非偶发）。
- **真实数据不变性实证**：全量回归前后快照逐项一致 ——
  `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 回写 0 / 成交记录 0 / 内容包 20 / 周报 3 / 技能日志 3`。
- 前端内联脚本语法通过，CSS 花括号 140/140 配平，JS 引用的 186 个 DOM id 无缺失，成交漏斗表头 7 列与渲染模板一致。

#### 后续计划（P1 / P2，未实施）

- **P1-4 接入真 LLM**：后台入口已就绪；**前提是先结构化事实源**——
  `knowledge/客户档案/*.md` 目前是自由文本，直接喂给 LLM 容易编造，会违反硬规则 2。
  建议先抽出机台数 / 认证 / MOQ / 交期 / 产能等结构化字段，再补 `llmGenerateTopics`。
- **P1-5 话术 A/B**：`variant` 字段已就位，等回写数据积累后即可跑出「哪版开场句回复率高」。
- **P2-6 前端拆分**：`app/index.html` 已突破 4,100 行、单文件内联。建议拆为 `app/js/*.js`（保持原生不引框架）。
- **P2-7 后端分域**：`server/index.js` 已 1,700+ 行，建议按域拆分为 `server/routes/*.js`。
- **P2-8 密码安全**：目前明文存储且登录页印着 admin/admin888，自用可接受，对外演示前需做 salt 哈希。

---

## [v2.3.0] - 2026-10-08

### L4 商业实施计划 · Sprint 6：事实源结构化与可信生成（29 条断言）

本轮解决的是**接大模型之前的必要前提**：把自由文本档案变成可机读事实，
并根除生成侧"用写死默认值冒充实证"的编造行为。新增 `scripts/test_s6_facts.mjs`。

#### T25 客户档案事实源结构化

- 新增 `server/fact_parser.js`：按 S0 档案的小标题写法归纳出 17 个字段别名表，
  解析出主营产品 / 起订量 / 认证 / 产能交期 / 目标市场 / 买家画像 / 采购量级 / 报价策略 /
  触达禁忌 / 英文关键词（编号列表）/ 证据库（整节）/ 效果数据等。
- 新增 `client_facts` 表缓存解析结果；新增 `GET /api/clients/:id/facts` 与
  `POST /api/clients/:id/facts/refresh`（改完档案可重新解析）。
- **只提取真实存在的内容，绝不补全与推断**；抽不到的字段一律留空并计入 `missing_fields`
  （区分 required / 非必填），供 UI 提醒补录。
- 人工录入的 `summary_json` 优先于文本解析（人工填写更可信）。

#### T26 生成引擎去编造（关键合规修复）

这是本轮最重要的修复。修复前引擎里有两处写死兜底：

```js
const certs = s.certifications || 'GRS 4.0 环保回收认证 / OEKO-TEX Standard 100 / SGS阻燃检测';
const moq   = s.moq           || '常规 500米/色; 定制 1000米/色';
```

即：**客户档案里没填认证和起订量时，系统会自动替他编一个**。
测试已实证（红灯 T26.8/T26.9）——给一个完全无数据的客户生成内容包，输出里照样出现
`OEKO-TEX` 与 `500米/色`。这直接违反 `AGENTS.md` 硬规则 2（不得编造客户数据、案例、认证）。

同类问题还有两处一并修复：

- `POST /api/clients` 新建客户时把认证写死为 `OEKO-TEX 100 / GRS 4.0`、起订量写死为
  `常规 500米/色` —— 同样是替客户编事实，已改为留空。
- 公众号长文里写死的经营数据「访问 3,200+ / 打样 12 笔 / 成交 2 笔 45,000 美元」、
  视频脚本里的「上个月直接截获 12 笔欧美专业询盘」——**对任何客户都输出同样的数字**，
  已改为：档案里有真实周指标就用真实值，没有就明确标注「事实缺口待补录」。

现在的行为：字段缺失即**省略或明示待补录**，并在 `metadata` 里输出
`fact_gaps[]` / `fact_gap_notice` / `quality_gate_passed`，审核人一眼可见哪些内容待补录。

顺带修复 `agent_engine.js` 中一处单引号普通字符串导致 `${moq}` 未被插值、
页面上原样显示 `${moq}` 的问题。

#### T27 大模型通道落地（基于结构化事实源）

- `generation_adapter.llmGenerateTopics` 由占位抛错改为真实调用：
  采用 **OpenAI 兼容的 `/chat/completions` 协议**（DeepSeek / 通义 / Moonshot / OpenAI 通用），
  不绑定任何厂商 SDK，只依赖后台配置的 Base URL + 模型名 + 密钥。
- **只把结构化事实喂给模型**，`null` 字段在 prompt 中明确标注为"未知，严禁编造认证/产能/交期/案例/数字"，
  要求输出严格 JSON。
- 20 秒超时（可用 `FDE_LLM_TIMEOUT_MS` 调）+ 全异常捕获，**任何失败自动回落确定性引擎**，
  生成流程绝不中断成 500。
- `/api/topics/generate` 现在回传 `generation_mode` 与 `fallback_reason`，
  提示语明确说明本次走的是哪条通道（不再假装没事）。
- 后台新增 `clear_llm_api_key` 能力，可彻底清除密钥（避免测试/演示残留）。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 23 / Sprint4 37 / Sprint5 37 / **Sprint6 29** /
  存量 7 套全绿（**共 192 条断言**）。
- Sprint6 连续两次运行均 29/29（稳定，且自清理生效）。
- **真实数据不变性实证**：全量回归前后快照逐项一致 ——
  `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 回写 0 / 成交 0 / 内容包 20 / 周报 3 / 日志 3`。
- 前端脚本语法通过，CSS 花括号 140/140 配平，JS 引用的 186 个 DOM id 无缺失。

#### 后续计划（P1 收尾 / P2，未实施）

- **P1-5 话术 A/B**：`variant` 字段与回写统计已就位，积累真实打开/回复数据后即可跑出"哪版开场句回复率高"。
- **P2-6 前端拆分**：`app/index.html` 已达 **4,395 行**单文件内联，建议拆为 `app/js/*.js`（保持原生不引框架）。
- **P2-7 后端分域**：`server/index.js` 已 1,900+ 行，建议按域拆分为 `server/routes/*.js`。（已于 v2.4.0 完成）
- **P2-8 密码安全**：明文存储 + 登录页印着 admin/admin888，对外演示前需做 salt 哈希。（已于 v2.4.0 完成）

---

## [v2.4.0] - 2026-10-08

### L4 商业实施计划 · Sprint 7：后端分域重构 + 密码加盐哈希（18 条断言）

#### T28 后端按业务域拆分

- **动机**：`server/index.js` 已达 2,157 行，路由、SQL、业务规则、工具函数全部混写，
  定位一个问题要全文搜索，改动极易误伤相邻逻辑。
- 拆分为 **12 个域模块**（`server/routes/`）：
  `auth`（登录/账号/战报）、`clients`（S0 档案与事实源）、`buyers`（S1 名单）、
  `outreaches`（S2 审核与回写）、`inquiries`（S4 询盘）、`reports`（S5 周报与工作台聚合）、
  `diagnostics`（S6 诊断）、`content`（选题/内容包/线索/实验看板）、`skills`（Skill 运行器）、
  `prospects`（拓客大盘与军师 Agent）、`deals`（成交漏斗）、`admin`（运行配置）。
- 新增 `server/route_kit.js` 承载跨域共享常量与工具（S2 词数上限与跟进节奏、S4 承诺关键词、
  成交阶段、时间计算、管理员校验、事实源读取、运行配置读取），避免 12 个文件各写一份。
- 各域模块通过 `ctx` 注入依赖（`db` / 工具函数 / 常量），不再各自 require。
- **`server/index.js` 从 2,157 行降到 121 行**，只保留：应用初始化、中间件、鉴权门禁、静态托管、
  健康检查、域挂载、启动监听。
- 拆分方式采用脚本机械搬运（按顶格 `});` 识别路由块边界），并对同一 method+path 做去重。

**拆分中发现的真实缺陷**：`app.delete('/api/outreaches/:id')` 在原文中**被定义了两次**，
第二个是永不生效的死代码，已在拆分时去重移除。

**拆分后必须修正的路径基准**：模块从 `server/` 移到 `server/routes/` 后，`__dirname` 少了一级，
`skills.js` 的 `skills` 目录、`clients.js` / `prospects.js` 的客户档案路径原本会指向
`server/skills`、`server/knowledge/...`（不存在）。已统一改为 `ROOT_DIR = path.join(__dirname,'..','..')`。
（该问题在 `/api/skills` 返回 500 时被端到端断言抓出，而非靠肉眼发现。）

#### T30 密码加盐哈希

- 新增 `server/password.js`：scrypt（Node 内置，无需第三方依赖）＋每账号 16 字节随机盐，
  存储格式 `scrypt$N$r$p$<salt-b64>$<hash-b64>`；校验用 `timingSafeEqual` 防时序侧信道。
- 登录由 `WHERE username = ? AND password = ?` 明文比对，改为**先按用户名取回记录再哈希校验**，
  且响应体不再包含 password 字段。
- **双层升级策略**，保证存量库平滑过渡：
  1. 登录成功时若发现仍是明文，就地升级为哈希（无需重置密码）；
  2. 启动时 `upgradePlaintextPasswords()` 全量扫描补齐——仅靠"登录时升级"会留下
     **从未登录过的账号长期保持明文**的窗口（实测 sales2 正是如此），启动时统一消除。
- 播种账号改为哈希落库；新建账号与重置密码均哈希后写入。
- 前端：新增业务员弹窗**不再预填弱密码 `123456`**，改为留空并提示"不少于 8 位"。

现状核验：库内 admin / sales1 / sales2 三个账号**全部为 scrypt 哈希**，静态数据中已无明文口令。

#### 测试基建同步

- Sprint 4 / 5 中若干静态断言原本只扫描 `server/index.js`，拆分后会误报。
  已改为扫描 `server/*.js` + `server/routes/*.js` 全量源码（含 `route_kit.js` 等工具模块）。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 23 / Sprint4 37 / Sprint5 37 /
  Sprint6 29 / **Sprint7 18** / 存量 7 套全绿（**共 210 条断言**）。
- 拆分后 19 个读端点端到端全部可用；未登录访问仍被 401 拦截（门禁未被拆分破坏）。
- 真实数据不变性：全量回归前后快照一致 ——
  `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 回写 0 / 成交 0 / 内容包 20 / 周报 3 / 日志 3 / 账号 3`。
- 前端脚本语法通过，CSS 花括号 140/140 配平，JS 引用的 186 个 DOM id 无缺失。

#### 后续计划（Sprint 8）

- **T29 前端拆分**：`app/index.html` 已达 **4,397 行**单文件内联，建议拆为 `app/js/*.js`
  （保持原生、不引框架），拆分顺序与风险点同后端一致（注意 DOM 就绪与加载顺序）。
- **P1-5 话术 A/B**：`variant` 字段与回写统计已就位，积累真实数据后即可跑出结论。

---

## [v2.5.0] - 2026-10-08

### L4 商业实施计划 · Sprint 8：写真残留清除 + 前端拆分（20 条断言）

#### T31 移除「宝宝写真实验看板」（更正 v2.1.0 的错误决策）

- **这是一次自我更正**。v2.1.0（Sprint 3 的 T10）我判断 `#v-photo_pilot` 是
  "100% 不可达的死视图需要接线"，于是补了导航入口、`pilot_metrics` 表、录入表单。
  **该判断是错的**——正确做法是删除。
- 依据（均出自本项目已有记录，非临时起意）：
  - `CHANGELOG.md` v1.3.0：「**剥离 C 端宝宝写真对工业外贸主线的干扰**，保留纯粹的工业 B2B 出海交付定位」；
  - `CHANGELOG.md` v1.8.3：项目档案已剔除 C 端 1 元情绪卡 / 9.9 元写真混杂内容，定位 100% 收敛于工业出海；
  - `AGENTS.md` 硬规则 4：「儿童照片相关内容必须遵守 `pilot/` 下的合规规则」。
- 结论：它是全系统**唯一与外贸主线无关**的模块；我给它做成"可录入运营数据的看板"，
  反而**扩大了硬规则 4 的合规面**——属于负收益。且库中是种子假数据（8 天 / 8900 曝光 / 14 单），无真实运营价值。
- 已移除：导航入口、`v-photo_pilot` 视图、`renderPilotBoard` / `loadPilotData` / `savePilotMetrics`、
  `GET/PUT /api/pilot/photo`、db 建表与种子、`route_kit.readPilotPhoto`、
  `pilot/宝宝写真2周实验方案.md`。
- **保留**：`pilot/面料工厂30天试点方案书.md`（外贸主线真资产）与 `/pilot` 静态托管。

> 遗留说明：历史库中 `pilot_metrics` 表仍物理存在（空表 + 种子假数据）。
> 本项目迁移纪律为「只加法」，不做 DROP 等破坏性 DDL，故保留为孤儿表，代码已完全不再引用。

#### T29 前端拆分

- `app/index.html` 内联脚本 **2,778 行 → 0**（现有 0 个内联 `<script>` 块），
  文件行数 **4,397 → 1,530**，只留 DOM 与 `<script src>` 引导。
- 拆分为 7 个模块（按依赖顺序加载）：
  `core.js`（629 行，全局状态/路由/门禁/工厂切换/团队）、
  `data.js`（787 行，统一加载/工作台/S0/买家/开发信/询盘/周报）、
  `growth.js`（154 行，成交漏斗/今日待办/回写复盘）、
  `admin.js`（57 行，运行配置）、
  `content.js`（566 行，诊断/选题/内容包/Skill）、
  `sales.js`（551 行，拓客大盘/军师话术/全息联络）、
  `boot.js`（34 行，fetch 鉴权拦截与启动引导）。
- 拆分方式同后端：脚本机械搬运，避免手工漏搬。
- **拆分断链防护**：新增断言校验 HTML 中 60 个内联事件处理器（`onclick` 等）
  在拆分后的 JS 中均有对应 `function` 实现——这是拆分最容易踩的坑。

#### 测试基建同步（本轮共修 6 处）

Sprint 1~7 中多条静态断言原本只扫 `app/index.html`，拆分后会把"代码搬家"误判为"功能丢失"。
已统一改为聚合 `app/index.html` + `app/js/*.js`：

- `test_s1_hemostasis`、`test_s2_compliance`、`test_s3_platform`、`test_s4_business`、`test_s5_growth`；
- `test_menu_and_logout`、`test_security_and_rbac_fixes`（改为按 `<script src>` 动态拉取模块）。
- `test_s3_platform` 的 T10（断言写真看板应存在）**断言方向反转**为"应不存在"，与 Sprint 8 的 T31 对齐；
- `test_menu_and_logout` 的"15 个视图"清单移除 `photo_pilot` 并补入 `deals`，改为动态计数。
- `test_s8` 的 DOM id 断言修正：部分 id 由运行时 `innerHTML` 生成（如 `pitchSubTabs`），
  只扫 index.html 会误报，已把 JS 模板串纳入"已定义"集合。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 16 / Sprint4 37 / Sprint5 37 /
  Sprint6 29 / Sprint7 18 / **Sprint8 20** / 存量 7 套全绿（**共 222 条断言**）。
- Sprint8 连续两次运行均 20/20。
- 真实数据不变性：全量回归前后快照一致 ——
  `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 回写 0 / 成交 0 / 内容包 20 / 周报 3 / 日志 3 / 账号 3`。
- CSS 花括号 140/140 配平；7 个前端模块语法全部通过；60 个内联事件处理器无断链。

#### 当前状态

架构债（P2）已全部清偿：

- `server/index.js` 2,157 → **121 行**，12 个域模块；
- `app/index.html` 4,397 → **1,530 行**，7 个前端模块、0 内联脚本；
- 密码已 scrypt 加盐哈希，静态无明文。

#### 后续计划

- **P1-5 话术 A/B**：`variant` 字段与回写统计已就位。建议先用 2~4 周积累真实打开/回复数据，
  再跑"哪版开场句回复率高"的结论——数据不足时做 A/B 只会得到噪声。
- 可考虑补充：客户档案结构化事实的**前端补录界面**（目前 `missing_fields` 只在接口层暴露，
  UI 尚未提示补录），让事实缺口闭环。（已于 v2.6.0 完成）

---

## [v2.6.0] - 2026-10-08

### L4 商业实施计划 · Sprint 9：事实缺口补录 + 数据沉淀降摩擦（22 条断言）

本轮解决两件事：**(1)** Sprint 6 的"去编造"只做到"标注待补录"，但没给人补录的入口——
等于把问题推给了用户；**(2)** 澄清并降低"沉淀数据"的操作成本。

#### T32 事实缺口前端补录（让"去编造"真正闭环）

- 新增 `PUT /api/clients/:id/facts`：白名单字段（主营产品 / 认证 / 起订量 / 目标市场 / 产能交期）
  一次写入，并**同步三处**，保证事实源唯一：
  1. 写回 `knowledge/客户档案/*.md` 对应标签行（已存在则替换值并保留原标签字面，不存在则追加到「## 1. 基本盘」）；
  2. 更新 `clients.summary_json`（人工填写优先于文本解析）；
  3. 重建 `client_facts` 结构化缓存。
- 新增 `fact_parser.upsertFactLine()` 与 `FACT_LABELS`（字段 → 档案标签关键词映射），
  档案写回采用"行级替换"而非整篇重写，避免破坏档案其他结构。
- 前端：S0 档案工作台顶部新增**事实缺口提示条**（区分关键/非关键缺失）+「✍️ 补录事实」弹窗
  （以已有事实预填，避免重复输入），保存后刷新档案与缺口。

#### T33 批量登记（降低"沉淀数据"的操作摩擦）

**关于"沉淀数据"的说明**（此前表述含糊，在此澄清）：指的是积累真实的开发信打开/回复记录，
让"哪版开场句回复率高"有样本支撑。**当前没有自动采集通道**——不接邮件服务器，
运行 S1/S2 Skill 也只生成草稿、不记录任何结果。唯一方式是人工登记：

> 在邮件客户端发信 → 收到回复或看到已读回执 → 回系统在这封信上登记。

原有交互是"每封信在卡片上点两次"，摩擦大、容易忘。本轮新增：

- `GET /api/outreaches/pending-track`：已发送且未登记打开/回复的信件列表；
- `POST /api/outreaches/track/batch`：`open` / `reply` / `clear`（clear 用于误登记纠错），
  批量操作会自动同步买家状态；
- 前端开发信视图新增「📥 待登记效果」面板：列出待登记信件 + 全选批量标记 + 撤销，
  并附一行方法说明，避免"不知道该怎么沉淀"。

#### T34 沉淀进度可见（样本不足不下结论）

- `/api/outreaches/stats` 新增 `tracked`（已登记数）、`min_sample`（建议阈值 30）、
  `conclusion_confidence`。样本不足时明确返回「样本不足（已登记 N / 建议 ≥30 封后再做话术版本对比）」。
- 前端复盘面板展示样本量与可信度提示（不足时琥珀色警示）。
- 设计理由：S2 要求"按话术版本分组复盘"，分组后每组样本更小，**更需要有阈值判断**，
  否则拿 3 封邮件的数据下 A/B 结论只会得到噪声。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 16 / Sprint4 37 / Sprint5 37 /
  Sprint6 29 / Sprint7 18 / Sprint8 20 / **Sprint9 22** / 存量 7 套全绿（**共 244 条断言**）。
- 真实数据不变性：全量回归前后快照一致 ——
  `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 回写 0 / 成交 0 / 内容包 20 / 周报 3 / 日志 3 / 账号 3`；
  且测试用过的 C01 档案**无补录校验值残留**（补录后已还原）。
- 前端：7 个模块语法通过，**65 个内联事件处理器**全部有对应实现（无断链），
  190 个 DOM id 引用无缺失，CSS 花括号 140/140 配平，`index.html` 1,580 行、0 内联脚本块。

#### 当前状态与下一步

至此 P0（商业闭环）、P1（事实源结构化 + 大模型通道落地）、P2（架构债）已全部清偿。

下一步建议回到业务本身：**用真实业务跑 2~4 周**，期间只做一件事——
发信后按「📥 待登记效果」面板登记打开/回复，把 `tracked` 从 0 堆到 30 以上。
届时 `/api/outreaches/stats` 的 `by_variant` 才会给出可信的"哪版开场句回复率高"。

在此之前不建议再开新功能：功能已够用，**缺的是数据，不是代码**。

---

## [v2.7.0] - 2026-10-08

### L4 商业实施计划 · Sprint 10：可信性修复（18 条断言）

本轮由使用中的三个疑问触发核查，结果确认了两处**会误导决策**的缺陷。

#### T35 修复「模拟业务员视角」（Sprint 2 遗留缺陷）

- **现象**：老板在【业务员与团队管理】点某个业务员的「👁️ 模拟视角」后，
  顶部虽显示"正在预览视角"，但看到的数据与老板完全一致；更糟的是会被踢回登录页。
- **根因链**：
  1. Sprint 2 把鉴权改为服务端令牌后，身份由 `X-FDE-Token` 决定；
  2. 而 `startBossPreview()` 只是把 `currentUser` 换成 `/api/users` 返回的对象——
     **该对象不含 token**；
  3. 请求拦截器发现 `currentUser.token` 为 undefined → 不带令牌 → 服务端 401
     → `handleSessionExpired()` 清空会话并弹出登录页；
  4. 即便不登出，令牌仍是老板的，服务端照旧返回全量数据——"模拟"只是个横幅装饰。
- **修复**：新增 `POST /api/admin/impersonate`，由**服务端签发受限令牌**
  （`role` 取目标业务员，附加 `impersonated_by` 声明，有效期缩短为 2 小时）。
  - 仅老板可调用；模拟态禁止再次嵌套模拟；不允许模拟另一个老板账号。
  - 前端改为换取真令牌后 `await loadAllData()` 整体重载；退出预览同样重载以拿回全量数据。
- 断言覆盖：模拟令牌可见工厂 ⊆ 老板可见、模拟态访问 `/api/deals` 与
  `/api/admin/settings` 仍为 403、业务员发起模拟为 403。

#### T36 Skill 运行器不再凭空造数据（违反硬规则 2）

核查「可用 Skill 列表 → 运行」的实际行为，发现两个 Skill 在**替客户编造业务数据**：

- **S1_买家名单**：从写死的 2 家公司随机挑一条 `INSERT` 进 `buyers` 表——
  `Nordic Wool & Active AS`（挪威）与 `Continental Technical Knits B.V.`（荷兰），
  连同网址、联系人、邮箱**全为编造**。红灯测试实证：运行一次买家数 6 → 7。
  → 现改为 **501 not_implemented** 并引导走已具备去重能力的「CSV 批量导入」通道。
  S1 的"公开名录采集"没有真实数据源就做不到，不能靠编数据假装跑通。
- **S2_开发信生成**：正文写死 `Hengxin Textile in Shaoxing`、
  `OEKO-TEX Standard 100 & GRS 4.0`、`15-day bulk delivery`——
  **给九鼎用会写错厂名，给无认证工厂用等于伪造资质**（与 Sprint 6 修掉的是同类问题，
  当时漏了 Skill 这条路径）。
  → 现改为读取该工厂结构化事实：厂名取自 `clients`、认证/起订量/产品取自 `client_facts`，
  缺失字段**省略或改为"可按需提供"**，绝不编造；结果摘要会标注"认证字段档案缺失"。

未实现的 Skill（S0/S3/S4/S5/S6）维持 Sprint 1 的诚实化行为：501 + `SKILL_NOT_IMPLEMENTED`。

#### 数据清理

清理历史运行中被 S1 编造功能写入的假买家记录及其关联开发信，买家库恢复为 9 条真实种子数据。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 16 / Sprint4 37 / Sprint5 37 /
  Sprint6 29 / Sprint7 18 / Sprint8 20 / Sprint9 22 / **Sprint10 18** / 存量 7 套全绿
  （**共 262 条断言**）。
- 真实数据不变性：全量回归前后快照一致 ——
  `clients 2 / 已签单 2 / 非待联系 0 / 买家 9 / 开发信 6 / 回写 0 / 成交 0 / 内容包 20 / 周报 3 / 日志 3 / 账号 3`。
- 前端：7 个模块语法通过，**65 个内联事件处理器**全部有实现，190 个 DOM id 无缺失，
  CSS 140/140 配平，`index.html` 1,580 行、0 内联脚本。
- 静态核查：编造买家常量与写死开发信正文均已消失（仅保留在说明性注释中）。

#### 当前 Skill 运行器的准确定位

| Skill | 状态 |
|---|---|
| S1 买家名单 | ❌ 未实现（需名录数据源）→ 请用 CSV 批量导入 |
| S2 开发信生成 | ✅ 可用（基于买家 + 工厂结构化事实，缺失不编造） |
| S0 / S3 / S4 / S5 / S6 | ❌ 未实现 → 按 `skills/*.md` 规范人工执行 |

即：**列表是真实的规范查阅入口，"运行"只有 S2 真正可用**。剩余 Skill 要么接入数据源，
要么承认其为人工作业指引——不能再用假成功或编造数据冒充自动化。

#### 下一步

回到业务：用 2~4 周积累真实打开/回复数据（`tracked` 从 0 到 30+）。功能侧暂无必做项。

---

## [v2.8.0] - 2026-10-08

### L4 商业实施计划 · Sprint 11：数据可信来源治理（13 条断言）

本轮由两个追问触发：**(1)** 编造数据具体违反哪条硬规则；
**(2)** 买家名单库为何显示 3 条而非此前所说的 9 条、数据从哪来、有什么用。
核查结果：**v2.7.0 的修复不完整**——还有第三个编造源头未被发现。

#### 关于数量不一致的说明（此前表述不准确）

- 9 条 = `buyers` 表**全库**总数；
- 3 条 = 界面实际显示条数，因为买家名单**按工厂隔离**，
  而前端默认工厂 `activeFactoryId = 'C02'`（海宁九鼎）。
- 分布：C01 恒信 5 条、C02 九鼎 3 条。切换顶栏「当前工厂」即可看到另一份。

#### 买家名单库的数据来源与作用

- **来源**：`server/db.js` 种子（B01~B05 属 C01、B101~B103 属 C02，标注为真实公开渠道画像样本）、
  手工录入（`+ 批量导入 CSV`，已内置去重）、（原 S1 自动生成，已停止）。
- **作用**：每个工厂一份**海外目标采购商池**。向下供 S2 生成开发信；
  向上是国内工厂面前的**谈单道具**——能列出德/瑞典等国的精准采购负责人。

#### T37 清除第三个编造源头

v2.7.0 只清了 `server/routes/skills.js`，遗漏了 **`scripts/skill_runner.mjs`**（`npm run run-skill` 走的 CLI 路径），
其中写死了 **3 家假买家**：

```
Bergmann Alpine Sports GmbH / København Performance Outerwear / Rocky Mountain Trail Gear
```

实测：**「Rocky Mountain Trail Gear」已于 2026-10-07 03:20 经 S1 运行真实写入过买家库**（B967288），
本次已清理其记录与关联开发信。

#### T38 删除与服务端重复的第二套实现

`scripts/skill_runner.mjs` 不只是有编造数据——它**把 Sprint 1 已修掉的缺陷又完整带回来一遍**：

| 缺陷 | 服务端（已修） | CLI（原本仍有） |
|---|---|---|
| 打开数造假 `sentCount * 0.5` | ✅ 已改 NULL | ❌ 仍在 |
| 周次算错 `getDate()/7` + 年份写死 | ✅ 已改 ISO 周次 | ❌ 仍在 |
| 开发信写死厂名/认证/产能 | ✅ 已改结构化事实 | ❌ 仍在（"80 台圆机 / OEKO-TEX 100 / 8-12% / 恒信署名"） |

根因是**同一套业务逻辑存在两份实现**，修一处漏一处。
故删除 `scripts/skill_runner.mjs` 及 `npm run run-skill`（文件在 git 中可恢复）。
如后续确需 CLI，正确做法是写一个**只调用 HTTP API 的薄客户端**，而不是再复制一份业务规则。

#### T39 防回归断言

新增 `scripts/test_s11_datasrc.mjs`，扫描 `server/` 与 `scripts/` 全部非测试源码：

- 全仓不得再出现任何已知编造买家常量；
- 库中不得存在编造买家记录；
- 运行 S1 不得新增买家、且必须返回 501；
- 买家写入口收敛到 `db.js` 种子 + `routes/buyers.js`（≤3 处）；
- 不得再有"按发送数估算打开数"、错误周次算法、写死厂名/认证/产能的生成路径。

**两条测试基建经验**（本轮踩到并修正）：
1. 扫描须**排除测试文件**——测试里含编造常量是作为"检测串"，计入会造成误报；
2. 扫描须**剥离注释**——"修复前是 X"这类说明文字会被误判为"仍存在 X"。

#### 验证

- `npm run test:all` → Sprint1 41 / Sprint2 25 / Sprint3 16 / Sprint4 37 / Sprint5 37 /
  Sprint6 29 / Sprint7 18 / Sprint8 20 / Sprint9 22 / Sprint10 18 / **Sprint11 13** /
  存量 7 套全绿（**共 275 条断言**）。
- Sprint11 连续两次运行均 13/13。
- 数据终态：买家 8 条（C01 五条 / C02 三条，全部为种子数据，无编造记录）；
  全量回归后已还原测试回写残留（O101），`tracked` 归零。

#### 需你确认的一项（未擅自处理）

`server/db.js` 中 C01（恒信）的 **3 封种子演示开发信**（O01/O02/O03）包含写死的
"GRS-certified recycled fleece""OEKO-TEX""50+ greige"等表述，且状态为
`approved` / `pending_review` / `sent`。

判定：它们属于**演示种子数据**（恒信档案的 `summary_json` 中确实登记了 OEKO-TEX 100 与 GRS 4.0，
表述与其档案一致），且是初始化时一次性写入、不参与运行期生成，故**未擅自删除**。
但如果你希望系统内**任何一处都不出现写死话术**，我可以把它们改为"仅保留结构与字段示例、
去掉具体认证/产能数字"，或整体移除——请告知你的偏好。

#### 下一步

回到业务：用 2~4 周积累真实打开/回复数据（`tracked` 从 0 到 30+）。功能侧暂无必做项。

---

## [v1.9.4] - 2026-10-08

### 登录门禁隐私安全加固：移除界面账号与密码明文提示
- **1. 痛点响应与安全加固**：
  - 响应用户需求：“登录页面下面不要显示帐号和密码”；
  - 移除了早期原型阶段遗留的账号密码提示卡片（`.auth-hint-card`），避免在公开展演或生产部署中明文泄露系统管理账号与业务员凭据；
  - 同步净化输入框占位符：将 `placeholder="输入用户名 (如: admin 或 sales1)"` 规范为 `placeholder="请输入系统账号"`，消除账号信息暗示。
- **2. 门禁交互体验**：
---

## [v2.0.1] - 2026-10-08

### 1Panel 面板线上容器化部署全套工程落地
- **1. 生产级容器化套件交付**：
  - **`Dockerfile`**：基于官方轻量 `node:22-alpine` 镜像构建，内置东八区时区，配置 `/app/data` 与 `/app/knowledge` 持久化卷与 `/api/status` 容器健康检查；
  - **`docker-compose.yml`**：标准 Compose 编排，支持在 1Panel【容器】->【编排】中一键创建与启停，端口默认映射 `3000:3000`；
  - **`.dockerignore`**：过滤 `node_modules`、`.git` 与原始 CSV 等无关大文件，构建体积控制在 150MB 以内。
- **2. 完整实战部署文档落地 (`docs/05_1PANEL部署指南.md`)**：
  - 详细编写 1Panel 容器编排部署（代码上传、创建编排、秒级启动）；
  - 详细编写 OpenResty (Nginx) 反向代理与 Let's Encrypt 自动化免费 SSL/HTTPS 证书申请配置；
  - 明确针对 `./data/fde_system.db` 与 `./knowledge/` 的 1Panel 计划任务定时备份策略；
  - 提供常见问题排查（Node 22 原生 sqlite 版本约束、端口冲突解决、密码重置）。

---

## [v2.2.0] - 2026-10-08

### Sprint 12 · 交付闭环与信任加固（29 条断言，29/29 通过）

本轮针对二次深度审查发现的「状态多真相来源」与「必然失败入口」两类问题，
以 TDD 闭环修复。新增 `scripts/test_s12_trust.mjs`，纳入 `npm run test:all`。

#### P0 · 会产生错误业务动作

- **T1 修复 CSV 批量导入恒落恒信(C01)**
  - 根因：`submitImportBuyers()` 只发 `csv_text`，服务端 `client_id || 'C01'`。
  - 实测：admin 登录导入一条，落库 `client_id = C01`——在九鼎(C02)空间导入的买家
    全部进恒信名下，当前列表纹丝不动，用户会以为"导入没生效"。
  - 新增 `currentFactoryId()` 助手（全局筛选优先，其次客户档案正在查看的工厂），
    所有写库入口统一透传。
  - 附带：CSV 解析改为显式保留空分级列，为自动分级留出判定空间。

- **T2 S2 首封幂等门（防重复触达同一买家）**
  - 根因：直接 `INSERT`，不检查该买家是否已有首封。实测库里 B02 存在两封首封
    （`O02` + `O294482`，均 pending_review）——两封都放行就是对同一采购负责人重复发信，
    这是外贸开发信最忌讳的事。跟进序列(T15)已做幂等，首封反而没做，两处标准不一致。
  - 新增 409 + `FIRST_OUTREACH_EXISTS`，并提示改用「生成跟进序列」。
  - 连带修正 S2 挑选买家逻辑：必须排除已有首封的买家（买家状态派生自"是否已发送"，
    一个买家可以状态是「待触达」却已有一封待审首封），否则会反复挑中同一批人并撞门。

#### P1 · 展示自相矛盾

- **T3 买家状态统一由开发信派生（单一真相来源）**
  - 实测矛盾：`B01` 标"已发首封"但信件从未发送；`B02` 标"待触达"却已有两封待审首封；
    `B102` 标"已回复"但对应的信根本没发出去。
  - `GET /api/buyers` 改为下发派生状态（有 sent 信→已发首封，否则→待触达；
    「已回复/无意向」属业务结果，保留人工判定），并附 `stored_status` 供审计。
  - 数据修复：`B102` 已回复→待触达（无已发送信件，状态不可信）。

- **T4 运行日志诚实渲染**
  - 根因：`renderSkillLogs` 只有二选一，`paused_for_review` 显示"⏸️ 已暂停"，
    **其余一律显示绿色"✓ 运行完毕"**——于是 S1 返回 501 时写入的 `not_implemented`
    日志也被渲染成成功。API 层在 Sprint 1 已诚实化，展示层又把它美化回去，自相矛盾。
  - 改为 `SKILL_LOG_STATUS` 状态映射表（未实现=灰色警示 / 暂停=琥珀 / 成功=绿色）。
  - 数据修复：删除历史遗留的假成功日志 `LOG264863`（S3_内容获客，从未真正执行
    却写了"执行完毕，数据已核验"）。

- **T7 approved 与 sent 边界**
  - 数据修复：`O01` 状态 `approved` 却带 `sent_at`，按证据归位为 `sent`
    （记录自己说"已于 2026-10-06 发送"）。

#### P1 · 必然失败的入口

- **T5 移除两处「运行S1采集新名单」按钮**
  - `app/index.html` 买家库与工作台流水线各一处，服务端 S1 无名录数据源、恒返回 501，
    点击必然弹"未实现"——等于明摆着邀请用户失败。
  - 改为直达可用的半自动采集入口（打开导入弹窗），并在 title 中说明真实流程。
  - 服务端 501 hint 文案更正：不再把 S1 列为"已接入"。

#### P2 · 体验一致性

- **T6 买家状态标签语义配色**：废弃「非待触达即绿色」的二选一，改为映射表
  （待触达=warn / 已发首封·已跟进=ok / 已回复=accent / **无意向=danger**）。
  修复前"无意向"这种负面结果也显示成绿色成功色。
- **T8 单条新增买家接线**：`POST /api/buyers` 服务端早已实现（含去重），
  但前端无任何入口，是死接口。补 `modalBuyerAdd` 弹窗与「+ 单个新增」按钮。

#### 新功能 · S1 半自动采集工作台（T9）

- 新增 `GET /api/buyers/sourcing-brief?client_id=X`：把 S0 档案里的买家画像
  结构化下发为**可执行筛选条件**（目标市场 / 英文产品关键词 / 我方认证 / 决策人角色 / MOQ），
  并给出四类**推荐数据源**（海关提单数据、展会名录、LinkedIn、品牌官网）及其用法。
- 导入时按画像自动分级：命中目标市场 +2，命中认证 +1，命中产品关键词 +1；
  ≥3 判 A、≥1 判 B、否则 C。修复前一律落默认 B，高价值买家被埋没。
- 前端买家库新增「🎯 采集筛选条件」面板。
- **设计原则**：系统不做"凭空采集"。真实买家名单只能来自外部数据源，
  硬做自动采集只有两条路——编造（违反硬规则 2）或爬来无效邮箱（毁域名信誉）。

#### 附带修复 · 两块"实现了但从没上线"的功能

DOM 容器完整性校验发现：Sprint 6 的**事实缺口提示条**与 Sprint 9 的**待登记效果面板**
都实现了完整逻辑（含接口、渲染函数、调用链），但 `app/index.html` 里**从未建对应容器**：
- `renderFactGapBar` 开头有 `if (!bar) return` 兜底 → 不报错也从不显示，整条
  "档案缺字段 → 提示 → 补录"链路静默失效；
- `openFactGapModal()` 无空值保护 → 点击「补录事实」会直接抛 TypeError。
- 已补建 `factGapBar` / `factGapList` / `modalFactGap`（含 `fg*` 输入项）/
  `pendingTrackBox` / `pendingTrackCount` 容器。
- 新增 **T10.1 防回归断言**：JS 引用的 DOM 容器必须均已定义（含动态模板生成的），
  杜绝这类"静默失效"再次发生。

#### 验证

- `npm run test:all` → Sprint 1~12 共 **305 条断言全绿**（S1 41 / S2 25 / S3 16 / S4 37 /
  S5 37 / S6 29 / S7 18 / S8 20 / S9 22 / S10 18 / S11 13 / S12 29），存量 7 套全绿。
- 前端脚本语法校验通过（app/js 全部文件），CSS 花括号配平。
- DOM 一致性校验：JS 引用的 194 个 id 全部存在（含动态模板生成）。
- 演练数据已清理复位：`clients` 2 家、`buyers` 8 条、`outreaches` 4 封、
  `inquiries` 3 条、`c_packs` 20 个、`weekly_reports` 3 份、
  `prospect_factories` 5,602 家（已签单 2 / 待联系 5,600），
  潜客归属与基线逐项对齐（公海池 1521 / 总顾问 1362 / 小张 1360 / 小李 1359）。

---

## [v2.3.0] - 2026-10-08

### Sprint 13 · 发信基础设施健康度 + 效果归因（20 条断言，20/20 通过）

#### 1. 发信基础设施健康度（决定"能不能送到"）

开发信文案只是触达成败的一半。域名没配 SPF/DKIM/DMARC、或新域名不预热就群发，
邮件照样进垃圾箱甚至域名被拉黑。此前系统完全没有这一层。

- **新增 `sending_domains` 表 + `GET/POST/PUT/DELETE /api/deliverability/domains`**
  - 记录发信域名、发信邮箱、每日上限、预热阶段、SPF/DKIM/DMARC 配置状态
  - 每个域名下发 `checklist`（三项待办）、`healthy`、`sent_today`、`remaining_today`
- **新增 `suppression_list` 表 + 黑名单接口**（GDPR / CAN-SPAM 合规红线）
- **发送前置两道硬拦截**（`POST /api/outreaches/:id/send`）
  - **黑名单拦截**：收件人在退订/退信黑名单中 → 400 + `SUPPRESSED`，依法不得再发
  - **日限额拦截**：该域名今日已达上限 → 400 + `DAILY_LIMIT_REACHED`，保护域名信誉
  - 实测：两道拦截均拒绝发送且**不产生状态副作用**（信件仍为 approved）
- **预热计划下发**：新域名必须逐步加量（1–2 周 20–30 封/天 → 5 周起 120–200 封/天，
  退信率 >3% 立即降档）
- **前端**：设置页新增「📮 发信健康度」面板（域名卡片 + 配置清单 + 预热建议 + 黑名单管理）
- 如实说明：系统不代发邮件，仅做状态登记与发送前拦截

#### 2. 效果归因（回答"哪类话术/哪类买家回复率最高"）

已有 `/api/outreaches/stats` 只按 variant(A/B) 分组，维度不足以指导
"下一步该找什么样的买家、用什么话术"。新增 `GET /api/attribution`：

- **四个归因维度**：买家分级 / 国家 / 名单来源 / **话术卖点角度**
- 话术角度由正文关键词启发式判定（认证检测 / 交期快反 / 价格成本 / 起订量 / 免费寄样 / 其他）
- **只统计"已发出"的信件**：草稿阶段数据进归因会稀释真实效果
- **样本量门槛**：已发 <30 封的分组明确标记「样本不足」，不拿 3 封邮件下 A/B 结论
- 前端开发信页新增「📊 效果归因」面板

#### 验证

- `npm run test:all` → Sprint 1~13 共 **325 条断言全绿**，存量 7 套全绿
- 前端语法校验通过，DOM 容器完整性通过

### 交付打包

- 新增 `release/` 发布目录与 `release.tar.gz`（0.85 MB），
  含 `Dockerfile` / `docker-compose.yml` / 全部源码 / `data/fde_system.db`（5,602 家潜客）
- 新增 `release/DEPLOY_1Panel.md`：`fde.mmreen.com` 的 1Panel 逐步部署说明
  （DNS → 上传 → 容器编排 → 反向代理 → Let's Encrypt → 备份计划 → FAQ）
- **打包安全**：剔除 `node_modules`、`.git`、`.auth_secret`（密钥不可随包分发）、
  9 条 TDD 演练 fixture 数据、`外贸独立站客户/` 原始线索表（18 个文件，属业务数据不随站点分发）
- 冒烟验证：从 `release/` 目录 `npm install --omit=dev` 后启动，
  `/api/status` 返回 v2.3.0，登录、潜客、买家、发信健康度、归因接口均正常

### 待你决策

1. `data/fde_system.db` 仍在 Git 版本控制内（历史遗留）。移除需重写历史，属破坏性操作。
2. `外贸独立站客户/` 目录仍有 18 个真实线索文件（CSV/XLSX/PDF/DOCX），
   未随发布包分发也未删除——属你的业务原始数据，删不删请你定。






