Files
PlantAI-rag-new/tooling/compile/compile_qa.sh
T
jerryandClaude Fable 5 bbd5db2315 feat(capabilities): S6 Superpowers+S7 终验(文档/humanizer CJK 修复/验收脚本)
- prompts/superpowers_{review,answer_quality,minimal_code}.md + prompt_pack.py
- agentic_controller/answer_composer Superpowers 注入点(env 总闸,关态逐字节一致)
- compile_qa.sh: prompts/ 目录自动拷贝
- humanizer: CJK 逗号规则 + 引用保护收窄(只护标记本身,带引用句可润色)
- docs: README 能力矩阵+env 表 / ARCHITECTURE Gateway 章 / API §6 / PRD:17 /
  TEST_CASES:126 多轮语义 / CHANGELOG
- tooling/cap/final_acceptance.sh 终验矩阵
- 终验: 金标 16/20 regressions=0, 多轮指代 PASS, 热加载 PID 不变 PASS,
  Humanizer 开态「此外」消除且 22 引用保留, 五上游全绿, 7913 已释放

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 18:27:41 +08:00

146 lines
5.4 KiB
Bash
Executable File
Raw 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
# Compile the QA V1.1.73 runtime surface into stripped Cython extensions.
set -euo pipefail
umask 027
SOURCE_ROOT="${1:?Usage: $0 <source-root> <output-dir> [python]}"
OUTPUT_DIR="${2:?Usage: $0 <source-root> <output-dir> [python]}"
PYTHON="${3:-python3}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VISIBILITY_TOOL="${ELF_VISIBILITY_TOOL:-$SCRIPT_DIR/tools/elf_visibility.py}"
ENTRY_SCRIPT="scripts/qa_v1_1_73_server.py"
SOURCE_ROOT="$(realpath "$SOURCE_ROOT")"
OUTPUT_DIR="$(realpath -m "$OUTPUT_DIR")"
[[ -d "$SOURCE_ROOT" ]] || { echo "QA source directory missing: $SOURCE_ROOT" >&2; exit 2; }
[[ -x "$PYTHON" ]] || { echo "Python is not executable: $PYTHON" >&2; exit 2; }
[[ -f "$VISIBILITY_TOOL" ]] || { echo "ELF visibility tool missing: $VISIBILITY_TOOL" >&2; exit 2; }
for command_name in gcc strip rsync; do command -v "$command_name" >/dev/null; done
case "$OUTPUT_DIR" in
"/"|"$(realpath -m "$HOME")"|"$SOURCE_ROOT")
echo "Unsafe output directory: $OUTPUT_DIR" >&2
exit 2
;;
esac
[[ ! -e "$OUTPUT_DIR" ]] || {
echo "Output already exists; refusing to overwrite: $OUTPUT_DIR" >&2
exit 2
}
mkdir -p \
"$OUTPUT_DIR/scripts" \
"$OUTPUT_DIR/src/rag/qa_v1_1_73" \
"$OUTPUT_DIR/src/rag/retrieval" \
"$OUTPUT_DIR/src/rag/dual_kb_taxonomy_rag" \
"$OUTPUT_DIR/configs/rag"
echo "[QA 1/6] Copying the audited runtime surface"
install -m 0750 "$SOURCE_ROOT/$ENTRY_SCRIPT" "$OUTPUT_DIR/$ENTRY_SCRIPT"
rsync -a --include='*/' --include='*.py' --exclude='*' \
"$SOURCE_ROOT/src/rag/qa_v1_1_73/" "$OUTPUT_DIR/src/rag/qa_v1_1_73/"
rsync -a --include='*/' --include='*.py' --exclude='*' \
"$SOURCE_ROOT/src/rag/retrieval/" "$OUTPUT_DIR/src/rag/retrieval/"
install -m 0640 \
"$SOURCE_ROOT/src/rag/dual_kb_taxonomy_rag/entity_alias.py" \
"$OUTPUT_DIR/src/rag/dual_kb_taxonomy_rag/entity_alias.py"
# 2026-08-31 主项目新增:normalized_release.py(backend_guard 校验 + 图适配器)
[[ -f "$SOURCE_ROOT/src/rag/normalized_release.py" ]] && install -m 0640 \
"$SOURCE_ROOT/src/rag/normalized_release.py" \
"$OUTPUT_DIR/src/rag/normalized_release.py"
for relative in \
configs/rag/entity_alias.yaml \
configs/rag/relation_taxonomy.yaml \
configs/capabilities.yaml \
pyproject.toml \
requirements.txt \
requirements-rag.txt
do
if [[ -f "$SOURCE_ROOT/$relative" ]]; then
install -D -m 0640 "$SOURCE_ROOT/$relative" "$OUTPUT_DIR/$relative"
fi
done
# S6:prompts/ 目录(Superpowers SKILL.md 明文注入包)
if [[ -d "$SOURCE_ROOT/prompts" ]]; then
install -d -m 0750 "$OUTPUT_DIR/prompts"
install -m 0640 "$SOURCE_ROOT"/prompts/*.md "$OUTPUT_DIR/prompts/" 2>/dev/null || true
fi
# Namespace/package markers are intentionally left as minimal Python files.
touch \
"$OUTPUT_DIR/scripts/__init__.py" \
"$OUTPUT_DIR/src/__init__.py" \
"$OUTPUT_DIR/src/rag/__init__.py" \
"$OUTPUT_DIR/src/rag/dual_kb_taxonomy_rag/__init__.py"
echo "[QA 2/6] Discovering Python modules"
PY_FILES=()
while IFS= read -r -d '' path; do PY_FILES+=("$path"); done \
< <(find "$OUTPUT_DIR" -type f -name '*.py' \
-not -path "*/$ENTRY_SCRIPT" \
-not -name '__init__.py' -print0)
TOTAL="${#PY_FILES[@]}"
(( TOTAL > 0 )) || { echo "No QA modules selected for compilation" >&2; exit 3; }
INCLUDE_PY="$("$PYTHON" -c 'import sysconfig; print(sysconfig.get_config_var("INCLUDEPY") or "")')"
EXT_SUFFIX="$("$PYTHON" -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX") or ".so")')"
[[ -n "$INCLUDE_PY" ]] || { echo "Python INCLUDEPY is empty" >&2; exit 3; }
echo "[QA 3/6] Cython preflight ($TOTAL modules)"
COUNT=0
CYTHON_FAILURES=0
for py_file in "${PY_FILES[@]}"; do
COUNT=$((COUNT + 1))
directory="$(dirname "$py_file")"
module="$(basename "$py_file" .py)"
c_file="$directory/$module.c"
echo " [$COUNT/$TOTAL] ${py_file#"$OUTPUT_DIR"/}"
if ! "$PYTHON" -m cython -3 \
--directive always_allow_keywords=true,annotation_typing=False \
--no-docstrings "$py_file" -o "$c_file"; then
CYTHON_FAILURES=$((CYTHON_FAILURES + 1))
fi
done
(( CYTHON_FAILURES == 0 )) || {
echo "QA Cython preflight failed: modules=$CYTHON_FAILURES" >&2
exit 3
}
echo "[QA 4/6] GCC hidden visibility + strip ($TOTAL modules)"
COUNT=0
for py_file in "${PY_FILES[@]}"; do
COUNT=$((COUNT + 1))
directory="$(dirname "$py_file")"
module="$(basename "$py_file" .py)"
c_file="$directory/$module.c"
so_file="$directory/$module$EXT_SUFFIX"
echo " [$COUNT/$TOTAL] ${py_file#"$OUTPUT_DIR"/}"
gcc -shared -pthread -fPIC -O2 -fvisibility=hidden \
-I"$INCLUDE_PY" -o "$so_file" "$c_file"
strip --strip-unneeded "$so_file"
"$PYTHON" -B "$VISIBILITY_TOOL" \
--hide-non-pyinit --check "$so_file" >/dev/null
rm -f -- "$c_file" "$py_file"
done
echo "[QA 5/6] Restoring package markers"
while IFS= read -r -d '' directory; do
if find "$directory" -maxdepth 1 -type f \( -name '*.so' -o -name '*.py' \) -print -quit | grep -q .; then
[[ -f "$directory/__init__.py" ]] || touch "$directory/__init__.py"
fi
done < <(find "$OUTPUT_DIR" -type d -print0)
echo "[QA 6/6] Final checks"
SO_COUNT="$(find "$OUTPUT_DIR" -type f -name '*.so' | wc -l)"
[[ "$SO_COUNT" -eq "$TOTAL" ]] || {
echo "QA count mismatch: selected=$TOTAL produced=$SO_COUNT" >&2
exit 4
}
if find "$OUTPUT_DIR" -type f -name '*.c' -print -quit | grep -q .; then
echo "Generated C source remains in output" >&2
exit 4
fi
echo "QA compile+harden complete: modules=$SO_COUNT output=$OUTPUT_DIR"