diff --git a/.aiexclude b/.aiexclude new file mode 100644 index 0000000..d37067e --- /dev/null +++ b/.aiexclude @@ -0,0 +1,2 @@ +agent-task/archive/** +agent-ops/roadmap/archive/** diff --git a/.clineignore b/.clineignore new file mode 100644 index 0000000..d37067e --- /dev/null +++ b/.clineignore @@ -0,0 +1,2 @@ +agent-task/archive/** +agent-ops/roadmap/archive/** diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 0000000..d37067e --- /dev/null +++ b/.cursorignore @@ -0,0 +1,2 @@ +agent-task/archive/** +agent-ops/roadmap/archive/** diff --git a/.geminiignore b/.geminiignore new file mode 100644 index 0000000..d37067e --- /dev/null +++ b/.geminiignore @@ -0,0 +1,2 @@ +agent-task/archive/** +agent-ops/roadmap/archive/** diff --git a/agent-ops/.version b/agent-ops/.version index 40e713d..c1847bf 100644 --- a/agent-ops/.version +++ b/agent-ops/.version @@ -1 +1 @@ -1.1.30 +1.1.31 diff --git a/agent-ops/bin/ai-ignore.sh b/agent-ops/bin/ai-ignore.sh new file mode 100755 index 0000000..dc5b276 --- /dev/null +++ b/agent-ops/bin/ai-ignore.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +# Shared AI ignore / permission defaults for init and sync flows. +AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN="agent-task/archive/**" +AGENT_OPS_ROADMAP_ARCHIVE_IGNORE_PATTERN="agent-ops/roadmap/archive/**" +AGENT_OPS_AI_IGNORE_FILES=(".geminiignore" ".aiexclude" ".cursorignore" ".clineignore") +AGENT_OPS_AI_PERMISSION_FILES=(".claude/settings.json" "opencode.json") +AGENT_OPS_AI_SYNC_FILES=("${AGENT_OPS_AI_IGNORE_FILES[@]}" "${AGENT_OPS_AI_PERMISSION_FILES[@]}") + +agent_ops_append_unique_line() { + local file="$1" + local line="$2" + + touch "$file" + if ! grep -qxF "$line" "$file"; then + printf "%s\n" "$line" >> "$file" + fi +} + +ensure_agent_ops_ai_ignore_config() { + local target_dir="$1" + local ignore_file + + for ignore_file in "${AGENT_OPS_AI_IGNORE_FILES[@]}"; do + agent_ops_append_unique_line "$target_dir/$ignore_file" "$AGENT_OPS_TASK_ARCHIVE_IGNORE_PATTERN" + agent_ops_append_unique_line "$target_dir/$ignore_file" "$AGENT_OPS_ROADMAP_ARCHIVE_IGNORE_PATTERN" + done + + mkdir -p "$target_dir/.claude" + if [[ ! -f "$target_dir/.claude/settings.json" ]]; then + cat > "$target_dir/.claude/settings.json" <<'EOF' +{ + "$schema": "https://json.schemastore.org/claude-code-settings.json", + "permissions": { + "deny": [ + "Read(./agent-task/archive/**)", + "Read(./agent-ops/roadmap/archive/**)" + ] + } +} +EOF + elif ! grep -q "agent-task/archive" "$target_dir/.claude/settings.json" || ! grep -q "agent-ops/roadmap/archive" "$target_dir/.claude/settings.json"; then + echo "Note: .claude/settings.json exists; add Read(./agent-task/archive/**) and Read(./agent-ops/roadmap/archive/**) manually." + fi + + if [[ ! -f "$target_dir/opencode.json" ]]; then + cat > "$target_dir/opencode.json" <<'EOF' +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": { + "agent-task/archive/**": "deny", + "agent-ops/roadmap/archive/**": "deny" + }, + "glob": { + "agent-task/archive/**": "deny", + "agent-ops/roadmap/archive/**": "deny" + } + }, + "watcher": { + "ignore": [ + "agent-task/archive/**", + "agent-ops/roadmap/archive/**" + ] + } +} +EOF + elif ! grep -q "agent-task/archive" "$target_dir/opencode.json" || ! grep -q "agent-ops/roadmap/archive" "$target_dir/opencode.json"; then + echo "Note: opencode.json exists; add agent-task/archive/** and agent-ops/roadmap/archive/** read/glob deny and watcher ignore manually." + fi +} diff --git a/agent-ops/bin/init-agent-ops.sh b/agent-ops/bin/init-agent-ops.sh index a8be7a5..e557db9 100755 --- a/agent-ops/bin/init-agent-ops.sh +++ b/agent-ops/bin/init-agent-ops.sh @@ -8,6 +8,7 @@ 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 " @@ -15,18 +16,6 @@ if [ -z "$1" ]; then fi TARGET_DIR=$(realpath "$1") -TASK_ARCHIVE_IGNORE_PATTERN="agent-task/archive/**" -ROADMAP_ARCHIVE_IGNORE_PATTERN="agent-ops/roadmap/archive/**" - -append_unique_line() { - local file="$1" - local line="$2" - - touch "$file" - if ! grep -qxF "$line" "$file"; then - printf "%s\n" "$line" >> "$file" - fi -} create_project_agent_ops_dirs() { local agent_ops_dir="$1" @@ -82,57 +71,7 @@ apply_agent_ops_entry_files "$COMMON_RULES" "$TARGET_DIR" ensure_common_rules_file "$SOURCE_DIR" "$TARGET_DIR/agent-ops" # 4. AI ignore / permission 설정 -append_unique_line "$TARGET_DIR/.geminiignore" "$TASK_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.geminiignore" "$ROADMAP_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.aiexclude" "$TASK_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.aiexclude" "$ROADMAP_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.cursorignore" "$TASK_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.cursorignore" "$ROADMAP_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.clineignore" "$TASK_ARCHIVE_IGNORE_PATTERN" -append_unique_line "$TARGET_DIR/.clineignore" "$ROADMAP_ARCHIVE_IGNORE_PATTERN" - -mkdir -p "$TARGET_DIR/.claude" -if [ ! -f "$TARGET_DIR/.claude/settings.json" ]; then - cat > "$TARGET_DIR/.claude/settings.json" <<'EOF' -{ - "$schema": "https://json.schemastore.org/claude-code-settings.json", - "permissions": { - "deny": [ - "Read(./agent-task/archive/**)", - "Read(./agent-ops/roadmap/archive/**)" - ] - } -} -EOF -elif ! grep -q "agent-task/archive" "$TARGET_DIR/.claude/settings.json" || ! grep -q "agent-ops/roadmap/archive" "$TARGET_DIR/.claude/settings.json"; then - echo "Note: .claude/settings.json exists; add Read(./agent-task/archive/**) and Read(./agent-ops/roadmap/archive/**) manually." -fi - -if [ ! -f "$TARGET_DIR/opencode.json" ]; then - cat > "$TARGET_DIR/opencode.json" <<'EOF' -{ - "$schema": "https://opencode.ai/config.json", - "permission": { - "read": { - "agent-task/archive/**": "deny", - "agent-ops/roadmap/archive/**": "deny" - }, - "glob": { - "agent-task/archive/**": "deny", - "agent-ops/roadmap/archive/**": "deny" - } - }, - "watcher": { - "ignore": [ - "agent-task/archive/**", - "agent-ops/roadmap/archive/**" - ] - } -} -EOF -elif ! grep -q "agent-task/archive" "$TARGET_DIR/opencode.json" || ! grep -q "agent-ops/roadmap/archive" "$TARGET_DIR/opencode.json"; then - echo "Note: opencode.json exists; add agent-task/archive/** and agent-ops/roadmap/archive/** read/glob deny and watcher ignore manually." -fi +ensure_agent_ops_ai_ignore_config "$TARGET_DIR" # 5. .gitignore 설정 TOUCH_GITIGNORE="$TARGET_DIR/.gitignore" diff --git a/agent-ops/bin/sync.sh b/agent-ops/bin/sync.sh index 75b33fa..2d8c349 100755 --- a/agent-ops/bin/sync.sh +++ b/agent-ops/bin/sync.sh @@ -11,6 +11,7 @@ RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; RESET='\033[0m' # ── 진입 파일 공통 관리 ────────────────────────────────────────────────────── source "$SCRIPT_DIR/entry-files.sh" +source "$SCRIPT_DIR/ai-ignore.sh" # ── 대상 경로 해석 (폴더명 / 상대경로 / 절대경로) ──────────────────────────── resolve_target() { @@ -130,6 +131,11 @@ agent_ops_git_paths() { printf '%s\n' "$f" fi done + for f in "${AGENT_OPS_AI_SYNC_FILES[@]}"; do + if [[ -e "$f" ]] || git ls-files --error-unmatch "$f" >/dev/null 2>&1; then + printf '%s\n' "$f" + fi + done } commit_and_push_agent_ops_scope() { @@ -179,6 +185,7 @@ sync_framework_to_target() { cp "$SRC_AO/.version" "$dst_ao/.version" apply_agent_ops_entry_files "$SRC_AO/rules/common/rules.md" "$target" fi + ensure_agent_ops_ai_ignore_config "$target" commit_and_push_agent_ops_scope "$target" "sync: agent-ops from $(basename "$PROJECT_ROOT") v$src_ver" echo -e "${GREEN}✓ 완료 → $(basename "$target")${RESET}" @@ -234,11 +241,8 @@ if [[ "$PULL_MODE" == "1" ]]; then sync_common "$DST_AO" "$SRC_AO" cp "$DST_AO/.version" "$SRC_AO/.version" apply_agent_ops_entry_files "$DST_AO/rules/common/rules.md" "$PROJECT_ROOT" - cd "$PROJECT_ROOT" - git add agent-ops/rules/common agent-ops/skills/common agent-ops/bin agent-ops/.version \ - "${AGENT_OPS_ENTRY_FILES[@]}" - git commit -m "sync: pull from agentic-framework v$DST_VER" - git push + ensure_agent_ops_ai_ignore_config "$PROJECT_ROOT" + commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: pull from agentic-framework v$DST_VER" echo -e "${GREEN}✓ 완료 (pull v$DST_VER)${RESET}" exit 0 fi @@ -293,18 +297,28 @@ SRC_VER="$(cat "$SRC_AO/.version" 2>/dev/null || echo "0.0.0")" DST_VER="$(cat "$DST_AO/.version" 2>/dev/null || echo "0.0.0")" echo " 현재 버전: $SRC_VER | framework 버전: $DST_VER" +COMMON_CHANGED="1" if ! common_differs "$SRC_AO" "$DST_AO"; then - echo " 공통 파일 변경 없음: .version 차이는 무시하고 버전 갱신/커밋을 건너뜀" - echo -e "${GREEN}✓ 완료 (변경 없음)${RESET}" - exit 0 + COMMON_CHANGED="0" fi -if version_gt "$DST_VER" "$SRC_VER"; then +if [[ "$COMMON_CHANGED" == "1" ]] && version_gt "$DST_VER" "$SRC_VER"; then echo -e "${RED}⚠ 버전 충돌: framework($DST_VER) > current($SRC_VER)${RESET}" echo -e "${YELLOW} 먼저 sync-pull로 내려받은 뒤 재시도하세요.${RESET}" exit 1 fi +ensure_agent_ops_ai_ignore_config "$PROJECT_ROOT" +ensure_agent_ops_ai_ignore_config "$TARGET" + +if [[ "$COMMON_CHANGED" == "0" ]]; then + echo " 공통 파일 변경 없음: AI ignore / permission 설정만 보강" + commit_and_push_agent_ops_scope "$TARGET" "sync: ensure agent-ops AI ignore config" + commit_and_push_agent_ops_scope "$PROJECT_ROOT" "sync: ensure agent-ops AI ignore config" + echo -e "${GREEN}✓ 완료 (공통 변경 없음)${RESET}" + exit 0 +fi + NEW_VER="$(bump_version "$SRC_VER")" sync_common "$SRC_AO" "$DST_AO" echo "$NEW_VER" > "$SRC_AO/.version" diff --git a/agent-ops/skills/common/sync-pull/SKILL.md b/agent-ops/skills/common/sync-pull/SKILL.md index adc2c42..c8ef90e 100644 --- a/agent-ops/skills/common/sync-pull/SKILL.md +++ b/agent-ops/skills/common/sync-pull/SKILL.md @@ -30,6 +30,7 @@ agent-ops/bin/sync.sh --pull - [ ] sync.sh 가 오류 없이 완료됐는가 - [ ] 현재 프로젝트 버전이 framework 버전과 일치하는가 - [ ] `agent-ops/bin/entry-files.sh`의 모든 진입 파일이 갱신됐고, 내용이 framework의 `agent-ops/rules/common/rules.md`와 일치하는가 +- [ ] `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`가 포함되어 있는가 ## 금지 사항 diff --git a/agent-ops/skills/common/sync-push/SKILL.md b/agent-ops/skills/common/sync-push/SKILL.md index 424f7bb..55487b9 100644 --- a/agent-ops/skills/common/sync-push/SKILL.md +++ b/agent-ops/skills/common/sync-push/SKILL.md @@ -35,7 +35,7 @@ description: 현재 프로젝트의 agent-ops를 agentic-framework로 올리거 3. **명시되지 않은 경우**: `agent-ops/bin/sync.sh` 실행 4. target이 없으면 `sync.sh`가 현재 프로젝트 기준 상위 폴더(`../`)의 하위 디렉터리 중 `agent-ops/` 폴더가 있는 프로젝트를 모두 대상으로 삼는다 5. `sync.sh`는 현재 agentic-framework의 `agent-ops/rules/common/rules.md` 내용을 대상 프로젝트 루트의 진입 파일에 덮어쓴다 -6. 적용 후 각 대상 repo에서 agent-ops 공통 관리 경로(`rules/common/rules.md` 포함)와 진입 파일만 stage 하여 commit/push 한다 +6. 적용 후 각 대상 repo에서 agent-ops 공통 관리 경로(`rules/common/rules.md` 포함), 진입 파일, AI ignore / permission 파일을 stage 하여 commit/push 한다 덮어쓰기 대상은 `init-agent-ops` 초기 세팅과 동일하며, 실제 목록은 `agent-ops/bin/entry-files.sh`의 `AGENT_OPS_ENTRY_FILES`를 단일 기준으로 사용한다. @@ -53,7 +53,7 @@ description: 현재 프로젝트의 agent-ops를 agentic-framework로 올리거 agent-ops/bin/sync.sh [target] ``` -푸시 대상 path는 항상 `agent-ops/.version`, `agent-ops/bin`, `agent-ops/rules/common`, `agent-ops/skills/common`과 `AGENT_OPS_ENTRY_FILES`의 진입 파일로 제한한다. +푸시 대상 path는 항상 `agent-ops/.version`, `agent-ops/bin`, `agent-ops/rules/common`, `agent-ops/skills/common`, `AGENT_OPS_ENTRY_FILES`의 진입 파일, `AGENT_OPS_AI_SYNC_FILES`의 AI ignore / permission 파일로 제한한다. ## 실행 결과 검증 @@ -61,7 +61,8 @@ agent-ops/bin/sync.sh [target] - [ ] 버전 충돌 경고가 없었는가 — 있었다면 사용자에게 수동 머지 필요함을 알린다 - [ ] 대상 repo의 `agent-ops/rules/common/rules.md`가 현재 agentic-framework의 `agent-ops/rules/common/rules.md`와 일치하는가 - [ ] agentic-framework에서 대상 프로젝트로 push한 경우, `agent-ops/bin/entry-files.sh`의 모든 진입 파일 내용이 현재 agentic-framework의 `agent-ops/rules/common/rules.md`와 일치하는가 -- [ ] 대상 repo에 commit/push 된 path가 agent-ops 공통 관리 경로와 진입 파일로 제한되었는가 +- [ ] `.geminiignore`, `.aiexclude`, `.cursorignore`, `.clineignore`에 `agent-task/archive/**`와 `agent-ops/roadmap/archive/**`가 포함되어 있는가 +- [ ] 대상 repo에 commit/push 된 path가 agent-ops 공통 관리 경로, 진입 파일, AI ignore / permission 파일로 제한되었는가 ## 금지 사항 diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..317a052 --- /dev/null +++ b/opencode.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "read": { + "agent-task/archive/**": "deny", + "agent-ops/roadmap/archive/**": "deny" + }, + "glob": { + "agent-task/archive/**": "deny", + "agent-ops/roadmap/archive/**": "deny" + } + }, + "watcher": { + "ignore": [ + "agent-task/archive/**", + "agent-ops/roadmap/archive/**" + ] + } +}