docs(prompt-mgmt): 方案A 协同回写 + 补声明 structlog 依赖

- memory/contracts.md:立 C6-ext(load_prompt/SPECS/SCHEMA_CATALOG/
  REVIEW_RESERVED_NAMES/SpecResolver + 打包契约)+ 变更日志一笔
- memory/decisions.md:方案A 决策(运行时值金标准/尾换行方案B/守卫前移/
  schema 留 Python/同一实例)
- memory/gotchas.md:spec.name 连字符命名 / 改稿须重生成金标准 /
  .gitattributes 完整嵌套路径 / wheel artifacts 带 .md / structlog 补声明 /
  SpecResolver 零 DB + 精确匹配
- PROGRESS.md:已封板「Prompt 管理重构 + 全量重写」波次
- ARCHITECTURE.md §5.1:补 prompt 外置 + SPECS/SCHEMA_CATALOG/SpecResolver,
  内置 agent 计数 8→21
- packages/{llm_gateway,core}/pyproject.toml:补声明 structlog>=24.1
  (原直接 import 未声明,靠 apps/api 传递;裸装 import ww_agents 会缺)
This commit is contained in:
Yaojia Wang
2026-06-24 08:25:26 +02:00
parent eb356c42a9
commit 0021426f09
8 changed files with 48 additions and 2 deletions

View File

@@ -326,9 +326,22 @@
- **token 纪律**job result/status/日志只记章号/计数/标志绝不含 prompt/正文/token(§5已断言)。
- 影响 @frontend链发起页/进度/裁决续跑面板**非目标本期不做**契约稳定后 follow-up `pnpm gen:api`@db/@devops C3检查点建表迁移 + 可选 jobs 注释)。
## C6-ext · Prompt 外置 + SpecResolver owner @llm(SPECS/loader/catalog) + @backend(resolver/守卫) 状态: 稳定方案A2026-06-24
> 设计真源:`docs/design/prompt-management.md`。纯重构、零功能/schema 变更、零迁移(前端无需 `pnpm gen:api`)。
- **`load_prompt(name) -> str`**`packages/agents/ww_agents/prompt_loader.py`@llm `prompts/<spec.name>.md` import 期读盘 BOM(`utf-8-sig`)/CRLF·CRLF/NFC/`rstrip('\n')` 内存缓存 返回完整 UTF-8 文本缺文件 `PromptNotFoundError`fail-fast fallback不插值)。
- **`SPECS: Final[dict[name, AgentSpec]]`**`specs.py`@llm21 内置 spec 集中名册`assert len(SPECS)==21``system_prompt=load_prompt(name)``output_schema=SCHEMA_CATALOG[name]`。**不变量**`SPECS[name] is *_spec`兼容期同一实例 `from ww_agents import *_spec` 不破`prompts/<name>.md`/`SPECS[name]`/`SCHEMA_CATALOG[name]` 三集合按 name 恒等
- **`SCHEMA_CATALOG: Final[dict[name, type[BaseModel]|None]]`**`schema_catalog.py`@llmnameoutput type **唯一真相源**`refiner=None``output_schema_for(name)`input None本波不建 input YAGNI)。
- **`REVIEW_RESERVED_NAMES: Final[frozenset]={continuity,foreshadow,style,pace}`**@llm四审受信名显式白名单非派生集合安全边界锚此
- **`SpecResolver`**`packages/skills/ww_skills/spec_resolver.py`@backend`build(skills)` 纯合并 `dict(SPECS)`+`SkillRegistry`读路径无冲突校验`get(name)` 先查内置 `SPECS`**纯内存 DB**未命中才查 registry都无`NOT_FOUND``output_schema_for`/`names`/`list_scope`name **精确字符串相等**无大小写/连字符归一)。
- **守卫前移**用户 skill 同名内置`REVIEW_RESERVED_NAMES set(SPECS)` **`SkillRegistry` 入库/加载校验期**即拒`AppError(VALIDATION)` `validate_declaration` 同处**不在 resolver 读路径**——内置 `get` 确定性零运行时分叉守不变量 #3
- **打包契约**@devops`.gitattributes` `packages/agents/ww_agents/prompts/*.md text eol=lf``packages/agents/pyproject.toml` hatchling `artifacts` 纳入 `prompts/*.md` wheel/sdist 分发CI `agents-wheel-smoke`build裸装`import ww_agents; assert ww_agents.SPECS` `.md` 漏带源码树 pytest 测不出)。`packages/{llm_gateway,core}` 补声明 `structlog`原直接 import 未声明 apps/api 传递)。
- 消费方`toolbox_registry.GeneratorTool.spec` `SPECS["<name>"]`不再直接 import 生成器 `*_spec`)。**本波不改**编排器`REVIEW_SPECS`/节点6.5 precheck/chain apps/api 3 路由`toolbox/outline/style`)——兼容期续用 `*_spec`因同一实例不变量无回归 resolver 列后续波次
## 契约变更日志append-only
> 格式:`- [date] @skill 改 Cx<改了什么> → 影响 <依赖方/任务>`
- [2026-06-24] @llm/@backend C6-extPrompt 外置方案A21 prompt 散文外置 `prompts/<name>.md` + `load_prompt`/`SPECS`/`SCHEMA_CATALOG`/`REVIEW_RESERVED_NAMES`@llm+ `SpecResolver` + SkillRegistry 入库守卫前移 + toolbox 桥接 `SPECS`@backend+ `.gitattributes`/wheel package-data/CI 冒烟@devops)。随后全量重写 21 prompt 内容任务对齐schema 契约/不变量保持金标准 fixture 重生成)。门禁绿ruff/format/mypy(209)/pytest(744)。→ 影响后续波次可将编排器 + apps/api 路由切 `SpecResolver` 并删 `*_spec` 导出前端零影响GeneratorTool 描述符字段不变)。
- [2026-06-23] @backend C-ChainC23 端点 + `schemas/chain.py` + `services/{chain_runner,chain_deps}.py` + `jobs` 零迁移复用 `status="awaiting_input"` + `JobRepo.set_awaiting`+ `ErrorCode.CONFLICT`(409) + `project_deps` `build_chain_gateway`/`get_chain_gateway`/`get_digest_gateway_builder`/`get_checkpointer_factory`OpenAPI 2 POSTGET /jobs 复用)。门禁绿ruff/format/mypy(193) 干净 + pytest 600 passed + alembic 无漂移。→ 影响 @frontendfollow-up `pnpm gen:api`)、@db/@devops C3检查点迁移)。
- [2026-06-20] @backend C3新增 **`GET /projects/{project_id}/chapters/{chapter_no}/injection`**本章注入透明B0 读端点)→ `InjectionResponse{project_id, chapter_no, selected:[InjectionEntity{kind,name,reasons[]}], recent_n}``schemas/injection.py`snake_case)。实现仅调既有 `assemble()` 回放确定性 `SelectionTrace`——** LLM commit DDL**项目不存在404无大纲`selected:[]`reasons 取值同 `SelectionReason`explicit_beat/main_character/recent_digest/foreshadow_window)。→ 影响 @frontend `pnpm gen:api` + `ChapterAssistant` 消费)。**B0 可控版PUT override + `select_relevant_entities` pinned/excluded/recent_n + draft 端点同读 override + 持久化尚未实现届时再扩本契约。**