diff --git a/.clinerules b/.clinerules index fd17c61..02c5957 100644 --- a/.clinerules +++ b/.clinerules @@ -3,7 +3,7 @@ - 현재 루트는 여러 하위 Git repository를 품은 workspace이며, 그 자체를 제품 repository로 단정하지 않는다. - 응답은 사용자가 다르게 요청하지 않는 한 한국어로 작성한다. - 기존 하위 repository의 구조와 규칙을 우선한다. -- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더만 대상으로 한다. +- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로만 대상으로 한다. - 하위 repository를 변경해야 할 때는 해당 repository의 진입 파일과 `agent-ops/rules/project/rules.md`를 먼저 확인한다. - 주기 분석, 주간 분석, 구현 전 점검은 `.workspace-skills/` 하위 skill을 사용한다. - `.workspace-skills/**`는 workspace 운영 도구이므로 하위 프로젝트 분석 대상에서 제외한다. 단, skill 또는 rule을 사용하기 위해 명시적으로 필요한 파일은 읽을 수 있다. diff --git a/.cursorrules b/.cursorrules index fd17c61..02c5957 100644 --- a/.cursorrules +++ b/.cursorrules @@ -3,7 +3,7 @@ - 현재 루트는 여러 하위 Git repository를 품은 workspace이며, 그 자체를 제품 repository로 단정하지 않는다. - 응답은 사용자가 다르게 요청하지 않는 한 한국어로 작성한다. - 기존 하위 repository의 구조와 규칙을 우선한다. -- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더만 대상으로 한다. +- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로만 대상으로 한다. - 하위 repository를 변경해야 할 때는 해당 repository의 진입 파일과 `agent-ops/rules/project/rules.md`를 먼저 확인한다. - 주기 분석, 주간 분석, 구현 전 점검은 `.workspace-skills/` 하위 skill을 사용한다. - `.workspace-skills/**`는 workspace 운영 도구이므로 하위 프로젝트 분석 대상에서 제외한다. 단, skill 또는 rule을 사용하기 위해 명시적으로 필요한 파일은 읽을 수 있다. diff --git a/.gitignore b/.gitignore index 4288866..c47c4b2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ # Generated or local-only directories should stay ignored even if an allowed # directory is added later. +/mattermost/ **/.git/ **/node_modules/ **/build/ diff --git a/.workspace-skills/rules/common/rules.md b/.workspace-skills/rules/common/rules.md index fd17c61..02c5957 100644 --- a/.workspace-skills/rules/common/rules.md +++ b/.workspace-skills/rules/common/rules.md @@ -3,7 +3,7 @@ - 현재 루트는 여러 하위 Git repository를 품은 workspace이며, 그 자체를 제품 repository로 단정하지 않는다. - 응답은 사용자가 다르게 요청하지 않는 한 한국어로 작성한다. - 기존 하위 repository의 구조와 규칙을 우선한다. -- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더만 대상으로 한다. +- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로만 대상으로 한다. - 하위 repository를 변경해야 할 때는 해당 repository의 진입 파일과 `agent-ops/rules/project/rules.md`를 먼저 확인한다. - 주기 분석, 주간 분석, 구현 전 점검은 `.workspace-skills/` 하위 skill을 사용한다. - `.workspace-skills/**`는 workspace 운영 도구이므로 하위 프로젝트 분석 대상에서 제외한다. 단, skill 또는 rule을 사용하기 위해 명시적으로 필요한 파일은 읽을 수 있다. diff --git a/.workspace-skills/rules/project/rules.md b/.workspace-skills/rules/project/rules.md index 2b1a7fa..4e2b72c 100644 --- a/.workspace-skills/rules/project/rules.md +++ b/.workspace-skills/rules/project/rules.md @@ -3,7 +3,7 @@ ## 프로젝트 개요 이 workspace는 서로 연관된 하위 Git repository들을 한 루트에서 운영하기 위한 작업 공간이다. -분석 대상은 workspace root 자체가 아니라, root `.gitignore`에서 ignore되는 하위 Git repository다. +분석 대상은 workspace root 자체가 아니라, root `.gitignore`에서 ignore되는 하위 Git repository 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로다. 현재 주요 하위 repository: @@ -18,7 +18,7 @@ ## 분석 대상 탐색 -- `.workspace-skills/shared/target-discovery.md` 규칙으로 root `.gitignore`에서 ignore되는 하위 Git repository를 찾는다. +- `.workspace-skills/shared/target-discovery.md` 규칙으로 root `.gitignore`에서 ignore되는 하위 Git repository를 찾고, `.workspace-skills/shared/target-excludes.txt`에 명시된 경로는 제외한다. - workspace root 자체의 `.git`은 관리 repository로만 보고 분석 대상 repository로 보지 않는다. - `.workspace-skills/**`는 운영 도구이므로 분석 대상 repository로 보지 않는다. - 분석 중 `.workspace-skills/`를 읽는 경우는 skill, shared reference, script를 사용해야 할 때로 제한한다. diff --git a/.workspace-skills/shared/scripts/collect-subprojects.sh b/.workspace-skills/shared/scripts/collect-subprojects.sh index ae16005..b0fba2d 100755 --- a/.workspace-skills/shared/scripts/collect-subprojects.sh +++ b/.workspace-skills/shared/scripts/collect-subprojects.sh @@ -2,30 +2,77 @@ set -euo pipefail ROOT="${1:-$(pwd)}" +if [[ "$ROOT" != "/" ]]; then + ROOT="${ROOT%/}" +fi + SINCE="${2:-}" UNTIL="${3:-}" +EXCLUDES_FILE="$ROOT/.workspace-skills/shared/target-excludes.txt" if [[ -z "$SINCE" ]]; then SINCE="$(date +%Y-%m-%d) 00:00" fi +normalized_excludes() { + local exclude + + [[ -f "$EXCLUDES_FILE" ]] || return 0 + + while IFS= read -r exclude || [[ -n "$exclude" ]]; do + exclude="${exclude%%#*}" + exclude="${exclude#"${exclude%%[![:space:]]*}"}" + exclude="${exclude%"${exclude##*[![:space:]]}"}" + exclude="${exclude#./}" + exclude="${exclude#/}" + exclude="${exclude%/}" + + [[ -z "$exclude" ]] && continue + + printf '%s\n' "$exclude" + done < "$EXCLUDES_FILE" +} + +is_excluded_repo() { + local rel="$1" + local exclude + + while IFS= read -r exclude; do + if [[ "$rel" == "$exclude" || "$rel" == "$exclude/"* ]]; then + return 0 + fi + done < <(normalized_excludes) + + return 1 +} + repo_paths() { - find "$ROOT" \ - -path "$ROOT/.git" -prune -o \ - -path "$ROOT/.workspace-skills" -prune -o \ - -path "$ROOT/.tmp" -prune -o \ - -path "$ROOT/.antigravitycli" -prune -o \ - -path "*/node_modules" -prune -o \ - -path "*/build" -prune -o \ - -path "*/dist" -prune -o \ - -path "*/.dart_tool" -prune -o \ - -path "*/coverage" -prune -o \ - -type d -name .git -print | + local -a find_args=( + "$ROOT" + -path "$ROOT/.git" -prune -o + -path "$ROOT/.workspace-skills" -prune -o + -path "$ROOT/.tmp" -prune -o + -path "$ROOT/.antigravitycli" -prune -o + -path "*/node_modules" -prune -o + -path "*/build" -prune -o + -path "*/dist" -prune -o + -path "*/.dart_tool" -prune -o + -path "*/coverage" -prune -o + ) + local exclude + + while IFS= read -r exclude; do + find_args+=(-path "$ROOT/$exclude" -prune -o) + done < <(normalized_excludes) + + find_args+=(-type d -name .git -print) + + find "${find_args[@]}" | sort | while IFS= read -r gitdir; do repo="$(dirname "$gitdir")" rel="${repo#$ROOT/}" - if git -C "$ROOT" check-ignore -q -- "$rel"; then + if git -C "$ROOT" check-ignore -q -- "$rel" && ! is_excluded_repo "$rel"; then printf '%s\n' "$repo" fi done diff --git a/.workspace-skills/shared/target-discovery.md b/.workspace-skills/shared/target-discovery.md index 7eb33ca..a05483d 100644 --- a/.workspace-skills/shared/target-discovery.md +++ b/.workspace-skills/shared/target-discovery.md @@ -3,27 +3,81 @@ ## 목적 workspace root의 Git 추적 대상이 아니라, root `.gitignore`에서 무시되는 하위 Git repository만 분석 대상으로 찾는다. +단, `.workspace-skills/shared/target-excludes.txt`에 명시된 경로는 분석 대상에서 제외한다. workspace root 자체와 `.workspace-skills/`는 분석 도구/관리 영역이므로 대상에서 제외한다. +## 명시 제외 목록 + +- `.workspace-skills/shared/target-excludes.txt`에 workspace root 기준 상대 경로를 한 줄에 하나씩 적는다. +- 빈 줄과 `#` 주석은 무시하고, 앞쪽 `./` 또는 `/`와 뒤쪽 `/`는 같은 경로로 정규화한다. +- 예: `mattermost`는 `mattermost/`와 그 하위 repository를 분석 대상에서 제외한다. +- 제외 경로는 `find` 단계에서 prune하여 내부 파일을 훑지 않는다. + ## 기본 명령 ```bash -find "$ROOT" \ - -path "$ROOT/.git" -prune -o \ - -path "$ROOT/.workspace-skills" -prune -o \ - -path "$ROOT/.tmp" -prune -o \ - -path "$ROOT/.antigravitycli" -prune -o \ - -path "*/node_modules" -prune -o \ - -path "*/build" -prune -o \ - -path "*/dist" -prune -o \ - -path "*/.dart_tool" -prune -o \ - -path "*/coverage" -prune -o \ - -type d -name .git -print | +if [[ "$ROOT" != "/" ]]; then + ROOT="${ROOT%/}" +fi +EXCLUDES_FILE="$ROOT/.workspace-skills/shared/target-excludes.txt" + +normalized_excludes() { + local exclude + + [[ -f "$EXCLUDES_FILE" ]] || return 0 + + while IFS= read -r exclude || [[ -n "$exclude" ]]; do + exclude="${exclude%%#*}" + exclude="${exclude#"${exclude%%[![:space:]]*}"}" + exclude="${exclude%"${exclude##*[![:space:]]}"}" + exclude="${exclude#./}" + exclude="${exclude#/}" + exclude="${exclude%/}" + + [[ -z "$exclude" ]] && continue + + printf '%s\n' "$exclude" + done < "$EXCLUDES_FILE" +} + +is_excluded_repo() { + local rel="$1" + local exclude + + while IFS= read -r exclude; do + if [[ "$rel" == "$exclude" || "$rel" == "$exclude/"* ]]; then + return 0 + fi + done < <(normalized_excludes) + + return 1 +} + +find_args=( + "$ROOT" + -path "$ROOT/.git" -prune -o + -path "$ROOT/.workspace-skills" -prune -o + -path "$ROOT/.tmp" -prune -o + -path "$ROOT/.antigravitycli" -prune -o + -path "*/node_modules" -prune -o + -path "*/build" -prune -o + -path "*/dist" -prune -o + -path "*/.dart_tool" -prune -o + -path "*/coverage" -prune -o +) + +while IFS= read -r exclude; do + find_args+=(-path "$ROOT/$exclude" -prune -o) +done < <(normalized_excludes) + +find_args+=(-type d -name .git -print) + +find "${find_args[@]}" | sort | while IFS= read -r gitdir; do repo="$(dirname "$gitdir")" rel="${repo#$ROOT/}" - if git -C "$ROOT" check-ignore -q -- "$rel"; then + if git -C "$ROOT" check-ignore -q -- "$rel" && ! is_excluded_repo "$rel"; then printf '%s\n' "$repo" fi done @@ -33,6 +87,7 @@ find "$ROOT" \ - workspace root 자체: 관리 repository로만 보고 제품 분석 대상에서 제외한다. - root `.gitignore`에서 ignore되지 않는 경로: workspace 관리 파일로 보고 하위 프로젝트 분석 대상에서 제외한다. +- `.workspace-skills/shared/target-excludes.txt`에 명시된 경로: 외부 대형 repository 또는 현재 평가 범위 밖의 프로젝트로 보고 제외한다. - `.workspace-skills/**`: skill/rule/script를 사용할 때만 읽는다. - `.tmp/**`, `.antigravitycli/**`: workspace 부속 디렉터리로 본다. - `**/.git/**`: git metadata는 git 명령으로만 확인한다. diff --git a/.workspace-skills/shared/target-excludes.txt b/.workspace-skills/shared/target-excludes.txt new file mode 100644 index 0000000..c168168 --- /dev/null +++ b/.workspace-skills/shared/target-excludes.txt @@ -0,0 +1,2 @@ +# Workspace-root relative paths excluded from daily/weekly subproject review. +mattermost diff --git a/AGENTS.md b/AGENTS.md index fd17c61..02c5957 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ - 현재 루트는 여러 하위 Git repository를 품은 workspace이며, 그 자체를 제품 repository로 단정하지 않는다. - 응답은 사용자가 다르게 요청하지 않는 한 한국어로 작성한다. - 기존 하위 repository의 구조와 규칙을 우선한다. -- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더만 대상으로 한다. +- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로만 대상으로 한다. - 하위 repository를 변경해야 할 때는 해당 repository의 진입 파일과 `agent-ops/rules/project/rules.md`를 먼저 확인한다. - 주기 분석, 주간 분석, 구현 전 점검은 `.workspace-skills/` 하위 skill을 사용한다. - `.workspace-skills/**`는 workspace 운영 도구이므로 하위 프로젝트 분석 대상에서 제외한다. 단, skill 또는 rule을 사용하기 위해 명시적으로 필요한 파일은 읽을 수 있다. diff --git a/CLAUDE.md b/CLAUDE.md index fd17c61..02c5957 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,7 +3,7 @@ - 현재 루트는 여러 하위 Git repository를 품은 workspace이며, 그 자체를 제품 repository로 단정하지 않는다. - 응답은 사용자가 다르게 요청하지 않는 한 한국어로 작성한다. - 기존 하위 repository의 구조와 규칙을 우선한다. -- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더만 대상으로 한다. +- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로만 대상으로 한다. - 하위 repository를 변경해야 할 때는 해당 repository의 진입 파일과 `agent-ops/rules/project/rules.md`를 먼저 확인한다. - 주기 분석, 주간 분석, 구현 전 점검은 `.workspace-skills/` 하위 skill을 사용한다. - `.workspace-skills/**`는 workspace 운영 도구이므로 하위 프로젝트 분석 대상에서 제외한다. 단, skill 또는 rule을 사용하기 위해 명시적으로 필요한 파일은 읽을 수 있다. diff --git a/GEMINI.md b/GEMINI.md index fd17c61..02c5957 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -3,7 +3,7 @@ - 현재 루트는 여러 하위 Git repository를 품은 workspace이며, 그 자체를 제품 repository로 단정하지 않는다. - 응답은 사용자가 다르게 요청하지 않는 한 한국어로 작성한다. - 기존 하위 repository의 구조와 규칙을 우선한다. -- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더만 대상으로 한다. +- 분석 대상 하위 repository는 workspace root `.gitignore`에서 ignore되는 프로젝트 폴더 중 `.workspace-skills/shared/target-excludes.txt`에 없는 경로만 대상으로 한다. - 하위 repository를 변경해야 할 때는 해당 repository의 진입 파일과 `agent-ops/rules/project/rules.md`를 먼저 확인한다. - 주기 분석, 주간 분석, 구현 전 점검은 `.workspace-skills/` 하위 skill을 사용한다. - `.workspace-skills/**`는 workspace 운영 도구이므로 하위 프로젝트 분석 대상에서 제외한다. 단, skill 또는 rule을 사용하기 위해 명시적으로 필요한 파일은 읽을 수 있다.