#!/usr/bin/env bash # Batch generate/test/close/commit Ops catalog ECRs 027-039 set -euo pipefail export PATH=/home/jack/.local/go/bin:$PATH ROOT=/www/Project/digital-psychology cd "$ROOT" declare -A NEXT_MAP NEXT_MAP=( [027]="ECR-028 KnowledgeChunk→ToolDefinition" [028]="ECR-029 BlockPolicy" [029]="ECR-030 ModerationCase" [030]="ECR-031 CrisisEvent" [031]="ECR-032 InterventionOutcome" [032]="ECR-033 HandoffCase" [033]="ECR-034 PrivacyRequest" [034]="ECR-035 StarConfig" [035]="ECR-036 RhythmConfig" [036]="ECR-037 ImageCardDeck" [037]="ECR-038 ReportTemplate" [038]="ECR-039 FunnelDefinition" [039]="ECR-040 ScaleDefinition 只读投影" ) declare -A PRED_MAP PRED_MAP=( [027]=ECR-026 [028]=ECR-027 [029]=ECR-028 [030]=ECR-029 [031]=ECR-030 [032]=ECR-031 [033]=ECR-032 [034]=ECR-033 [035]=ECR-034 [036]=ECR-035 [037]=ECR-036 [038]=ECR-037 [039]=ECR-038 ) for ECR in 027 028 029 030 031 032 033 034 035 036 037 038 039; do echo "======== ECR-$ECR ========" SPEC="docs/WAVE0/slice-specs/ecr-$ECR.json" python3 scripts/ops-read-catalog-gen.py --spec "$SPEC" # extract fields TEST=$(python3 -c "import json;print(json.load(open('$SPEC'))['test_name'])") SLUG=$(python3 -c "import json;print(json.load(open('$SPEC'))['slug'])") CONCEPT=$(python3 -c "import json;print(json.load(open('$SPEC'))['concept'])") CAP=$(python3 -c "import json;print(json.load(open('$SPEC'))['capability'])") MIG=$(python3 -c "import json;print(json.load(open('$SPEC'))['migration'])") TITLE=$(python3 -c "import json;print(json.load(open('$SPEC'))['title'])") ROUTE=$(python3 -c "import json;d=json.load(open('$SPEC'));print(d['route_group']+'/'+d['route_resource'])") (cd apps/api && go test ./internal/integration/ -run "^${TEST}$" -count=1) NEXT="${NEXT_MAP[$ECR]}" NEXT_ECR=$(echo "$NEXT" | awk '{print $1}') NEXT_LABEL=$(echo "$NEXT" | cut -d' ' -f2-) PRED="${PRED_MAP[$ECR]}" python3 scripts/ess-slice-close.py \ --ecr "$ECR" --slug "$SLUG" --title "$TITLE" \ --concept "$CONCEPT" --capability "$CAP" --migration "$MIG" \ --test "$TEST" --ui "admin client · $ROUTE" --predecessor "$PRED" \ --next-ecr "$NEXT_ECR" --next-label "$NEXT_LABEL" \ --readme-line "| [ops-${SLUG}.md](ops-${SLUG}.md) | ${CAP} ${CONCEPT} | §7 | \`GET /admin${ROUTE}*\` | Ops-D · **ECR-${ECR} Closed** |" # keep README table tidy: move appended line next to ops-scheduled if at EOF python3 - << PY from pathlib import Path p = Path('.ai/product/feature-spec/README.md') t = p.read_text() line = '| [ops-${SLUG}.md](ops-${SLUG}.md) | ${CAP} ${CONCEPT} | §7 | \`GET /admin${ROUTE}*\` | Ops-D · **ECR-${ECR} Closed** |' # if line at end after markdown prose, relocate before "新功能" if line in t: t2 = t.replace('\n'+line, '').replace(line+'\n', '') anchor = '| [ops-scheduled-publication.md](ops-scheduled-publication.md)' # find last ops- closed line in table import re m = list(re.finditer(r'\| \[ops-[^\n]+\| Ops-D · \*\*ECR-\d+ Closed\*\* \|\n', t2)) if m: last = m[-1] t2 = t2[:last.end()] + line + '\n' + t2[last.end():] p.write_text(t2) PY python3 scripts/ess-validate.py --phase review --ecr "ECR-$ECR" python3 scripts/ess-gate-check.py --ecr "ECR-$ECR" git add -A git reset HEAD .gates 2>/dev/null || true git add .ai apps docs proto scripts 2>/dev/null || true git commit -m "feat(ECR-${ECR}): ${CAP} ${CONCEPT} 只读并 Closed ${CONCEPT} catalog (${MIG}) · Loop continuous." SHA=$(git rev-parse --short HEAD) sed -i "s/commit: \`PENDING\`/commit: \`$SHA\`/" "docs/TEST_REPORT/ECR-$ECR.md" git add "docs/TEST_REPORT/ECR-$ECR.md" git commit -m "docs(ECR-${ECR}): TEST_REPORT 补 commit sha" echo "CLOSED ECR-$ECR @ $SHA" done echo ALL_DONE_027_039