Files
wenzi/scripts/prd_review_cycle.sh

157 lines
5.2 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
PROJECT_DIR="/home/long/project/蚊子"
REPORT_DIR="$PROJECT_DIR/logs/prd-review"
RUN_LOG="$PROJECT_DIR/logs/prd_review_cycle.log"
LOCK_FILE="/tmp/mosquito_prd_review_cycle.lock"
PID_FILE="$PROJECT_DIR/logs/prd-review/cycle.pid"
FORCE_RERUN="${FORCE_RERUN:-0}"
STALE_SECONDS="${STALE_SECONDS:-10800}"
CLAUDE_BIN="$HOME/.cursor/extensions/anthropic.claude-code-2.1.15-linux-x64/resources/native-binary/claude"
EVIDENCE_CHECK_SCRIPT="$PROJECT_DIR/scripts/verify_review_evidence.sh"
# cron环境下PATH通常不完整显式补齐nvm/codex
export HOME="${HOME:-/home/long}"
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
export PATH="$HOME/.local/bin:$HOME/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
if ! command -v codex >/dev/null 2>&1; then
if [ -s "$NVM_DIR/nvm.sh" ]; then
# shellcheck disable=SC1090
. "$NVM_DIR/nvm.sh" >/dev/null 2>&1 || true
nvm use --silent 20 >/dev/null 2>&1 || true
nvm use --silent default >/dev/null 2>&1 || true
fi
fi
CODEX_BIN="$(command -v codex || true)"
if [ -z "$CODEX_BIN" ] && [ -x "$HOME/.nvm/versions/node/v20.19.0/bin/codex" ]; then
CODEX_BIN="$HOME/.nvm/versions/node/v20.19.0/bin/codex"
fi
mkdir -p "$REPORT_DIR" "$PROJECT_DIR/logs"
if [ -f "$PID_FILE" ]; then
prev_pid="$(cat "$PID_FILE" 2>/dev/null || true)"
if [ -n "${prev_pid:-}" ] && kill -0 "$prev_pid" 2>/dev/null; then
now_ts=$(date +%s)
pid_age=$((now_ts - $(stat -c %Y "$PID_FILE" 2>/dev/null || echo "$now_ts")))
if [ "$FORCE_RERUN" = "1" ] || [ "$pid_age" -gt "$STALE_SECONDS" ]; then
echo "[$(date '+%F %T')] force/stale rerun: killing previous pid=$prev_pid age=${pid_age}s" >> "$RUN_LOG"
kill "$prev_pid" 2>/dev/null || true
sleep 2
fi
fi
fi
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
echo "[$(date '+%F %T')] skip: previous cycle still running" >> "$RUN_LOG"
exit 0
fi
echo $$ > "$PID_FILE"
trap 'rm -f "$PID_FILE"' EXIT
cd "$PROJECT_DIR"
TIMESTAMP="$(date '+%Y%m%d_%H%M%S')"
REPORT_FILE="$REPORT_DIR/review_${TIMESTAMP}.md"
LATEST_REPORT="$REPORT_DIR/latest_review.md"
CLAUDE_SUMMARY="$REPORT_DIR/claude_apply_${TIMESTAMP}.md"
PRD_FILES=()
for f in "$PROJECT_DIR/docs/PRD.md" "$PROJECT_DIR/docs/prd"/*.md; do
if [ -f "$f" ]; then
PRD_FILES+=("$f")
fi
done
if [ ${#PRD_FILES[@]} -eq 0 ]; then
echo "[$(date '+%F %T')] error: no PRD files found" >> "$RUN_LOG"
exit 1
fi
PRD_LIST=$(printf '%s\n' "${PRD_FILES[@]}")
CODEX_PROMPT=$(cat <<EOF
你是严格的项目评审官。请在仓库 $PROJECT_DIR 执行全面review并以 PRD 为基准进行差距分析。
PRD文件如下
$PRD_LIST
输出要求中文Markdown
1. 总体结论是否满足最新PRD
2. PRD事项对照矩阵事项/当前状态/证据文件路径/优先级)
3. 未完成清单P0/P1/P2
4. 给Claude可直接执行的优化任务清单按顺序包含具体文件与验收标准
5. 建议执行命令构建、测试、e2e
请务必面向“可执行落地”,不要空泛建议。
EOF
)
if [ -z "$CODEX_BIN" ]; then
echo "[$(date '+%F %T')] error: codex binary not found (PATH=$PATH)" >> "$RUN_LOG"
exit 1
fi
echo "[$(date '+%F %T')] cycle start: generating codex report with $CODEX_BIN" >> "$RUN_LOG"
"$CODEX_BIN" exec \
--cd "$PROJECT_DIR" \
--dangerously-bypass-approvals-and-sandbox \
--output-last-message "$REPORT_FILE" \
"$CODEX_PROMPT" >> "$RUN_LOG" 2>&1
if [ ! -s "$REPORT_FILE" ]; then
echo "[$(date '+%F %T')] error: codex report is empty: $REPORT_FILE" >> "$RUN_LOG"
exit 1
fi
cp -f "$REPORT_FILE" "$LATEST_REPORT"
echo "[$(date '+%F %T')] codex report ready: $REPORT_FILE" >> "$RUN_LOG"
CLAUDE_PROMPT=$(cat <<EOF
请读取并执行该评审报告中的优化任务:
$REPORT_FILE
要求:
1) 按优先级执行修复优先完成P0/P1
2) 可以直接修改代码并运行必要命令(含后端测试、前端测试、端到端测试)
3) 若修复后仍有失败,继续迭代直到通过或给出明确阻塞原因
4) 输出最终摘要执行命令、修改文件、测试结果、剩余未完成PRD项
5) 必须输出“证据矩阵”,每条包含:命令 | 退出码 | 原始日志路径 | 结果结论
6) 所有结论都要附可追溯日志路径(如 logs/*.log、target/surefire-reports/*.xml
若无法提供可追溯证据,必须明确写“证据不足-本轮无效”。
请直接开始执行,不要只给计划。
EOF
)
echo "[$(date '+%F %T')] cycle continue: running claude apply" >> "$RUN_LOG"
"$CLAUDE_BIN" -p \
--permission-mode dontAsk \
--dangerously-skip-permissions \
"$CLAUDE_PROMPT" > "$CLAUDE_SUMMARY" 2>> "$RUN_LOG"
if [ ! -s "$CLAUDE_SUMMARY" ]; then
echo "[$(date '+%F %T')] error: claude summary is empty: $CLAUDE_SUMMARY" >> "$RUN_LOG"
exit 1
fi
if [ -x "$EVIDENCE_CHECK_SCRIPT" ]; then
if "$EVIDENCE_CHECK_SCRIPT" "$CLAUDE_SUMMARY" "$PROJECT_DIR" >> "$RUN_LOG" 2>&1; then
echo "[$(date '+%F %T')] evidence gate pass" >> "$RUN_LOG"
else
echo "[$(date '+%F %T')] error: evidence gate failed, mark cycle invalid" >> "$RUN_LOG"
exit 1
fi
else
echo "[$(date '+%F %T')] warn: evidence checker missing: $EVIDENCE_CHECK_SCRIPT" >> "$RUN_LOG"
exit 1
fi
echo "[$(date '+%F %T')] cycle done: $CLAUDE_SUMMARY" >> "$RUN_LOG"