# S3 节点 — 核心执行机制

> 来源：workflow-s3.md 拆分，对应原文行 1–316
> **导航**：[写稿规范与 Brief →](./workflow-s3-writing-guide.md) | [收口规则 →](./workflow-s3-closure.md)

## 阶段 3：写稿

> **进入条件（P0 强制）**：S2.5 节点确认完成，所有 checkbox 均已确认 `[x]` 状态后才可进入 S3。
> ```
> 确认步骤：
> 1. 读取 [S2.5] 节点确认.md，确认所有待确认项已确认
> 2. 若存在未确认项 [ ]，告知用户 S2.5 未完成，不可跳入 S3
>    若用户要求跳过，说明风险并写入 .fbs/project-config.json
>    字段 "s25ActionPlanStatus": "acknowledged-incomplete"
> 3. 以上全部完成后，才可以进入 S3 写稿
> ```

> **参考**：`large-scale-book-strategy.md`，M3/M2/M1 规模 P0 强制
> **多成员说明**：Team API 可直接用于并行写稿；问题不在宿主是否支持并行，而在 Skill 是否完成章节拆分、写入隔离、台账更新与心跳编排。
> **默认不主动推荐多 Writer 并行**；若用户明确要求或章节边界清晰，可直接启用 Agent Teams，由 team-lead 统一维护台账、术语与交接。

> **书稿规模说明**：S2 规模字数将自动决定 S3 写稿策略，见 [`../05-ops/large-scale-book-strategy.md`](../../05-ops/large-scale-book-strategy.md)
> **禁止行为（P0）**：禁止跳过节点确认进入 S3；须按 `large-scale-book-strategy.md` 规模策略执行；M3 规模时强制完成 S0-E 原料充分性覆盖。

**说明**：若使用 Task（多成员），超过 5 章应暂停汇报。

---

### S3 联网查证规则（超时与速率限制处理）

> **说明**：联网查证每次 query 超时约 15s，超时则记录降级，不得无限等待。

| 情况 | 处理方式 |
|------|---------|
| 单次超时 | 超时 15s 后触发超时处理，降级为模型知识，继续写稿 |
| 超时 30s 继续等待 | 禁止；超时后立即降级，告知用户 |
| 触发 14003 / too many requests | 退避等待 10s（`rateLimitGuard.backoffOnRateLimitMs`），超过 `maxRetriesOnRateLimit`（默认 2 次）后记录 `ok=false reason=rate_limit`，禁止无限重试 |
| 规范不一致 | 联网查证超时后，Read 工具调用不超过 3 次，查阅 [`skill-index.md`](../skill-index.md) |
| 超时降级 | 降级为模型知识，告知用户降级写稿 |

#### 触发 14003 标准处理流程（WorkBuddy 宿主）

| 步骤 | 操作 |
|------|------|
| 1 | 停止发送 WebSearch，记录触发时间戳 |
| 2 | 等待 10s（`rateLimitGuard.backoffOnRateLimitMs`），期间禁止写稿 |
| 3 | 确保间隔 `minIntervalBetweenQueriesMs` 后才继续 |
| 4 | 超过 `maxRetriesOnRateLimit` 次数（默认 2）时，记录 `rate_limit`，停止重试 |
| 5 | 告知用户已触发 QPS 限速，后续章节使用模型知识替代联网查证 |
| 6 | 确认 `search-policy.json` 的 `s0MaxConcurrentQueries` 并发限制为 2 |

**实现参考**：`BookWorkflowOrchestrator`、`SearchBundle.executeChapterGate`、`MultiAgentPipeline` 均已内置退避策略，`rateLimitGuard` 自动累计退避等待。

#### S3 写稿中出现 14003 的处置

> **策略**：最小中断写稿——记录超时但不让超时中断写稿，超时后继续写稿。

| 触发场景 | 恢复策略 |
|----------|---------|
| 单次 30s 超时触发 14003 | 等待 30~60s 后恢复写稿 |
| 多次超时 | 进入 WorkBuddy 限速等待，暂停写稿 |
| 写稿降级 | 继续写稿，使用模型知识补充 |

**联网查证超时注意**：
- 超时后必须继续写稿，不得无限等待
- 禁止超时后无限重试
- 超时后改用模型知识降级

---

#### S3 大规模写稿自动断点·Auto-Run Unit 机制

> **使用场景**：大规模书稿超过阈值时，自动触发断点，防止单次 token 超限影响章节连贯性。
> **执行单位**：以章节 Part 为单位断点，避免单次处理过多章节。

**Auto-Run 前置条件（M2 项目必须启用，见 `large-scale-book-strategy.md §4.1`）**

```
1. 恢复 .fbs/book-context-brief.md 上下文记录
2. 加载 .fbs/chapter-status.md，调用 restoreStateFromDisk
3. 检查 .fbs/rate-budget.json，rateLimitRate > 0.3 时触发警告
4. 检查并恢复 emergency-draft-*.md 草稿文件
```

**Auto-Run 执行单位停顿条件**

| 条件 | 处置 |
|------|------|
| 单章超时 5s | 记录超时，继续写下一章 |
| 写稿异常 | 记录异常 + 更新 `.fbs/chapter-status.md` + 保存紧急草稿 |
| 书稿结构变更 | **暂停**，等待用户确认后重启 |
| 连续写稿超过 20 章 | **必须暂停**，报告进度，请求确认继续，记录到 `.fbs/structure-arbitration-log.md` |
| rateLimitRate > 0.6 | **强制暂停**，报告速率已触发，建议等待 1 分钟后继续 |
| 连续 3 次写稿均失败 | **停止**，等待用户干预 |

**Auto-Run 进度汇报格式**

| 情况 | 输出格式 |
|------|----------|
| 完成一批 | 完成 X 章，已完成 N 章，进度写入 `.fbs/auto-run-unit-report.md`，等待继续 |
| 进度报告 | 已完成约 {X}%，估计还剩 {N} 批 |
| 骨架检测 | 发现骨架章节 {N} 个，记录到 `.fbs/structure-arbitration-log.md`，等待用户确认 |
| 反复失败 | 连续 3 次失败，等待用户干预，建议查看 emergency-draft 草稿 |

**Auto-Run 执行原则**：
- 触发条件满足时自动暂停，暂停后必须等待用户确认才能继续
- rateLimitRate > 0.6 时强制暂停
- 暂停后必须记录书稿状态，保证恢复时能续写

---

### S3 写稿质量要求

| 项目 | 标准 | 执行工具 / 参考 |
|----|------|-------------|
| **过渡段缺失** | 每 200~300 字节需要过渡段或 C1 级别 P0 | `quality-PLC.md` C1节 |
| **排比堆砌** | 禁止连续 3 句以上排比 | 见 C2 节 |
| **章节标题编号** | `##`/`###` 标题含编号，`.` 分隔不含括号 | `node scripts/quality-auditor.mjs --check-section-ids` |
| **空泛表述** | 禁止无案例 / 无论证的空洞表述 | 见 P1 节 |
| **重复词密度** | 禁止同节重复超高频词 | `quality-PLC.md` B2-B，G4 节 |
| **去 AI 味** | 按 `qualityGate` 执行最终 S 分项通过后输出 | `quality-S.md` S6 节，`--fail-on-s6-warn` |
| **联网查证记录** | 联网查证记录必须完整记录到 `search-policy.json` | 参考 SKILL.md 第 2 节 |

**工具调用**：`node scripts/quality-auditor.mjs --skill-root <技能根> --glob "chapters/*.md"` 加 `--enforce` 或 `--enforce-strict`

---

### §3.3 写稿断点检查机制（P0 强制）

**策略**：S3 写稿中断点恢复后必须先检查台账状态，确保写稿连贯性。

---

#### §3.3.1 写稿断点恢复（P0 强制）

> **说明**：每章写稿完成后须同步 `chapter-status.md` 台账，暂停/恢复写稿时须先恢复台账状态。

**断点恢复（P0 强制要求）**：
```
写稿恢复/开始新写稿前，必须执行：

Step 1：使用 write_to_file 创建章节文件前，先确认台账
        路径：{workspace}/[S3-ChNN] 第N章章节名.md

Step 2：更新 .fbs/chapter-status.md 记录
        写稿前先标注该章节状态为 → 写稿中
        若章节字符数明显不足 < 目标 60%，触发 §3.3.2
        写完章节字符数达到预期，则标注 → 完成
若触发字符数明显不足 → 触发骨架标注，提示用户确认"章节内容不足警告"
```

**台账标准格式**：`.fbs/chapter-status.md` 台账行格式
```
| ChNN | {章标题} | 写稿状态 | {字符数} | {ISO时间戳} | {说明} |
```

**禁止绕过台账更新**，见 `SKILL.md` 第 D 节。

---

#### §3.3.2 骨架检测与字符数不足警告（P0 强制）

> **说明**：章节字符数低于目标字数的 60% 时触发骨架警告。

**骨架警告（P0 强制）**：
```
Step 1：读取章节文件，检查当前字符数与 Chapter Brief 目标字数
Step 2：对照目标字数判断

  若 字符数 ≥ 目标字数 × 80%
  → 无骨架警告，继续写稿

  若 字符数 ≥ 目标字数 × 60% 但未到 × 80%
  → 触发骨架预警（软警告）：
    字符数 {已写} / 目标 {目标}，{已完成}%，进入下一章后续写

  若 字符数 < 目标字数 × 60%
  → 触发骨架强警告
    告知用户 [骨架章节] {章名} {N}字，目标 {目标}字，覆盖率 {N}%
    禁止自动补写骨架，需等待用户确认
    > ⚠ 骨架章节 目标{目标}字 / 当前{字数}字，{完成}%
    > 请确认是否继续写稿

若触发 < 60%，禁止在 S6 转化或发布准备中标注为已完成
```

**S6 骨架章节说明**：见 §3.6 节收口规则，骨架章节进入 S6 时必须在 `⚠ 骨架章节汇总` 中标注。

---

#### §3.3.3 书稿类型对应写法（P1 强制，建议执行）

> 书稿类型决定写法风格，见 `project-config.json` 字段 `genreTag` 映射：
- 非虚构叙事类：`非虚构/叙事/报告/散文/人物`
- 调查报道类：`报道/新闻写作/调查/记录`
- 行研报告类：`行研/学术/商业/分析`

**写法差异 P1 建议（M2/M3 项目推荐 P0）**：
```
Step 1：读取 .fbs/book-context-brief.md 核心论题与书型标签
Step 2：对照 Chapter Brief 书型/写法，给出 A/B/C 格式选项
        A. 使用推荐风格（优先+写法建议）
        B. 按用户风格写稿
        C. 保持现有风格不强制推荐
Step 3：书型/写法/叙事风格确认写入 .fbs/book-context-brief.md
```

---

#### §3.3.4 台账字符数强制实测（P0 强制）

> **措施**：通过读取实际文件字符统计，不依赖估算。

**台账实测（P0 强制要求）**：
```
1. 每章写稿完成后，必须实测字符数：使用 read_file 读取对应章节文件
   禁止估算占位：
   错误示例：| Ch01 | 章标题 | ~8000字 |
   正确示例：| Ch01 | 章标题 | 8,234字（实测）|

2. 若无法读取实测字符数，禁止写入估算字数
3. PowerShell 可用时，使用脚本实测：
   Get-ChildItem "{路径}" -Filter "*.md" |
     Where-Object {$_.Name -match "S3"} |
     ForEach-Object {
       "$($_.Name): $((Get-Content $_.FullName -Raw -Encoding UTF8).Length)字符"
     }
```

**台账字符数格式（2.0.1 强制标注实测）**：
```markdown
| 章序列 | 章名 | 章节状态 | 实测字符数 | 时间戳 | 说明 |
|---------|------|---------|---------|------|------|
| Ch01    | 章标题 | 完成 | 12,456字（实测） | {ISO} | 156% |
| Ch02    | 章标题 | 骨架标注 | 1,234字（实测） | {ISO} | 15% 骨架 |
| Ch03    | 章标题 | 待写 | 无 | {ISO} | 0% |
```

> **阈值说明**：A 达成 ≥80%，B 警告 80%~69%，D 骨架 ≤10%

---

### 单章写稿流程（Agent 执行版本）
```
→ Agent 写稿流程
  0. 读取项目状态，确认未重复写稿，chapter-dependencies 确认
  1. 读 Chapter Brief，确认核心仰角与本章核心论点，确认联网查证资料
  2. 执行联网查证（如果需要），2 次以内，rateLimitGuard 退避
  3. 查证超时 15s 后降级，继续联网查证降级记录
  4. 执行写稿，章节内容完整写出，不止列提纲
  5. 写完 [S3-ChNN] 第N章章节名.md + 台账更新
  阈值评估：
  若 ≥7.5 分，台账标注通过，继续下一章
  若 7.0~7.5 分，台账通过警告
  若 <7.0 分，触发重写，台账标注失败
```
