#!/bin/bash # agent-ops/bin/init-agent-ops.sh # 프로젝트에 agent-ops 스캐폴드를 초기화하는 스크립트 set -e SCRIPT_DIR=$(realpath "$(dirname "$0")") SOURCE_DIR=$(realpath "$SCRIPT_DIR/..") source "$SCRIPT_DIR/entry-files.sh" source "$SCRIPT_DIR/ai-ignore.sh" if [ -z "$1" ]; then echo "Usage: $0 " exit 1 fi TARGET_DIR=$(realpath "$1") create_project_agent_ops_dirs() { local agent_ops_dir="$1" mkdir -p "$agent_ops_dir/rules/project/domain" mkdir -p "$agent_ops_dir/rules/private" mkdir -p "$agent_ops_dir/skills/project" } copy_common_agent_ops() { local source_dir="$1" local target_agent_ops_dir="$2" mkdir -p "$target_agent_ops_dir/rules" mkdir -p "$target_agent_ops_dir/skills" cp "$source_dir/.version" "$target_agent_ops_dir/" rm -rf "$target_agent_ops_dir/bin" rm -rf "$target_agent_ops_dir/rules/common" rm -rf "$target_agent_ops_dir/skills/common" cp -r "$source_dir/bin" "$target_agent_ops_dir/" cp -r "$source_dir/rules/common" "$target_agent_ops_dir/rules/" cp -r "$source_dir/skills/common" "$target_agent_ops_dir/skills/" } ensure_common_rules_file() { local source_dir="$1" local target_agent_ops_dir="$2" local source_rules="$source_dir/rules/common/rules.md" local target_rules="$target_agent_ops_dir/rules/common/rules.md" if [ ! -f "$source_rules" ]; then echo "Error: common rules file not found: $source_rules" >&2 exit 1 fi mkdir -p "$(dirname "$target_rules")" cp "$source_rules" "$target_rules" } ensure_gitignore_entry() { local gitignore_file="$1" local entry="$2" if ! grep -qxF "$entry" "$gitignore_file"; then printf '%s\n' "$entry" >> "$gitignore_file" fi } discover_agent_test_domains() { local target_dir="$1" local domain_root="$target_dir/agent-ops/rules/project/domain" local project_rules="$target_dir/agent-ops/rules/project/rules.md" if [ -d "$domain_root" ]; then find "$domain_root" -mindepth 2 -maxdepth 2 -name rules.md -print \ | while IFS= read -r rule_file; do basename "$(dirname "$rule_file")" done fi if [ -f "$project_rules" ]; then grep -Eo 'agent-ops/rules/project/domain/[^/`[:space:]]+/rules\.md' "$project_rules" \ | awk -F/ '{ print $(NF-1) }' fi } ensure_agent_test_route() { local rules_file="$1" local route_line="$2" local placeholder="- 현재 등록된 도메인/검증 시나리오별 테스트 문서 없음." local tmp if grep -qxF -- "$route_line" "$rules_file"; then return fi tmp="$(mktemp "$rules_file.tmp.XXXXXX")" if grep -qxF -- "$placeholder" "$rules_file"; then awk -v placeholder="$placeholder" -v route_line="$route_line" ' $0 == placeholder { print route_line; next } { print } ' "$rules_file" > "$tmp" else awk -v route_line="$route_line" ' BEGIN { added = 0 } { print } !added && $0 == "## 라우팅" { print "" print route_line added = 1 } END { if (!added) { print "" print "## 라우팅" print "" print route_line } } ' "$rules_file" > "$tmp" fi mv "$tmp" "$rules_file" } ensure_agent_test_profile() { local target_dir="$1" local env="$2" local profile="$3" local domain="$4" local verification_type="$5" local scope="$6" local today="$7" local profile_file="$target_dir/agent-test/$env/$profile.md" local rules_file="$target_dir/agent-test/$env/rules.md" local route_line mkdir -p "$(dirname "$profile_file")" if [ ! -f "$profile_file" ]; then cat > "$profile_file" < ## 분류 - domain: $domain - verification_type: $verification_type - scope: $scope ## 환경 - host: - port: - runtime: - package manager: - docker: - external service: - model endpoint: - credential: ## 명령 - setup: - lint: - unit: - smoke: - e2e: - model: - full-cycle: ## 필수 검증 - <확인 필요> ## 보조 검증 - <확인 필요> ## 판정 기준 - <확인 필요> ## 기준 출력 예시 \`\`\`text <필요한 경우 기대 출력 예시> \`\`\` ## 차단 기준 - <확인 필요> ## 보고 항목 - 실행한 명령: - 성공한 검증: - 실패/차단된 검증: - 생략 사유: - 남은 위험: ## 금지 사항 - 확인되지 않은 host, port, token, endpoint를 추측해 쓰지 않는다. - secret, token, 개인 endpoint 원문은 tracked 파일에 기록하지 않는다. EOF fi route_line="- $domain / $verification_type / $scope: \`agent-test/$env/$profile.md\`" ensure_agent_test_route "$rules_file" "$route_line" } ensure_agent_test_local() { local target_dir="$1" local local_rules="$target_dir/agent-test/local/rules.md" local today local domain local created_domain_profile="0" today="$(date +%F)" mkdir -p "$(dirname "$local_rules")" mkdir -p "$target_dir/agent-test/runs" if [ ! -f "$local_rules" ]; then cat > "$local_rules" <-smoke 문서를 기본 baseline으로 둔다. - 도메인이 아직 없을 때만 project-smoke를 fallback baseline으로 둔다. - 도메인/검증 시나리오별 문서는 다른 테스트 문서로 라우팅하지 않는다. EOF fi while IFS= read -r domain; do [ -n "$domain" ] || continue created_domain_profile="1" ensure_agent_test_profile \ "$target_dir" \ "local" \ "$domain-smoke" \ "$domain" \ "smoke" \ "도메인 기본 smoke 검증" \ "$today" done < <(discover_agent_test_domains "$target_dir" | sort -u) if [ "$created_domain_profile" = "0" ]; then ensure_agent_test_profile \ "$target_dir" \ "local" \ "project-smoke" \ "project-wide" \ "smoke" \ "프로젝트 기본 smoke 검증" \ "$today" fi } echo "Initializing agent-ops in: $TARGET_DIR" echo "Source agent-ops: $SOURCE_DIR" # 1. 대상 폴더 생성 (프로젝트 전용 폴더는 내용 복사 없이 폴더만 생성) create_project_agent_ops_dirs "$TARGET_DIR/agent-ops" # 2. 공통 요소 복사 (프로젝트 전용 설정은 제외) copy_common_agent_ops "$SOURCE_DIR" "$TARGET_DIR/agent-ops" # 3. 에이전트 진입 파일 생성 (common/rules.md 복사) COMMON_RULES="$SOURCE_DIR/rules/common/rules.md" apply_agent_ops_entry_files "$COMMON_RULES" "$TARGET_DIR" ensure_common_rules_file "$SOURCE_DIR" "$TARGET_DIR/agent-ops" # 4. AI ignore / permission 설정 ensure_agent_ops_ai_ignore_config "$TARGET_DIR" # 5. .gitignore 설정 TOUCH_GITIGNORE="$TARGET_DIR/.gitignore" touch "$TOUCH_GITIGNORE" agent_ops_ensure_gitignore_task_artifact_block "$TOUCH_GITIGNORE" if ! grep -q "agent-ops/rules/private/" "$TOUCH_GITIGNORE"; then echo "" >> "$TOUCH_GITIGNORE" echo "# Agent-Ops Private Rules" >> "$TOUCH_GITIGNORE" echo "agent-ops/rules/private/" >> "$TOUCH_GITIGNORE" fi if ! grep -qxF "# Agent-Test Local Environment" "$TOUCH_GITIGNORE"; then echo "" >> "$TOUCH_GITIGNORE" echo "# Agent-Test Local Environment" >> "$TOUCH_GITIGNORE" fi ensure_gitignore_entry "$TOUCH_GITIGNORE" "agent-test/local/" ensure_gitignore_entry "$TOUCH_GITIGNORE" "agent-test/runs/" # 6. local 테스트 환경 생성 ensure_agent_test_local "$TARGET_DIR" echo "Successfully initialized agent-ops in $TARGET_DIR" echo "Note: agent-ops/rules/project and agent-ops/skills/project are initialized as empty." echo "Note: agent-test/local rules and baseline test profiles are initialized and ignored by git."