#!/usr/bin/env sh set -eu # Vendor a trimmed Playbook snapshot into a target project (offline copy), # then run sync_standards to materialize .agents// and .gitattributes in # the target project root. # # Usage: # sh scripts/vendor_playbook.sh # default: tsl # sh scripts/vendor_playbook.sh tsl cpp # sh scripts/vendor_playbook.sh --langs tsl,cpp # # Notes: # - Snapshot is written to: /docs/standards/playbook/ # - Existing snapshot is backed up before overwrite. SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)" SRC="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd -P)" usage() { cat <<'EOF' >&2 Usage: sh scripts/vendor_playbook.sh # default: tsl sh scripts/vendor_playbook.sh tsl cpp sh scripts/vendor_playbook.sh --langs tsl,cpp EOF } if [ "$#" -lt 1 ]; then usage exit 1 fi if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then usage exit 0 fi PROJECT_ROOT="$1" shift langs="" if [ "${1:-}" = "--langs" ]; then langs="${2:-}" shift 2 || true fi if [ -z "${langs:-}" ] && [ "$#" -gt 0 ]; then langs="$*" fi if [ -z "${langs:-}" ]; then langs="tsl" fi timestamp="$(date +%Y%m%d%H%M%S 2>/dev/null || echo bak)" mkdir -p "$PROJECT_ROOT" PROJECT_ROOT_ABS="$(CDPATH= cd -- "$PROJECT_ROOT" && pwd -P)" DEST_PREFIX="$PROJECT_ROOT_ABS/docs/standards/playbook" DEST_STANDARDS="$PROJECT_ROOT_ABS/docs/standards" mkdir -p "$DEST_STANDARDS" if [ -e "$DEST_PREFIX" ]; then mv "$DEST_PREFIX" "$DEST_STANDARDS/playbook.bak.$timestamp" echo "Backed up existing snapshot -> docs/standards/playbook.bak.$timestamp" fi mkdir -p "$DEST_PREFIX" # Always include: scripts + gitattributes + docs/common + codex/skills cp "$SRC/.gitattributes" "$DEST_PREFIX/.gitattributes" cp -R "$SRC/scripts" "$DEST_PREFIX/" cp -R "$SRC/codex" "$DEST_PREFIX/" cp "$SRC/SKILLS.md" "$DEST_PREFIX/SKILLS.md" mkdir -p "$DEST_PREFIX/docs" cp -R "$SRC/docs/common" "$DEST_PREFIX/docs/" mkdir -p "$DEST_PREFIX/.agents" cp "$SRC/.agents/index.md" "$DEST_PREFIX/.agents/index.md" mkdir -p "$DEST_PREFIX/templates" old_ifs="${IFS}" IFS=', ' set -- $langs IFS="${old_ifs}" langs_csv="" for lang in "$@"; do [ -n "$lang" ] || continue case "$lang" in ""|*/*|*\\*|*..*) echo "ERROR: invalid lang=$lang" >&2 exit 1 ;; esac if [ ! -d "$SRC/docs/$lang" ]; then echo "ERROR: docs not found for lang=$lang ($SRC/docs/$lang)" >&2 exit 1 fi if [ ! -d "$SRC/.agents/$lang" ]; then echo "ERROR: agents ruleset not found for lang=$lang ($SRC/.agents/$lang)" >&2 exit 1 fi cp -R "$SRC/docs/$lang" "$DEST_PREFIX/docs/" cp -R "$SRC/.agents/$lang" "$DEST_PREFIX/.agents/" if [ -d "$SRC/templates/$lang" ]; then cp -R "$SRC/templates/$lang" "$DEST_PREFIX/templates/" fi if [ -n "$langs_csv" ]; then langs_csv="$langs_csv,$lang" else langs_csv="$lang" fi done cat >"$DEST_PREFIX/docs/index.md" <>"$DEST_PREFIX/docs/index.md" <<'EOF' ## TSL(tsl) - 代码风格:`tsl/code_style.md` - 命名规范:`tsl/naming.md` - 语法手册:`tsl/syntax_book/index.md` - 工具链与验证命令(模板):`tsl/toolchain.md` EOF ;; cpp) cat >>"$DEST_PREFIX/docs/index.md" <<'EOF' ## C++(cpp) - 代码风格:`cpp/code_style.md` - 命名规范:`cpp/naming.md` - 工具链与验证命令(模板):`cpp/toolchain.md` - 第三方依赖(Conan):`cpp/dependencies_conan.md` - clangd 配置:`cpp/clangd.md` EOF ;; python) cat >>"$DEST_PREFIX/docs/index.md" <<'EOF' ## Python(python) - 代码风格:`python/style_guide.md` - 工具链:`python/tooling.md` - 配置清单:`python/configuration.md` EOF ;; esac } for lang in "$@"; do [ -n "$lang" ] || continue append_docs_section "$lang" done commit="" if command -v git >/dev/null 2>&1; then commit="$(git -C "$SRC" rev-parse HEAD 2>/dev/null || true)" fi cat >"$DEST_PREFIX/README.md" <"$DEST_PREFIX/SOURCE.md" </dev/null || date) - Langs: ${langs_csv} - Generated-by: scripts/vendor_playbook.sh EOF echo "Vendored snapshot -> $DEST_PREFIX" PROJECT_AGENTS_ROOT="$PROJECT_ROOT_ABS/.agents" PROJECT_AGENTS_INDEX="$PROJECT_AGENTS_ROOT/index.md" mkdir -p "$PROJECT_AGENTS_ROOT" if [ ! -f "$PROJECT_AGENTS_INDEX" ]; then cat >"$PROJECT_AGENTS_INDEX" <>"$PROJECT_AGENTS_INDEX" ;; cpp) printf '%s\n' "- .agents/cpp/:C++ 相关规则集(C++23,含 Modules)" >>"$PROJECT_AGENTS_INDEX" ;; python) printf '%s\n' "- .agents/python/:Python 相关规则集" >>"$PROJECT_AGENTS_INDEX" ;; esac done cat >>"$PROJECT_AGENTS_INDEX" <<'EOF' 入口建议从: EOF for lang in "$@"; do printf '%s\n' "- .agents/$lang/index.md" >>"$PROJECT_AGENTS_INDEX" done cat >>"$PROJECT_AGENTS_INDEX" <<'EOF' 标准快照文档入口: - docs/standards/playbook/docs/index.md EOF fi SYNC_ROOT="$PROJECT_ROOT_ABS" sh "$DEST_PREFIX/scripts/sync_standards.sh" "$@" echo "Done."