scripts/butler-memory-monthly-probe.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
# Memory monthly probe — M1–M7 automated gate (pytest) + optional WeChat manual hints.
#
# Usage:
# bash scripts/butler-memory-monthly-probe.sh
# bash scripts/butler-memory-monthly-probe.sh --log # append pilot-log row on PASS
# bash scripts/butler-memory-monthly-probe.sh --manual # print 5-min WeChat script only
#
set -uo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
LOG=0
MANUAL=0
for arg in "$@"; do
case "$arg" in
--log) LOG=1 ;;
--manual) MANUAL=1 ;;
-h|--help)
sed -n '1,10p' "$0"
exit 0
;;
esac
done
if [[ -f "$ROOT/.env" ]]; then
set -a
# shellcheck disable=SC1091
source "$ROOT/.env" 2>/dev/null || true
set +a
fi
export PYTHONPATH="${PYTHONPATH:-$ROOT}:$ROOT"
_wechat_manual() {
cat <<'EOF'
微信 5 分钟月度探针(灵文1号;自动化绿后可选真机复验):
1. /诊断
2. 灵文试点统一测试是哪天?
3. 我们决定下周试点 Redis → /记忆待审 → /拒绝记忆 1
4. 重复发第 2 句 → /诊断(预取缓存: 命中)
5. 项目用什么技术栈?顶层有哪些目录?
6. /新对话 → 我们刚才聊过什么?
7. 请记住:月度探针打卡 YYYY-MM-DD → /记忆待审 → /批准记忆 全部
详见 docs/guides/memory-ops.md §微信 5 分钟月度探针
EOF
}
if [[ "$MANUAL" -eq 1 ]]; then
_wechat_manual
exit 0
fi
STAMP="$(date +%Y-%m-%d)"
FAIL=0
echo "=== Butler memory monthly probe ($STAMP) ==="
echo "semantic=${BUTLER_SEMANTIC_MEMORY:-0} prefetch=${BUTLER_QUEUE_PREFETCH:-0}"
echo ""
if [[ "${BUTLER_SEMANTIC_MEMORY:-0}" != "1" ]]; then
echo "FAIL: BUTLER_SEMANTIC_MEMORY 未开 — 先 bash scripts/butler-memory-phase-a.sh"
exit 1
fi
_probe() {
local id="$1"
local desc="$2"
shift 2
printf " %-3s " "$id"
if python3 -m pytest "$@" -q --tb=line >/dev/null 2>&1; then
echo "✅ $desc"
return 0
fi
echo "❌ $desc"
FAIL=1
return 0
}
_probe_optional() {
local id="$1"
local desc="$2"
shift 2
printf " %-3s " "$id"
if python3 -m pytest "$@" -q --tb=line >/dev/null 2>&1; then
echo "✅ $desc"
else
echo "⚠️ $desc(加分项,不计入 FAIL)"
fi
}
echo "M1–M7 自动化探针(handler/记忆模块 pytest,非真机 LLM):"
_probe M1 "/诊断 记忆分层与向量快照" \
tests/test_semantic_memory_p1.py::TestDiagnosticsNoSession
_probe M2 "paraphrase 召回统一测试日" \
tests/test_semantic_memory_p1.py::TestProjectPrefetchAndFence::test_search_project_memory_vectors
_probe M3 "Pending → /拒绝记忆 向量清理" \
tests/test_memory_m3_m4_smoke.py::TestM3RejectPendingGateway::test_reject_via_slash_command
_probe M4 "同句预取缓存命中" \
tests/test_memory_m3_m4_smoke.py::TestM4PrefetchCacheHit::test_repeat_query_hits_warm_cache
_probe M5 "novel-factory / 关键词 facts 召回" \
tests/test_memory_recall_fixtures.py::TestMemoryRecallFixtures::test_keyword_fallback_case \
tests/test_memory_p1_p2.py::TestNovelFactoryStatusWorkflow::test_builtin_resolves_with_steps
_probe M6 "/新对话 清空上下文摘要" \
tests/test_p0_memory_pilot.py::TestNewCommandMemoryFeedback::test_new_appends_extraction_summary
_probe M7 "记住 → 批准 → 向量同步" \
tests/test_semantic_memory_p1.py::TestProjectMemoryVectors::test_remember_pending_then_approve_syncs_vectors
echo ""
_probe_optional M1b "/记忆图谱 三元组展示" \
tests/test_memory_retrieval_triplets.py::test_memory_graph_command
_probe_optional M1c "observation store 迁移/诊断" \
tests/test_observation_migrate.py
echo ""
if [[ "$FAIL" -ne 0 ]]; then
echo "MEMORY MONTHLY PROBE: FAIL(修复后重跑 phase-b / monthly-probe)"
exit 1
fi
echo "MEMORY MONTHLY PROBE: PASS (M1–M7)"
echo ""
_wechat_manual
if [[ "$LOG" -eq 1 ]]; then
LOG_FILE="$ROOT/projects/LingWen1/docs/pilot-log.md"
ROW="| $STAMP | **记忆月度探针** | butler-memory-monthly-probe.sh M1–M7 PASS |"
if [[ -f "$LOG_FILE" ]] && ! grep -q "记忆月度探针.*$STAMP" "$LOG_FILE" 2>/dev/null; then
sed -i "/^|------|/a\\$ROW" "$LOG_FILE"
echo ""
echo "Appended: $LOG_FILE"
fi
fi
exit 0