Files
brunoandQwen-Coder de601a98ba Add mobile/screen modules, ADRs, and enhance admin UI
New Modules:
- ljwx-platform-mobile: UniApp mobile app (login/home/work/message/mine)
- ljwx-platform-screen: Data visualization dashboard (ECharts charts)

Documentation:
- README.md: Project overview and quick start
- FULL_MANIFEST.txt: Complete file manifest
- docs/adr/: 5 Architecture Decision Records
  - 001: Module dependency DAG
  - 002: Audit field interceptor
  - 003: JWT authorities convention
  - 004: Frontend semver tilde-only
  - 005: Changelog

Admin UI Enhancements:
- Breadcrumb, TagsView, ThemeSwitch components
- Permission store and composables
- Router guards for auth
- Monitor views (loginlog, operlog)
- System views (file, notice)

Backend Updates:
- AuthController refinements
- DTO updates (Login, User, Role)
- Application.yml configuration

Phase Briefs:
- phase-20.md to phase-27.md

Total: 95 files, +11489 insertions, -932 deletions

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-24 14:57:48 +08:00

229 lines
8.7 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
# ═══════════════════════════════════════════════════════════
# phase-execute.sh — 单 Phase 执行器(含重试、manifest 写入、追溯日志)
# 用法: bash scripts/phase-execute.sh <phase-number> [--skip-preflight]
#
# 流程: preflight → 解析 Phase Brief → Claude 生成 → gate-all → 重试(×3)
# → diff-review → code-reviewer → 写 PHASE_MANIFEST.txt → git commit
# ═══════════════════════════════════════════════════════════
set -euo pipefail
PHASE_NUM="${1:?Usage: phase-execute.sh <phase-number> [--skip-preflight]}"
SKIP_PREFLIGHT="${2:-}"
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$PROJECT_ROOT"
export CLAUDE_PROJECT_DIR="$PROJECT_ROOT"
PHASE_PADDED=$(printf '%02d' "$PHASE_NUM")
PHASE_BRIEF="spec/phase/phase-${PHASE_PADDED}.md"
LOG_DIR="logs/phase-${PHASE_PADDED}"
MAX_RETRIES=3
mkdir -p "$LOG_DIR"
if [[ ! -f "$PHASE_BRIEF" ]]; then
echo "ERROR: $PHASE_BRIEF not found"
exit 1
fi
# ── Parse Phase Brief ──────────────────────────────────────
source scripts/lib/parse-phase-brief.sh "$PHASE_BRIEF"
echo "════════════════════════════════════════"
echo "Phase $PHASE_NUM: $PHASE_TITLE"
echo " Backend: $TARGET_BACKEND | Frontend: $TARGET_FRONTEND"
echo " Scope files: ${#PHASE_SCOPE[@]}"
echo "════════════════════════════════════════"
echo ""
# ── Update CLAUDE.md current phase marker ─────────────────
# Preserves the title portion: "Phase: 0 (Skeleton) — ..." → "Phase: N ..."
sed -i.bak "s/^Phase: [0-9][0-9]*/Phase: $PHASE_NUM/" CLAUDE.md && rm -f CLAUDE.md.bak
# ── Step 0: Preflight ─────────────────────────────────────
if [[ "$SKIP_PREFLIGHT" != "--skip-preflight" ]]; then
echo "═══ STEP 0: Preflight Check ═══"
bash scripts/preflight/preflight-check.sh
echo ""
fi
# Record files already changed before this phase starts (for diff-review baseline)
PRE_PHASE_FILE=$(mktemp)
git diff --name-only HEAD > "$PRE_PHASE_FILE" 2>/dev/null || true
# ── Build generation prompt ───────────────────────────────
BUILD_PROMPT="You are executing Phase $PHASE_NUM of the LJWX Platform.
Phase title: $PHASE_TITLE
Backend: $TARGET_BACKEND | Frontend: $TARGET_FRONTEND
## Your task
1. Read CLAUDE.md for all hard rules
2. Read spec/phase/${PHASE_BRIEF} for scope, deliverables, and acceptance criteria
3. Read only the spec files referenced in the Phase Brief reading list
4. Generate EVERY file listed in the scope section — complete content, no placeholders
5. After generating backend files: run mvn clean compile -f pom.xml and fix all errors
6. After generating frontend files: run pnpm run type-check and fix all type errors
7. Write a PHASE_MANIFEST.txt entry in this exact format:
## PHASE $PHASE_NUM
Title: $PHASE_TITLE
Completed: \$(date -u +%Y-%m-%dT%H:%M:%SZ)
Files:
$(for f in "${PHASE_SCOPE[@]}"; do echo " - $f"; done)
Status: PENDING
8. Then run: bash scripts/gates/gate-all.sh $PHASE_NUM
9. If any gate FAILS, fix every FAIL and re-run gates until all PASS
10. Once gates PASS, update the Status in PHASE_MANIFEST.txt to: PASSED
11. Do NOT stop until all gates pass and PHASE_MANIFEST.txt is updated
Follow spec/08-output-rules.md for output format strictly."
# ── Step 1-2: Generation with retry ───────────────────────
RETRY=0
GATE_PASSED=false
while [[ $RETRY -lt $MAX_RETRIES ]]; do
ATTEMPT=$((RETRY + 1))
echo "═══ STEP 1: Generation — Attempt $ATTEMPT / $MAX_RETRIES ═══"
ATTEMPT_LOG="$LOG_DIR/attempt-${ATTEMPT}.log"
if [[ $RETRY -eq 0 ]]; then
PROMPT="$BUILD_PROMPT"
else
# Collect gate failures for retry prompt
GATE_OUTPUT=$(bash scripts/gates/gate-all.sh "$PHASE_NUM" 2>&1 || true)
PROMPT="Phase $PHASE_NUM gate check FAILED on attempt $RETRY. Fix ALL issues below:
$GATE_OUTPUT
After fixing:
1. Re-run: bash scripts/gates/gate-all.sh $PHASE_NUM
2. Ensure ALL gates PASS
3. Update PHASE_MANIFEST.txt Status to PASSED
4. Do not stop until gates pass."
fi
# Run claude in headless mode
# --agent flag is used to activate the agent definition from .claude/agents/
if [[ "$TARGET_BACKEND" == "true" && "$TARGET_FRONTEND" != "true" ]]; then
claude -p "$PROMPT" \
--agent backend-builder \
--max-turns 80 \
--output-format text \
2>&1 | tee "$ATTEMPT_LOG"
elif [[ "$TARGET_FRONTEND" == "true" && "$TARGET_BACKEND" != "true" ]]; then
claude -p "$PROMPT" \
--agent frontend-builder \
--max-turns 60 \
--output-format text \
2>&1 | tee "$ATTEMPT_LOG"
else
# Both or neither: use no specific agent (full Claude)
claude -p "$PROMPT" \
--max-turns 80 \
--output-format text \
2>&1 | tee "$ATTEMPT_LOG"
fi
echo ""
echo "═══ STEP 2: Gate Check — Attempt $ATTEMPT ═══"
if bash scripts/gates/gate-all.sh "$PHASE_NUM" 2>&1 | tee "$LOG_DIR/gate-attempt-${ATTEMPT}.log"; then
GATE_PASSED=true
echo "Gates PASSED on attempt $ATTEMPT."
break
else
echo "Gates FAILED on attempt $ATTEMPT."
RETRY=$((RETRY + 1))
if [[ $RETRY -ge $MAX_RETRIES ]]; then
echo "All $MAX_RETRIES attempts exhausted. Phase $PHASE_NUM FAILED."
echo "Phase $PHASE_NUM FAILED — $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> logs/failed.log
exit 1
fi
echo "Retrying with gate error feedback..."
echo ""
fi
done
if [[ "$GATE_PASSED" != "true" ]]; then
exit 1
fi
# ── Step 3: Zero-token diff review ────────────────────────
echo "═══ STEP 3: Diff Review (zero-token rules scan) ═══"
bash scripts/review/diff-review.sh "$PHASE_NUM" "$PRE_PHASE_FILE" 2>&1 | tee "$LOG_DIR/diff-review.log"
REVIEW_EXIT=${PIPESTATUS[0]}
if [[ "$REVIEW_EXIT" -ne 0 ]]; then
echo "DIFF REVIEW FAILED — aborting."
exit 1
fi
echo ""
# ── Step 4: Semantic review via code-reviewer agent ───────
echo "═══ STEP 4: Semantic Review ═══"
CHANGED_FILES=$(git diff --name-only HEAD 2>/dev/null || true)
if [[ -n "$CHANGED_FILES" ]]; then
REVIEW_RESULT=$(claude -p "You are the code-reviewer. Review ONLY these changed files:
$CHANGED_FILES
Phase $PHASE_NUM allowed scope:
$(for f in "${PHASE_SCOPE[@]}"; do echo " $f"; done)
Read CLAUDE.md and spec/01-constraints.md.
Check all hard rules. Flag files outside scope as CRITICAL (scope-violation).
Output: [CRITICAL|WARNING|INFO] <file>:<line> — <rule-id> — <description>
End with: REVIEW PASSED or REVIEW FAILED: N critical, M warnings." \
--agent code-reviewer \
--max-turns 20 \
--output-format text \
2>&1 | tee "$LOG_DIR/semantic-review.log")
echo "$REVIEW_RESULT"
echo ""
if echo "$REVIEW_RESULT" | grep -q "REVIEW FAILED"; then
echo "Semantic review found CRITICAL issues — aborting."
exit 1
fi
else
echo "No changed files to review."
fi
# ── Step 5: Ensure PHASE_MANIFEST.txt is written ──────────
echo "═══ STEP 5: PHASE_MANIFEST.txt ═══"
MANIFEST="PHASE_MANIFEST.txt"
MARKER="## PHASE $PHASE_NUM"
if grep -q "$MARKER" "$MANIFEST" 2>/dev/null; then
# Update status to PASSED if not already
sed -i.bak "/$MARKER/,/^## PHASE/{s/Status: PENDING/Status: PASSED/}" "$MANIFEST" && rm -f "${MANIFEST}.bak"
echo " Manifest entry updated: $MARKER → PASSED"
else
# Write new entry
{
echo ""
echo "$MARKER"
echo "Title: $PHASE_TITLE"
echo "Completed: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "Files:"
for f in "${PHASE_SCOPE[@]}"; do
echo " - $f"
done
echo "Status: PASSED"
} >> "$MANIFEST"
echo " Manifest entry written: $MARKER"
fi
# ── Step 6: Git commit ────────────────────────────────────
echo "═══ STEP 6: Git Commit ═══"
rm -f "$PRE_PHASE_FILE"
git add -A
git commit -m "feat(phase-${PHASE_NUM}): ${PHASE_TITLE} — auto-verified" || true
echo ""
echo "════════════════════════════════════════"
echo "Phase $PHASE_NUM COMPLETE: $PHASE_TITLE"
echo "Logs: $LOG_DIR/"
echo "════════════════════════════════════════"