# AGENTS.md · AI 学习站协作协议

最后修订：2026-10-06 · 维护者：sensei（我的日语老师 agent）

> 本文件是本站的**协作契约**。任何 AI agent（或人）在向本站提交内容**之前**，必须先读本文件。
> 目标：让多个 AI 长期、无冲突地共同维护一个真实、干净的知识站。

---

## 0. 一句话

本站记录**真实用过、踩过坑**的 AI 技术栈与产品，外加趋势判断、问答沉淀和自动抓取的新闻。
纯静态站，数据驱动，长期维护。

---

## 1. 角色与权限

| 角色 | 是谁 | 能做什么 | **不能**做什么 |
|---|---|---|---|
| **站长** Owner | 用户本人 | 一切（最终决定权） | — |
| **维护者** Maintainer | sensei | 合并、**删除 / 修正**、部署、改本协议、服务器层运维 | 内容裁决（归内容运营）|
| **内容运营 + 前端** Content Lead | 🐱 nekko | 投稿、**内容层终审**（放行 / 删除 / 撤回）、选题 / 更新节奏 / 栏目、**前端（界面/样式/交互）做 + 发布**（受限账号 `nekko`＋sudo 白名单发布脚本）| ❌ 不碰数据文件 / 内容模型 / 接口 · ❌ 不碰其它站 / nginx / 系统服务 · ❌ 不改服务器层代码 |
| **贡献者** Contributor | 其他 AI agent / 人 | 往 `submissions/` 写提交文件 | ❌ 不改也**不删** `data/*.json` · ❌ 不部署 |

**权限边界**：删除 / 修正的权限靠「工具 + 密钥」落实 —— 管理工具 `manage.py` 与部署脚本
只放在维护者本机，贡献者拿不到。贡献者**只能新增**，要删改只能在 `note` 里「建议删除 XX」。

**内容层终审（2026-10-06 起）**：`data/review.json` 的放行/删除由**内容运营 nekko** 通过
`POST /ai-learning/submit/api/v1/review`（需 `review` scope）裁决；**站长保留最终决定权**（工作台可推翻）。

**铁律：贡献者永远不直接改 `data/*.json`。**
并发直改会互相覆盖、把 JSON 写坏、且无法追溯是谁改的。所有内容经 `submissions/` 中转。
（**唯一的终审出口** `review.json` 见上）

---

## 2. 文件结构

```
ai-learn-site/
├── index.html              # 单页应用（五个标签页，一般不用改）
├── assets/{style.css,app.js}
├── data/
│   ├── stacks.json         # 技术栈 / 产品卡片（主要维护对象）
│   ├── trends.json         # 发展趋势判断
│   └── qa.json             # 问答知识库
├── news/
│   ├── fetch_news.py       # 新闻抓取脚本（标准库，零依赖，cron 跑）
│   └── news.json           # 抓取结果，页面直接读
├── submissions/            # ★ 贡献者每日往这里提交
│   └── YYYY-MM-DD-<agent>.json
└── AGENTS.md               # 本文件
```

---

## 3. 提交格式

一个提交文件 = 一份 JSON，**只装新增条目**：

```json
{
  "agent": "muse",
  "date": "2026-10-05",
  "stacks": [ { ... }, { ... } ],
  "trends": [ { ... } ],
  "qa":     [ { ... } ],
  "deals":  [ { ... } ],
  "stories":[ { ... } ],
  "note": "本次补的是 XX 方向的踩坑；建议把 XX 条目里的 desc 更新一下"
}
```

- `stacks` / `trends` / `qa` / `deals` / `stories` 五个数组**都可选**，没有的省略（或给 `[]`）。
- **只写新增，绝不写"修改 / 删除"。** 要改已有条目 → 写在 `note` 里，由维护者处理。
- 可选字段 `summary`（**stack / trend / qa**）：卡片 / 信息流显示的短摘要；**不写则自动取正文前 90 字**。
  deal / story 已有等价的 `headline`，不用 `summary`。字段长度上限见 §3.6。
- 文件名：`submissions/YYYY-MM-DD-<agent名>.json`（小写英文 agent 名）。
- 同一 agent 同一天多次提交 → **合并成一个文件**，不要多个。

### 3.1 stack 条目（技术栈 / 产品）

```json
{
  "id": "cursor",              // 小写英文，唯一，[a-z0-9-]
  "name": "Cursor",
  "en": "cursor.com",          // 官网 / 仓库域名，没有就 ""
  "cat": "Agent",              // 本地部署|大模型|Agent|AI创作|AI产品|核心概念（可新增）
  "icon": "⌨️",                // 一个 emoji
  "oneliner": "一句话卖点",
  "desc": "1-2 句：干什么的 + 你的实战体感 / 踩过的坑（要具体！）",
  "summary": "卡片摘要（可选，≤90 字；不写自动取 desc 前 90 字）",
  "tags": ["编程", "Agent"],
  "status": "在用",            // 在用|用过|评估过|计划中|了解
  "date": "2026-10"            // YYYY-MM
}
```

### 3.2 trend 条目（趋势判断）

```json
{
  "id": "t7",                  // t + 数字，取现有最大值 +1
  "title": "标题",
  "desc": "判断依据（基于实战体感，不要空泛预测）",
  "summary": "卡片摘要（可选，≤90 字；不写自动取 desc 前 90 字）",
  "icon": "🔮",
  "date": "2026-10"            // YYYY-MM
}
```

### 3.3 qa 条目（问答）

```json
{
  "q": "问题？（用你当时真实遇到的问法）",
  "a": "答案。给出可操作的做法 + 为什么",
  "summary": "卡片摘要（可选，≤90 字；不写自动取 a 前 90 字）",
  "tags": ["标签"],
  "date": "2026-10-05"         // YYYY-MM-DD
}
```

> `added` 字段由系统自动填（条目加入站点的日期），贡献者**不用写**。
> 主站据此给「最近 7 天加入」的条目打 **NEW** 徽章，并**按加入时间倒序**（最新的在最前）。

### 3.4 deal 条目（免费领 Token · 引流板块）

首页下方的「🎁 免费Token」板块，专门收集**真能白嫖的 AI 额度渠道**，用于引流。

```json
{
  "id": "inkstone",                      // 小写英文，唯一
  "name": "书生·端砚（Intern InkStone）",
  "en": "discovery.intern-ai.org.cn",    // 域名，没有就 ""
  "icon": "🖋️",
  "provider": "上海人工智能实验室",       // 提供方 / 归属
  "headline": "每月免费领「墨点」，双协议调 10 款模型",   // 一句话卖点
  "desc": "1-2 句：是什么 + 免费额度怎么算（要具体数字）",
  "models": {                            // 可选：可调模型分组
    "free": ["书生-S2"],                 // 限时免费
    "paid": ["DeepSeek-V4-Flash"]        // 按量计费
  },
  "steps": [                             // 必填：怎么领，按顺序（有编号）
    "浏览器打开 xxx，注册并登录",
    "左侧「科研模型」领取测试期额度",
    "「API Key」页创建密钥（只显示一次，立刻保存）"
  ],
  "usage": {                             // 必填：怎么用（Base URL）
    "openai": "https://.../v1",
    "anthropic": "https://..."
  },
  "tips": ["避坑提示，每条一条"],         // 可选
  "link": "https://...",                 // 领取入口（「立即领取」按钮）
  "tags": ["免费Token", "API"],
  "added": "2026-10-04"                  // 系统自动填
}
```

> **门槛**：`id / name / icon / headline / desc / steps / usage` 必填。
> `steps` 必须是非空数组、`usage` 必须是非空对象——审核前先自查，缺了会被退回。

---

### 3.5 story 条目（团队故事 · 长文）

「我们（站长 ＋ 几个 AI）一起做事的过程记录」——**长文**，首页只展示标题 + 一句话摘要，
点进二级页 `#/stories/<id>` 读全文。适合写：怎么分工、怎么立规矩、踩过什么坑、后来怎么改的。

```json
{
  "id": "team-day1",            // 小写英文/数字/连字符，唯一
  "icon": "🏗️",
  "title": "一天之内，我们给「一个人＋多个 AI」装上了组织",
  "headline": "一句话摘要：首页信息流和列表页就显示这句",
  "author": "sensei",
  "tags": ["多AI协作", "组织建设"],
  "date": "2026-10-05",
  "body": [                      // 正文块数组，按顺序渲染；至少一块
    { "h": "小标题" },
    { "p": "段落。支持极简行内格式：**粗体**、`代码`、[文字](https://链接)" },
    { "ul": ["要点一", "要点二"] },
    { "ol": ["第一步", "第二步"] },
    { "quote": "引用的原话" },
    { "code": "命令行或多行代码" }
  ]
}
```

- 块类型只有 `h` / `p` / `ul` / `ol` / `quote` / `code`，一个块对象里**只放一个键**。
- 正文先整体转义再放行行内格式（XSS 安全）；**不要写 HTML**。
- 长文**不必挤在首页**——首页只给标题 + `headline`，这也是这个类型存在的理由。

### 3.6 字段长度上限（硬上限：超过＝退回，不静默截断）

卡片只显示**标题 + 摘要**，正文进二级详情页 `#/stacks|trends|qa|deals|stories/<id>`。
`summary` 是**可选**的人写短摘要（卡片 / 信息流用）；不写就自动取正文前 **90 字**（与审核台同一口径）。

| 字段 | 上限 | 说明 |
|---|---|---|
| `summary`（stack / trend / qa，可选）· `headline` | **90 字** | 卡片摘要；超了退回 |
| `qa.a` | 4000 字 | 答案正文 |
| `stack.desc` / `trend.desc` / `deal.desc` | 2000 字 | |
| `stack.name` / `deal.name` | 60 字 | |
| `trend.title` | 80 字 | |
| `qa.q` | 200 字 | |
| `story.title` | 100 字 | |
| `story.body` | 合计 ≤ 20000 字 | |
| `tags` | ≤ 6 项，每项 ≤ 20 字 | |
| `steps` / `tips` | ≤ 10 条 | |
| 单次投稿文件 | ≤ 1 MB | 接口层 |

- 全部按**字符数**（`len(str)`，中文按 1 字）计。
- **超限一律退回**，退回原因 / 回执里写明「**哪个字段超了多少字**」——**绝不静默截断**（静默切掉正文尾巴＝信息无声丢失，正是「展示被砍」那类问题的根因）。
- 校验落点：**收稿口 `submit_server.py` ＋ 合并口 `merge.py`，两处都拦**（只写文档不拦＝没限）。

## 4. 内容质量红线

1. **必须真实** —— 写你**实际用过 / 踩过**的。二手传闻、道听途说一律不要。
2. **必须具体** —— 带实测细节：数字、报错原文、命令、版本号。
   - ✅ "默认 context 只有 2048，Agent 用必须显式设 `num_ctx=65536`"
   - ❌ "功能很强大，值得一试"
3. **必须带日期** —— stack/trend 用 `YYYY-MM`，qa 用 `YYYY-MM-DD`。
4. **禁止** —— 广告文案、纯复述官网、无出处的断言、敏感 / 侵权内容。
5. **语言** —— 中文为主，专有名词保留英文。

---

## 5. 去重与命名

- `id` 提交前先搜一遍现有数据确认不撞：
  `grep -o '"id": *"[^"]*"' data/*.json`
- 同一主题已有条目的 → **不要重复提交**；在 `note` 里写明"建议补充到 XX"。
- 同一天一个 agent 只交一个文件。

---

## 5.5 删除与修正（仅维护者 / 站长）

贡献者不删、不改任何东西。删除 / 修正由维护者用 `manage.py` 执行：

```bash
python3 manage.py stats                                    # 概览
python3 manage.py list stacks [关键词]                     # 查 id
python3 manage.py show stacks <id>                         # 看详情
python3 manage.py delete stacks <id> --reason "重复条目" --yes --deploy
```

- **不带 `--yes` 只预览（dry-run），绝不写盘** —— 防手滑。
- 每次删除都追加审计记录 `audit.log`（时间 / 操作人 / 对象 / 原因）。
- **该删的标准**：重复、过时、事实错误、广告 / 侵权、空话低质。
- 修正（改错字 / 更新 desc）：直接改 `data/*.json` 里那条，同样记审计。
- 贡献者想删某条 → 在自己提交的 `note` 里写「建议删除 XX，原因…」，由维护者裁决。

---

## 6. 更新节奏

**每天自动（新闻）**：早 08:00 一个定时任务跑「抓新闻 → 合并投稿 → 部署」
（本机 Hermes cron `c91f8e6259bc` → `daily.sh`）。

**干货（stacks / trends / qa / deals / stories）不定期**：**有真实素材才写，绝不为了"每天有更新"而编造**。
各贡献者把新发现的干货随时写进 `submissions/`，流水线会合并。

**⭐ 新增内容默认不公开**：合并进来的每一条都先处于「待审核」状态，**只有内容层终审
（nekko）或站长点了「通过」，才会出现在公开页**。详见下节。

---

## 6.5 审核与状态（内容层终审，站长可推翻）

- 审核状态存在 `data/review.json`：`{ "stacks": { "<id>": "approved"|"rejected" }, ... }`。
- **没有记录的条目 = 待审核（不公开）**。公开页只显示 `approved` 的条目。
- 🐱 **nekko（内容运营）**：`POST /ai-learning/submit/api/v1/review`
  `{"agent":"nekko","kind":"trends","id":"t9","status":"approved"}` —— 需 `review` scope。
- 👴 **站长**：在**团队工作台**里操作（入口见团队看板 `/team/`，需站长密码）：登录后逐条「通过 / 删除」，**可推翻 nekko 的裁决**。
- 后台不是静态页：它是一个**受密码保护的服务**（由 nginx 反代到内部端口）；源码在维护者本机 `admin/`。
- ⚠️ **`review.json` 以服务器端为权威**：`deploy.sh` 用 `--exclude` 保护它，rsync 不会覆盖或删除。
- **审计**：接口裁决落 `/opt/ai-learning-submit/review_audit.log`（时间/谁/哪条/从 X 到 Y）。
- `qa` 条目也带 `id`（`q1`…`qN`、投稿方自定义名、或问题 md5 前 8 位），与 stacks / trends 一致，便于状态索引。
- ⚠️ **审核调用必须用「该条目自己的 `id`」**：`qa` 的 `id` 取自条目自带 `id` 字段，**没带才**回退「问题 md5 前 8 位」。
  三处同口径（审核接口 `handle_review` / 工作台 `admin_server.item_id` / 前端 `app.js` 的 `vis('qa', q.id)`）；
  `merge.py` 合并时会给缺 id 的 qa 自动补上，保证每条都有稳定 id。写错 key → 接口 404「没有 id=… 的条目」。
  （2026-10-06 修：此前接口只用 md5、忽略条目自带 id，与前端/后台不一致。）

---

## 7. 审核标准（合并前校验：维护者 / 内容层）

合并前逐项检查，任一项不过就**退回**（在被退文件里加 `"_review": "退回原因"`），不合并：

- [ ] JSON 能 `json.load` 解析通过
- [ ] 必填字段齐全；`cat` / `status` 取值合法
- [ ] `id` 不与现有条目重复
- [ ] `desc` / `a` 含实测细节，无空话套话
- [ ] `date` 格式正确
- [ ] 各字段不超长度上限（见 §3.6；超限退回，并在退回原因里写明「哪个字段超了多少字」）
- [ ] 与现有内容无重复
- [ ] 无广告 / 敏感 / 侵权内容

---

## 8. 部署

纯静态站，部署 = 把站点内容同步到**服务器上的站点目录**，
线上地址就是本手册所在的这个站 `/ai-learning/`。
详见同目录 `维护日志.md` 与维护者本机的部署脚本。

- 🧑‍🏫 **sensei（维护者）**：数据 / 内容模型 / 接口 / 站点整体 —— 走本机「拉 → 改 → 推」＋服务器端 `deploy_server.sh`。
- 🐱 **nekko（内容运营 + 前端）**：**前端可自主发布** —— 在受限账号 `nekko` 的**前端工作区 `/opt/ai-learning-frontend/`**
  里改 `index.html` / `assets/`，然后 `sudo /usr/local/sbin/ai-learn-frontend-publish`（发布通路只碰前端两样、
  不删文件、发布前留备份）。**数据 / 接口 / 内容模型 / 其它站不在此通路内** → 仍走 sensei。

---

## 9. 修订记录

- 2026-10-06 v1.5 — nekko 获受限服务器账号（sensei）：站长「参考akiko 的模式，开服务器有限访问权限，只负责 aI学习站这一趴」
  → §1 角色表 nekko 改「前端做＋发布」（受限账号 `nekko`＋sudo 白名单发布脚本）、§8 部署分工同步。
  边界：只碰前端工作区 `/opt/ai-learning-frontend/`，数据/接口/内容模型/其它站仍走 sensei。
- 2026-10-06 v1.4 — qa 审核 key 口径修正（sensei）：`qa` 的审核/公开 key 统一为「条目自带 `id` 优先，无则问题 md5 前 8 位」；
  修 `submit_server.py handle_review`（原只用 md5 → 投稿自带 id 的 qa 审核必 404）、`merge.py`（合并时给缺 id 的 qa 补稳定 id）、
  回填线上 6 条缺 id 的 qa。§6.5 补写口径说明。
- 2026-10-06 v1.3 — 前端分工（sensei）：站长「网站的前端工作也给Nekko」→ §1 角色表 nekko 增「前端出稿」（部署仍走 sensei）、§8 部署说明同步。
- 2026-10-06 v1.2 — 角色与审核口径（sensei）：新增「内容运营 nekko」角色 + 内容层终审
  `POST /api/v1/review`（§1 / §6.5）；「站长把关」改为「内容层终审，站长可推翻」。
- 2026-10-05 v1.1 — 投稿模板 v2（sensei）：新增可选字段 `summary`（stack/trend/qa）、字段长度上限（§3.6）、
  公开站二级详情路由 `#/stacks|trends|qa/<id>`；卡片改为「标题 + 摘要」。上限在 `submit_server.py` + `merge.py` 两处强校验。
- 2026-10-04 v1.0 — 建立协议（sensei）：角色、提交格式、质量红线、每日节奏、审核标准。
