# 设计契约 · 续补三件（拆书入库 / 续写式链 / 模板库）

> 分支 `feat/backlog-followups` · 实施前唯一契约源。Agent 先读本文 + CLAUDE.md 不变量。范围 = 用户选定「全部可建的续补」（排除多租户/市场/push/browse/K1）。

## Context
Scope B 已合并（链 UI + 4 生成器）。本批补三个**贴现有框架**的续补功能：把竞品对标的剩余可建项做完。守不变量 #1/#2/#3/#9；preview→ingest 经验收闸；单用户原型（owner_id stub）。

---

## F1 · 拆书落库成 rules（teardown → rules ingest）
现状：teardown 生成器是 preview-only。目标：可把拆书结论入库为项目 `rules`，供写章注入。
- **@llm**（packages/agents）：`teardown_spec.writes=["rules"]`（其余不动；只声明 tier #2）。
- **@backend**（packages/skills + apps/api）：
  - `skill_permissions.KNOWN_TABLES` 加 `"rules"`（确认未在则加）。
  - `toolbox_registry` teardown entry 加 `ingest=IngestSpec(table="rules")`。
  - `routers/toolbox.py`：在通用 ingest dispatcher（现 `_ingest_world_entities`/`_ingest_outline`，:344-365 的 "其余表未实现" 分支）加 `_ingest_rules` handler——把 `BookTeardownResult`(themes/archetypes/structure/hooks) 转成 `rules` 行（scope=project 级，复用既有 `rules` repo/表；规则文本由结构化字段拼成可读条目）。`partition_writes` 白名单已据 spec.writes 放行；rules 无需 continuity 预检（meta 规则非设定卡）→ ingest 直接落库（仿 `_ingest_outline` 无 409 路径）。
- **@frontend**（apps/web）：teardown 现 output_kind 已可预览；因 registry 加了 ingest，`GeneratorRunner` 的入库分支应自动出现「入库为规则」按钮（复用既有 ingest UI）。确认渲染 + `pnpm gen:api`。
- **@qa**：ingest E2E（teardown generate→ingest→`rules` 真落行；负向：预览仍不写库）。
- DoD：后端门禁绿；teardown 可入 rules；不变量 #3（入库经白名单）守住。

## F2 · 续写式链（continue_volume chain）
现状：链只有 `draft_volume`（从 start 章按记忆写）。目标：新增 `continue_volume`——每章写作以**上一章 accepted 正文末尾**作前文引子（复用 `build_continuation_context`），比纯 digest 续写更顺。
- **@llm**（packages/core/orchestrator/chain）：`write_chapter` 节点支持「续写模式」——据 state 的 `chain_key`，`continue_volume` 时调 `build_continuation_context(prior_text=上一章 accepted 正文)`（经注入的 reader，仿现有 accept_op 注入；core 不 import apps/api）；`draft_volume` 保持原行为。ChainState 加 `chain_key`（已有则复用）。
- **@backend**（apps/api）：`SUPPORTED_CHAINS`（chain.py:63）加 `"continue_volume"`；run 端点据 chain_key 选模式；chain_runner 注入「读上一章 accepted 正文」的 reader 给图。
- **@frontend**（apps/web）：`ChainStarter` 加链类型选择（draft_volume=从头写 / continue_volume=续写），传 chain_key。
- **@qa**：E2E（continue_volume 两章：第二章请求上下文含第一章正文末尾；其余同链 E2E 范式，mock 网关零 token）。
- DoD：两种链都可跑；续写模式前文注入经 E2E 断言；守不变量 #1/#5。

## F3 · 提示词/模板库（单用户本地版）
现状：无。目标：作者保存/复用提示词模板，可一键填入生成器的 brief/text。**不做分享/市场**（需多租户）。
- **@db**（packages/db）：新表 `prompt_templates`（`UuidPk`+`CreatedAt`+`Base` mixin；列：`owner_id`(stub)、`title:str`、`body:str`、`category:str|None`、`tool_key:str|None`(可选关联生成器)）+ alembic 迁移。`alembic check` 无漂移。
- **@backend**（packages/core/domain + apps/api）：`TemplateRepo`/`SqlTemplateRepo`（list/create/delete，owner stub 过滤）+ `routers/templates.py`（`GET/POST/DELETE /templates`，POST 校验 title/body 非空→422）+ `schemas/templates.py` + main 注册。
- **@frontend**（apps/web）：`pnpm gen:api`；模板库页 `app/templates/page.tsx`（列表/新建/删除）+ nav 入口；生成器 Runner 可选「从模板填入」（把模板 body 填进 brief/text 输入）。
- **@qa**：E2E（创建→列出→删除 真 pg；title 空→422）。
- DoD：模板 CRUD 可用 + 可填入生成器；后端+前端门禁绿。

---

## Workflow 结构（顺序建造避免共享树写冲突 → 交叉评审 → 全门禁）
- Phase F1（1-2 agent）→ Phase F2（@llm+@backend 顺序 + @frontend）→ Phase F3（@db→@backend→@frontend，+@qa）→ 各 feature E2E。
- 交叉评审（并行只读）：python / fastapi / typescript / 不变量。
- 全门禁（并行独立复跑）：后端 ruff/format/mypy/alembic check/pytest · 前端 lint/tsc/vitest/build。
- 我汇总 review；CRITICAL/HIGH → 派 fix agent 复绿再合并。

## 验证
- 后端：`uv run ruff check . && uv run mypy packages apps && uv run alembic check && uv run pytest -q`（pg 在跑）。
- 前端：`cd apps/web && pnpm gen:api && pnpm lint && pnpm typecheck && pnpm test && pnpm build`。
- 实景（app 在 localhost:3000/8000，需 provider key）：teardown 可入 rules；链可选 continue_volume；模板库可建/填入。

## 风险/取舍
- F1 rules 入库：rules 表结构若与拆书结构化字段不匹配，则拍平为可读规则文本（一条 teardown=一/多条 rule），E2E 断真落行即可。
- F2 续写 reader 跨层：端点读 chapter accepted 正文→注入图节点（仿 accept_op，core 不 import apps/api）。
- F3 模板填入生成器：前端把模板 body 写进现有 brief/text 输入即可，不改生成器后端。
- owner_id 全程 stub（单用户原型）；分享/市场不做。
