feat(toolbox): F1 拆书 teardown 落库成项目 rules

- teardown_spec.writes=["rules"](只声明 tier,入库仍经白名单 gate,不变量 #3)
- toolbox_registry teardown entry 加 ingest=IngestSpec(table="rules")
- routers/toolbox.py 通用 ingest dispatcher 加 _ingest_rules:
  BookTeardownResult(themes/archetypes/structure/hooks) 拍平为可读 rules 条目,
  落项目级(无 continuity 预检,仿 _ingest_outline 无 409)
- schemas/toolbox.py 加 TeardownIngestView + ToolIngestRequest.teardown
- 单测:teardown ingest→rules 真落行 + 预览(generate)不写库

后端门禁绿:ruff/format/mypy clean · alembic no drift · pytest 644 passed
This commit is contained in:
Yaojia Wang
2026-06-23 20:00:25 +02:00
parent 44642c37b4
commit 61398a1452
8 changed files with 216 additions and 17 deletions

View File

@@ -19,13 +19,13 @@ _NEW_KEYS = {
"glossary",
"opening",
"fine-outline",
# 竞品快赢Scope B续写 / 扩写 / 降AI率 / 拆书(全 preview-only
# 竞品快赢Scope B续写/扩写/降AI率 preview-only拆书 F1 可落库 rules
"continue",
"expand",
"de-ai",
"teardown",
}
_INGEST_KEYS = {"golden-finger", "glossary", "fine-outline"}
_INGEST_KEYS = {"golden-finger", "glossary", "fine-outline", "teardown"}
def test_toolbox_has_all_tools() -> None:
@@ -70,6 +70,9 @@ def test_ingest_tools_declare_known_table() -> None:
assert TOOLBOX["glossary"].ingest.table == "world_entities"
assert TOOLBOX["fine-outline"].ingest is not None
assert TOOLBOX["fine-outline"].ingest.table == "outline"
# F1拆书结论落库为项目 rules。
assert TOOLBOX["teardown"].ingest is not None
assert TOOLBOX["teardown"].ingest.table == "rules"
def test_chapter_tools_have_chapter_no_field() -> None:

View File

@@ -197,7 +197,7 @@ TOOLBOX: dict[str, GeneratorTool] = {
input_fields=[_chapter_no_field(), _BRIEF_FIELD],
ingest=IngestSpec(table="outline"),
),
# ---- 竞品快赢Scope B续写 / 扩写 / 降AI率 / 拆书(全 preview-onlywrites=[]----
# ---- 竞品快赢Scope B续写/扩写/降AI率 preview-only拆书 F1 可落库 rules ----
"continue": GeneratorTool(
key="continue",
title="续写生成器",
@@ -252,6 +252,7 @@ TOOLBOX: dict[str, GeneratorTool] = {
_SOURCE_TEXT_FIELD,
_BRIEF_FIELD,
],
ingest=IngestSpec(table="rules"), # F1拆书结论拍平为项目 rules 条目落库
),
}