zizi b0bc7a8745 框架: 技能按动作-对象重组 + 先审后入创作闭环
一、技能重组(动作-对象命名)
- 旧目录 clean/confirm/continuation/db/detect/embed/… 重组为
  clean-book-text/decide-candidate/write-next-chapter/access-database/
  check-content-consistency/embed-knowledge/…(git 识别为 rename,内容保持)
- agents/*.md、AGENTS.md/CLAUDE.md 收编、example_skill 登记表同步新名

二、先审后入创作闭环(本次核心)
正文接受从"机械门一过就写正典"改为"机械门+语义审查双通过+用户批准+单事务原子提交",
DB 级兜底,编排层跳步即被硬拒。
- candidate_cas.py + example_candidate_cas(109):持久化 CAS 状态链
- fact_delta.py + example_fact_delta/example_fact_ledger(106):结构化事实增量,
  模型只提六型闭集增量+正文证据引文,仅用户批准的增量随正文同事务入账本
- projection_registry.py + example_projection_run(107):投影登记与恢复
- acceptance_state.py:接受前置实时状态重读
- lesson_registry.py + example_lesson(108):经验升格链,禁止自动升格
- DDL 105:example_candidate 增 semantic_status/semantic_report_sha256
- write_canonical.accept:语义兜底+同事务合并增量+登记投影;
  run_writer_pipeline/persist_writer_run/run_writer_semantic_detector/step2 接入全链
- claude_runtime:兼容新 CLI modelUsage 信息字段

三、审查修复(独立子代理四维审查后)
- 事实增量 propose→approve 翻态正道,不撞唯一键
- 冻结配置探针重刷(CLI 2.1.211→2.1.231 漂移),profileSha256/adapterVersion 再登记
- 可视化合同悬空路径/五六空间矛盾、 SoT 旧技能名漂移、行尾空白清理

测试:离线 65 套 + 真实库集成 5 套(CAS/接受故障注入/事实增量/投影/经验升格)+ 回放 79 项全绿。
创作内容(docs/design、生成正文 artifacts)按"框架与创作分开"未入本提交。
2026-08-14 10:24:08 +08:00

5.1 KiB
Raw Blame History

name, description
name description
embed-knowledge 使用固定 Qwen3 嵌入模型将知识草稿或实体批量写入 pgvector,并按内容哈希幂等处理 owner 与版本。知识行需要建立或刷新检索向量时使用;不嵌入参考书全文。

嵌入知识内容

对应 muse API 面:AI 网关(嵌入)。通道事实见 db/连接信息.md:BASE http://100.64.0.8:3000、模型 Qwen/Qwen3-Embedding-8B、请求体 "dimensions":1024(实测生效)、禁系统代理(trust_env=False)。

用法

# 批量补嵌 pending 草稿(无活向量,或活向量的当前 payload+model hash 已过期)
.venv/bin/python .claude/skills/embed-knowledge/scripts/embed_drafts.py

# 指定 work(默认兼容参考书拆书批次,按 source_id)或限量
.venv/bin/python .claude/skills/embed-knowledge/scripts/embed_drafts.py --work-id 3 --limit 100

# 章后抽卡按作品的 draft.work_id 筛选(source_id 是章节 id)
.venv/bin/python .claude/skills/embed-knowledge/scripts/embed_drafts.py --work-id 12 --source-type chapter_extract

# 自由文本试嵌(调试/B3 查询端复用同实现)
.venv/bin/python .claude/skills/embed-knowledge/scripts/embed_drafts.py --probe "机甲近战的节奏控制"

合同

  • 嵌入文本构造:【型】名称:一句话摘要\n字段正文摘选(draft_payload 的 embed_text 字段优先;无则兼容中文键 型/名称/一句话摘要/字段 与作品抽卡英文键 type/name/brief/fields),与检索端 query 语义对齐。
  • 幂等与 owner:sha256(嵌入文本+模型) 为 content_hash(uk: tenant+hash+model)。只有唯一行 deleted=FALSE、绑定同一 draft_id,且 owner draft 同租户并 deleted=FALSE 时才幂等跳过;entity_id 非空或其他 active draft owner 明确冲突并失败,绝不迁移 owner。旧 owner draft 已软删时,允许在写前活性重验后把唯一行条件迁到当前 draft。
  • 批量:读取每个 pending draft 的全部活向量,在 Python 中复用统一文本与 hash 规则筛选“无活向量”或“活向量 hash/model 与当前目标不一致”的候选;对完整候选集完成状态、同批 hash 与目标 owner 只读预检并提交后,limit 才限制实际 HTTP/写入行,每个实际 chunk 在 HTTP 前再次预查 owner 以封住竞态。每请求 ≤16 条文本;响应 index 必须是范围内唯一整数并完整覆盖请求槽位,缺项、重复或越界进入既有整批重试和逐条降级。失败整批重试 2 次(指数退避),仍失败逐条降级重试,坏行记错并继续(不断批)。网络异常、返回 bad、向量缺项或 None 均只记失败,不改旧向量,下一轮仍可重试;owner 冲突、多条活向量、同批目标 hash 冲突属于确定性异常,明确报告后令整条命令失败退出,不降级成失败计数。
  • 落库与 reset/confirm/parse 并发:HTTP 期间不持数据库事务。每个 draft 写入使用独立事务,先 SELECT ... FOR UPDATE 锁定 draft 并重验租户、deleted=FALSE、status='pending';同时读取当前 draft_payload,重构文本与 hash,和 HTTP 前快照任一不一致即跳过。随后 SELECT ... FOR UPDATE 锁定该 draft 全部活向量:多条活向量是异常状态并失败关闭,任一 entity_id 非空则冲突失败,同 hash 且同 model 的当前活向量才幂等跳过,其他 hash 或 model 的无 entity 旧活向量在 UPSERT 前统一软删,保证每 draft 仅一个活向量。最后锁同 hash 唯一行,执行带 owner 条件的 UPSERT 并用 RETURNING draft_id 校验。同批多个 draft 的目标 hash 相同时整组失败,不按执行顺序抢 owner。该 draft 行锁与 reset 的 11 表 SHARE ROW EXCLUSIVE(4 个输入源表 + 7 个产出表)配合:embed 先锁时 reset 等待且随后能发现快照漂移;reset 先完成时 embed 等待后看到软删并跳过。confirm/parse 先完成时 embed 在锁后看到状态或 payload/hash 漂移并跳过。以上跳过或失败路径均零向量写入。
  • 落库字段:example_knowledge_embedding(draft_id, content_hash, embed_text, model, dimensions=1024, embedding);draft 确认落 entity 后由 confirm 流程把 owner 迁到 entity_id 并清空 draft_id,关系草稿确认后关闭无 canonical owner 的临时向量。
  • 汇报:新嵌 N、跳过 M、失败 K;幂等、失活和冲突原因均输出可追踪明细。

离线验证

.venv/bin/python .claude/skills/embed-knowledge/scripts/test_embed_drafts_offline.py
.venv/bin/python -m py_compile .claude/skills/embed-knowledge/scripts/embed_drafts.py \
  .claude/skills/embed-knowledge/scripts/test_embed_drafts_offline.py

离线测试只使用 fake connection 检查并发顺序、SQL 条件和 owner 反例,不连接真实数据库,不调用 embedding 或 reset。

红线

  • 调用必须 trust_env=False(系统代理会假 502);令牌用 MUSE_AI_NEW_API_TOKEN(勿用管理令牌,打 /v1 报无效)。
  • 只嵌知识行内容,不嵌参考书原文全文(原文私有库不进向量面——脱敏边界在 B2 拆书层保证)。