test(qa): AI 对话(聊天记录)E2E + #1/#6 真源围栏守卫(AC-4)

计划 §6/§8。收口 AI-chat-history 功能(AC-1..AC-4 全交付)。

- tests/test_ai_chat_history_e2e.py:真 pg、零 LLM/无网关(纯 CRUD 侧记录),
  覆盖 §6 全 6 用例——缓冲多轮线程一批落库 + GET newest-first/meta 保真、
  作用域分区(本章 ∪ 项目级 NULL)、跨批分页 + kind 过滤、
  append 只写 ai_messages(其它业务表零变 + usage_ledger 恒 0)/GET 只读、
  404 + 五类 422 失败零落库、clarify-abandon(服务端无部分写路径)。
- tests/test_ai_messages_not_in_generation_path.py:AST 静态围栏——
  memory/orchestrator 两目录无一 import/引用 ai_messages,
  MemoryRepos 捆绑与 assemble 形参都不含它;植入违规自证探测器非空,能变红。
- memory/gotchas.md:登记 ai_messages 真源围栏(append-only 侧记录,
  绝不喂 assemble/prompt;接入生成链 = code-review BLOCKER)。

门禁全绿:ruff/format · mypy 238 · alembic 无漂移 · pytest 1002 passed(+10)。
This commit is contained in:
Yaojia Wang
2026-07-09 17:42:45 +02:00
parent 5ba3eabda3
commit f6e88d7438
4 changed files with 679 additions and 2 deletions

View File

@@ -90,3 +90,4 @@
- [2026-06-24] @llm/@devops Prompt 外置`prompts/*.md` 文件名按 **spec.name连字符** Python 变量名——`style` agent name `"style"``style.md` `style_drift`另有 `character-gen.md`/`golden-finger.md`/`book-title.md`/`fine-outline.md`/`de-ai.md`。** prompt 内容后必须重生成金标准** `uv run python packages/agents/tests/_gen_golden.py`覆盖 `tests/fixtures/prompt_hashes.json`否则 `test_prompt_loader.py` 字节回归红旧常量含反斜杠折行——外迁/比对一律用**运行时值**别用源码文本`.gitattributes` `prompts/*.md text eol=lf`路径含斜杠是**根锚定**必须写完整嵌套路径 `packages/agents/ww_agents/prompts/*.md` 才匹配 `prompts/*.md` 不生效)。
- [2026-06-24] @devops wheel 默认不打非-`.py` 数据文件——`prompts/*.md` 必须在 `packages/agents/pyproject.toml` 显式纳入hatchling `artifacts`**别用 `force-include`**hatchling 已含包目录下全部文件force-include duplicate-path 构建失败源码树 pytest **测不出**漏带fail-fast 仅裸装时触发 CI `agents-wheel-smoke`build裸装`import ww_agents; assert ww_agents.SPECS``ww_agents` import 链拉起 `ww_llm_gateway``types.Tier`)→ `structlog` `packages/{llm_gateway,core}` 必须自声明 `structlog`原靠 apps/api 传递裸装 import ModuleNotFoundError)。
- [2026-06-24] @backend `SpecResolver`内置 name `SPECS` 纯内存、** DB**保留命名空间守卫在 **SkillRegistry 入库校验期** resolver 读路径用户 skill 与内置同名`REVIEW_RESERVED_NAMES set(SPECS)`)→ `AppError(VALIDATION)`name **精确字符串相等**拼错近似名`character_gen` vs `character-gen``output_schema_for` None/不命中是预期行为非 bug
- [2026-07-09] @qa **`ai_messages` append-only 旁路侧记录 `usage_ledger` 同物种绝不喂 `assemble()`/prompt——守不变量 #1/#6计划 §8)。** 它是作者AI 说了什么的真源**不是手稿/审稿真源**无记忆注入(#6)、无裁决(#3/#4)权威生成链`packages/core/ww_core/{memory,orchestrator}`任一模块 import/引用 `AiMessage`/`AiMessageRepo`/`ai_message_repo` = 制造第二个非确定性真源** code-review BLOCKER**。围栏已工具化`tests/test_ai_messages_not_in_generation_path.py`AST 扫两目录 import/Name/Attribute + 断言 `MemoryRepos` 捆绑与 `assemble` 形参都不含它植入违规自证非空守卫)—— ai_message repo 接进 `assemble()`/prompt 会直接变红日后加新 kind 或改 repo 都别越过这道墙