# 输出与目录标准（claude-code-qiwei-assistant）

本文件定义技能包所有生成文件的目录规则。任何工具、脚本或 Skill 生成文件时必须遵循本标准，并通过 `mcp/src/core/output-paths.js` 模块解析路径，禁止直接拼 `process.cwd() + 'outputs'`。

## 1. 顶层目录职责

```text
claude-code-qiwei-assistant/
├── bin/          # CLI 入口，不生成文件
├── mcp/          # MCP 服务源码与接口清单（catalog 为构建产物，由 scripts/build-catalog.py 生成）
├── skills/       # SKILL.md 定义，只读
├── scripts/      # 构建 / 安装 / 冒烟脚本
├── docs/         # 人工与生成文档（见第 4 节）
└── outputs/      # 所有运行期生成文件（见第 2 节，git 忽略）
```

## 2. /outputs 生成规则

统一根目录：`<包根>/outputs`，可用环境变量 `QIWEI_OUTPUTS_DIR` 覆盖。目录不存在时由 `output-paths.js` 自动创建。

第一层为固定类别，禁止在 outputs 根目录直接放文件：

| 类别 | 用途 |
|---|---|
| `login/` | 扫码登录二维码与预览页（保持固定文件名，最新一次覆盖） |
| `api-calls/` | `qiwei_api_call` 落盘的请求/响应样本 |
| `subscription/` | 订阅、席位、余额查询快照 |
| `meetings/` | 官方 CLI 会议相关导出 |
| `docs/` | 官方 CLI 文档能力导出 |
| `messages/` | 消息发送记录与回执 |
| `knowledge/` | 持续知识库与知识沉淀（当前注册 `meetings/`） |
| `goals/` | 目标、里程碑与行动项状态 |
| `groups/` | 外部群同步结果与确认/导入映射 |
| `portraits/` | 客户画像 JSON |
| `broker-playbooks/` | 顾问 playbook JSON |
| `tags/` | 本地客户标签 |
| `transfers/` | 客户交接包 |
| `voice/` | 语音消息本地文件与转写结果 |
| `webhook/` | Relay / 本地 webhook 回调事件（按 run 目录归档） |
| `relay/` | Relay 客户端运行日志与状态 |
| `customers/` | 客户档案（customerId 为主键） |
| `brokers/` | 经纪人/顾问档案（brokerId 为主键） |
| `devices/` | 设备 guid → wecomUserId / brokerId 映射 |
| `smoke/` | 冒烟测试产物 |
| `tmp/` | 临时文件，可随时清理 |

### 2.1 两种落盘模式

1. **latest 模式**（固定文件名，覆盖写）：适用于"只关心最新一份"的文件，如登录二维码。
   路径：`outputs/<类别>/<固定文件名>`，通过 `latestPath(category, filename)` 获取。
2. **run 模式**（按次归档）：适用于每次运行都要保留的产物。
   路径：`outputs/<类别>/<YYYY-MM-DD>/<HHmmss>-<slug>/`，通过 `createRunDir(category, slug)` 创建。
   每个 run 目录必须包含 `manifest.json`（用 `writeRunManifest(runDir, meta)` 生成），至少含：

```json
{
  "createdAt": "2026-07-12T09:00:00.000Z",
  "tool": "qiwei_official_call",
  "summary": {},
  "files": ["meeting-list.json"]
}
```

3. **persistent-store 模式**（持续知识库）：适用于需要跨次同步、增量更新和稳定索引的知识沉淀。
   路径：`outputs/<类别>/<已注册库名>/`。库名必须在 `OUTPUT_PERSISTENT_STORES` 中注册；当前仅允许 `outputs/knowledge/meetings/`。
   此模式可包含索引、按业务键组织的记录目录和说明文件，不按单次 run 生成 manifest。

### 2.2 命名规则

- 目录与文件名一律小写 kebab-case；slug 由 `slugify()` 生成，最长 60 字符。
- 日期用 `YYYY-MM-DD`，时间用 `HHmmss`（UTC）。
- 禁止绝对路径、空格和平台保留字符。

### 2.3 保留与清理

- `tmp/` 可随时删除；其余类别按日期目录归档，建议保留最近 30 天。
- `outputs/` 整体在 `.gitignore` 中，不入库。

## 3. 输出模块 API

`mcp/src/core/output-paths.js` 暴露：

```js
outputsRoot()                       // outputs 根目录（含 QIWEI_OUTPUTS_DIR 覆盖）
categoryDir(category)               // 确保并返回类别目录
latestPath(category, filename)      // latest 模式路径
createRunDir(category, slug, date?) // run 模式目录
writeRunManifest(runDir, manifest)  // 写 manifest.json
slugify(value) / dateStamp() / timeStamp()
OUTPUT_CATEGORIES                   // 允许的类别列表
OUTPUT_PERSISTENT_STORES            // 允许的持续知识库目录
```

新增输出类别时：先在 `OUTPUT_CATEGORIES` 注册，再更新本文件第 2 节表格。

## 4. /docs 生成规则

```text
docs/
├── OUTPUT-STANDARD.md   # 本标准
├── specs/               # 设计与需求规格（人工撰写，kebab-case.md）
├── guides/              # 使用指南、课程讲义
└── generated/           # 脚本生成的文档，文件头必须注明生成脚本与时间，不手工编辑
```

- 生成型文档只能写入 `docs/generated/`，并以 `<主题>-<YYYY-MM-DD>.md` 命名；
- 运行期数据（JSON 快照、日志、二维码等）一律进 `outputs/`，不得写入 `docs/`；
- `docs/` 入库（git 跟踪），`outputs/` 不入库。

## 5. 校验

运行 `npm run outputs:validate`（`scripts/validate-output-standard.js`）检查：

1. outputs 第一层只包含注册类别；
2. run 模式目录包含 `manifest.json`；
3. docs 第一层只包含本节列出的文件与目录。

`npm run check` 已包含上述脚本的语法检查。
