8.5 KiB
title, date, based-on, kanban-board, status
| title | date | based-on | kanban-board | status |
|---|---|---|---|---|
| 重构任务清单 | 2026-02-26 | refactor-plan | refactor-board | 进行中 |
重构任务清单
看板视图见 refactor-board。完成任务后勾选 checkbox,填写完成时间和实际结果。
Phase 1 · 数据安全与正确性
必须按顺序执行,P1-4 是验收步骤。
P1-1 · 删除 blacklist 过宽字面量
| 字段 | 内容 |
|---|---|
| 状态 | ✅ DONE |
| 优先级 | 🔴 Critical |
| 文件 | blacklist.py |
| 关联问题 | C4(49% 误隔离率) |
| 完成时间 | 2026-02-26 |
| 实际结果 | 已删除 api_key、access_key 两行字面量 |
改动:从 SENSITIVE_LITERAL_MARKERS 删除以下两行(已被正则覆盖)
'api_key',
'access_key',
验收:重建索引后 memory_primary 条数显著增加,memory_secure_audit 条数下降。
- 完成改动
- 验收通过
P1-2 · stale 清理排除 failed_ids
| 字段 | 内容 |
|---|---|
| 状态 | ✅ DONE |
| 优先级 | 🔴 Critical |
| 文件 | ingest_vault.py 第 88 行 |
| 关联问题 | C1(embed 失败文档被静默删除) |
| 完成时间 | 2026-02-26 |
| 实际结果 | 已在 stale 计算中排除 failed_ids |
改动:
# 修改前
stale_primary_ids = sorted(db_primary_ids - valid_ids)
# 修改后
stale_primary_ids = sorted(db_primary_ids - valid_ids - set(failed_ids))
验收:全量重建时模拟 embed 失败,确认失败文档的旧向量保留。
- 完成改动
- 验收通过
P1-3 · hook 清理 changes 临时文件
| 字段 | 内容 |
|---|---|
| 状态 | ✅ DONE |
| 优先级 | 🔴 Critical |
| 文件 | install-hook.sh(修改后需重新安装 hook) |
| 关联问题 | C3(每次 commit 留下临时文件) |
| 完成时间 | 2026-02-26 |
| 实际结果 | 已加 rm -f '$changes_file',hook 已重新安装 |
改动:
# 修改前
nohup uv run ... --changes-file "$changes_file" >> "$log_file" 2>&1 &
# 修改后
nohup bash -c "uv run ... --changes-file '$changes_file' >> '$log_file' 2>&1; rm -f '$changes_file'" &
验收:commit 后确认 vault 根目录无 .memory-changes-*.txt 残留。
- 完成改动
- 重新安装 hook
- 验收通过
P1-4 · 重建全量索引验收
| 字段 | 内容 |
|---|---|
| 状态 | ✅ DONE |
| 优先级 | 🔴 Critical |
| 依赖 | P1-1 ~ P1-3 全部完成后执行 |
| 完成时间 | 2026-02-26 |
| 实测 primary | 96 |
| 实测 secure | 85 |
操作:
psql $PG_DSN -c "TRUNCATE memory_primary, memory_secure_audit;"
uv run python ingest_vault.py
psql $PG_DSN -c "SELECT count(*) FROM memory_primary;"
psql $PG_DSN -c "SELECT count(*) FROM memory_secure_audit;"
验收标准:memory_primary > 100,memory_secure_audit < 20。
- 执行全量重建
memory_primary> 100 ⚠️ 实测 96(Infrastructure/Home-Automation 被路径规则整体隔离)memory_secure_audit< 20 ⚠️ 实测 85(同上原因)
Phase 2 · 性能与一致性
依赖 Phase 1 全部完成后执行。
P2-1 · 增量索引加 hash 检查
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟠 Important |
| 文件 | incremental_ingest.py |
| 关联问题 | C2(P95=1.4s 的直接原因) |
| 完成时间 | — |
| 实际结果 | — |
改动:调用 embed_text 前先查 content_hash,匹配则跳过
new_hash = sha256_text(text)
cur.execute('SELECT content_hash FROM memory_primary WHERE id=%s', (rel_path,))
row = cur.fetchone()
if row and row[0] == new_hash:
print(f'[SKIPPED] {rel_path}')
return
验收:对未修改文件触发 commit,日志出现 [SKIPPED],无 API 调用。预期 P95 < 0.1s(hash 命中时)。
- 完成改动
- 验收通过(日志出现
[SKIPPED])
P2-2 · 统一 ingest 目录范围
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟠 Important |
| 文件 | incremental_ingest.py |
| 关联问题 | I2(增量处理任意目录,全量只处理 PRIMARY_DIRS) |
| 完成时间 | — |
| 实际结果 | — |
改动:upsert_file() 入口加目录过滤
PRIMARY_DIRS = {'01_Projects', '02_Areas'}
top_dir = Path(rel_path).parts[0] if Path(rel_path).parts else ''
if top_dir not in PRIMARY_DIRS:
print(f'[SKIPPED-OUT-OF-SCOPE] {rel_path}')
return
验收:提交 03_Resources/ 下的文件,日志出现 [SKIPPED-OUT-OF-SCOPE]。
- 完成改动
- 验收通过
P2-3 · 换用 HNSW 索引
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟠 Important |
| 文件 | schema.sql |
| 关联问题 | I1(ivfflat lists=100 对 81 行无效) |
| 完成时间 | — |
| 实际结果 | — |
改动:
DROP INDEX IF EXISTS memory_primary_embedding_idx;
CREATE INDEX memory_primary_embedding_idx
ON memory_primary USING hnsw (embedding vector_cosine_ops);
验收:EXPLAIN SELECT ... ORDER BY embedding <=> ... 显示使用新索引。
- 执行 SQL 变更
- EXPLAIN 确认使用 HNSW 索引
P2-4 · 修复 VAULT_DIR 推导
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟠 Important |
| 文件 | agent-with-memory.sh |
| 关联问题 | I4(路径推导假设脚本在特定目录层级) |
| 完成时间 | — |
| 实际结果 | — |
改动:从 .env.memory 读取 VAULT_DIR,加校验
ENV_FILE="$SCRIPT_DIR/.env.memory"
if [[ -f "$ENV_FILE" ]]; then
VAULT_DIR="$(grep '^VAULT_DIR=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' | tr -d "'")"
fi
if [[ -z "${VAULT_DIR:-}" ]]; then
echo "错误: 未找到 VAULT_DIR,请在 .env.memory 中配置" >&2
exit 1
fi
验收:从任意目录执行脚本,VAULT_DIR 正确解析。
- 完成改动
- 验收通过
P2-5 · 查询加相似度阈值
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟠 Important |
| 文件 | query_pgvector.py |
| 关联问题 | I5(无关查询仍返回 top_k 结果) |
| 阈值(初始) | 0.5(需实测调整) |
| 完成时间 | — |
| 实际结果 | — |
改动:加 threshold 参数
def query(text: str, top_k: int = 5, max_chars: int = 2500, threshold: float = 0.5) -> str:
cur.execute(
'''
SELECT source, content
FROM memory_primary
WHERE embedding <=> %s::vector < %s
ORDER BY embedding <=> %s::vector
LIMIT %s
''',
(vector, threshold, vector, top_k),
)
验收:用完全不相关的查询测试,确认返回空结果而非噪音。
- 完成改动
- 验收通过(无关查询返回空)
Phase 3 · 可观测性与运营
可选,按需执行。
P3-1 · audit 表记录触发原因
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟡 Nice |
| 文件 | schema.sql、blacklist.py、index_common.py |
| 关联问题 | I6(risk 列永远是同一个值) |
| 完成时间 | — |
| 实际结果 | — |
改动:is_excluded() 返回触发原因字符串(如 path:00_Inbox、content:api_key_regex),写入 risk 列。
- 完成改动
- 验收通过
P3-2 · hook 失败写入可见日志
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟡 Nice |
| 文件 | install-hook.sh |
| 关联问题 | I7(所有错误静默) |
| 完成时间 | — |
| 实际结果 | — |
改动:Python 进程退出码非 0 时,向 .memory-sync.log 写入带时间戳的 [ERROR] 行。
- 完成改动
- 验收通过
P3-3 · 添加 health-check 脚本
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟡 Nice |
| 文件 | 新增 health-check.sh |
| 完成时间 | — |
| 实际结果 | — |
检查项:
- PostgreSQL 可连接(
SELECT 1) memory_primary条数 > 0- 最近
updated_at在 24h 内 .env.memory存在且关键字段非空
P3-4 · 日志轮转
| 字段 | 内容 |
|---|---|
| 状态 | TODO |
| 优先级 | 🟡 Nice |
| 文件 | install-hook.sh |
| 关联问题 | O1(.memory-sync.log 无限增长) |
| 完成时间 | — |
| 实际结果 | — |
改动:hook 里检查日志大小,超过 5MB 时保留最后 1000 行。
- 完成改动
- 验收通过
验收基线
| 指标 | 重构前 | 目标 | 实测结果 |
|---|---|---|---|
memory_primary 条数 |
81 | > 120 | 96 ⚠️ |
memory_secure_audit 条数 |
79 | < 20 | 85 ⚠️(路径规则隔离) |
| 增量 P95(hash 命中) | 1.4s | < 0.1s | 待测 |
| 增量 P95(实际 embed) | 1.4s | < 0.8s | 待测 |
| Recall@5 | 90% | ≥ 90% | 待测 |