Files
writer-work-flow/packages/agents/tests/test_toolbox_specs.py
Yaojia Wang f43ccd293f feat(toolbox): T6 创作工具箱通用生成器框架 — 8 新生成器 + 声明驱动落地页 + P2 收尾
通用执行路径驱动全部生成器("加生成器=加一份声明"):
- @llm: ww_agents +7 输出 schema + 7 spec(book-title/blurb/name/golden-finger/
  glossary/opening/fine-outline,只声明 tier)+ build_outline_chapter_context
- @backend: ww_skills GeneratorTool 描述符 + TOOLBOX(11) + get_tool;3 通用端点
  GET /skills/toolbox · POST .../skills/{tool_key}/generate(预览不写库,仅记账) ·
  POST .../ingest(复用 continuity 409 + partition_writes 白名单);纯 context 派发
- @frontend: 工具箱落地页 RSC + 声明驱动 GeneratorRunner + lib/toolbox 纯函数
  + LeftNav「工具箱」+ ⌘K nav-toolbox/action-gen-*;legacy 3 跳现页
- @qa: tests/test_t6_toolbox_e2e.py 5 用例真 pg + mock 网关零 token,无端点 bug
- P2 收尾: 限流→decisions.md 记延后(单用户原型);noopener/Committable 早已修

守不变量 #2(只声明 tier)/#3(预览不写库,入库经验收 gate)/#9(缓存前缀)。无 DB 迁移。
门禁绿: 后端 ruff/format/mypy 195/alembic 无漂移/pytest 583;前端 lint/tsc/vitest 279/build。
spec 回写 PRODUCT_SPEC §7 + ARCHITECTURE §7.2 端点表。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 20:37:55 +02:00

85 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""T6 创作工具箱 · 7 个文本生成器的 spec 契约测试。
契约测试——校验每个 spec 的 name/tier/reads/writes/output_schema/scope/input_schema
对齐不变量 #2只声明 tier/ #3writes 经验收才生效)。不联网、无 DB。
"""
from __future__ import annotations
import pytest
from ww_agents import (
AgentSpec,
BlurbResult,
DetailedOutlineResult,
GlossaryResult,
GoldenFingerResult,
NameListResult,
OpeningResult,
TitleListResult,
blurb_spec,
book_title_spec,
fine_outline_spec,
glossary_spec,
golden_finger_spec,
name_spec,
opening_spec,
)
# (spec, name, tier, reads, writes, output_schema)
_TOOLBOX_SPECS = [
(book_title_spec, "book-title", "light", ["projects"], [], TitleListResult),
(blurb_spec, "blurb", "analyst", ["projects"], [], BlurbResult),
(name_spec, "name", "light", ["projects", "world_entities", "characters"], [], NameListResult),
(
golden_finger_spec,
"golden-finger",
"writer",
["projects", "world_entities"],
["world_entities"],
GoldenFingerResult,
),
(
glossary_spec,
"glossary",
"analyst",
["projects", "world_entities"],
["world_entities"],
GlossaryResult,
),
(opening_spec, "opening", "writer", ["projects", "outline"], [], OpeningResult),
(
fine_outline_spec,
"fine-outline",
"analyst",
["projects", "outline"],
["outline"],
DetailedOutlineResult,
),
]
@pytest.mark.parametrize(
("spec", "name", "tier", "reads", "writes", "output_schema"),
_TOOLBOX_SPECS,
)
def test_toolbox_spec_declares_expected_contract(
spec: AgentSpec,
name: str,
tier: str,
reads: list[str],
writes: list[str],
output_schema: type,
) -> None:
assert spec.name == name
assert spec.tier == tier
assert spec.reads == reads
assert spec.writes == writes
assert spec.output_schema is output_schema
assert spec.scope == "builtin"
assert spec.input_schema is None # 注入材料为序列化文本,非结构化入参
@pytest.mark.parametrize("spec", [row[0] for row in _TOOLBOX_SPECS])
def test_toolbox_spec_has_nonempty_system_prompt(spec: AgentSpec) -> None:
assert spec.system_prompt.strip()